繁体   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