首頁  >  文章  >  web前端  >  關於new從一個BUG說起

關於new從一個BUG說起

一个新手
一个新手原創
2017-09-26 10:30:251362瀏覽


前言

今天在一個前端群組裡,看到有人發出一個問題:

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 = &#39;123&#39;;
    obj = new Object();
    obj.name = &#39;456&#39;;
}

foo(o);
console.log(o.name)Object = _Object;

這次這位同學先重寫了Object對象,讓它回傳o這個對象,這就避免了this指向的變動,有才啊,佩服。默默收藏<_<


努力吧,總有人能教你點什麼

以上是關於new從一個BUG說起的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn