JavaScript和TypeScript下的this關鍵字

背景

在js或者ts使用過程中,在方法中使用了this的時候,一個不小心就可能因其引起莫名其妙的錯誤。這通常是this所指向的上下文不是我們所期望的上下文引起的。

規則

在一個方法中(如果是ts,這裏僅限於非lambda表達式定義的方法)有使用this關鍵字,那麼可以按照下面的優先級順序來推斷this指向的是什麼:

如果這個函數是function#bind調用的結果,那麼this指向的是傳入bind的參數
如果函數是以foo.func()形式調用的,那麼this值爲foo
如果是在嚴格模式下,this將爲undefined
否則,this將是全局對象(瀏覽器環境裏爲window)

驗證

var x = {
    name: "x",
    sayHello: function () {
        console.log("_" + this.name);
    }
};

x.sayHello();//_x;
var say = x.sayHello;
say();//非嚴格模式_,嚴格模式拋出異常Cannot read property 'name' of undefined
var name = "y";
say();//非嚴格模式_y
var z={
    name:"z",
    say:x.sayHello
}
z.say();//_z
say.bind(z)();//_z

TS中lambda表達式中的this

看下面的代碼

class Foo {
  name = "z";
  x = {
    name: "x",
    sayHello: () => {
      let y = {
        name: "y",
        sayHello: () => {
          console.log("hello,I'm " + this.name);
        }
      }
      y.sayHello();
    }
  };
  sayHello(){
    this.x.sayHello();
  }
}
let  foo=new Foo();
foo.sayHello();//z
var t={
   name:"t",
   x:foo.x
}
foo.sayHello.bind(t)();//z
Foo.prototype.sayHello.bind(t)();//z

全部都輸出z,說明了再TS中,如果方法是lambda表達式定義的,那麼其中的this關鍵字總是指向類實例,而不在乎其引用鏈是怎樣的,這實際上。實際上,如果方法是靜態的,this會指向類本身。
foo.sayHello.bind(t)()和Foo.prototype.sayHello.bind(t)()的方式也沒能改變this的指向,其實這是因爲t.x指向了foo.x,而foo.x.sayHello()中的this指向foo的。
如果我們做下面的修改,就會發現了不一樣了。

let foo2=new Foo();
foo2.name="t";
foo.sayHello.bind(foo2)();//t
Foo.prototype.sayHello.bind(foo2)();//t
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章