今天在一個前端群組裡,看到有人發出一個問題:
var o = new Object();function foo(obj){ var obj = o; obj.name = '123'; obj = new Object(); obj.name = '456'; } foo(o); console.log(o.name)
如上程式碼所示,在不改變任何條件和數據的情況下,有沒有可能輸出「456」?
沒多久,群組中人就開始下結論,正常情況下是不能的。
原因嗎,稍微知道引用型別的使用方式的人都知道的,new Object(),改變了obj的指向,永遠沒辦法獲得456。
正常情況下不可能輸出456,那在什麼樣的錯誤情況下能夠輸出456呢?畢竟程式設計師就是擅長寫BUG的嗎,應該能夠搞得非正常狀況的吧。
然後,手殘的自己突然想到前兩天剛學習的Proxy。我們現在是賦值時出的問題,那麼能不能從元資料解決問題呢?試試:
//demo_01var o = new Object(); o = new Proxy(o,{ set(target, key, value,receiver){ if(Object.is('name',key)) return Reflect.set(target, key, `456`,receiver); return Reflect.set(target, key, value , receiver); } })function foo(obj){ var obj = o; obj.name = '123'; obj = new Object(); obj.name = '456'; } foo(o); console.log(o.name)
完美,成功地輸出了456。
什麼?你不知道Proxy是什麼?點擊這裡 –> ES6 攔截器,Proxy
那麼,現在就是嘚瑟的時間了,準備將結果送到群組炫耀下。先翻看下聊天記錄,呦呵,已經有人給了一個答案,比我還快。好吧,先看看人家的答案:
//demo_02var o = new Object();Object.defineProperty(o,'name',{ set(val){ this.value = '456'; }, get(){ return this.value; } })function foo(obj){ var obj = o; obj.name = '123'; obj = new Object(); obj.name = '456'; } foo(o); console.log(o.name)
厲害的小伙子,跟我想到了一起去了,都是在getter和setter上做文章,都是在元級別上處理數據。
這位同學同時貼出一篇文章,說是從這裡獲取的靈感,狠戳這裡,一起欣賞下吧,寫得的確很不錯–> 無懈可擊的鉤子
接下來,也貼下我的答案吧,就當時湊個熱鬧吧。等等,有人表示不服了,說他是投機取巧。 demo_02碼完全等價與demo_03碼:
//demo_03var o = new Object();function foo(obj){ var obj = o; obj.name = '123'; obj = new Object(); obj.name = '456'; } foo(o); o.name = '456'; console.log(o.name);
當demo_02的方法中最後一行程式碼」obj.name = '456';」進行修改時,demo_02的程式碼中的」this.value = '456 ';」也得隨之修改。
說的好有道理,我們的確是在投機取巧,我寫得demo_01也是同樣的問題,還好沒點回車鍵,不然就沒臉了。
那麼有沒得到什麼辦法可以解決這裡問題,實作真正的輸出456
話說我們現在的問題是什麼呢?問題就是處在了new Object()上,它修改了obj的this指向,那我們有沒有什麼辦法規避呢?
什麼?你問我為什麼this指向改變了,我只能說,你真的得好好學習JS了,看看這篇文章吧,作者的筆風好有趣,從一個士兵說起new都做了什麼
我記得在Proxy的handler中有個construct方法,如果我能在Object建構器中修改它的this。想法很好,但是失敗了,沒能實現。如果,有哪位能在這個思路上走下去,求告知答案>_<
查看聊天記錄,那位同學又給了一種解決方法:
var o = new Object();var _Object = Object;Object = function(){ return o; }function foo(obj){ var obj = o; obj.name = '123'; obj = new Object(); obj.name = '456'; } foo(o); console.log(o.name)Object = _Object;
這次這位同學先重寫了Object對象,讓它回傳o這個對象,這就避免了this指向的變動,有才啊,佩服。默默收藏<_<
以上是關於new從一個BUG說起的詳細內容。更多資訊請關注PHP中文網其他相關文章!