關於JS中this作為方法調用?
在學習JS時遇到了下面這段代碼:
運行結果為後面注釋,百度上告訴我這是this作為方法被調用,但是有一些不解。以下是本人猜想:①o.sayColor=sayColor;這行代碼意思是「相當於給o對象新添加一個名為sayColor的屬性,屬性的值為sayColor函數」?②o.sayColor();這是把o對象的sayColor屬性當作方法調用的嗎?
為了證實②的猜想,我在想,是不是上面的sayColor();這段代碼也是被當作某個對象的方法來調用的,而毫無疑問,sayColor();的對象是window。於是,我把sayColor();改為window.sayColor();,得到的結果和sayColor()的結果相同。不知道是不是驗證了②的猜想。另外,我在搜索關於this的調用方法時,看到一句話:this指的是包含它的函數作為方法被調用時所屬的對象。結合好幾個例子,我發現這句話的確挺有道理,不知道各位大神怎麼認為?以上就是我的全部問題,主要是希望有大神幫我驗證。。。PS:①本人剛接觸JS沒多久,可能提出的問題比較小白,望見諒。②代碼出自《JS高程3》,P114。鞠躬,不勝感激!
window.sayColor()的時候this是window
o.sayColor()的時候this是o在瀏覽器裡面,當你沒有明確指定this是誰的時候,this就是window。再加上
window.color == "red"o.color == "blue"
這也沒什麼難以理解的。實例化的對象中,this指的是對象本身;未實例化中,this指的是實際調用者的對象。算是一種比較簡便的判斷this含義的思路。關於你的猜想,現階段的確可以這麼理解。即:o對象執行了一個獲取該對象color屬性值的方法。
如果只針對你說的這兩句話,樓上很多答案都有說過原因了。對應規範裡面的解釋,正好你這個問題就是我在 根治JavaScript中的this-ECMAScript規範解讀 - leon lee的文章 - 知乎專欄 文章實戰篇中對應的兩種情況:
- foo();
- foo.bar();
如果你希望刨根知底,一勞永逸,可以再去看看這篇文章,正如 @魯小夫 所說,這篇文章裡面遠不能覆蓋到this的方方面面,但是如果你能學到如何從規範中尋找答案,以後這種問題就都能自己搞定了。
這個案例中,或許用 this 指向中的就近原則來解釋可能會更好一點。
在對象方法中的 this,this 的綁定只受最靠近的成員引用的影響,總結就是就近原則。
舉個非嚴格模式下的栗子:
function sayNmae() {
console.log(this.name);
}
let obj = {
aa: {
name: "aa",
sayNmae: sayNmae,
bb: {
name: "bb",
sayNmae: sayNmae,
cc: {
name: "cc",
sayNmae: sayNmae
}
}
}
};
obj.aa.sayNmae(); // aa
obj.aa.bb.sayNmae(); // bb
obj.aa.bb.cc.sayNmae(); // cc
不知道這麼說題主理解沒有。
剛好最近寫了一篇博客:不愛吃西紅柿的魚的博客防炸預警。絕大部分都是來自this - JavaScript | MDN,只做了點微小的工作,謝謝大家。
lz如果能深入了解下JS引擎就能有點理解了
JS代碼在運行時需要設置1. 全局執行棧(ECStack)用數組表示和全局執行環境(EC),並將EC壓棧2. 全局對象GO(主要是系統內置的對象如String,Number等)GO = {
String: {}, ..., window: this}3. 創建於EC關聯的全局變數對象(VO),它有指針指向GO,同時包含全局變數和函數的定義
注意函數定義時其內部的[[Scope]]屬性指向其定義所在的執行環境則ECStack = [ EC(G) = { VO(G):{GO,
o: {color:true}, sayColor : function sayColor() {...}, sayColor[[Scope]]: this//this為VO(G) }]執行函數sayColor()1.創建函數執行環境EC(sayColor)並將其壓入ECStack(此時處於棧頂)2.創建函數sayColor的作用域鏈(prototype鏈)用於查找變數等標識符,初始化為當前函數[[Scope]]所指向對象3.創建函數活動對象AO(sayColor) 包含函數中變數或函數定義(處理方式同全局方式3)並插入作用域鏈頂端此時ECStack = [
EC(sayColor) = { [[Scope]]: VO(G), AO(sayColor): { arguments:[], this:window }, scopeChain: &...
}]可以發現此時this為window對象對於o.sayColor()注意其this指向o對象本身總結一條就是this指向函數調用棧的次一級(最低為全局(瀏覽器內是window)對象)如果改為function test(fn) { return fn();}test(o.sayColor);//red
lz可以試一下,注意test()在調用結束後會從ECStack刪除因而在運行o.sayColor()之前調用棧為ECStack = [EC(sayColor), EV(G)],其this指向window其實判斷「this指的是什麼」有四個規則,分別是new Binding、explicit binding、implicit binding和default binding。而這裡用到最後兩種隱式綁定(優先順序第三)和默認綁定(優先順序最低)。
o.sayColor()由於被o調用,所以this指向o。
window.sayColor()同o.sayColor(),this指向window。這兩個都是隱式綁定,this指向調用該函數的對象。而sayColor()由於沒有隱式綁定,所以默認綁定規則生效,簡單來說,在非strict模式下這裡this指全局對象,strict模式下為undefined。
隱式綁定有個地方要注意的,就是上面說到o.sayColor()輸出為blue,但是如果是使用var say = o.sayColor; say(); 的話,那輸出就是red了。
此外的Explicit binding則是由call和apply等指定this具體的指代對象。優先順序排第二。有趣的是一旦通過這層綁定,後續再調用this也會指向剛才指定的對象。
而最高的就是new binding了。通過new產生的對象自動綁定this到該對象身上,如果沒有特殊處理的話。
this還有其他很多內容。總之,this非常有趣!謝邀。
this 是 JS 中最複雜的內容,涉及到函數、函數調用、eval 、call/apply/bind、基本包裝類型、構造函數實例化、嚴格模式等等方方面面,蔚為大觀。
而 ES6 引入的 arrow function 和 class 更是把 this 複雜化了。
昨天我看到 @leon lee 為此寫了一篇專欄,雖然內容很好,但依然沒能覆蓋到關於 this 的方方面面。
根治JavaScript中的this-ECMAScript規範解讀 - leon lee的文章 - 知乎專欄
網上關於 this 的文章也是千千萬萬,其中不乏錯漏之處。
就是開車多年的老司機,也難免在關於 this 的一些邊邊角角上翻車。
所以在這個問題上,我已經不指望能靠教程、科普把初學者掰過來了,我也不推薦任何此類文章。
我的建議就是,先啃完 《JavaScript 高級程序設計》(第三版),英文版風味更佳,把 ES3、ES5 中的內容消化掉,再看看 ES6 in depth,這就差不多了。
初學者要想紮實地掌握 JS ,除了看權威和全面一點的書之外,沒有捷徑。
在基礎不紮實的情況下,去看那些水平層次不齊的網文和博客都只會擾亂你的思考,而直接去看規範又是千頭萬緒、細密繁瑣。
只能等 《JavaScript 高級程序設計》 更新第四版,把 ES 後續的內容補足,可能會有一個全面的梳理。
相關內容:《JavaScript高級程序設計(第4版)》什麼時候出版? - 魯小夫的回答《javascript高級程序設計》能先跳過第六章面向對象和第七章函數表達式,然後看BOM和DOM嗎? - 魯小夫的回答《JavaScript高級程序設計》 第 18 章 JavaScript 與 XML太暈了怎麼辦? - 魯小夫的回答為什麼不能直接把一個原型對象賦給另一個原型對象?看JavaScript高級程序設計的疑問 - 魯小夫的回答ES6 In Depth ArticlesMozilla Hacks
嚴格模式下情況已經不太一樣,直接定義的函數如果不指明 this,會變成 undefined。
咱們還是跟著潮流走吧。
this是運行時當前對象的指代。
通常的錯誤出現在定義時與運行時的差別。
以問題例子看。
js中默認的this為window。如果直接調用saycolor()。會在當前運行對象中查找saycolor(),所以是window.saycolor()。這是this.color.為red。o.saycolor(),這裡調用對象o的saycolor。那麼
this會從window轉換為o。然後在當前運行對象o中查找saycolor。所以是o.saycolor()。this.color為blue。函數調用返回後this切換會window。點語法(.)會切換運行時當前對象。將運行時當前對象壓棧,點語法執行完後,彈出當前運行時對象,獲取上個運行時對象。理解調用的Env多多畫這樣的圖圖來自於 Structure and Interpretation
of Computer Programs
開始學的時候就簡單點記吧,this指代的就是調用函數的對象 sayColor() 是全局的方法,就是window.sayColor()o.sayColor是對象o的方法,你要確定this指代的是誰 你就看方法的.前面的對象就可以了
記住一點,this 指向當前調用的對象。
請參考 "js權威指南" 隨便哪一版
js在運行的時候,會有一個全局對象,對於瀏覽器來說這個全局對象就是window。聲明的全局變數,函數什麼的都會成為他的屬性或方法,所以能寫window.saycolor()
把函數賦給對象相當於給對象添加方法
this的作用域就是它所在的對象直接在全局中調用 sayColor()時,sayColor的this-&>window(非嚴格模式下),
因此this.color===window.color-&>"red"當o.sayColor()調用時,調用位置有上下文(context),被某個對象(o)"擁有"或者"包含",會隱式綁定到這個上下文對象此時o.sayColor()-&>this.color===o.color-&>"blue"你就記住誰調用就指向誰,反正你如果想徹底弄明白,你需要把js裡面一些比較容易混的地方都徹底弄懂,作用域阿,執行上下文阿什麼的,而且js這門語言還和c. Java不一樣,總之你就多讀那本高程3就對了,你能想到的所有令你疑惑的問題那本書里基本上都有很好的解釋了
this指的是當前環境對象 關於環境對象建議回頭看看高程第四章的內容
可以看下 Mozilla 的官方文檔,this - JavaScript
它把使用到的場景都介紹的很清楚了 ,主要是
- Global context
- Function context
- Arrow functions
- As an object method
- As a constructor
- call and apply
- The bind method
- As a DOM event handler
- In an in–line event handler
看完這些基本就都清楚了
我最近開始看了Javascript,剛看了倆月。有些觀點可能有出入的地方多包涵吶。回答問題:第四行,在那個sayColor()的函數中,它僅僅是在定義而已,它沒被實例化成對象,也沒運行。所以誰調用它,裡面那個this就指代誰(的上下文)。問題①:對沒錯。當屬性是函數的時候,我們稱這個屬性為「方法」。問題②:對,不過描述得有點怪,它就是方法,不需要「當做」方法。當調用函數而沒指定對象的時候,就默認是在全局對象下調用,瀏覽器的全局對象就是window。this我覺得是指代一種上下文,就像你這個返回顏色的函數,我總得知道你想要的是誰的顏色的吧?這個「誰」就由this來給出啦。如果你要把你這段函數alert(this.color)裡面的this刪掉了,那它運行的時候,它就只能默認你想要的是全局對象下的color屬性,就總是返回window.color了。另外後面兩行可以簡化為:sayColor.apply(o); 這樣就不用非得讓o多一個sayColor方法啦。
看來你需要這篇博客 深入理解函數之動態的this - MaoTr - 博客頻道 - CSDN.NET
1.把apply函數仔細看看,第一個參數就是你能用的this。2.你可以認為所有函數都被用apply方式調用。3.你可以認為你的所有代碼都在一個大函數里。4.現在簡單了,無非就是傳哪個東西作為this,把你能調用函數的方式各寫一個,跑一下全明白了。
你應該理解形參和實參吧?this是一個隱藏的、預設為window對象的形參。js提供五種語法來指定調用函數時傳遞給this的實參:func()// window被傳遞給thisobj.func(...)// obj被傳遞給thisfunc.call(obj, ...)// 顯式指定obj傳遞給thisfunc.apply(obj, [...])// apply是call的爸爸func_for_only_obj=func.bind(obj)// copy一個func,但不管怎麼調,this都是obj
this如果在對象裡邊,我都當做c++的this。
不在對象裡邊,就是對象包含這個對象的那個東西(可以是對象,系統,巴拉巴拉的)個人理解,A調用了B,那麼B裡面的this就指向A。B如果是全局函數,那麼B中的this指向window。錯了就刪。
推薦閱讀:
※如何評價 TypeScript 1.7?
※npm、bower、jamjs 等包管理器,哪個比較好用?
※js 數組賦值問題 :值傳遞還是引用?
※在自學前端,但是沒有什麼實踐的資源,大家來推薦一下論壇或者別的可供練習的資源吧?
※JS立即執行如何使用?還是說圓括弧本身是用來改變JS的執行上下文環境?
TAG:前端開發 | JavaScript | 編程 |