你不知道的this

MDN中的this定義

當前執行代碼的環境對象。程序員

多麼簡約凝練的歸納,寥寥11個字,將伴隨程序員的前世此生。話很少說,讓咱們一塊兒探討你不知道的thisapp

牛刀小試

function foo() {
      console.log( this.a );
  }
  var a = 10;
  foo();
答案:
10
this —> window
function foo() { 
      console.log( this.a );
  }
  var obj2 = { 
      a: 42,
      foo: foo 
  };
  var obj1 = { 
      a: 2,
      obj2: obj2 
  };
  obj1.obj2.foo();
42
this -> obj2

初露鋒芒

function foo() {
      setTimeout(() => this.a = 1, 0)
      console.log( this.a );
  }
  function foo2() {
      setTimeout(() => this.a = 1, 500)
      console.log( this.a );
  }
  function doFoo(fn) {
      this.a = 4
      fn();
  }
  var obj = {
      a: 2,
      foo: foo,
      foo2: foo2
  };
  var a =3
  doFoo( obj.foo );
  setTimeout( obj.foo, 0 )
  setTimeout( obj.foo2, 100 )
答案:
4
1
1
foo函數,第2行是一個定時器,哪怕定時器的延遲時間爲0,仍然先執行第3行。故爲4
當使用定時器調用函數時,先執行函數內代碼,在進行函數調用。故爲1
同理: 故爲1

展露頭腳

a = 3
function foo() {
    console.log( this.a );
}
var obj = {
    a: 2
};
foo.call( obj ); 
foo.call( null );
foo.call( undefined ); 
foo.call(  ); 
var obj2 = {
    a: 5,
    foo
}
obj2.foo.call() // 3,不是5!
//bind返回一個新的函數
function foo(something) {
    console.log( this.a, something );
    return this.a + something;
}
var obj = {
    a: 2
}
var bar = foo.bind( obj );
var b = bar( 3 ); 
console.log( b );
答案:
2 undefined
3 undefined
3 undefined
3 undefined
3 undefined
2 3
5
第8行: this -> obj = 2, msg沒有傳值,故爲undefined
第9~12行: 當call的第一個參數爲null, undefined或者不傳值時,只想window, this -> window = 3, msg沒有傳值,故爲undefined
第25行:bind改變指向 -> obj,第26行:msg爲3, 故爲2 3
第27行:執行函數,爲2+3 = 5

銳不可當

隱式丟失

一個最多見的 this綁定問題就是被隱式綁定的函數會丟失綁定對象,也就是說它會應用默認綁定,從而把 this 綁定到全局對象或者 undefined 上,取決因而否是嚴格模式函數

function foo() { 
    console.log( this.a );
}
function doFoo(fn) {
    fn()
}
var obj = {
    a: 2,
    foo: foo 
};
var a = "oops, global";
doFoo( obj.foo );
答案: oops, global
第5行fn()引用第位置其實foo, 所以doFoo()至關因而一個不帶修飾符的函數調用,所以應用了默認綁定—> window = oops, global

捨我其誰

function foo(something) { 
    this.a = something;
}
var obj1 = { 
    foo: foo
};
var obj2 = {};
obj1.foo( 2 );
console.log( obj1.a );
obj1.foo.call( obj2, 3 );
console.log( obj2.a );
var bar = new obj1.foo( 4 ); 
console.log( obj1.a );
答案:
2
3
2
4
new 綁定比隱式綁定優先級高,也閉隱式綁定綁定優先級高

總結

  1. 函數是否在new中調用(new綁定)?若是是的話this綁定的是新建立的對象。
    var bar = new foo()
  2. 函數是否經過call、apply(顯式綁定)或者硬綁定調用?若是是的話,this綁定的是 指定的對象。
    var bar = foo.call(obj2)
  3. 函數是否在某個上下文對象中調用(隱式綁定)?若是是的話,this 綁定的是那個上 下文對象。
    var bar = obj1.foo()
  4. 若是都不是的話,使用默認綁定。若是在嚴格模式下,就綁定到undefined,不然綁定到 全局對象。var bar = foo()
相關文章
相關標籤/搜索