闲聊js中的apply、call和arguments
JavaScript提供了apply和call两种调用方式来确定函数中的this的指向,在现实编码中,我确实
很少接触到这两个方法。但很无奈,很多面试题都要考这两种方法,我又没怎么用到,所以我们先来
闲聊下他们到底有什么用和到底怎么用。
我们先来聊一下apply的用法吧,它是用来改变函数的指向的,说白了,就是指向了别的函数的作用域。
例如看一下下面这个例子。
var A={
name:"我是小A",
fun:function(){
console.log("大家好! "+this.name)
}
}
var B = {
name:"我是小B"
}
A.fun(); //大家好! 我是小A
A.fun.apply(B); //大家好! 我是小B
可以看出来,当我们使用了apply将引用指向了B时,A调用fun时并不是调用本身中的name 而是调用了B中的那么;
但如果我们在调用函数中并没用引用到this,那么是不是说apply就失去了意义?再来看一下下面的例子
var A={
name:"我是小A",
fun:function(num,money){
console.log("大家好! "+this.name+" 我有"+num+"张"+money+"块")
}
}
var B = {
name:"我是小B"
}
var monies = [10,20];
A.fun.apply(B,monies); //大家好! 我是小B 我有10张20块
可以看出:apply中
第一个参数为thisObject,调用时采用传入的thisObject代替函数体中this的指向
第二个参数传入一个数组,函数会用数组的值取代“参数列表"。
这里聊一下monies,就要说到参数列表,当然我们会想到arguments,在这里插入聊一下arguments。网
上arguments是具有数组某些特性的‘类数组‘(伪数组);其实JS并没有重载函数的功能,但是auguments对象
能够模拟重载。每个函数都有一个Arguments对象实例arguments,它引用着函数的实参,可以用数组下
标的方式”[]“引用arguments的元素。arguments.length为函数实参个数。
function test() {
var s = "";
for (var i = 0; i < arguments.length; i++) {
alert(arguments[i]);
s += arguments[i] + ",";
}
return s;
}
test("name", "age")
输出
name,age
在匿名函数中可以用arguements.callee引用函数自身。
例如 function(){
if(n>0) return 0;
else return n+arguments.callee(n+1);
}
回归正题,我们可以用arguments来代替函数中的参数
var A={
name:"我是小A",
fun:function(num,money){
console.log("大家好! "+this.name+" 我有"+arguments[0]+"张"+arguments[1]+"块")
}
}
var B = {
name:"我是小B"
}
var monies = [10,20];
A.fun.apply(B,monies); //大家好! 我是小B 我有10张20块
这里又有一个问题,可不可以用Array.prototype.shift.apply(arguments)来代替arguments[0]呢?直接看代码
var A={
name:"我是小A",
fun:function(num,money){
console.log("大家好! "+this.name+" 我有"+Array.prototype.shift.apply(arguments)+"张"+arguments[1]+"块")
}
}
var B = {
name:"我是小B"
}
var monies = [10,20];
A.fun.apply(B,monies); //大家好! 我是小B 我有10张undefined块
当我们使用Array.prototype.shift.apply(arguments)调用之后,arguments[0]就会被抹去,所以arguments[1]就会冒到arguments[0]上。
这可以看出arguments这个”伪数组“,除了不是”原型继承自’Array.prototype‘“职位,其他特征和数组是一样的。
最后,我们考虑一下,如果使用apply方法时,传入的第一个参数是null时,调用函数时,会发生什么情况,会不会报错呢!
不多说,直接上例子
var A={
name:"我是小A",
fun:function(num,money){
console.log("大家好! "+this.name+" 我有"+num+"张"+money+"块")
}
}
var B = {
name:"我是小B"
}
var monies = [10,20];
name="我是小C"
A.fun.apply(null,monies); //大家好! 我是小C 我有10张20块
可以看到 如果第一传入的参数是null的话,在函数提内的this会指向全局对象,在浏览器中就是window。
所以可以总结出两点:
1.如果函数中有明确使用this,那么this就会指向传入的第一个参数的作用域。
2.如果传入的第一参数为null时,this就会指向全局的作用域。
apply的另一种用法就是用于将数组分割为一个个元素。
例如想在数组中a[1,2,3,4]中寻找出最大的袁术出来。
如果直接调用Math.max(a);就会输出NaN,所以这时候我们可以这样
Math.max.apply(null,a); //输出4
聊完了apply之后,我们再聊一下call就更简单了,其实他们的作用都是一样的。他们唯一的区别就是
apply和call在形式参数上的不同,apply只能传入两个参数且,第二个参数传入的是数组,而call在
第二参数开始可以接受任意个参数。大家看下面的例子就一目了然了
var A={
name:"我是小A",
fun:function(num,money){
console.log("大家好! "+this.name+" 我有"+num+"张"+money+"块")
}
}
var B = {
name:"我是小B"
}
var monies = [10,20];
A.fun(monies[0],monies[1]); //大家好! 我是小A 我有10张20块
A.fun.apply(B,monies); //大家好! 我是小B 我有10张20块
A.fun.call(B,monies); //大家好! 我是小B 我有10,20张undefined块
A.fun.call(B,monies[1],monies[2]); //大家好! 我是小B 我有20张undefined块
闲聊js中的apply、call和arguments的更多相关文章
- 兄台息怒,关于arguments,您的想法和大神是一样一样的----闲聊JS中的apply和call
JavaScript提供了apply和call两种调用方式来确定函数体中this的指向,表现出来的特征就是:对象可以'借用'其他对象的方法.之前的几篇博客回顾了一些Web控件的一些开发方法,我们聊了如 ...
- 深入理解js中的apply、call、bind
概述 js中的apply,call都是为了改变某个函数运行时的上下文环境而存在的,即改变函数内部的this指向. apply() apply 方法传入两个参数:一个是作为函数上下文的对象,另外一个是作 ...
- js中的apply和call API
借用网上的一个例子: fun.call(this,arg1,arg2,arg3) fun.apply(this,arguments) this.fun(arg1,arg2,arg3) 三种方法等效. ...
- js中call apply方法的使用介绍
js call call 方法 请参阅 应用于:Function 对象 要求 版本 5.5 调用一个对象的一个方法,以另一个对象替换当前对象. call([thisObj[,arg1[, arg2[, ...
- js 中call,apply,bind的区别
call.apply.bind方法的共同点与区别: apply.call.bind 三者都是用来改变函数的this对象的指向: apply.call.bind 三者都可以利用后续参数传参: bind ...
- js中call(),apply(),以及prototype的含义
最近段时间主要学习前端去了,然而所遇到的一些问题我觉得有必要去深究一下 prototype: 1 js中有三种表达方法 类方法,属性方法,原型方法 function People(name) { th ...
- Js中的apply和call
1.call和apply都是为了改变某个函数运行时的上下文而存在的 2.也就是改变函数体内this的指向. 3.二者的作用完全一样,只是接受参数的方式不太一样. 4.call 需要把参数按顺序传递进去 ...
- js中的apply调用
今天看了阮一锋老师的一篇文章,感觉很明了对闭包的理解,尤其是文章中的apply的介绍 apply()是函数对象的一个方法,它的作用是改变函数的调用对象,它的第一个参数就表示改变后的调用这个函数的对象. ...
- js中函数的 this、arguments 、caller,call(),apply(),bind()
在函数内部有两个特殊的对象,arguments 和 this,还有一个函数对象的属性caller. arguments对象 arguments是一个类似数组的对象,包含着传入函数的所有参数. func ...
随机推荐
- Java多线程:线程与进程
实际上,线程和进程的区别,在学OS时必然是学习过的,所缺的不过是一些总结. 1. 进程 2. 线程 3. 进程与线程 4. 多进程与多线程对比 5. Java多进程与多线程 5.1. Java多进程 ...
- 在C# 中 如何限制在文本框(textBox)中输入的类型为正整数
在文本框的 KeyPress 事件中写下这些代码就可以保证是正整数了 private void textBox1_KeyPress(object sender, KeyPressEventArgs e ...
- 【多线程】-Thread
Thread介绍(实例化): Thread类可以创建和控制线程,Thread类的构造函数重载为接受ThreadStart和ParameterizedThreadStart类型的委托参数.微软官网给出的 ...
- PAT1011:World Cup Betting
1011. World Cup Betting (20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Wit ...
- 一步一步实现HTTP服务器-开篇
缘起 翻开清单,一条条计划一直列在那里,一天又一天,不知道什么时候写下了它,也知不道什么时候完成它,它一直在那静静的等待着. 静下心来,反思自己,才发现自己是多么的无知,多么的没有毅力.设定了无数目标 ...
- LeetCode Javascript实现 169. Majority Element 217. Contains Duplicate(两个对象比较是否相等时,如果都指向同一个对象,a==b才是true)350. Intersection of Two Arrays II
169. Majority Element /** * @param {number[]} nums * @return {number} */ var majorityElement = funct ...
- Redis in Python:HyperLogLog(pfadd、pfcount、pfmerge)
redis HyperLogLog 可以接受多个元素作为输入,并给出输入元素的基数估算值. 基数:集合中不同元素的数量.比如 [foo', 'bar', 'foobar', 'bar', 'test' ...
- GitHub 系列之「怎样使用 GitHub?」
1.写在前边的话,为什么要写CitHub? 跟朋友在交流的时候听到求职的时候发现有些公司要附Github帐号,一个优秀的 GitHub 账号当然能让你增色不少.自己之前听说过,但没有花时间研究,最后花 ...
- python使用@property
在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改: s = Student() s.score = 9999 这显然不合逻辑.为了限制score的 ...
- 各位情人节快乐, Python帮忙撒狗粮, 我连夜做了这个程序!
阅读本文大概需要5分钟 码农的情人节 一年一度的情人节要来啦,这个浪漫温馨的节日,走在大街小巷,走在地铁里,走在商场里,走在电影院,姑娘们手里几乎都捧着一束花,心里都是乐滋滋的,一脸幸福的样子,忽然想 ...