JavaScript this用法總結

來源:互聯網
上載者:User

標籤:efi   src   alt   ext   return   對象引用   指定   全域對象   箭頭   

JavaScript this用法總結

在JavaScript中,this關鍵字可以說是最複雜的機制之一。對this的作用機制缺乏比較深入的理解很容易在實際開發中出現問題。

1、this的作用

為什麼要在JavaScript中使用this呢?因為this提供了一種簡明的方式來隱式傳遞一個對象引用,可以讓函數介面設計的簡單且容易複用:

function display() {    console.log(this.name);}var obj1 = {name: "obj1"};var obj2 = {name: "obj2"};display.call(obj1);  //  "obj1"display.call(obj2);  //  "obj2"

 通過call方法,我們可以在調用display函數時為this傳入不同的對象。如果不使用this關鍵字,那麼上面的函數就需要顯示增加一個調用時上下文參數:

function display(context) {    console.log(context.name);}var obj1 = {name: "obj1"};var obj2 = {name: "obj2"};display(obj1);  //  "obj1"display(obj2);  //  "obj2"

實際上這不夠簡潔,當使用模式比較複雜時,顯示的上下文傳遞會讓代碼變得混亂複雜。使用this關鍵字,我們可以在調用時為this傳入不同的對象引用,保證了方法的使用靈活性。

 

2、this的使用複雜性

this使用機制複雜,在開發容易出問題的根本原因在於:this是在運行時綁定,而不是在編寫時綁定,this實際值取決於函數調用時的上下文。this的綁定和函式宣告的位置沒有關係,只取決於函數的調用方式。在JavaScript中,當函數被調用時,會建立一個活動記錄(執行時上下文),這個記錄包含函數在何處調用、函數的調用方法和傳入參數等資訊,this會記錄其中一個屬性。判斷this實際綁定值,關鍵在於分析函數實際調用的位置。

 

3、this綁定規則

前面說了函數的實際調用位置決定了this的綁定值。在JavaScript中,this有4種綁定規則。

3.1、new綁定

在JavaScript中使用new調用函數會自動執行下面的操作:

  (1)建立一個新的對象

  (2)對新對象執行原型連結

  (3)新對象會被綁定到函數的this

  (4)如果函數沒有返回其他對象,那麼新對象會被返回

 

new綁定容易理解,下面是一段常見的用new調用函數建立對象的代碼:

function Book(name, author, isbn) {    this.name = name;    this.author = author;    this.isbn = isbn;}let book = new Book("Zakas", "ES6", 12345);console.log(book.name);  //  "Zakas"
 3.2、隱式綁定

 當對象內部包含一個指向函數的屬性,並且在調用時通過這個屬性間接引用函數(obj.prop()的形式),那麼函數內的this會隱式指向這個對象,也即隱式綁定:

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

在調用位置上,函數是通過obj.foo來引用的,可以說函數被調用時obj對象擁有或包含它。此時,this綁定在obj這個內容物件上。

3.3、顯示綁定

在某些情況下,我們希望函數內的this綁定在某些指定的對象上,這稱為顯示綁定。在JavaScript中可以使用call和apply為函數顯示指定this綁定。call和apply的第一個參數是一個對象,這個對象會被綁定到this上:

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

使用bind也可以讓this綁定在指定對象上,bind綁定也是一種顯示綁定,又稱為硬綁定:

function foo(something) {    this.a = something;}var obj1 = {};var bar = foo.bind(obj1);bar(2);console.log(obj1.a);  //  2
3.4、預設綁定

當使用獨立函數調用(func()形式),會發生預設綁定,可以把這條規則看成是無法使用其他規則時的預設規則。看下面的範例程式碼:

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

當調用foo時,使用預設綁定規則,this被綁定到全域對象上。在strict模式下,this會綁定到undefined。

 

4、綁定優先順序

上面4種綁定規則獨立使用的話,判斷this的綁定值並不複雜。但實際函數調用時,可能多條綁定規則都可以使用,那麼這時就要根據每個規則的綁定優先順序來判斷this實際的綁定值。接下來看各種綁定規則的優先順序。

4.1、預設綁定優先順序最低

預設綁定的優先順序最低,這個容易理解。因為當無法使用其他的綁定規則時才會使用預設規則。

4.2、顯示綁定優先順序高於隱式綁定
function foo() {    console.log(this.a);}var obj1 = {a: 2, foo: foo};var obj2 = {a: 3, foo: foo};obj1.foo();  //  2obj1.foo.call(obj2);  //  3

上面的代碼中,obj1.foo()使用隱式綁定規則,this綁定到obj1對象上。obj1.foo.call()可同時使用隱式綁定和顯示綁定規則,顯示綁定優先順序高於隱式綁定,this綁定到obj2對象上。

4.3、new綁定優先順序高於隱式綁定
function foo(something) {    this.a = something;}var obj1 = {    foo: foo};var obj2 = {};obj1.foo(2);console.log(obj1.a);  //  2obj1.foo.call(obj2, 3);console.log(obj2.a);  //  3var bar = new obj1.foo(4);console.log(obj1.a);  //  2console.log(bar.a);  //  4

上面代碼中,new obj1.foo(4)可同時使用new綁定和隱式綁定。由bar.a的值為4可以知道,new綁定優先順序高於隱式綁定。

4.4、new綁定優先順序高於顯示綁定
function foo(something) {    this.a = something;}var obj1 = {};var bar = foo.bind(obj1);bar(2);console.log(obj1.a);  //  2var baz = new bar(3);console.log(obj1.a);  //  2console.log(baz.a);  //  3

上面代碼中,new bar(3)可同時使用new綁定和bind綁定。baz.a的值為3,說明new綁定優先順序高於隱式綁定。

4.5、綜述

現在可以根據this綁定優先順序判斷函數在調用位置實際綁定的值。實際可以按照下面的順序判斷:

  (1、函數是否在new中調用?如果是的話this綁定新建立的對象。調用例子:var bar = new foo()。

  (2、函數是否通過apply、call顯示綁定或者bind硬綁定?如果是,this綁定指定的對象。調用例子:var bar = foo.call(obj)。

  (3、函數是否在某個內容物件中調用(隱式綁定)?如果是,this綁定在內容物件上。調用例子:var bar = obj.foo()。

  (4、如果都不是的話,使用預設綁定。在strict 模式下,this綁定到undefined,在非strict 模式下,綁定到全域對象。調用例子:var bar = foo()。

 

5、箭頭函數中的this

ES6中引入了箭頭函數,箭頭函數使用操作符=>定義。箭頭函數不使用上面4種this綁定規則,而是根據外層範圍來決定this:

function foo() {    return (a) => {        console.log(this.a);    };}    var obj1 = {a:2};var obj2 = {a:3};var bar = foo.call(obj1);bar.call(obj2);  //  2

foo內部的箭頭函數建立時,foo函數內this綁定到obj1上,bar(箭頭函數)的this也會綁定到obj1上,箭頭函數內的this是不能被修改的。

JavaScript this用法總結

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.