關於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的綁定規則為默認綁定
如果此時使用了嚴格模式,即在代碼中加了"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的綁定就發生了隱式綁定
對於這種方式,我在代碼中也經常用到。把可以歸類的方法、變量都寫成一個對象的形式,就形成了一個模塊,也相當於一種設計模式,模塊模式。
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綁定的四種方式