2.2 .this的綁定規則

来源:https://www.cnblogs.com/Tiancheng-Duan/archive/2018/01/16/8296908.html
-Advertisement-
Play Games

2.this的綁定規則 1.預設綁定 在代碼中,foo()函數不帶任何修飾的引用進行調用的,那麼只能使用預設綁定。 2.隱式綁定 調用位置使用obj上下文來引用函數foo2,故可以說函數被調用時obj對象“擁有”或“包含”該函數foo2()。那麼foo2函數被調用時,確實加上了對obj的引用。當函數 ...


2.this的綁定規則

1.預設綁定

1 function foo(  )
2 {
3    console.log(this.a);
4 }
5 var a=1;
6 foo();  //1

在代碼中,foo()函數不帶任何修飾的引用進行調用的,那麼只能使用預設綁定。


2.隱式綁定

1 function foo1()
2 {
3    console.log( this.a );
4 }
5 var obj = {
6    a: 1,
7    foo: foo1
8 };
9 obj.foo();  //1


調用位置使用obj上下文來引用函數foo2,故可以說函數被調用時obj對象“擁有”或“包含”該函數foo2()。
那麼foo2函數被調用時,確實加上了對obj的引用。當函數引用有上下文對象時,
隱式綁定規則會把函數調用中的this綁定到這個上下文對象。
故上文中的this.a等同於obj.a。


PS1:對象屬性引用鏈中只有上一層或者最後一層在調用位置中起作用。

 1 function foo2()
 2 {
 3    console.log( this.a );
 4 }
 5 var obj2 = {
 6    a: 2,
 7    foo: foo2
 8 };
 9 var obj1 = {
10    a: 3,
11    obj2: obj2
12 };
13 obj1.obj2.foo();    //2


距離this最近的對象上下文時obj2,故this.a等同與obj2.a,同時等同於obj1.obj2.a。


PS2:隱式丟失

 1 function foo3()
 2 {
 3    console.log( this.a );
 4 }
 5 var obj3 = {
 6    a: 33,
 7    foo: foo3
 8 };
 9 var bar=obj3.foo;
10 var a=3;
11 bar();  //3


這裡的要點就是關註var bar=obj3.foo;
雖然bar只是obj3.foo的一個引用,但bar實際引用的時foo3()函數本身。
因此此時的bar()其實是一個不帶任何修飾的函數調用,所以應用預設綁定。


PS2:隱式丟失(發生在函數調用時)。

 1 function foo4(  )
 2 {
 3    console.log(this.b);
 4 }
 5 function doFOO( fn )
 6 {
 7    var b=44;
 8    fn();
 9 }
10 var obj4={
11    b:10,
12    foo:foo4
13 };
14 var b=4;
15 doFOO(obj4.foo);    //4


參數傳遞其實就是一個隱式賦值,故傳入函數也會被隱式賦值。
所以結果與上面例子一致。
同理,這裡傳入的是自定義函數。即使傳入的是內置函數,結果也是一樣的。


PS3:如上所見,回調函數丟失this綁定是很常見的。
與此同時,另一種丟失情況更加出人意料:調用回調函數可能會修改this。
在一些流行的js庫中,事件處理器經常會把回調函數的this綁定到DOM元素上。



3.顯式綁定
顯式綁定,即是通過call,apply等方法來強制綁定。
call與apply的第一個參數都是thisObj,表示this的指向。第二個參數,call是輸入單個參數,apply是輸入參數數組。多個參數時,後者性能更優。

1 function foo()
2 {
3    console.log( this.a );
4 }
5 var obj = {
6    a: 3
7 };
8 foo.call( obj );   //2     函數沒有參數輸入時,call只需要一個參數thisObj輸入。


通過foo.call(),可以在調用foo時強制把它的this綁定到obj上。

PS1:“裝箱”
如果thisObj參數傳入的是一個原始值(簡單數據類型),這個原始值會被轉換成它的對象形式(如new String(..),new Boolean(..),或者new Number(..))。這通常稱為“裝箱”。

PS2:解決之前提出的丟失綁定問題。
1.硬綁定(顯式綁定的一個變種)

 1 function foo2()
 2 {
 3    console.log( this.a );
 4 }
 5 var obj2 = {
 6    a: 3
 7 };
 8 var bar = function()
 9 {
10    foo2.call( obj );
11 };
12 bar();  //3
13 setTimeout( bar, 100 ); //3
14 
15 //切記,硬綁定的bar不可能在修改它的this。
16 bar.call( window );   //3


