在javascript中创建对象的两种方法

Posted

技术标签:

【中文标题】在javascript中创建对象的两种方法【英文标题】:two ways of creating object in javascript 【发布时间】:2011-10-03 06:30:26 【问题描述】:

我正在通过以下方式创建 javascript 对象:

function field(name,label)
        this.name = name
        this.label= label;


var a = new field("market","Mkt").

然后我将 a 分配给另一个对象。

object.newField = a;

第二种方式是直接新建一个属性

object.2ndNewField = 
    name: "market2",
    label:"Mkt2"

我尝试在其他函数中读取对象。它们的行为不同,但是,当我对对象进行字符串化时,它看起来还不错。我创建的两个属性有什么区别?

顺便说一句,下面的对象有什么不同吗?

 object.2ndNewField = 
        "name": "market2",
        "label":"Mkt2
    

【问题讨论】:

这两个对象的行为有何不同? 【参考方案1】:

对于第一个选项...远离使用“新”。如果“new”被错误地使用,或者在应该使用时被省略,你可能会严重影响你的全局命名空间。另外,您必须小心在代码中的某些地方使用“this”,因为它可能会绑定到您认为不正确的东西,甚至绑定到您的全局数据。

在您提供的第二个选项中,您可以安全地将其用于仅用作数据/方法集合的对象(即不是“类类”行为)。如果您想要一些可以使用私有和公共变量/方法创建多个实例并且可以从中继承的东西,那么您应该使用返回对象的函数。

我写了一篇关于如何安全地创建基础对象和使用继承的示例here。如果您点击链接,您会明白为什么我没有在这篇文章中重新输入所有内容;)。

希望这会有所帮助...

【讨论】:

呃.....“远离......新”......“不良影响......命名空间”?我不明白。 new 根本不影响命名空间。同样使用new“错误”或省略并不比任何其他语义上无效的代码更严重。 @pst,如果您在 JavaScript 中定义了一个类似“类”的对象,该对象打算使用“new”,并且在初始化新对象时忘记使用“new”运算符......” this" 绑定到全局对象,而不是类对象。这可能会导致与全局数据发生变量冲突的许多问题。因此,如果您在创建新对象时忘记调用 new,您可以在不知情的情况下影响代码的其他区域,并且不会报错。通常最好使用从函数返回的对象...尤其是在您编写 API 时 1) 没有类 ;-) 2) 忘记指定 new 与任何其他语义错误没有什么不同 -- 这是代码中的错误,必须修复并且因此不是唯一的(在函数中没有return,它在尝试使用新对象时很容易检测到,因为函数的结果将是undefined)3)@987654327 @ 是使用 [[prototype]] 链所必需的,因为 [不幸] 缺乏指定创建后原型的能力。 @pst,我知道没有类,提示引号。虽然它们是对象而不是类,但对于受过经典训练的程序员(大多数程序员)来说,更容易将它们描述为类。是的,忘记指定new 在技术上是语义,是的,您必须使用new 才能使用原型对象。如果您不打算使用原型类型继承模式,则不需要[[prototype]]。作为一名 API 编写者,我更喜欢闭包,因为用户搞砸的方式似乎更少……但你是对的,这都是语义【参考方案2】:

不同的是,在第一种情况下,创建的对象继承自field.prototype然后Object.prototype(即其内部[[Prototype]]是field.prototype)。原型,其内部 [[Prototype]] 是 Object.prototype),而在第二种情况下,它仅继承自 Object.prototype

另一种看待它的方式是:

object.newField instanceof field; // true
object.newField instanceof Object; // true

object.newField2 instanceof field; // false
object.newField2 instanceof Object; // true

或者继承链是:

object.newField  -> field.prototype -> Object.prototype -> null

object.newField2 -> Object.prototype -> null

其中 '->' 表示“继承自”。

【讨论】:

我正在尝试在另一个函数中遍历对象,field.prototype 使它无法按预期工作。有什么办法可以解决吗? @CKeven function F () ; F.prototype = hello: "world"; var f = new F(); alert(f.hello); f 中的对象具有 [[prototype]] 但没有 prototype 属性(某些浏览器将其公开为 __proto__ 属性或类似属性)。构造函数F 有一个prototype 属性,用作新对象[[prototype]] 的基础。 @CKeven 至少 FF 支持新对象的 constructor 属性,但我不知道规范对此有何规定。请注意,构造函数prototypenew 时应用于新对象——稍后将新对象分配给prototype 对先前创建的对象没有影响(但原型对象可以改变,这将当然是共享的)。 @pst - 在 ECMA-262 中,所有内置原型都有一个公共构造函数属性,该属性指向它们相关的内置构造函数,例如Array.prototype.constructor === Array。如果您使用不同的构造函数(即您自己编写的构造函数)创建原型链,则可以手动将公共 constructor 属性设置为“正确”的构造函数对象,否则它们将指向 Function 或 Object 或其他.

以上是关于在javascript中创建对象的两种方法的主要内容,如果未能解决你的问题,请参考以下文章

iOS中创建单例的两种方式

java中创建线程的两种方式有啥区别

java 在Java中创建Fibonacci的两种方法

Java 中创建线程的两种方法实现

传统线程技术中创建线程的两种方式

java并发传统线程技术中创建线程的两种方式