根據一道題引起的call、apply、bind方法總結

這是一道今天遇到的面試題面試

clipboard.png

由於setTimeout屬於匿名函數,this指向window,因此this.id = 1
但仍是先總結一下call和apply的用法。app

首先介紹一下call和apply的定義函數

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

call和apply的做用是改變函數運行時的上下文環境(改變this的指向),將obj綁定到thisObj,或者說this.Obj調用了obj裏面的方法。this

call和apply的做用

當一個對象須要調用另一個對象裏面的方法的時候,能夠用到call和apply,call和apply能夠理解成是繼承另一個對象的方法。spa

首先咱們創建兩個對象obj1和obj2code

clipboard.png

若是obj2對象要調用obj1中的func1方法(能夠理解爲在obj2的環境中執行obj1.func1方法),則對象

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

call和apply第一個參數都是表示obj1綁定的對象,若是obj1要綁定到this,此時obj1就是綁定到全局,如:blog

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方法調用父構造函數ip

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();

執行成功

相關文章
相關標籤/搜索