我应该使用对象文字还是构造函数?

IT技术 javascript
2021-01-20 16:00:13

我对应该以哪种方式在 javascript 中创建对象感到困惑。似乎至少有两种方法。一种是使用对象字面量表示法,而另一种是使用构造函数。一个比另一个有优势吗?

6个回答

如果您没有与对象关联的行为(即,如果对象只是数据/状态的容器),我将使用对象文字。

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;
}

然而,这对于封装来说是不利的:理想情况下,与实体关联的所有数据 + 行为应该一起存在。

很好的解释,但是将函数放入对象字面量呢?我以前见过这样做过。实际上,下面的帖子有一个这样的例子。
2021-03-13 16:00:13
我相信你错过了一件重要的事情。只有构造函数可以提供私有成员和公共成员(封装)。在对象文字中 - 它们都是公开的。
2021-04-01 16:00:13
如果您将函数定义作为对象字面量的一部分包含在内,或this.fn = function ...在构造函数中使用该方法,则您的每个对象实例都将拥有自己的函数副本。使用原型方法,您只附加一次每个函数:它们将通过原型继承被实​​例继承。
2021-04-11 16:00:13
使用游戏引擎的更好方法是什么?我使用了构造函数方法,但我的原型无法访问构造函数数据。
2021-04-11 16:00:13

它基本上归结为是否需要对象的多个实例;使用构造函数定义的对象允许您拥有该对象的多个实例。对象字面量基本上是具有所有公共变量/方法的单例。

// 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
根据我的经验,这正是造成差异的原因。很好的例子。
2021-03-17 16:00:13
这是决定时要牢记的一个很好的点。谢谢。
2021-04-05 16:00:13

另一种以统一方式创建对象的方法是使用返回对象的函数:

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);
由于您在对象文字中声明了该函数。这是否意味着当您使用Object.create文字内部的函数创建对象时,每个实例都是唯一的?
2021-03-20 16:00:13

这取决于你想做什么。如果你想在你的对象中使用(半)私有变量或函数,构造函数就是这样做的方法。如果你的对象只包含属性和方法,对象字面量就可以了。

function SomeConstructor(){
    var x = 5;
    this.multiply5 = function(i){
        return x*i;
    }
}
var myObj = new SomeConstructor;

var SomeLiteral = {
    multiply5: function(i){ return i*5; }
}

现在,该方法multiply5myObjSomeLiteral做同样的事情。唯一的区别是 myObj 使用私有变量。后者在某些情况下可能有用。大多数情况下,对象字面量就足够了,并且是创建 JS 对象的好方法。

没有太大区别,例如参见web-source.net/javascript_tutorial/...实际上,在 DOMscripting(浏览器中的客户端 js)中,我会说所有函数都成为 window-object(全局命名空间)的方法(您可以将所有“独立”函数称为 window.[somefunction]。
2021-03-13 16:00:13
函数和方法有什么区别?我来自 ac# 背景,所以对我来说一个函数是独立的,一个方法只是一个类的一部分的函数。
2021-04-09 16:00:13