摘要:第七問(wèn),可以看做,同上面的結(jié)果一樣得到一個(gè)匿名函數(shù),這個(gè)匿名函數(shù)與前面的以及后面的組成一個(gè)新的對(duì)象創(chuàng)建表達(dá)式,這個(gè)表達(dá)式在執(zhí)行時(shí),會(huì)調(diào)用其中的構(gòu)造函數(shù),因此會(huì)彈出。
緣由
開(kāi)通文章是為了能夠有個(gè)地方長(zhǎng)篇大論今天遇到的問(wèn)題
由于提了一個(gè)問(wèn)題(見(jiàn) 這里),被人嘲諷。但是這個(gè)嘲諷我的人(@xiaoboost )的答案并不對(duì),他的答案只是根據(jù)結(jié)果解釋能夠得出這個(gè)結(jié)果的執(zhí)行。至于為什么以及JavaScript在執(zhí)行過(guò)程中進(jìn)行了哪些判斷并沒(méi)有進(jìn)行詳細(xì)的解釋或者說(shuō)完整的解釋。其余的幾個(gè)朋友要么鄙視這道題、要么鄙視我把運(yùn)算符優(yōu)先級(jí)牽扯進(jìn)來(lái)。最讓我納悶的是大家都認(rèn)為這里面不牽扯到運(yùn)算符的優(yōu)先級(jí)判斷。
在此,我以自己的理解來(lái)解釋一下JavaScript在執(zhí)行過(guò)程中進(jìn)行了哪些判斷和操作。
function Foo() { getName = function () { alert(1); }; return this; } Foo.getName = function () { alert(2); }; Foo.prototype.getName = function () { alert(3); }; var getName = function () { alert(4); }; function getName() { alert(5); } Foo.getName(); getName() Foo().getName() getName() new Foo.getName() new Foo().getName() new new Foo().getName()我的答案:
首先,JS中會(huì)對(duì)變量聲明和函數(shù)聲明在編譯階段進(jìn)行提升,所以實(shí)際代碼會(huì)表現(xiàn)成這樣:
// 此處是變量提升的演示,是在編譯階段進(jìn)行的 var getName; function Foo() { getName = function () { alert(1); }; return this; } function getName() { alert(5); } // 此處則只有到了執(zhí)行階段才會(huì)執(zhí)行 Foo.getName = function () { alert(2); }; Foo.prototype.getName = function () { alert(3); }; getName = function () { alert(4); };
其次,除了第六問(wèn)和第七問(wèn),所有有成員訪問(wèn)運(yùn)算符(也叫屬性訪問(wèn)器).的表達(dá)式,.的優(yōu)先級(jí)都是最高,沒(méi)有一個(gè)表達(dá)式有圓括號(hào),有圓括號(hào)的要么是函數(shù)調(diào)用,要么是new 運(yùn)算(對(duì)象創(chuàng)建表達(dá)式)的組成部分。
這里專(zhuān)門(mén)說(shuō)明沒(méi)有圓括號(hào)是因?yàn)榭吹竭@個(gè)問(wèn)題原作者自己的分析文章將new Foo().getName()中的new Foo()先執(zhí)行解釋為由于圓括號(hào)的優(yōu)先級(jí)高于.。附上問(wèn)題原作者自己的分析文章:http://www.cnblogs.com/xxcang...
以下為各問(wèn)題的數(shù)字輸出以及為什么:
第一問(wèn)2,直接調(diào)用Foo函數(shù)的getName方法。
第二問(wèn)4,變量聲明和函數(shù)聲明會(huì)在編譯階段被提升。此時(shí),函數(shù)聲明會(huì)覆蓋變量聲明。但是到了執(zhí)行階段,如果變量有賦值操作,那么變量會(huì)因賦值而覆蓋之前的函數(shù)聲明。因此第二問(wèn)的getName()實(shí)際執(zhí)行的是賦值了匿名函數(shù)function () {alert(4)}的函數(shù)表達(dá)式。
第三問(wèn)1,.運(yùn)算符優(yōu)先級(jí)最高,按照.運(yùn)算符的關(guān)聯(lián)性從左往右先計(jì)算左操作數(shù),Foo()是一個(gè)函數(shù)調(diào)用表達(dá)式,函數(shù)內(nèi)部在執(zhí)行時(shí),由于函數(shù)內(nèi)部沒(méi)有查找到局部變量getName,因此引擎會(huì)沿著作用域鏈向上查找getName變量。在全局作用域中找到getName變量(同時(shí)也是window的屬性/方法),給它賦值一個(gè)新的匿名函數(shù)function(){alert(1)}。return的this此時(shí)指向當(dāng)前方法所屬的對(duì)象window,因此,計(jì)算右操作數(shù)時(shí),就是調(diào)用了window對(duì)象上的getName方法。而前面左操作數(shù)Foo()中已經(jīng)給getName變量重新賦值了一個(gè)匿名函數(shù),因此會(huì)出現(xiàn)新賦值函數(shù)所彈出的數(shù)字1。
第四問(wèn)1,getName()已經(jīng)因?yàn)榍懊娴?b>Foo()的調(diào)用而賦值了新的匿名函數(shù),因此彈出數(shù)字1。
第五問(wèn)2,new可以與Foo結(jié)合組成一個(gè)沒(méi)有參數(shù)的對(duì)象創(chuàng)建表達(dá)式,但是這樣它的優(yōu)先級(jí)低于".",因此這里.運(yùn)算符優(yōu)先級(jí)高于new和函數(shù)調(diào)用(),整個(gè)表達(dá)式則可以理解為:new (Foo.getName)(),當(dāng)Foo.getName執(zhí)行完畢會(huì)返回一個(gè)匿名函數(shù)function(){alert(2)},此時(shí)會(huì)與new運(yùn)算符、()組成一個(gè)新的表達(dá)式:new function(){alert(2)}(),這是一個(gè)對(duì)象創(chuàng)建表達(dá)式,這個(gè)表達(dá)式在執(zhí)行執(zhí)行的時(shí)候,構(gòu)造函數(shù)部分function(){alert(2)}會(huì)被執(zhí)行,結(jié)果就是2。另外,對(duì)象創(chuàng)建表達(dá)式在沒(méi)有傳入?yún)?shù)的情況下可以省略括號(hào),因此原題中的new Foo.getName();可以把后面的括號(hào)省略掉new Foo.getName,結(jié)果一樣。
第六問(wèn)3,帶有參數(shù)的對(duì)象創(chuàng)建表達(dá)式(new constructor())和成員訪問(wèn)表達(dá)式的優(yōu)先級(jí)是一樣,這里就牽扯到應(yīng)該理解成
(new Foo()).getName()還是new (Foo().getName)()。如果是new (Foo().getName)(),那么在執(zhí)行Foo()時(shí),它是一個(gè)函數(shù)調(diào)用,優(yōu)先級(jí)低于帶參數(shù)的new,因此這樣不行。那么只能是(new Foo()).getName()。new Foo()實(shí)例化一個(gè)對(duì)象,然后通過(guò).訪問(wèn)getName屬性,對(duì)象本身沒(méi)有這個(gè)屬性,順著原型鏈查找到Foo.prototype中有這個(gè)屬性,并且賦值了一個(gè)匿名函數(shù)。最后通過(guò)函數(shù)調(diào)用運(yùn)算符調(diào)用它,得到3。
3,可以看做 new((new Foo()).getName)(),(new Foo()).getName同上面的結(jié)果一樣得到Foo.prototype.getName一個(gè)匿名函數(shù):function () {alert(3)},這個(gè)匿名函數(shù)與前面的new以及后面的()組成一個(gè)新的對(duì)象創(chuàng)建表達(dá)式new function () {alert(3)} (),這個(gè)表達(dá)式在執(zhí)行時(shí),會(huì)調(diào)用其中的構(gòu)造函數(shù)function (){alert(3)},因此會(huì)彈出3。
以上是我對(duì)這個(gè)問(wèn)題的解釋?zhuān)渲械诹鶈?wèn)得到@zonxin 的解答,再次感謝,附上地址:https://segmentfault.com/q/10...
最后,附上我被嘲諷并且被4個(gè)人"踩"的問(wèn)題地址,如果覺(jué)得我的解答是正確的,麻煩幫我"平反"╥﹏╥...;如果有錯(cuò)誤的地方,請(qǐng)留言指出,我會(huì)十分感謝。
我的原問(wèn)題地址:https://segmentfault.com/q/10...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/81681.html
摘要:面試會(huì)進(jìn)入下一個(gè)環(huán)節(jié)。如果在頁(yè)面中有多個(gè)按鈕,那么這個(gè)彈出窗要如何實(shí)現(xiàn)同上,根據(jù)之前的建議在回答問(wèn)題之前要問(wèn)清楚問(wèn)題中模棱兩可的地方。是否觸發(fā)不同按鈕彈出的窗口現(xiàn)實(shí)的內(nèi)容不同。 這道面試題,當(dāng)初我面試的時(shí)候被問(wèn)過(guò)兩次,因此比較深,此外,我記得還有設(shè)計(jì)模式的考察,所以,有深刻的體會(huì)。 面試題主要考察什么 面試不是個(gè)輕松的活,不管是對(duì)面試官還是面試者都一樣。對(duì)于面試官來(lái)說(shuō),別的先不管,首先...
摘要:然后最外層這個(gè)函數(shù)會(huì)返回一個(gè)新對(duì)象,對(duì)象里面有一個(gè)屬性,名為,而這個(gè)屬性的值是一個(gè)匿名函數(shù),它會(huì)返回。 最近看到一條有意思的閉包面試題,但是看到原文的解析,我自己覺(jué)得有點(diǎn)迷糊,所以自己重新做一下這條題目。 閉包面試題原題 function fun(n, o) { // ① console.log(o); return { // ② fun: function(m) ...
摘要:說(shuō)明最近看到這樣一段代碼問(wèn)三行的輸出分別是什么覺(jué)得有點(diǎn)意思,和大家一起來(lái)聊聊。說(shuō)到這里,這道題基本上可以解決了,希望大家能聽(tīng)明白我上面說(shuō)的話,下面的就簡(jiǎn)單了。 說(shuō)明 最近看到這樣一段代碼 function fun(n,o){ console.log(o); return { fun:function(m){ return fun...
摘要:說(shuō)明最近看到這樣一段代碼問(wèn)三行的輸出分別是什么覺(jué)得有點(diǎn)意思,和大家一起來(lái)聊聊。說(shuō)到這里,這道題基本上可以解決了,希望大家能聽(tīng)明白我上面說(shuō)的話,下面的就簡(jiǎn)單了。 說(shuō)明 最近看到這樣一段代碼 function fun(n,o){ console.log(o); return { fun:function(m){ return fun...
閱讀 1194·2021-11-22 13:53
閱讀 1766·2021-11-17 09:33
閱讀 2525·2021-10-14 09:43
閱讀 3089·2021-09-01 11:41
閱讀 2499·2021-09-01 10:44
閱讀 3184·2021-08-31 09:39
閱讀 1657·2019-08-30 15:44
閱讀 1978·2019-08-30 13:02