1. 程式人生 > >關於this綁定的四種方式

關於this綁定的四種方式

面向 總結 調用 默認 執行 的人 做了 數組 就是

一、前言

我們每天都在書寫著有關於this的javascript代碼,似懂非懂地在用著。前陣子在看了《你不知道的JavaScript上卷》之後,也算是被掃盲了一邊關於this綁定的四種方式。

二、綁定規則

關於this應用的是哪條規則,得先找到調用的位置,再判斷應用了哪條規則。

1、默認綁定

先上代碼:

var a = 2;

function foo() {
    console.log(this.a);
}

foo(); // 結果:2

先來分析下上面的代碼聲明,

首先我們在全局作用域中定義了一個變量a,而在全局作用域聲明的變量,就相當於為window對象聲明了同名屬性a並賦值為2,接著又在全局作用域下聲明了foo函數,最後我們在調用foo函數時,是直接不帶任何修飾下調用foo函數,此時的this的綁定規則為默認綁定

,this指向window對象,所以結果輸入為2。

如果此時使用了嚴格模式,即在代碼中加了"use strict",this指向undefined,調用的結果就會出錯而不是輸出2。

2、隱式綁定

var a = 2;

function foo() {
    console.log(this.a);
}

var obj = {
    a: 4,
    foo:foo
};

foo(); // 結果:2
obj.foo();  // 結果4

代碼還是差不多的代碼,只是加了一個obj對象,對象有一個a屬性和一個foo屬性引用了foo函數。對於foo();輸出結果2,在上一節已經說明,因為是沒用帶任何修飾的情況下調用,應用了默認綁定。而在obj.foo()的調用中,foo函數的調用上下文是obj對象,obj包含了foo函數,此時this的綁定就發生了隱式綁定

,this指向obj,this.a相當於obj.a,所以結果自然而然也輸入4。

對於這種方式,我在代碼中也經常用到。把可以歸類的方法、變量都寫成一個對象的形式,就形成了一個模塊,也相當於一種設計模式,模塊模式。

3、顯示綁定

var a = 2;

function foo() {
    console.log(this.a);
}

var obj = {
    a: 4
};

foo.call(obj); // 結果:4
foo.apply(obj); // 結果:4
foo.bind(obj)(); // 結果:4

對於call、apply、bind的這三種調用方式都是屬於顯示綁定,作用是通過顯示傳入一個對象,改變this的上下文為此對象。call和apply是直接改變上下文對象直接調用,而bind是返回一個已經顯示綁定的上下文的函數。

call和apply兩個都是顯示改變上下文並執行,唯一不同的就是傳參方式,call是對象後面可以跟著多個參數,而apply傳遞參數,需要傳遞一個數組,即:

foo.call(obj, arg1, arg2, arg3, ...);
foo.apply(obj, [arg1, arg2, arg3, ...])

4、new綁定

學過後端語言的人都知道,通過構造函數,可以new一個對象實例,而在JavaScript中,對象也是通過new構造函數生成的,但,卻和面向對象語言的new方式是不一樣。下面來看看new操作符到底做了什麽。

當使用new來調用函數時,發生了以下步驟:

a、創建了一個全新的對象,如:var obj = {};

b、連接全新對象與調用函數之間的[[Prototype]],讓函數的prototype指向全新對象,如obj.__proto__ = foo.prototype;

c、新對象會綁定到函數調用的this,如:foo.call(obj);

d、返回對象。如果函數沒有返回其他對象,那麽new操作會自動返回這個新對象。

三、優先級

一般情況下:new綁定 > 顯示綁定 > 隱式綁定 > 默認綁定

四、總結

還有其他的一些細節知識點,推薦還是看《你不知道的JavaScript上卷》這本書,真心不錯。

關於this綁定的四種方式