You Don't Know JS筆記(一):this綁定規(guī)則

1.默認綁定

function foo( ){
  console.log(this.a);
}
var a = 2;
foo( );  // 2

在代碼中,foo()是直接使用不帶任何修飾的函數引用進行調用的,因此只能使用默認綁定。默認綁定this指向全局變量。
如果處于嚴格模式(strict mode),那么全局變量將無法使用默認綁定,因此this會綁定到undifined:

function foo( ){
 "use strict";
  console.log(this.a);
}
var a = 2;
foo( ); //undefined

雖然this的綁定規(guī)則完全取決于調用位置,但是只要foo()運行在非 strict mode下時,默認綁定才能綁定到全局變量;嚴格模式下與foo( )的調用位置無關:

function foo( ){
  console.log(this.a);
}
var a = 2;
(function(){
    "use strict";
    foo();  //2
})();

2.隱式綁定

function foo( ){
  console.log( this.a );
}
var obj = {
   a: 2,
   foo: foo
};
obj.foo(); //2

foo函數嚴格來說并不屬于obj對象。然而,調用位置會使用obj的上下文來引用對象。當函數擁有上下文對象時,隱式綁定規(guī)則會把函數中的this綁定到這個上下文對象。this.a 和 obj.a是一樣的。
對象引用鏈中只有最后一層會影響調用位置。

function foo( ){
    console.log(this.a);
}
var obj2 = {
   a: 42,
   foo: foo
};
var obj1 = {
   a: 2,
   obj2: obj2;
};
obj1.obj2.foo(); // 42

隱式丟失(取決于是否是嚴格模式):

function foo( ){
  console.log( this.a );
}
var obj = {
   a: 2,
   foo: foo
};
var bar = obj.foo( ); //函數別名
var a = "oops, global" ;
bar(); // "oops, global" ;

雖然bar是obj.foo的一個引用,但是實際上,它引用的是foo函數本身,因此此時的bar()其實是一個不帶任何修飾的函數調用,因此應用了默認綁定。
** 回調函數如 :setTimeout(obj.foo, 100) 會丟失this綁定。**

3.顯示綁定

如果我們不想在對象內部包含函數引用,而是想在某個對象上強制調用函數,該怎么做?
可以使用call(...)apply(...)方法。第一個參數是一個對象,它們會把這個對象綁定到this, 接著在調用函數時指定這個this.

function foo(this.a){
    console.log(this.a);
}
var obj = {
    a: 2;
};
foo.call(obj); //2

通過foo.call(...),我們可以在調用foo時強制把它的this綁定到obj上。
bind會返回一個硬編碼的新函數,它會把參數設置為this的上下文并調用初始函數。
第三方的許多庫和js語言和宿主環(huán)境中許多新的內置函數,都提供一個可選的參數,起作用和bind(...)一樣。

4.new綁定

function foo(a){
     this.a = a;
}
var bar = new foo(2);
console.log(bar.a); //2

使用new來調用函數時,會自動執(zhí)行下面的操作:

  1. 創(chuàng)建一個空對象。
  2. 這個對象會被執(zhí)行[ [原型] ]連接。
    3.這個新對象會被綁定到函數調用的this.
    4.返回這個新對象。

5. 優(yōu)先級

根據優(yōu)先級判斷函數在某個調用位置應用的是哪條規(guī)則,可以按照下面的順序來進行判斷:

  1. 函數是否在new中調用?如果是的話this綁定的是新創(chuàng)建的對象
  2. 函數是否通過call, apply(顯示綁定)
  3. 函數是否在某個上下文對象中調用(隱式綁定)
  4. 如果都不是的話,使用默認綁定。

6. ES6新東西-- 箭頭函數

箭頭函數可以像bind一樣確保函數的this被綁定到指定對象。

var obj = {
   a : 2,
  foo:function foo(){
          setTimeout(()=>{ console.log(this.a);},100)
       }
};
obj.foo(); // 2

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 現(xiàn)在了解了函數調用中this綁定的四條規(guī)則,需要做的是找到函數的調用位置并判斷應用了哪條規(guī)則。如果調用位置應用多條...
    李友勝閱讀 602評論 0 2
  • 默認綁定 JS中最常用的函數調用類型:獨立函數調用。可將其看作無法應用其他規(guī)則時的默認規(guī)則。 聲明在全局作用域中的...
    明滅_閱讀 156評論 0 2
  • 關于 this this 關鍵字是 JavaScript 中最復雜的機制之一。它是一個很特別的關鍵字,被自動定義在...
    游學者灬墨槿閱讀 633評論 1 2
  • 每個函數的this是在調用時被綁定的,完全取決于函數的調用位置(也就是函數的調用方法) 調用位置 在理解this的...
    李友勝閱讀 301評論 0 0
  • this 的四種綁定策略( 默認綁定、隱式綁定、顯式綁定、new 綁定 ) 默認綁定:this 一般默認指向全局作...
    南航閱讀 1,932評論 0 0

友情鏈接更多精彩內容