js中call,apply和bind

1,首先先做一个定义:每个函数都包含两个非继承的方法:apply()和call(),apply和call这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值,两者唯一的区别就是第二个参数不同,apply是传一个数组或者arguments对象,call则需要逐个列出来。(call是把它们一个一个都叫过来,apply是整个应用)

函数a.apply(b, [1,2]) == 函数a.call(b, 1, 2),其实含义就是在b里面执行a函数,作用域是b所在的执行环境,这里有个注意点,就是在使用了apply和call之后,会立即执行该函数。

传递参数的示例代码就不写了,太多了。。

事实上,传递参数并非call和apply真正的用武之地,它们真正强大的地方是扩充作用域。

window.color = "red";

var o = {
  color: 'blue'  
};

function fn(){
   console.log(this.color)
};

fn();    // red
fn.call(this);    // red
fn.call(window);    // red
fn.call(o);    // blue

上面换成apply也一样。call和apply如果传递的是null或者undefined,默认就是在window中。

一些类数组,比如arguments和NodeList,只能使用数组索引而不能用push,pop等数组方法,我们就可以用apply或call为其添加数组的方法。

(function(){
  Array.prototype.push.call(arguments,4);
  console.log(arguments);//[1, 2, 3, 4]
})(1,2,3)

还有之前提到的如何判断类型:

console.log(Object.prototype.toString.call(123)) //[object Number]
console.log(Object.prototype.toString.call('123')) //[object String]
console.log(Object.prototype.toString.call(undefined)) //[object Undefined]
console.log(Object.prototype.toString.call(true)) //[object Boolean]
console.log(Object.prototype.toString.call({})) //[object Object]
console.log(Object.prototype.toString.call([])) //[object Array]
console.log(Object.prototype.toString.call(function(){})) //[object Function]

2,而bind方法会创建一个函数的实例,其this值会被绑定到传给bind()函数的值,和call和apply方法不同的是,bind不会立即执行。

window.color = 'red';

function fn(){
   alert(this.color)
};

var b = {
   color: 'blue'
}

var o = fn.bind(b);
o();    // 'blue'

记住一定要给bind绑定后赋值,因为它返回的是一个函数实例,不然没办法触发。

bind是ES5定义的,所以可能部分浏览器不支持,需要模拟bind():

Function.prototype.bind = function(context){
    var self = this;
    return function(){
         return self.apply(context, arguments)
    }
}
原文地址:https://www.cnblogs.com/yanchenyu/p/7592927.html