原型中的数组和对象 - 不被视为引用

Posted

技术标签:

【中文标题】原型中的数组和对象 - 不被视为引用【英文标题】:Arrays and Objects In Prototypes - Not Treated as References 【发布时间】:2017-03-21 23:22:05 【问题描述】:

我在 javascript 中有一个原型对象,当我初始化原型的新实例并更新原型中的属性时,它会更新所有元素。我知道数组和对象是通过引用传递的,并且想知道可以解决这个问题的解决方案吗?

let Test = function () 

Test.prototype = 
    array: [],
    add: function (value) 
        this.array.push(value)
    


let test1 = new Test();
let test2 = new Test();

test1.add(1);
test1.add(2);

// Prints [1, 2]
console.log(test2.array);

一种解决方案是:

class Test 

    constructor() 
        this.array = []
    

    add(value) 
        this.array.push(value)
    


let test1 = new Test();
let test2 = new Test();

test1.add(1);
test1.add(2);

// Prints []
console.log(test2.array);

但我不是在寻找 ES6 方法,而是更“原生”的 javascript。

感谢您的帮助!

【问题讨论】:

“但我不是在寻找 ES6 方法,而是更“原生”的 javascript。” class 完全是原生 JavaScript,从 2015 年 6 月就开始了。也支持本机但所有最新的浏览器,并且可以为过时的浏览器进行转换。 永远记住 - JS 不做“经典”面向对象,即使你使用 class 关键字,你也不是真的创建一个班级。这一切都只是变相的原型。 @Hecksa:在计算机科学意义上(封装和继承),它们确实是类。它们与 Java 或 C# 等语言中的静态编译时构造不同。通过原型实现的类仍然是类。 @TJCrowder:我实际上想说的和你刚才说的差不多(JS 类不像人们可能从 C# 或 Java 知道它们),但我设法没有真正说出来全部。我当然不是想争辩说 class 关键字不会创建一个类(是的,尽管这正是我所说的)。感谢您的澄清,很高兴周围有人可以真正解释事情以防止我混淆大家! 【参考方案1】:

就是这样:它们视为参考。

当你这样做时:

Test.prototype = 
    array: [], // <- This creates a new array and it's being used in all instances
    add: function (value) 
        this.array.push(value)
    

您想要的是为不同的类实例获取不同的数组实例。在这种情况下,只需在构造函数中执行 this.array = []

let Test = function ()  this.array = []; 

let Test = function ()  this.array = []; 

Test.prototype = 
    array: [],
    add: function (value) 
        this.array.push(value)
    


let test1 = new Test();
let test2 = new Test();

test1.add(1);
test1.add(2);

console.log(test1.array);
// => [1, 2]

console.log(test2.array);
// => []

【讨论】:

【参考方案2】:

在构造函数中初始化可变成员,而不是在原型中。如果它在原型中,它将在所有实例之间共享:

let Test = function () 
    this.array = [];


Test.prototype = 
    add: function (value) 
        this.array.push(value)
    


let test1 = new Test();
let test2 = new Test();

test1.add(1);
test1.add(2);

console.log(test1.array);
console.log(test2.array);

【讨论】:

【参考方案3】:

在实例而不是原型上定义数组:

function Test() 
    this.array = [];


Test.prototype.add = function (value) 
    this.array.push(value)

【讨论】:

【参考方案4】:

我了解数组和对象是通过引用传递的

不,他们不是。但是它们被对象引用引用,这是完全不同的事情,1 确实是您遇到的问题。

并且想知道可以解决这个问题的解决方案吗?

完全按照您在 ES6 方法中所做的操作:将其放在对象本身上,而不是原型上:

let Test = function () 
    this.array = [];
;

1(“通过引用传递”和“对象引用”这两个概念的共同点是它们都使用“引用”这个词。在前者中,它是对 变量 [和 JavaScript 没有的概念]。在后者中,它是对对象的引用。)

【讨论】:

以上是关于原型中的数组和对象 - 不被视为引用的主要内容,如果未能解决你的问题,请参考以下文章

KeyValuePairs 如何比较相等?

JavaScript基础--------三座大山(前端面试必考)

原型和闭包重点

JavaScript——原型5个规则

为啥 Firestore 返回一个集合引用,但我的程序将其视为一个数组?

原型的几点总结