前言
今天在一個前端群組裡,看到有人發出一個問題:
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運算子做了什麼工作呢?
話說我們現在的問題是什麼呢?問題就是處在了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中文網其他相關文章!

JavaScript是現代網站的核心,因為它增強了網頁的交互性和動態性。 1)它允許在不刷新頁面的情況下改變內容,2)通過DOMAPI操作網頁,3)支持複雜的交互效果如動畫和拖放,4)優化性能和最佳實踐提高用戶體驗。

C 和JavaScript通過WebAssembly實現互操作性。 1)C 代碼編譯成WebAssembly模塊,引入到JavaScript環境中,增強計算能力。 2)在遊戲開發中,C 處理物理引擎和圖形渲染,JavaScript負責遊戲邏輯和用戶界面。

JavaScript在網站、移動應用、桌面應用和服務器端編程中均有廣泛應用。 1)在網站開發中,JavaScript與HTML、CSS一起操作DOM,實現動態效果,並支持如jQuery、React等框架。 2)通過ReactNative和Ionic,JavaScript用於開發跨平台移動應用。 3)Electron框架使JavaScript能構建桌面應用。 4)Node.js讓JavaScript在服務器端運行,支持高並發請求。

Python更適合數據科學和自動化,JavaScript更適合前端和全棧開發。 1.Python在數據科學和機器學習中表現出色,使用NumPy、Pandas等庫進行數據處理和建模。 2.Python在自動化和腳本編寫方面簡潔高效。 3.JavaScript在前端開發中不可或缺,用於構建動態網頁和單頁面應用。 4.JavaScript通過Node.js在後端開發中發揮作用,支持全棧開發。

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

記事本++7.3.1
好用且免費的程式碼編輯器

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),