apply、call与bind方法修改this指向

2019-03-08  本文已影响0人  GoFzy

以下都是在非严格模式下进行讨论

一、apply与call

function f1(x,y){
  console.log("结果是:" + (x + y) + this); 
}
f1(10,20); //30[object Window]    此时this指向window对象,很好理解
f1.apply(null,[10,20]);  //30[object Window] 
f1.call(null,10,20);  //30[object Window] 

  apply和call方法中如果第一个参数传入的是null,那么调用该方法的函数对象中this仍默认的指向。两个作用一致,只是传参形式不同。

function f1(x,y){
  console.log("结果是:" + (x + y) + this); 
}
var obj = {
  age: 10,
  sex: "male"
}
f1.apply(obj,[10,20]);  //30[object Object] 
f1.call(obj,10,20);  //30[object Object] 
console.dir(obj); // obj中不存在f1方法

  第一个参数传入对象后,可以修改this指向,此时指向传入的对象。需要注意的是apply和call只是”临时借用“obj对象,并不会将方法添加到该对象中。

二、扩展问题:apply和call到底属于谁的方法?

    function f(){
        console.log(this+'我被调用了');
    }
    f.apply();
    f.call();
    console.dir(f);
输出结果

  首先我们知道f既是函数也是对象,上段代码中显示f能够调用apply和call方法,那么f中是否含有apply和call呢?所以我用console.dir查看了下f函数的结构:


f函数对象结构

  发现事情并不简单,两个方法并不是直接存在与f函数对象中。那就往原型对象中查找,函数对象f是谁的实例对象呢?Function!

   console.log(f.__proto__ == Function.prototype) //true
  console.dir(Function);
Function对象

  现在结果就很明了了,所有函数都是Function的实例对象,而apply和call都属于Function的原型对象(prototype)之中。

三、bind方法

function f1(x,y){
  console.log("结果是:" + (x + y) + this); 
}
f1.bind(); //此时函数并没有执行,这里只是单纯的复制了一份
var ff = f1.bind(); 
ff(10,20); //30[object Object]  此时没有传入指向对象,故保持默认
var fz = f1.bind(null,10,20);
fz(); //30[object Object]  与ff结果一样,只不过是第二种写法,参数两处都可以传入
var obj = {
  age: 10,
  sex: "male"
}
var fzy = f1.bind(obj,10,20);
fzy(); //30[object Object] 

  总结一下:
  ①bind方法是复制的意思,即复制一份新函数,参数可以在复制的时候传入,也可以在复制之后调用时传入
  ②call和apply是调用的时候改变this指向--适用于直接调用
  ③bind是复制该函数 的时候改变了this 的指向,适合作为参数传递

上一篇下一篇

猜你喜欢

热点阅读