javascript - 修改实例属性对修改前已输出到控制台的内容也有影响?
过去多啦不再A梦
过去多啦不再A梦 2017-05-19 10:35:27
0
3
545

不是原型动态性的问题,是控制台的问题
先贴上我的代码

function Father(){
    this.colors = ["red", "green", "blue"],
    this.sayColor = function(){
    console.log(this.colors);
    };
}
function Child(){}
Child.prototype = new Father();

var child1 = new Child();
child1.sayColor(); // ["red", "green", "blue"] 原始值

child1.colors.push("black"); // 属性修改
var child2 = new Child();
child2.sayColor(); // ["red", "green", "blue", "black"]
child1.sayColor(); // ["red", "green", "blue", "black"]

注释为正常运行的结果,但若在浏览器里(Firefox和Chrome)打开,控制台会返回3个相同的数组:

以及

点击刷新页面后,返回正常的结果;
或将console.log改为alert,打开页面即返回正常的结果;
因为IE每次都需要手动载入脚本,相当于刷新了一次页面,所以结果正常;
所以我觉得,是不是控制台输出结果的方式和我想的不一样?求解答。

过去多啦不再A梦
过去多啦不再A梦

全部回复(3)
洪涛

我也遇到过这样的问题,以下是我提出的问题:
/q/10...

如果你不想看,总的来说console.log 是有惰性求值的问题!

先说结论:console.log 是不靠谱的由于它并非标准里确定的 API,所以浏览器的实现是没有标准可言的。有时候会出现同步的 console.log 与异步的 console.log 的困惑,也有立刻求值的 console.log 和惰性求值的 console.log 的差异。你遇到的是后者。

补充参考:http://stackoverflow.com/ques...

Peter_Zhu

好吧,问题中已经说明不是原型问题,是控制台问题。 敲了这么多字,觉得还有点价值,没舍得删...
以下解释与提问者所想知道的不一致。
我回答的是: 为什么实例对象的属性变更会影响另外一个实例?
权当给对原型继承理解不清的人一个解释。

我的Chrome(Mac平台下,版本57.0.2987)并没有出现你说的问题,输出结果和期望一致:

  • 第一个输出: ["red", "green", "blue"]

  • 第二个输出: ["red", "green", "blue", "black"]

  • 第三个输出: ["red", "green", "blue", "black"]

解答问题前,请看一个示例, 可以解释你遇到的问题。

var father_colors = ["red", "green", "blue"];
var child1_colors = father_colors

console.log(child1_colors);  // ["red", "green", "blue"] 原始值

child1_colors.push("black");
var child2_colors = father_colors;

console.log(child2_colors);  // ["red", "green", "blue", "black"]
console.log(child2_colors);  // ["red", "green", "blue", "black"]

原因

好,现在回到你的问题: 为什么改了child1实例的属性,确影响到了child2?

  1. 创建实例后,实例的 __proto__ 属性会指向父类的 .prototype 属性, 记住是一个指向(引用)而不是复制!

  2. 访问实例属性时,先在实例自己身上找,如果没有找到,通过 __proto__属性去父类的 prototype属性中寻找: child1.colors 指向 Father.prototype.colors, 因此对colors的操作会直接影响父类中的引用对象。

  3. child2.colors 也会去找 Father.prototype.colors, 结果自然是child1修该colors之后的结果。

怎样避免?

child1.colors你重新赋值而不是直接操作,就不会有问题。 (记住,对父类中的引用类型属性都不要直接操作!)

child1.colors = ["red", "green", "blue", "black"];
// 或者用
child1.colors = child1.colors.concat().push["black"];  //concat()方法复制了一份父类的colors数组。
滿天的星座

自答一个:
正如采纳答案所说,是console.log的惰性求值问题;console.log的惰性求值问题;
当输出的内容为引用类型中的ArrayObject当输出的内容为引用类型中的ArrayObject时,很有可能会出现问题中的情况;

目前我看到的最佳解决方法是:
将输出的内容改为console.log(JSON.stringify(yourArray))console.log(JSON.stringify(yourArray))
不会改变输出的类型和内容,却规避了console.log不会改变输出的类型和内容,却规避了console.log的惰性求值问题;

最后感谢所有回答者!

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板