原型为数组的Javascript对象成员变为由所有类实例共享 [英] Javascript object members that are prototyped as arrays become shared by all class instances

查看:113
本文介绍了原型为数组的Javascript对象成员变为由所有类实例共享的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有人注意到这种行为?这真的让我失望了...我会期望原型数组对每个类实例是私有的,而不是在所有类实例之间共享。



有人可以验证正确的行为,也许可以更详细地解释这个行为。



注意注释的代码及其如何影响脚本的行为。

 < html> 
< head>

< script type =text / javascript>

function print_r(title,object){

var output ='';
for(var key in object){

output + = key +:+ object [key] +\\\
;

}

output = title +\\\
\\\
+ output;

alert(output);

}

函数Sandwich(){

//取消注释以解决问题
//this.ingredients = [] ;

}

Sandwich.prototype = {

ingredients:[],
addIngredients:function(ingArray){

for(var key in ingArray){

this.addIngredient(ingArray [key]);

}

},
addIngredient:function(thing){

this.ingredients.push

}

}

var cheeseburger = new Sandwich();
cheeseburger.addIngredients([汉堡,cheese]);

var blt = new Sandwich();
blt.addIngredients([bacon,lettuce,tomato]);

var spicy_chicken_sandwich = new Sandwich();
spicy_chicken_sandwich.addIngredients([辣鸡蛋,莴苣,番茄,蜂蜜dijon mayo,爱]);

var onLoad = function(){

print_r(Cheeseburger contains:,cheeseburger.ingredients);

};

< / script>

< / head>
< body onload =onLoad();>
< / body>
< / html>

非常感谢。

解决方案

对象的原型只是一个对象。原型属性在从该对象继承的所有对象之间共享。如果您创建了一个类的新实例(类在JS中不存在),则不会创建属性副本,即从原型继承的对象。



它只会对如何使用这些继承的属性产生影响:

  function Foo(){} 

Foo.prototype = {
array:[],
func:function(){}
}

a = new Foo
b = new Foo();

a.array.push('bar');
console.log(b.array); // prints [bar]

b.func.bar ='baz';
console.log(a.func.bar); // prints baz

在所有这些情况下,你总是使用相同的对象。



但是如果你给对象的属性赋值一个值,该属性将被设置/创建在对象本身,而不是它的原型,因此是不共享:

  console.log(a.hasOwnProperty('array')); // prints false 
console.log(a.array); // prints [bar]
a.array = ['foo'];
console.log(a.hasOwnProperty('array')); // prints true
console.log(a.array); // prints [foo]
console.log(b.array); // prints [bar]






想要为每个实例创建自己的数组,你必须在构造函数中定义它:

  function Foo(){
this.array = [];
}

因为这里, this 是指在调用 new Foo()时生成的 new 对象。



经验法则是:实例 - 应将具体数据分配给构造函数

$





$ b p>您可能需要阅读 对象模型的详细信息 ,介绍基于类的语言与基于原型的语言之间的差异以及对象实际工作原理。



更新: >

您可以通过 Object.getPrototypeOf(obj)(可能在非常旧的浏览器中工作)访问对象的原型,和 Object.getPrototypeOf(a)=== Object.getPrototypeOf(b)给你 true 。它是同一个对象,也被称为 Foo.prototype


Has anyone noticed this behavior before? This really threw me off... I would have expected prototyped arrays to be private to each class instance rather than shared between all class instances.

Can someone verify that this is the correct behavior and perhaps explain this behavior in more detail?

Notice the commented code and how it affects the behavior of the script.

<html>
<head>

<script type="text/javascript">

function print_r( title, object ) {

    var output = '';
    for( var key in object ) {

        output += key + ": " + object[ key ] + "\n";

    }

    output = title + "\n\n" + output;

    alert( output );

}

function Sandwich() {

    // Uncomment this to fix the problem
    //this.ingredients = [];

}

Sandwich.prototype = {

    "ingredients" : [],
    "addIngredients" : function( ingArray ) {

        for( var key in ingArray ) {

            this.addIngredient( ingArray[ key ] );

        }

    },
    "addIngredient" : function( thing ) {

        this.ingredients.push( thing );

    }

}

var cheeseburger = new Sandwich();
cheeseburger.addIngredients( [ "burger", "cheese" ] );

var blt = new Sandwich();
blt.addIngredients( [ "bacon", "lettuce", "tomato" ] );

var spicy_chicken_sandwich = new Sandwich();
spicy_chicken_sandwich.addIngredients( [ "spicy chicken pattie", "lettuce", "tomato", "honey dijon mayo", "love" ] );

var onLoad = function() {

    print_r( "Cheeseburger contains:", cheeseburger.ingredients );

};

</script>

</head>
<body onload="onLoad();">
</body>
</html>

Many thanks.

解决方案

The prototype of an object is just an object. The prototype properties are shared between all objects that inherit from that object. No copies of the properties are made if you create a new instance of a "class" (classes don't exist anyway in JS), i.e. an object which inherits from the prototype.

It only makes a difference on how you use the these inherited properties:

function Foo() {}

Foo.prototype = {
    array: [],
    func: function() {}
}

a = new Foo();
b = new Foo();

a.array.push('bar');
console.log(b.array); // prints ["bar"]

b.func.bar = 'baz';
console.log(a.func.bar); // prints baz

In all these cases you are always working with the same object.

But if you assign a value to a property of the object, the property will be set/created on the object itself, not its prototype, and hence is not shared:

console.log(a.hasOwnProperty('array')); // prints false
console.log(a.array); // prints ["bar"]
a.array = ['foo'];
console.log(a.hasOwnProperty('array')); // prints true
console.log(a.array); // prints ["foo"]
console.log(b.array); // prints ["bar"]


If you want to create own arrays for each instance, you have to define it in the constructor:

function Foo() {
    this.array = [];
}

because here, this refers to the new object that is generated when you call new Foo().

The rule of thumb is: Instance-specific data should be assigned to the instance inside the constructor, shared data (like methods) should be assigned to the prototype.


You might want to read Details of the object model which describes differences between class-based vs. prototype-based languages and how objects actually work.

Update:

You can access the prototype of an object via Object.getPrototypeOf(obj) (might not work in very old browsers), and Object.getPrototypeOf(a) === Object.getPrototypeOf(b) gives you true. It is the same object, also known as Foo.prototype.

这篇关于原型为数组的Javascript对象成员变为由所有类实例共享的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