摘要:的綁定和函數聲明的位置沒有任何關系,只取決于函數的調用方式。這是一種顯示的強制綁定,稱為硬綁定。調用的上下文調用的時候把綁定到綁定關于,有一個重要的點實際上并不存在所謂的構造函數,只有對于函數的構造調用。
this是什么
this是運行時進行綁定的,并不是在編寫時綁定,它的上下文取決于函數調用的各種條件。this的綁定和函數聲明的位置沒有任何關系,只取決于函數的調用方式。this的綁定規則 默認綁定當一個函數被調用時,會創建一個活動記錄(也稱執行上下文)。
this既不指向函數本身,也不指向函數的詞法作用域。
function foo(){ console.log(this.a); } var a=2; foo();//2
本例中函數調用時應用了this的默認綁定,因為foo()是直接使用不帶任何修飾的函數引用進行調用的,因此this指向全局對象。
*:如果使用嚴格模式,則不能將全局對象用于默認綁定,因此this會綁定到undefined。
**:對于默認綁定來說,決定this綁定對象的并不是調用位置是否處于嚴格模式,而是函數體是否處于嚴格模式。
function foo(){ console.log(this.a); } var obj={ a:2, foo:foo }; obj.foo();//2
當foo()被調用時,它的前面確確實實加上了對obj的引用。當函數引用有上下文對象時,隱式綁定規則會把函數調用中的this綁定到這個上下文對象。因此調用foo()時this被綁定到obj,因此this.a和obj.a是一樣的。
對象屬性引用鏈中只有上一層或者說最后一層在調用位置中起作用。
function foo(){ console.log(this.a); } var obj={ a:2, foo:foo }; var bar=obj.foo; var a=3; bar();//3
雖然bar是obj.foo的一個引用,實際上,它引用的是foo函數本身,因此此時的bar()其實是一個不帶任何修飾的函數調用,因此應用了默認綁定。
同樣,傳人回調函數時也會發生隱式丟失,不管傳入的是自己聲明的函數還是傳入語言內置的函數。
顯式綁定function foo(){ consol.log(this.a); } var obj={ a:2 }; foo.call(obj);//2
通過foo.call(),我們在調用foo()時強制把它的this綁定到obj上。
*:從this綁定的角度來看,call()和apply()是一樣的。
function foo(){ console.log(this.a); } var obj={ a:2 }; var bar=function(){ foo.call(obj); }; bar();//2 setTimeout(bar,100);//2 bar.call(window);//2
本例中我們創建了bar(),并在內部手動調用了foo.call(obj),強制把foo的this綁定到了obj。無論之后怎樣調用bar,它都會手動在obj上調用foo。這是一種顯示的強制綁定,稱為硬綁定。
由于硬綁定是一種非常常用的模式,ES5內置了bind()方法。其會返回一個新函數,把你指定的參數設置為this的上下文并調用原始函數。
function foo(el){ console.log(el,this.id); } var obj={ id="awesome" }; //調用 foo()的時候把this綁定到obj [1,2,3].forEach(foo,obj); //1 awesome 2 awesome 3 awesomenew綁定
關于new,有一個重要的點:實際上并不存在所謂的“構造函數”,只有對于函數的“構造調用”。
使用new來調用函數,或者說發生構造函數調用時,會執行下列操作:
(1):創建一個全新的對象
(2):這個新對象會被執行[[Prototype]]連接
(3):這個新對象會綁定到函數調用的this
(4):如果函數沒有返回其他對象,那么new表達式中的函數會自動返回這個新對象
function foo(a){ this.a=a; } var bar=new foo(2); console.log(bar.a);//2
使用new來調用foo()時,我們會構造一個新對象并把它綁定到foo()調用的this上。
優先級判斷this:
函數是否在new中調用(new綁定)?如果是的話,this綁定的是新創建的對象
var bar=new foo();
函數是否通過call、apply(顯式綁定)或者硬綁定調用?如果是的話,this綁定的是指定的對象
var bar=foo.call(obj2);
函數是否在某個上下文對象中調用(隱式綁定)?如果是的話,this綁定到的是那個上下文對象
var var=obj1.foo();
如果都不是的話,使用默認綁定。如果在于按個模式下,就綁定到undefined,否則綁定到全局對象
var bar =foo();綁定例外 被忽略的this
如果你把null或者undefined作為this的綁定對象傳入call、apply或者bind,這些值在調用時會被忽略,實際應用的是默認綁定規則。
function foo(a,b){ console.log("a:"+a+",","b:"+b); } //把數組展開成參數 foo.apply(null,[2,3]);//a:2,b:3 //使用bind()進行柯里化 var bar=foo.bind(null,2); bar(3);//a:2,b:3
一種更安全的做法是把this綁定到一個特殊的對象,且不會對程序造成任何副作用??梢允褂靡粋€DMZ對象,比如"xx"=Object.create(null)以保護全局變量。間接引用
間接引用最容易在賦值時發生:
function foo(){ console.log(this.a); } var a=2; var o={ a:3, foo:foo }; var p={ a:4 }; o.foo();//3 (p.foo=o.foo)();//2————p.foo=o.foo的返回值是目標函數的引用,因此調用位置是foo()而不是p.foo()或o.foo(),這里應用的是默認綁定軟綁定
function foo(){ console.log("name"+this.name); } var obj={ name:"obj"}; var obj1={ name:"obj1"}; var obj2={ name:"obj2"}; var fooOBJ=foo.softBind(obj); fooOBJ();//obj obj2.foo=foo.softBind(obj); obj2.foo();//obj2 fooOBJ.call(obj3);//obj3 setTimeout(obj.foo,10);//objthis詞法
function fo(){ return (a)=>{ console.log(this.a); }; } var obj1={a:1}; var obj2={a:2}; var bar=foo.call(obj1); bar.call(obj2);//1
foo()內部創建的箭頭函數會捕獲到調用foo()的this,由于foo()的this綁定到obj1,bar的this也會綁定到obj1,箭頭函數的綁定無法被修改!
具體來說,箭頭函數會繼承外層函數調用的this綁定。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/95911.html
摘要:但是如果非全局的變量如果被遮蔽了,無論如何都無法被訪問到。但是如果引擎在代碼中找到,就會完全不做任何優化。結構的分句中具有塊級作用域。第四章提升編譯器函數聲明會被提升,而函數表達式不會被提升。 本書屬于基礎類書籍,會有比較多的基礎知識,所以這里僅記錄平常不怎么容易注意到的知識點,不會全記,供大家和自己翻閱; 上中下三本的讀書筆記: 《你不知道的JavaScript》 (上) 讀書筆記...
摘要:綁定使用來調用函數,或者說發生構造函數調用時,會自動執行下面的操作。 1 this的概念 this 在任何情況下都不指向函數的詞法作用域。作用域對象無法通過 JavaScript代碼訪問,它存在于 JavaScript 引擎內部。 this 是在運行時進行綁定的,并不是在編寫時綁定,它的上下文取決于函數調用時的各種條件。this 的綁定和函數聲明的位置沒有任何關系,只取決于函數的調用方...
摘要:然而,臨近規范發布時,有建議提及未來的版本號切換為編年制,比如用同來指代在年末前被定稿的所有版本??偟脕碚f就是版本號不再那么重要了,開始變得更像一個萬古長青的活標準。 你不知道的JS(下卷)ES6與之未來 第一章:ES的今與明 在你想深入這本書之前,你應該對(在讀此書時)JavaScript的最近標準掌握熟練,也就是ES5(專業來說是ES 5.1)。在此,我們決定全方面地談論關于將近的...
摘要:綁定書中提到在中,實際上并不存在所謂的構造函數,只有對于函數的構造調用。規則使用構造調用的時候,會自動綁定在期間創建的對象上。指向新創建的對象綁定比隱式綁定優先級高。 showImg(http://ww1.sinaimg.cn/large/005Y4rCogy1fstcwvzkjzj30sg0g0qqn.jpg); 前言 最近正在看《你不知道的JavaScript》,里面關于this綁...
摘要:強制類型轉換本章介紹了的數據類型之間的轉換即強制類型轉換包括顯式和隱式。強制類型轉換常常為人詬病但實際上很多時候它們是非常有用的。隱式強制類型轉換則沒有那么明顯是其他操作的副作用。在處理強制類型轉換的時候要十分小心尤其是隱式強制類型轉換。 前言 《你不知道的 javascript》是一個前端學習必讀的系列,讓不求甚解的JavaScript開發者迎難而上,深入語言內部,弄清楚JavaSc...
閱讀 2950·2023-04-26 01:32
閱讀 1543·2021-09-13 10:37
閱讀 2282·2019-08-30 15:56
閱讀 1676·2019-08-30 14:00
閱讀 3047·2019-08-30 12:44
閱讀 1967·2019-08-26 12:20
閱讀 1065·2019-08-23 16:29
閱讀 3233·2019-08-23 14:44