关于call()
,apply()
,bind()
之前学习全靠死记硬背,当然时间长不用就忘了,又得重新找博客学习.造成这种学了忘,忘了再学的主要问题还是没有理解.
先看看这三种方法的区别:
-
返回值不同:
call
,apply
返回函数执行的结果;
bind
返回的是没有执行的函数,需要手动调用 -
传递的参数不同:
apply
的参数要求是一个数组
call
的参数则是一个个元素
bind
的参数也是单个元素
网上很多文章解释这些方法都是从改变this
的指向开始,这样理解部分案例还是比较好理解的如果在this
漫天飞的情况下就很头痛了,因为this
指向不变的情况下都没弄明白指的谁,更何况变了的情况.比如:
fn.apply(this, arguments);
难道是这里的this指向发生了变化?这个问题我希望留到后面解答.
我们先看这样一段代码:
var mult = function () {
console.log('开始计算乘积');
var a = 1;
for (var i = 0, l = arguments.length; i < l; i++) {
a = a * arguments[i];
}
console.log(a);
};
var proxyMult = (function() {
var cache = {};
return function() {
console.log(this); //window
var args = Array.prototype.join.call(arguments, ',');
if(args in cache) {
return cache[args];
}
return cache[args] = mult.apply(this, arguments);
}
})();
proxyMult(1,2,3,4);
proxyMult(1,2,3,4);
这里用到了call
和apply
两种方法,并且方法里面还有this
.我们先看call
这个方法
var args = Array.prototype.join.call(arguments, ',');
我们知道arguments
是个类数组对象,是没法调用join
方法的,所以我们需要从数组中借用这个方法,于是就"打电话"(call)叫这个方法来帮个忙.
于是arguments
叫join
来帮忙,所以join
在arguments
的环境下执行,这里我把第一个参数理解成执行环境(谁调用了这个方法),而第二个参数便是要传入借用函数的参数,如果arguments
有join
方法的话,上面的那行代码等价于
arguments.join(',');
我们再看下面一行代码,
mult.apply(this, arguments);
这里我们需要得到mult
的执行结果,不在乎是谁调用,所以直接在window
下执行,而这里的this
由打印可知指的是window
.
那么this
指向发生改变作何理解呢?
我们再看一个案例
var personA = {
name: 'XL',
sayName: function (hobby){
console.log(this.name + ' likes ' + hobby);
}
};
personA.sayName('basketball'); // 'XL likes basketball'
var personB = {
name: 'xl'
}
personA.sayName.call(personB, 'basketball'); // 'xl likes basketball'
personA.sayName.apply(personB, ['basketball']); // 'xl likes basketball'
由上文我们知道personB从personA那里借到sayName
这个方法,而在sayName
方法中,this
原先指的是personA这个对象,但是真正调用sayName
方法的却是personB,举个例子:你从别人那里借了100元,你用这100元挣了200元,那么你还的时候难道将你挣得200元也还给被人?
用执行环境来理解就是在当前环境下执行了某个方法,某个方法的this
便指向当前的环境
以上是我的个人理解,欢迎指正
网友评论