首页 >web前端 >js教程 >关于new从一个BUG说起

关于new从一个BUG说起

一个新手
一个新手原创
2017-09-26 10:30:251405浏览


前言

今天在一个前端群组里,看到有人发出一个问题:

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