我对应该以哪种方式在 javascript 中创建对象感到困惑。似乎至少有两种方法。一种是使用对象字面量表示法,而另一种是使用构造函数。一个比另一个有优势吗?
我应该使用对象文字还是构造函数?
如果您没有与对象关联的行为(即,如果对象只是数据/状态的容器),我将使用对象文字。
var data = {
foo: 42,
bar: 43
};
应用KISS 原则。如果除了简单的数据容器之外不需要任何东西,请使用简单的文字。
如果要向对象添加行为,可以使用构造函数并在构造过程中向对象添加方法或为类提供原型。
function MyData(foo, bar) {
this.foo = foo;
this.bar = bar;
this.verify = function () {
return this.foo === this.bar;
};
}
// or:
MyData.prototype.verify = function () {
return this.foo === this.bar;
};
像这样的类也充当数据对象的模式:您现在拥有某种契约(通过构造函数)对象初始化/包含哪些属性。自由文字只是无定形的数据块。
您也可以拥有一个verify
作用于普通旧数据对象的外部函数:
var data = {
foo: 42,
bar: 43
};
function verify(data) {
return data.foo === data.bar;
}
然而,这对于封装来说是不利的:理想情况下,与实体关联的所有数据 + 行为应该一起存在。
它基本上归结为是否需要对象的多个实例;使用构造函数定义的对象允许您拥有该对象的多个实例。对象字面量基本上是具有所有公共变量/方法的单例。
// define the objects:
var objLit = {
x: 0,
y: 0,
z: 0,
add: function () {
return this.x + this.y + this.z;
}
};
var ObjCon = function(_x, _y, _z) {
var x = _x; // private
var y = _y; // private
this.z = _z; // public
this.add = function () {
return x + y + this.z; // note x, y doesn't need this.
};
};
// use the objects:
objLit.x = 3;
objLit.y = 2;
objLit.z = 1;
console.log(objLit.add());
var objConIntance = new ObjCon(5,4,3); // instantiate an objCon
console.log(objConIntance.add());
console.log((new ObjCon(7,8,9)).add()); // another instance of objCon
console.log(objConIntance.add()); // same result, not affected by previous line
另一种以统一方式创建对象的方法是使用返回对象的函数:
function makeObject() {
var that = {
thisIsPublic: "a public variable"
thisIsAlsoPublic: function () {
alert(that.thisIsPublic);
}
};
var secret = "this is a private variable"
function secretFunction() { // private method
secret += "!"; // can manipulate private variables
that.thisIsPublic = "foo";
}
that.publicMethod = function () {
secret += "?"; // this method can also mess with private variables
}
that.anotherPublicVariable = "baz";
return that; // this is the object we've constructed
}
makeObject.static = "This can be used to add a static varaible/method";
var bar = makeObject();
bar.publicMethod(); // ok
alert(bar.thisIsPublic); // ok
bar.secretFunction(); // error!
bar.secret // error!
由于 JavaScript 中的函数是闭包,我们可以使用私有变量和方法并避免new
.
来自http://javascript.crockford.com/private.html关于 JavaScript 中的私有变量。
下面的代码显示了创建对象的三种方法、对象字面量语法、函数构造函数和Object.create()
. 对象字面量语法只是动态地创建和对象,因此它__prototype__
是Object
对象,它将可以访问Object
. 严格地从设计模式的角度来看,应该使用简单的对象文字来存储数据的单个实例。
函数构造函数有一个名为 的特殊属性.prototype
。此属性将成为__prototype__
由函数构造函数创建的任何对象的 。添加到.prototype
函数构造函数的属性的所有属性和方法将可用于它创建的所有对象。如果您需要数据的多个实例或需要对象的行为,则应使用构造函数。请注意,当您想要模拟私有/公共开发模式时,也最好使用函数构造函数。请记住将所有共享方法放在 上,.prototype
这样它们就不会在每个对象实例中创建。
创建对象Object.create()
使用对象文字作为__prototype__
此方法创建的对象。添加到对象字面量的所有属性和方法将可用于通过真正的原型继承从它创建的所有对象。这是我的首选方法。
//Object Example
//Simple Object Literal
var mySimpleObj = {
prop1 : "value",
prop2 : "value"
}
// Function Constructor
function PersonObjConstr() {
var privateProp = "this is private";
this.firstname = "John";
this.lastname = "Doe";
}
PersonObjConstr.prototype.greetFullName = function() {
return "PersonObjConstr says: Hello " + this.firstname +
" " + this.lastname;
};
// Object Literal
var personObjLit = {
firstname : "John",
lastname: "Doe",
greetFullName : function() {
return "personObjLit says: Hello " + this.firstname +
", " + this.lastname;
}
}
var newVar = mySimpleObj.prop1;
var newName = new PersonObjConstr();
var newName2 = Object.create(personObjLit);
这取决于你想做什么。如果你想在你的对象中使用(半)私有变量或函数,构造函数就是这样做的方法。如果你的对象只包含属性和方法,对象字面量就可以了。
function SomeConstructor(){
var x = 5;
this.multiply5 = function(i){
return x*i;
}
}
var myObj = new SomeConstructor;
var SomeLiteral = {
multiply5: function(i){ return i*5; }
}
现在,该方法multiply5
在myObj
和SomeLiteral
做同样的事情。唯一的区别是 myObj 使用私有变量。后者在某些情况下可能有用。大多数情况下,对象字面量就足够了,并且是创建 JS 对象的好方法。