3

这是一道今天遇到的面试题

clipboard.png

因为setTimeout属于匿名函数,this指向window,所以this.id = 1
但还是先总结一下call和apply的用法。

首先介绍一下call和apply的定义

obj.call(thisObj, arg1, arg2,...)
obj.apply(thisObj, [arg1, arg2,...])

call和apply的作用是改变函数运行时的上下文环境(改变this的指向),将obj绑定到thisObj,或者说this.Obj调用了obj里面的方法。

call和apply的作用

当一个对象需要调用另外一个对象里面的方法的时候,可以用到call和apply,call和apply可以理解成是继承另外一个对象的方法。

首先我们建立两个对象obj1和obj2

clipboard.png

如果obj2对象要调用obj1中的func1方法(可以理解为在obj2的环境中执行obj1.func1方法),则

 obj1.func1.call(obj2); //输出:obj2Name
 obj1.func1.apply(obj2);//输出:obj2Name

call和apply第一个参数都是表示obj1绑定的对象,如果obj1要绑定到this,此时obj1就是绑定到全局,如:

 obj1.func1.call(this);//输出:windowName
 obj1.func1.apply(this);//输出:windowName

如果obj2对象要调用obj1中的func2方法,则

  obj1.func2.call(obj2,1,2);//输出:3
  obj1.func2.apply(obj2,[1,2]);//输出:3

call和apply实现继承

使用call方法调用父构造函数

function Product(name, price) {
  this.name = name;
  this.price = price;

  if (price < 0) {
    throw RangeError(
      'Cannot create product ' + this.name + ' with a negative price'
    );
  }
}

function Food(name, price) {
  Product.call(this, name, price);
  this.category = 'food';
}

//等同于
function Food(name, price) {
  this.name = name;
  this.price = price;
  if (price < 0) {
    throw RangeError(
      'Cannot create product ' + this.name + ' with a negative price'
    );
  }

  this.category = 'food';
}

//function Toy 同上
function Toy(name, price) {
  Product.call(this, name, price);
  this.category = 'toy';
}

var cheese = new Food('feta', 5);
var fun = new Toy('robot', 40);

bind方法和call、apply的区别

bind方法也是用来改变this的指向

var a = {
    user:"追梦子",
    fn:function(){
        console.log(this.user);
    }
}
var b = a.fn;
b.bind(a);

没有被打印,这就是bind方法与apply、call方法的不同。bind方法返回的是修改过后的函数

var a = {
    user:"追梦子",
    fn:function(){
        console.log(this.user); //追梦子
    }
}
var b = a.fn;
var c = b.bind(a);
c();

执行成功


qqqq
160 声望3 粉丝