摘要:原文??蜕嫌羞@么一道的題目。先來分析一下題目,和都從來,為什么同名的屬性值不一樣可以看出,是對這個函數的調用方式不一樣,是函數的調用結果,而則是作為構造函數調用的結果。所以這題的重點應該是如何區分函數調用和構造函數調用。
原文:http://blog.e10t.net/talk-abo...
??蜕嫌羞@么一道 JavaScript 的題目。
//填寫內容讓下面代碼支持a.name = “name1”; b.name = “name2”; function obj(name){ 【1】 } obj.【2】 = "name2"; var a = obj("name1"); var b = new obj;
【1】和【2】是填寫的內容,【2】的答案是 prototype.name,沒爭議。
問題是【1】,參考答案居然是 if(name){ this.name = name;}return this;,這么隨便地玩弄 this 不就是明擺著污染全局變量嗎?暴力賦值不可取。
下面的一些高票討論還說了一大堆解釋的廢話,連他自己都說自己好羅嗦。對,你不但羅嗦,而且還沒有改錯。注釋里都說了給 window 的屬性賦值,還不自知出問題,真是誤人子弟。
先來分析一下題目,a 和 b 都從 obj 來,為什么同名的屬性值不一樣?可以看出,是對 obj 這個函數的調用方式不一樣,a 是 obj 函數的調用結果,而 b 則是 obj 作為構造函數調用的結果。所以這題的重點應該是如何區分_函數調用_和_構造函數調用_。
一個關鍵字 new 決定了不同。new 的作用是什么呢?MDN 上說了,面試也會考你的,簡單來說是三步,new foo:
生成一個繼承于 foo.prototype 的對象
foo 會被調用,其中的 this 值會被綁定為 1 中的對象
如果 foo 沒有返回一個對象(注意是對象?。瑒t返回 1 的對象
從 2 就可以看出 this 值會被 new 綁定為一個確定的對象,而不是像普通函數調用中那樣自己不可預料,要看上下文的進程。
于是就可以在這里做文章。先來判斷 this 的值。
if (this instanceof obj) {}
instanceof 會檢查 this 的原型鏈上是否存在 foo.prototype。也就是說能判斷是否滿足第 1 條,確保了對象能從 prototype 中讀取到 name 屬性。(畢竟代碼中并沒有給 b 的賦值中傳入)
instanceof 并不是完美的判斷方法,但是在這里足夠了,后面會談到這個問題。
if (this instanceof obj) { // new 調用 } else { // 非 new 調用 return { name: name } }
非 new 調用的情況下,直接返回一個新對象就 OK 了。
而在 new 調用的情況下,可以看到 function obj(name) 定義的時候是有參數的,調用的時候卻沒參數,這就要小心了,為了安全起見,還是判斷一下為妙。
if (this instanceof obj) { // new 調用 if (name !== undefined) { this.name = name } } else { // 非 new 調用 return { name: name } }
一般來說,判斷會寫成 if (name),但是碰到 null、0、false 就 GG 了,所以還是謹慎點吧。
問題到這里就可以比較完美地解答了。
bonus: instanceof 的問題『instanceof 會檢查 this 的原型鏈上是否存在 foo.prototype』,為什么說得這么拗口,是因為需要表達出 instanceof 本來就不是真的用來檢測是否調用 new 的方法。
在題目里面,要求的是 a 需要從原型鏈上讀取到特定的屬性值,所以 instanceof 的作用剛好在這里能符合要求而已。
函數調用除了題目中的方法還有第三種方法,那就是 foo.call、foo.apply,而且也能為函數指定 this 的值(所以還有 bind)。因此是存在方法調戲 instanceof 的。
foo.prototype.name = "foo" var midman = new foo("fake foo") var a = foo.call(midman) var b = foo.call(midman, "b") a // undefined, WTF?! b // undefined, WTF?!
這里的 foo 調用的方式是作為函數來調用,但是為 this 綁定的值是從 foo 上 new 出來的,換句話說,其原型鏈上存在 foo.prototype,于是就騙過了 instanceof。
于是 ES2015 來搭救你了,新增了一個 new.target。于是修改成:
if (new.target !== undefined) { // new 調用 if (name !== undefined) { this.name = name } } else { // 非 new 調用 return { name: name } }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/91344.html
摘要:接下來,我主要從三個階段回顧我的秋招,分別是前期中期尾聲。到了這里,我的秋招算是正式的塵埃落定了,簽完三方后,我的秋招結束了。四復盤總結這次的復盤主要是我自己整個秋招的歷程縮影,很多細節無法在一篇文章就說清楚。 ...
摘要:正如我標題所說,簡歷被拒??戳宋液啔v之后說頭條競爭激烈,我背景不夠,點到為止。。三準備面試其實從三月份投遞簡歷開始準備面試到四月份收,也不過個月的時間,但這都是建立在我過去一年的積累啊。 本文是 無精瘋 同學投稿的面試經歷 關注微信公眾號:進擊的java程序員K,即可獲取最新BAT面試資料一份 在此感謝 無精瘋 同學的分享 目錄: 印象中的頭條 面試背景 準備面試 ...
摘要:正如我標題所說,簡歷被拒??戳宋液啔v之后說頭條競爭激烈,我背景不夠,點到為止。。三準備面試其實從三月份投遞簡歷開始準備面試到四月份收,也不過個月的時間,但這都是建立在我過去一年的積累啊。 本文是 無精瘋 同學投稿的面試經歷 關注微信公眾號:進擊的java程序員K,即可獲取最新BAT面試資料一份 在此感謝 無精瘋 同學的分享目錄:印象中的頭條面試背景準備面試頭條一面(Java+項目)頭條...
摘要:直接開始題目是厲害了說句實話開發中誰寫成這樣保證會被打死。不過面試就是面試,有面試官的考量點。官方是這么說的。結果完美,不過小姐姐的意思是數組的方法會自動觸發數組的。 直接開始題目是 if(a==1 && a==2 && a==3){ alert(厲害了) } 說句實話開發中誰寫成這樣保證會被打死。 不過面試就是面試,有面試官的考量點。 我理解的點有兩個 1、隱式類型轉換 先說...
閱讀 1904·2021-11-09 09:46
閱讀 2486·2019-08-30 15:52
閱讀 2445·2019-08-30 15:47
閱讀 1320·2019-08-29 17:11
閱讀 1746·2019-08-29 15:24
閱讀 3501·2019-08-29 14:02
閱讀 2442·2019-08-29 13:27
閱讀 1199·2019-08-29 12:32