js裏this的幾種用法

this的幾種用法

關於this

this是什麼?segmentfault

理論上this是執行上下文的一個屬性,this的值在進入到執行上下文的時候就已經肯定了,且不會再改變。這一點很重要。數組

this的做用?app

this 的機制提供了一個優雅的方式,隱式地傳遞一個對象,這可讓函數設計的更加簡潔,而且複用性更好。函數

總覽

  • new綁定,this指向由new建立的對象this

  • 顯示綁定,this指向apply或者call函數的第一個參數設計

  • 隱式綁定,this指向函數的調用者。code

  • 默認綁定,嚴格模式下指向undefinded,非嚴格模式this指向全局對象。對象

  • 箭頭函數綁定,this指向箭頭函數外邊包裹的普通函數作用域

new綁定

當用new建立一個新的對象的時候,this指向了由new關鍵字聲明建立的對象。get

class Person(name){
    constructor(name){
        this.name = name;
    }
    showThis(){
        return this;
    }
}
var p1 = new Person('zhang');
var p2 = new Person('zhao');
console.log(p1.showThis() === p1);    //true
console.log(p2.showThis() === p2);    //true
console.log(p1.showThis() === Persion)    //false

能夠看到,這種狀況下this的值指向了由new建立的對象的引用。this會被綁定到這個對象上去。

顯式綁定

所謂的顯式綁定,指的是經過apply或者call方法的第一個參數。

call和apply的不一樣,兩個方法的第一個參數都是this賦給的對象。不一樣在於,以後的參數被看成call方法的形參依次傳進去,而apply則是接受一個數組。

看代碼:

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

var obj = {
    a:2
}

foo.call(obj);

隱式綁定

隱式綁定用的次數比較多。一個最重要的特色就是,this的指定順序和在哪裏定義沒有關係,而是取決於調用者。

嚴格意義來講,this是上下文裏的一個屬性(存放各類變量的變量對象一樣也是上下文裏的屬性),this的值老是指向當前上下文的父級上下文,其實也就是當前上下文的調用者。

看代碼:

//第一個簡單的例子
var obj = {
    a : 1,
    foo : function(){
        console.log(this === obj);     //trun
        console.log(this.a === 1);     //true
    },
    bar : bar
}

//假如把一個屬性定義在對象外邊
function bar(){
    console.log(this === obj);      //true
}

obj.foo();
obj.bar();     //都是true

再來一個例子

function bar(){
    console.log(this === obj1);
    console.log(this === obj2);
}
function foo(){
    console.log(this === obj1);
    console.log(this === obj2);
}

var obj1 = {
    bar: bar,
    foo: foo
}

var obj2 = {
    bar: obj1.bar,
    foo: obj1.foo,
}

obj1.foo();     //true  false
obj2.foo();     //false  true
obj1.bar();     //true  false
obj2.foo();     //false  true

很簡單,foo和bar兩個方法分別由obj1和obj2調用,哪怕obj2中的foo和bar是obj1的也不要緊,與在哪裏定義沒有關係,純粹看是看誰調用的,obj2.foo()就是obj2調用的foo方法,因此,這個時候this指向obj2。

多說一句,若是既有顯示綁定又有隱式綁定,固然是以顯示綁定爲準。

默認綁定

這種狀況下,this不屬於任何一個函數方法內,即在全局做用域下,這種狀況下稱爲默認綁定。

非嚴格模式下,這個時候this值爲window全局對象。

function foo(){
    console.log(this === window);
}

foo();

嚴格模式下,this的值是undefined

"use strict";

function foo() {
  console.log( this === undefined );
}

foo();               // true
foo.call(undefined); // true
foo.call(null);      // false

箭頭函數

箭頭函數實際上是一個語法躺,箭頭函數的裏的this指向包裹箭頭函數的那個函數的this值。很好理解。

// ES6
function foo() {
  setTimeout(() => {
    console.log(this === obj); // true
  }, 100);
}

const obj = {
  a : 1
}

foo.call(obj);

// ES5
function foo() {
  var _this = this;

  setTimeout(function () {
    console.log(_this === obj); // true
  }, 100);
}

var obj = {
  a : 1
}

foo.call(obj);

最後的總結

用僞代碼的形式來表示

if (`newObj = new Object()`) {
  this = newObj
} else if (`bind/call/apply(thisArgument,...)`) {
  if (`use strict`) {
    this = thisArgument
  } else {
    if (thisArgument == null || thisArgument == undefined) {
      this = window || global
    } else {
      this = ToObject(thisArgument)
    }
  }
} else if (`Function Call`) {
  if (`obj.foo()`) {
    // base value . Reference = base value + reference name + strict reference
    // 例外: super.render(obj).  this = childObj ?
    this = obj 
  } else if (`foo()`) {
    // 例外: with statement. this = with object
   
    this = `use strict` ? undefined : window || global
  }
}

本文參考

相關文章
相關標籤/搜索