摘要:使用調用函數時,會自動執行以下操作創建一個全新的對象該對象會被執行連接該對象會綁定到函數調用的若函數沒有返回其他對象,表達式中的函數調用會自動返回該對象。
使用this可以減少傳入上下文對象,可以隱式傳遞一個對象引用。使API簡潔而復用,可以自動引用合適的上下文對象。
【要注意的幾個點】1. this不一定指向自身; 2. this不一定指向函數作用域(因為作用域無法通過js代碼訪問,它存在js引擎內部); 3. this是在運行時(函數被調用時)綁定的,不是編寫代碼時綁定。this的綁定取決于函數的調用位置,不是函數聲明的位置; 4. 不能通過this來引用一個詞法作用域內部的東西
####【找this的指向】
分析調用棧(為了到達當前執行位置所調用的所有函數),找到當前正在執行的函數的前一個調用,即調用棧的第二個元素。因為函數被調用時,會創建一個活動記錄(執行上下文)。該活動記錄包括(函數的調用棧、傳入的參數、函數的調用方法……)
[方法]:在代碼前插入一條debugger語句,在開發者工具中查看call stack中的第二個元素,就是this的調用位置.
function first(){ //當前調用棧first //當前的調用位置是全局作用域 console.log("first"); second();//second的調用位置 } function second(){ //當前調用棧first->second //當前的調用位置是first console.log("second"); third();//third的調用位置 } function third(){ //當前調用棧first->second->third //當前的調用位置是second console.log("third"); } //first的調用位置 first();//firstsecondthird【四條this規則】:
1.默認綁定(綁定到全局對象),但嚴格模式下this會綁定到undefin
ed:
【例子】:不帶任何修飾的函數調用
function example(){ console.log(this.a); } var a="karine"; example(); //karine
2.隱式綁定
(在一個對象內部包含一個指向函數的屬性,通過該屬性間接地引用函數,從而把this間接地綁定到該對象上。)
function example(){ console.log(this.a); } var obj={ a:"karine", example:example }; obj.example(); //karine
在對象屬性引用鏈中,只有最頂層(最后一層)會影響調用位置。
function example(){ console.log(this.a); } var obj1={ a:"karine", example:example }; var obj2={ a:"wu", obj1:obj1 }; obj2.obj1.example(); //karine
當函數引用有上下文對象時,函數里的this綁定在這個上下文對象上。
但是這種情況可能會出現“隱式丟失”,即丟失綁定的對象,應用默認綁定(全局對象/undefinded):
1. 將函數引用賦值給一個新變量,然后執行。 var obj3 = obj1.example; obj3(); //全局or undefined 實際上obj3引用的是example函數本身,因此this還是指向全局/undefined 2. 或者是調用回調函數的函數修改了this function test(fn){ fn(); } test(obj1.example); //全局or undefined 實際上,參數傳遞也是一種賦值,只不過是隱式賦值。所以道理同上。也會指向全局。
3.顯式綁定
(在對象上強制調用函數,可以使用call(對象)、apply(對象)方法,會把形參里的對象綁定到this上,接著在調用函數時指定這個this。如果傳入的參數為原始值(string、number、boolean),該原始值會自動轉為其對象形式(new String()、new Number()、new Boolean()),這通常被稱為“裝箱”)
function example(){ console.log(this.a); } var obj = { a:"karine" }; example.call(obj); //karine example.apply(obj);//karine var o = example.bind(obj); o(); //karine “硬綁定”bind 的this不會被顯示or隱式綁定修改。
4.new綁定
在js中,構造函數只是使用new操作符是被調用的普通函數而已,不屬于某個類,也不會實例化一個類。使用new調用函數時,會自動執行以下操作:
1.創建一個全新的對象 2.該對象會被執行[[prototype]]連接 3.該對象會綁定到函數調用的this 4.若函數沒有返回其他對象,new表達式中的函數調用會自動返回該對象。
function example(a){ this.a=a; } var obj4 = new example(“karine”); console.log(obj4.a);//“karine”【四種this綁定方法的優先級】
new綁定 > 顯式綁定 >隱式綁定 > 默認綁定
【例外】:
1.null、undefined作為this的綁定對象傳入call、apply、bind時,會被忽略,實際應用的是默認綁定(全局對象)
function example(){ console.log("a:"+this.a); } var a = "karine"; example.call(null); //a:karine
傳入null的情況:
(1)使用apply來展開一個數組
(2)使用bind進行柯里化
function example(a,b){ console.log("a:"+a+“,b:”+b); } //使用apply來展開一個數組 example.apply(null,[2,3]); //a:2,b:3 //使用bind進行柯里化(預先設置一些參數) var o = example.bind(null,2); o(3);//a:2,b:3
若想避免不必要的this綁定,可以使用ES6的…操作符來代替apply()
example.apply(null,[2,3]) === example(…[2,3])
為了安全,若想忽略this綁定,可以給this傳入一個空的非委托對象Φ ("Object.create(null)"),不會產生任何副作用,因為this會限制在這個空對象中,不會對全局對象產生任何影響。
**Object.create(null)**和{}很像,但是不會創建object.prototype,所以比{}“更空”
var Φ = Object.create(null); example.apply(Φ,[2,3]); //a:2,b:3 var o = example.bind(Φ,2); o(3); //a:2,b:3
2.間接引用(經常在賦值時發生),會應用默認綁定。
3.ES6中 "=>"定義的箭頭函數不使用this的四種標準規則。而是根據外層作用域來決定this。箭頭函數的綁定無法修改。
function example(){ return(a)=>{ console.log(this.a); } } var obj1={a:2}; var obj2={a:3}; var test = example.call(obj1); test.call(obj2); //2
由于example()的this綁定到obj1,所以test中引用箭頭函數的this也會綁定到obj1。
【總結】:1.找到this的調用位置
2.根據四條規則判定this的綁定對象:
(1)new:綁定到新創建的對象 (2)call、apply、bind:綁定到指定的對象 (3)上下文對象:綁定到該上下文對象 (4)默認:全局或者undefined(嚴格模式下)
3.箭頭函數根據當前的詞法作用域來決定this
4.有些調用可能無意中使用默認規則,可以使用一個空對象Object.create(null)忽略this綁定,來保護全局對象
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/89611.html
摘要:綁定書中提到在中,實際上并不存在所謂的構造函數,只有對于函數的構造調用。規則使用構造調用的時候,會自動綁定在期間創建的對象上。指向新創建的對象綁定比隱式綁定優先級高。 showImg(http://ww1.sinaimg.cn/large/005Y4rCogy1fstcwvzkjzj30sg0g0qqn.jpg); 前言 最近正在看《你不知道的JavaScript》,里面關于this綁...
摘要:中,實例化一個對象,會用到關鍵字。這里再解釋一下構造函數我們一般把后面的函數稱為構造函數,如,其中就為構造函數第四點的,可能比較難理解。有點需要注意如果構造函數內沒有返回值,則默認是返回當前上下文,要不然就返回任意非原始類型值。 Javascript中,實例化一個對象,會用到new關鍵字。 經常有人會問對于一個函數,什么時候該使用new關鍵字。 在回答這個問題之前,需要先了解清楚new...
摘要:理解的函數基礎要搞好深入淺出原型使用原型模型,雖然這經常被當作缺點提及,但是只要善于運用,其實基于原型的繼承模型比傳統的類繼承還要強大。中文指南基本操作指南二繼續熟悉的幾對方法,包括,,。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。 怎樣使用 this 因為本人屬于偽前端,因此文中只看懂了 8 成左右,希望能夠給大家帶來幫助....(據說是阿里的前端妹子寫的) this 的值到底...
摘要:但是如果非全局的變量如果被遮蔽了,無論如何都無法被訪問到。但是如果引擎在代碼中找到,就會完全不做任何優化。結構的分句中具有塊級作用域。第四章提升編譯器函數聲明會被提升,而函數表達式不會被提升。 本書屬于基礎類書籍,會有比較多的基礎知識,所以這里僅記錄平常不怎么容易注意到的知識點,不會全記,供大家和自己翻閱; 上中下三本的讀書筆記: 《你不知道的JavaScript》 (上) 讀書筆記...
閱讀 2022·2021-11-24 09:39
閱讀 1885·2019-08-30 15:55
閱讀 2180·2019-08-30 15:53
閱讀 577·2019-08-29 13:16
閱讀 992·2019-08-26 12:20
閱讀 2394·2019-08-26 11:58
閱讀 3156·2019-08-26 10:19
閱讀 3315·2019-08-23 18:31