javascript - 修改實例屬性對修改前已輸出到控制台的內容也有影響?
过去多啦不再A梦
过去多啦不再A梦 2017-05-19 10:35:27
0
3
520

不是原型動態性的問題,是控制台的問題
先貼上我的程式碼

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的惰性求值問題;

最後感謝所有回答者!

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板