簡體   English   中英

由本機對象引起的奇怪行為是什么?

[英]What is the weird behavior of native objects caused by?

最近我開始學習JavaScript中的面向對象編程。 我所理解的是,在引用變量時,我們實際上並未引用它們的實際值,而是引用內存中的位置。 這就是為什么那些應該復制實例的“ 返回此 ”方法不起作用的原因。

那么,示例代碼:

//An example object with a simple property and
//failing "copy" function.
function MyObject()
{
    this.myProperty = 123;
    this.copy = function() { return this; };
}

var iOne = new MyObject();
var iTwo = iOne.copy();
iTwo.myProperty = 321;

現在iOne和iTwo的“myProperty”屬性等於321,因為“copy”方法返回了一個引用,而不是一個值。 這種行為是預期的,一切都很好。

現在,我嘗試使用本機對象類型Number進行相同操作。 讓我們以更加面向對象的程序員友好的方式創建它的實例:

var iOne = new Number(123);
var iTwo = iOne; //Equals "iTwo = iOne.copy()", except there isn't a copy method

iOne = 321;

現在,發生了一件可怕的事情。 iOne等於321,但iTwo保持其值,仍然等於123。

我不知道這是由什么造成的。 也許Number是某種“特殊”? 也許與之相關的十進制數不僅僅是一個屬性? 或者也許它應該讓沒有經驗的程序員的生活變得更容易? 最后一個選項與運營商有關。 如果有人對此有所了解,請不要讓我理解JavaScript的方式崩潰。

對象,數組和字符串通過引用(而不是通過副本)分配。 所有其他類型在分配時都是有效的副本(例如,它們創建一個與舊的無關的新變量)。

字符串是一種特殊情況,因為它們是不可變的,因此當您更改字符串時,它總是創建一個新字符串,因此即使前一個賦值是引用,它的行為也更像是復制它。

分配:

iOne = 321;

用簡單的原始數字類型替換iOne的值,因此它對任何其他變量都沒有影響。

var iOne = new Number(123);
var iTwo = iOne; //Equals "iTwo = iOne.copy()", except there isn't a copy method

iOne = 321;

您將覆蓋iOne變量持有的對象引用,並使用不同的原始數字。

對象作為引用保留,但它們不是可以直接解除引用的指針,因此您無法替換該內存位置中保存的數據。 你只能改變它(如果對象是可變的)

具體來說, Number對象包裝器不可變,或者至少它所擁有的原始值不能被替換。 您只能替換整個對象。

iOne = 321;

此代碼執行了預期的操作,您為變量iOne分配了321 ,覆蓋了它最初引用的內容。

Javascript中的“本機類型”和對象之間的行為沒有真正的區別(除了本機類型是不可變的)。

在你的第二個例子中,你只是簡單地改變iOne指向的變量,為什么要改變另一個獨立的iTwo變量所指向的?

在第一種情況下,你有兩個指向同一個對象的變量,如果你使用一個變量來改變對象,你也可以使用另一個變量來觀察變化(顯而易見......它指向同一個對象)。

在Javascript中,您可以想象一切都始終通過引用而從不通過值(復制)。 如果你想要復制一些東西你需要明確地...對於數組你可以使用x.slice()來制作x的淺表副本; 對於對象,沒有用於執行相同操作的原始函數,因此您必須調用構造函數。

一個常見的OOP模式是擁有一個成員函數.clone() ,它返回一個副本,因此需要副本的人不需要知道如何制作每個類的副本。

function P2d(x, y) {
    this.x = x;
    this.y = y;
}

P2d.prototype.clone = function() {
    return new P2d(this.x, this.y);
}

另一種特定於Javascript的原型模型的可能性在某些情況下可能很有用,就是創建一個單獨的對象,它看起來像一個淺拷貝,可以在不影響原始的情況下進行變異,而是在讀取時引用原始對象:

function fakeCopy(x) {
    function f() { }
    f.prototype = x;
    return new f;
}

p = new P2d(10, 20);
q = fakeCopy(p);
console.log(q.x); // Displays 10
q.y = 30;
console.log(q.y); // Displays 30
console.log(p.y); // Displays 20 -- original not changed
p.x = 99;
console.log(q.x); // Displays 99 (!)

發生這種情況是因為Javascript對象具有在訪問成員進行讀取時搜索的“原型鏈”。 q被創建為一個空對象,以p為原型,因此在查找屬性(用於讀取)時,如果在q內找不到某些內容,它將在p內搜索。 然而,在寫入時,將在q內部設置屬性,不影響p並且將返回q存在的值的那一點,而不是必須在原型鏈中上升。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM