1. 程式人生 > >簡析JavaScript中的Function型別(五)——設定函式的作用域

簡析JavaScript中的Function型別(五)——設定函式的作用域

開發十年,就只剩下這套架構體系了! >>>   

在JavaScript中,函式執行時都具有特定的作用域,如下程式碼:

var name = 'Jack';
var person = {
  name: 'Bob',
  sayName: function(code, msg){
    console.log(code, msg + this.name);
  }
}

person.sayName(0, 'hello ');// 0 "hello Bob"

var newSay = person.sayName;
newSay(0, 'hello ');// 0 "hello Jack"

先宣告一個name變數,然後宣告一個person物件,person包含namesayName屬性。當直接在物件上進行方法的呼叫時:person.sayName(),函式的作用域遵循“誰呼叫就是誰”的原則,sayName的作用域(也就是this)指向的就是person

當把person.sayName賦值給新變數newSay時,呼叫newSay()為直接的函式呼叫,此時函式的作用域變為了window。本質上來講,newSay()相當於window.newSay(),所以同樣也是遵循“誰呼叫就是誰”的原則。

但是函式有三個方法可以用來設定作用域,分別為applycallbind

還是上面的例子,使用如下方式呼叫:

person.sayName.apply(window, [0, 'hello ']);//0 "hello Jack"

apply接收兩個引數,第一個引數為函式執行時的作用域,也就是this的值,這樣就可以人為的改變函式執行時的作用域了。

使用call方法也是一樣:

person.sayName.call(window, 0, 'hello ');//0 "hello Jack"

區別在於apply接收一個數組用於函式的引數,而call需要把引數一一列出。

對於bind,來看下面的程式碼:

var newSay2 = person.sayName.bind(person);
newSay2(0, 'hello');//0 "hello Bob"

console.log(person.sayName === newSay);// true
console.log(person.sayName === newSay2);// false

bind也是改變了作用域,但bind建立了一個新的函式,這個函式具有和原函式相同的程式碼體。而applycall都是