如何在基础对象上声明数据结构,使它们在每个扩展对象中保持独立?
How to declare data structures on base objects, so they remain independent in each extended object?
示例:
var Person = {
name : '',
collection : new Array(),
addToCollection : function(x)
{
this.collection.push(x);
},
printCollection: function() {
console.log(this.collection);
}
};
var skywalker = Object.create(Person);
skywalker.name = 'Anakin Skywalker';
skywalker.addToCollection(1);
skywalker.printCollection(); // prinnts [1]
var skywalker2 = Object.create(Person);
skywalker2.name = 'Anakin Skywalker 2';
skywalker.addToCollection(2);
skywalker2.printCollection(); // prints [1, 2]
我想实现 skywalker2.printCollection();打印 [2]。我希望基础对象 Person 关注集合,并公开 addToCollection(x) 等操作。
你必须这样做;
var Person = {
name : '',
addToCollection : function(x)
{
this.collection.push(x);
},
printCollection: function() {
console.log(this.collection);
}
};
var sw1 = Object.create(Person),
sw2 = Object.create(Person);
sw1.collection = new Array();
sw2.collection = new Array();
sw1.addToCollection(1);
sw2.addToCollection(2);
sw1.printCollection(); // <- 1
sw2.printCollection(); // <- 2
好吧,根据 OP 的评论,提供了一些关于在 JS 中创建对象的信息。 Object.create() 将允许您定义一个对象的原型,并且原型中的任何内容都在实例化对象之间共享。所以在这种情况下,集合数组是共享的。如果您不希望 collection
被共享,您只需在实例化对象中创建它,如我在前面的代码片段中所示。但是据我了解,您不希望那样。好的,还有另一种方法可以实现这一目标。我们可以将 collection
数组作为私有 属性 函数下的数组,并通过我们的原型方法通过闭包访问它。然后我们将实现我们想要的。就这样;
function collectionInClosure(){
var collection = [],
getCollection = function(){return collection},
setCollection = function(v) {collection.push(v)};
return {
printCollection: function() {console.log(getCollection())},
addToCollection: setCollection
};
}
var sw1 = Object.create(collectionInClosure());
sw2 = Object.create(collectionInClosure());
sw1.addToCollection(1);
sw2.addToCollection(2);
sw1.printCollection(); // <- 1
sw2.printCollection(); // <- 2
这是非常普遍的做法,能够在基础 classes 中抽象一些属性是一个很大的便利,这样我们在实例化或扩展对象时就不需要关心它们了。 class 像 Java 这样的其他 class 面向对象的语言为我们做到了这一点,它通常被认为是开发人员理解的更直观的行为。
可以通过两种方式解决此特定问题:
1) 使用 ES6:
class Animal {
constructor(name) {
this.name = name;
this.collection = [];
}
addToCollection(x) {
this.collection.push(x);
}
printCollection() {
console.log(this.collection);
}
}
var dog = new Animal();
dog.addToCollection(1);
dog.printCollection(); // prints 1
var dog2 = new Animal();
dog2.addToCollection(2);
dog2.printCollection(); // prints 2
由于并非所有浏览器都支持 ES6(大多数浏览器默认关闭 ES6),请使用 Babel 或类似的 polyfill 才能使用上述语法。
Babel 将使用 ES5 来模拟 ES6 语法,javascript 类似于:
"use strict";
var _createClass = function() {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function(Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
var Animal = function() {
function Animal(name) {
// .. some Babel Class checks here
this.name = name;
this.collection = [];
}
_createClass(Animal, [{
key: "addToCollection",
value: function addToCollection(x) {
this.collection.push(x);
}
}, {
key: "printCollection",
value: function printCollection() {
console.log(this.collection);
}
}]);
return Animal;
}();
var dog = new Animal();
dog.addToCollection(1);
dog.printCollection(); // prints 1
var dog2 = new Animal();
dog2.addToCollection(2);
dog2.printCollection(); // prints 2
2) 另一种方法是使用受 Babel 方法启发的 ES5 语法:
var Person = function() {
function Person(name) {
this.name = name;
this.collection = [];
this.addToCollection = function (x) {
this.collection.push(x);
}
this.printCollection = function () {
console.log(this.collection);
}
};
return Person;
}();
var p1 = new Person();
p1.addToCollection(1);
p1.printCollection(); // prints 1
var p2 = new Person();
p2.addToCollection(2);
p2.printCollection(); // prints 2
通过将构造函数 Person 包装在立即执行的函数中,我们确保每次有人实例化 Person 时都会创建一个新的构造函数 class;
示例:
var Person = {
name : '',
collection : new Array(),
addToCollection : function(x)
{
this.collection.push(x);
},
printCollection: function() {
console.log(this.collection);
}
};
var skywalker = Object.create(Person);
skywalker.name = 'Anakin Skywalker';
skywalker.addToCollection(1);
skywalker.printCollection(); // prinnts [1]
var skywalker2 = Object.create(Person);
skywalker2.name = 'Anakin Skywalker 2';
skywalker.addToCollection(2);
skywalker2.printCollection(); // prints [1, 2]
我想实现 skywalker2.printCollection();打印 [2]。我希望基础对象 Person 关注集合,并公开 addToCollection(x) 等操作。
你必须这样做;
var Person = {
name : '',
addToCollection : function(x)
{
this.collection.push(x);
},
printCollection: function() {
console.log(this.collection);
}
};
var sw1 = Object.create(Person),
sw2 = Object.create(Person);
sw1.collection = new Array();
sw2.collection = new Array();
sw1.addToCollection(1);
sw2.addToCollection(2);
sw1.printCollection(); // <- 1
sw2.printCollection(); // <- 2
好吧,根据 OP 的评论,提供了一些关于在 JS 中创建对象的信息。 Object.create() 将允许您定义一个对象的原型,并且原型中的任何内容都在实例化对象之间共享。所以在这种情况下,集合数组是共享的。如果您不希望 collection
被共享,您只需在实例化对象中创建它,如我在前面的代码片段中所示。但是据我了解,您不希望那样。好的,还有另一种方法可以实现这一目标。我们可以将 collection
数组作为私有 属性 函数下的数组,并通过我们的原型方法通过闭包访问它。然后我们将实现我们想要的。就这样;
function collectionInClosure(){
var collection = [],
getCollection = function(){return collection},
setCollection = function(v) {collection.push(v)};
return {
printCollection: function() {console.log(getCollection())},
addToCollection: setCollection
};
}
var sw1 = Object.create(collectionInClosure());
sw2 = Object.create(collectionInClosure());
sw1.addToCollection(1);
sw2.addToCollection(2);
sw1.printCollection(); // <- 1
sw2.printCollection(); // <- 2
这是非常普遍的做法,能够在基础 classes 中抽象一些属性是一个很大的便利,这样我们在实例化或扩展对象时就不需要关心它们了。 class 像 Java 这样的其他 class 面向对象的语言为我们做到了这一点,它通常被认为是开发人员理解的更直观的行为。
可以通过两种方式解决此特定问题:
1) 使用 ES6:
class Animal {
constructor(name) {
this.name = name;
this.collection = [];
}
addToCollection(x) {
this.collection.push(x);
}
printCollection() {
console.log(this.collection);
}
}
var dog = new Animal();
dog.addToCollection(1);
dog.printCollection(); // prints 1
var dog2 = new Animal();
dog2.addToCollection(2);
dog2.printCollection(); // prints 2
由于并非所有浏览器都支持 ES6(大多数浏览器默认关闭 ES6),请使用 Babel 或类似的 polyfill 才能使用上述语法。
Babel 将使用 ES5 来模拟 ES6 语法,javascript 类似于:
"use strict";
var _createClass = function() {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function(Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
var Animal = function() {
function Animal(name) {
// .. some Babel Class checks here
this.name = name;
this.collection = [];
}
_createClass(Animal, [{
key: "addToCollection",
value: function addToCollection(x) {
this.collection.push(x);
}
}, {
key: "printCollection",
value: function printCollection() {
console.log(this.collection);
}
}]);
return Animal;
}();
var dog = new Animal();
dog.addToCollection(1);
dog.printCollection(); // prints 1
var dog2 = new Animal();
dog2.addToCollection(2);
dog2.printCollection(); // prints 2
2) 另一种方法是使用受 Babel 方法启发的 ES5 语法:
var Person = function() {
function Person(name) {
this.name = name;
this.collection = [];
this.addToCollection = function (x) {
this.collection.push(x);
}
this.printCollection = function () {
console.log(this.collection);
}
};
return Person;
}();
var p1 = new Person();
p1.addToCollection(1);
p1.printCollection(); // prints 1
var p2 = new Person();
p2.addToCollection(2);
p2.printCollection(); // prints 2
通过将构造函数 Person 包装在立即执行的函数中,我们确保每次有人实例化 Person 时都会创建一个新的构造函数 class;