前言今天在一个前端群组里,看到有人发出一个问题:
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说起 的详细内容。