有没有人注意到这种行为?这真的让我失望了……我希望原型(prototype)数组对每个类实例都是私有(private)的,而不是在所有类实例之间共享。
有人可以验证这是正确的行为,也许可以更详细地解释这种行为?
请注意注释的代码以及它如何影响脚本的行为。
<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>
非常感谢。
最佳答案
对象的原型(prototype)只是一个对象。原型(prototype)属性在从该对象继承的所有对象之间共享。如果您创建“类”的新实例(类在JS中始终不存在),即从原型(prototype)继承的对象,则不会复制属性。
它仅对如何使用这些继承的属性有所不同:
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
在所有这些情况下,您始终使用相同的对象。
但是,如果为对象的属性分配值,则该属性将在对象本身而不是原型(prototype)上设置/创建,因此不会共享:
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
时生成的new Foo()
对象。经验法则是:实例-特定数据应分配给构造函数内部的实例,共享数据(如方法)应分配给原型(prototype)。
您可能需要阅读Details of the object model,它描述了基于类的语言与基于原型(prototype)的语言之间的差异以及对象的实际工作方式。
更新:
您可以通过
Object.getPrototypeOf(obj)
访问对象的原型(prototype)(可能无法在非常老的浏览器中使用),Object.getPrototypeOf(a) === Object.getPrototypeOf(b)
为您提供true
。它是同一对象,也称为Foo.prototype
。