硬綁定的典型應用場景就是創建一個包裹函數,負責接收參數並返回值;
另一個使用方法就是創建一個可以重覆應用的輔助函數:

 1 function foo3( something )
 2 {
 3    console.log( this.d, something );
 4    return this.d + something;
 5 }
 6 function bind( fn, obj )
 7 {
 8    return function()
 9    {
10       return fn.apply( obj, arguments );
11    };
12 }
13 var obj3 = {
14    d: 2
15 };
16 var bar3 = bind( foo3, obj3 );
17 var e = bar3( 3 );  //2 3
18 console.log( e ); //5


由於硬綁定是一個非常常用的模式,故ES5提供了一個內置方法bind,和上述用法類似。

 1 function foo4( something )
 2 {
 3    console.log( this.a4, something );
 4    return this.a4 + something;
 5 }
 6 var obj4 = {
 7    a4: 2
 8 };
 9 var bar4 = foo4.bind( obj4 );
10 var b4 = bar4( 5 ); //2 5
11 console.log( b4 );    //7


bind(..)會返回一個硬編碼的新函數(切記,新函數),這會將指定的參數設置為this的上下文並調用原始函數。

2.API調用的“上下文”
第三方庫的許多函數,以及JS語言和宿主環境(如瀏覽器環境)中許多內置函數,都提供了一個可選參數,通常稱為“上下文(context)。
其作用與bind(..)類似,確保回調函數使用指定的this。

 1 function foo5( el )
 2 {
 3    console.log( el, this.id );
 4 }
 5 var obj5 = {
 6    id: "awesome"
 7 };
 8 
 9 //調用foo5(..)函數是將this綁定到obj。
10 [ "1", 2, 3 ].forEach( foo5, obj5 );    //console.log輸出數字和字元串時,數字在前,字元串會有雙引號;反之則沒有。
11 // 1 awesome; 2 awesome; 3 awesome

 

4.new綁定
在此先糾正js中new與其他語言中new的區別。
在其它面向類語言中,”構造函數“是類中的一些特殊方法,使用new 初始化類時調用類中的構造函數。
在JS中,構造函數只是一些使用new操作符時被調用的函數。它們不屬於某個類,也不會實例化一個類。

JS中使用new來調用函數,或者說發生構造函數調用時,會自動執行以下操作。
  1.創建(或者說構造)一個全新的對象。
  2.這個新對象會被執行[[Prototype]]鏈接。
  3.這個新對象會綁定到函數調用的this。
  4.如果函數沒有返回其他對象,那麼new表達式中的函數調用會自動返回這個新對象。

1 function foo( a )
2 {
3    this.a = a;
4 }
5 var bar = new foo( 4 );
6 console.log( bar.a );
7 
8 //使用new來調用foo(..)時,會構建一個新對象並將它綁定到foo(..)調用的this上,並將該對象返回給bar。

 







您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 21、數組 定義數組 * 字面量方式 var 數組名稱 = [ value,value,... ] * 構造函數方式 var 數組名稱 = new Array(value,value,...); var 數組名稱 = new Array(length) 創建對象方式創建數組分析圖 附:var num ...
  • 閱讀本書主要目的: 自從學會CSS以來,雖然熟練掌握了其使用方法和技巧,但對其底層的原理和實現並不清晰,閱讀本書想進一步系統化的學習和深入研究其本質,對這門前端基礎語言從熟練使用到真正理解。 第1章 CSS和文檔 1.1 WEB的衰落(為了表現增加很多標記元素如font等,這些阻礙了頁面的結構化) ...
  • 眾所周知,文本溢出顯示省略號用CSS就可以: 單行文本: 多行文本: 如果想中間顯示省略號呢?? 現在需求是,一段文本很長,但最後有一個關鍵詞很重要,而且改關鍵詞有括弧括起來的,需要顯示出來,所以如果文本過長,不單隻做省略號處理,還要把括弧裡面的內容顯示出來。 上面的代碼意思是:如果文本長度大於13 ...
  • 三種密碼強度的正則表達式: 較弱:全是數字或全是字母 6-16個字元:/^[0-9]{6,16}$|^[a-zA-Z]{6,16}$/; 中級:數字、26個英文字母 6-16個字元: /^[A-Za-z0-9]{6,16}$/; 較高:由數字、26個英文字母或者下劃線組成的字元串 6-16個字元: ...
  • 1、概述 簡單值(基本類型)通過值複製的方式來賦值/傳遞。 複合值(對象)通過引用複製的方式來賦值/傳遞。 結合記憶體示意圖,理解會更深刻。 簡單類型的值在常量池只有一份,變數a和變數b都是常量池中2的一個副本。 變數c和變數d都是指向堆中的一個數組對象。 ...
  • <! TOC "作用域與閉包" "什麼是作用域" "編譯器" "理解作用域" "嵌套的作用域" "詞法作用域" "詞法分析時" "欺騙詞法作用域" "函數與塊作用域" "函數中的作用域" "隱藏標識符於普通作用域" "函數作為作用域" "塊作為作用域" "提升" "先有雞還是先有蛋?" "編譯器再次 ...
  • 本文詳細介紹了table-layout的屬性值、定義和用法、固定表格佈局、自動表格佈局等……希望可以幫到你喲! ...
  • 需求:用的heightcharts插件,點擊曲線圖想獲得所點擊點的返回值,如圖 問題代碼: (function chart_line(){ var data={"title":["01","02","03","04","05","06","07","08","09","10","11","12"], ...
一周排行
    -Advertisement-
    Play Games
  • GoF之工廠模式 @目錄GoF之工廠模式每博一文案1. 簡單說明“23種設計模式”1.2 介紹工廠模式的三種形態1.3 簡單工廠模式(靜態工廠模式)1.3.1 簡單工廠模式的優缺點:1.4 工廠方法模式1.4.1 工廠方法模式的優缺點:1.5 抽象工廠模式1.6 抽象工廠模式的優缺點:2. 總結:3 ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 本章將和大家分享ES的數據同步方案和ES集群相關知識。廢話不多說,下麵我們直接進入主題。 一、ES數據同步 1、數據同步問題 Elasticsearch中的酒店數據來自於mysql資料庫,因此mysql數據發生改變時,Elasticsearch也必須跟著改變,這個就是Elasticsearch與my ...
  • 引言 在我們之前的文章中介紹過使用Bogus生成模擬測試數據,今天來講解一下功能更加強大自動生成測試數據的工具的庫"AutoFixture"。 什麼是AutoFixture? AutoFixture 是一個針對 .NET 的開源庫,旨在最大程度地減少單元測試中的“安排(Arrange)”階段,以提高 ...
  • 經過前面幾個部分學習,相信學過的同學已經能夠掌握 .NET Emit 這種中間語言,並能使得它來編寫一些應用,以提高程式的性能。隨著 IL 指令篇的結束,本系列也已經接近尾聲,在這接近結束的最後,會提供幾個可供直接使用的示例,以供大伙分析或使用在項目中。 ...
  • 當從不同來源導入Excel數據時,可能存在重覆的記錄。為了確保數據的準確性,通常需要刪除這些重覆的行。手動查找並刪除可能會非常耗費時間,而通過編程腳本則可以實現在短時間內處理大量數據。本文將提供一個使用C# 快速查找並刪除Excel重覆項的免費解決方案。 以下是實現步驟: 1. 首先安裝免費.NET ...
  • C++ 異常處理 C++ 異常處理機制允許程式在運行時處理錯誤或意外情況。它提供了捕獲和處理錯誤的一種結構化方式,使程式更加健壯和可靠。 異常處理的基本概念: 異常: 程式在運行時發生的錯誤或意外情況。 拋出異常: 使用 throw 關鍵字將異常傳遞給調用堆棧。 捕獲異常: 使用 try-catch ...
  • 優秀且經驗豐富的Java開發人員的特征之一是對API的廣泛瞭解,包括JDK和第三方庫。 我花了很多時間來學習API,尤其是在閱讀了Effective Java 3rd Edition之後 ,Joshua Bloch建議在Java 3rd Edition中使用現有的API進行開發,而不是為常見的東西編 ...
  • 框架 · 使用laravel框架,原因:tp的框架路由和orm沒有laravel好用 · 使用強制路由,方便介面多時,分多版本,分文件夾等操作 介面 · 介面開發註意欄位類型,欄位是int,查詢成功失敗都要返回int(對接java等強類型語言方便) · 查詢介面用GET、其他用POST 代碼 · 所 ...
  • 正文 下午找企業的人去鎮上做貸後。 車上聽同事跟那個司機對罵,火星子都快出來了。司機跟那同事更熟一些,連我在內一共就三個人,同事那一手指桑罵槐給我都聽愣了。司機也是老社會人了,馬上聽出來了,為那個無辜的企業經辦人辯護,實際上是為自己辯護。 “這個事情你不能怪企業。”“但他們總不能讓銀行的人全權負責, ...