`new Object()`和object literal notation有什么区别?

ect*_*ype 190 javascript jslint object

这个基于构造函数的语法创建对象有什么区别:

person = new Object()
Run Code Online (Sandbox Code Playgroud)

...和这个文字语法:

person = {
    property1 : "Hello"
};
Run Code Online (Sandbox Code Playgroud)

虽然JSLint更喜欢使用对象文字表示法,但它们似乎都做同样的事情.

哪一个更好,为什么?

Rém*_*VID 226

没有方法的简单对象没有区别,如您的示例所示.但是,当您开始向对象添加方法时,会有很大的不同.

文字方式:

function Obj( prop ) { 
    return { 
        p : prop, 
        sayHello : function(){ alert(this.p); }, 
    }; 
} 
Run Code Online (Sandbox Code Playgroud)

原型方式:

function Obj( prop ) { 
    this.p = prop; 
} 
Obj.prototype.sayHello = function(){alert(this.p);}; 
Run Code Online (Sandbox Code Playgroud)

两种方式都允许创建这样的实例Obj:

var foo = new Obj( "hello" ); 
Run Code Online (Sandbox Code Playgroud)

但是,使用文字方式,您可以sayHello在对象的每个实例中携带方法的副本.然而,使用原型方法,该方法在对象原型中定义并在所有对象实例之间共享. 如果你有很多对象或很多方法,那么文字方式会导致相当大的内存浪费.

  • 对我来说,问题更多的是使用`new Object()`vs` {}`来创建空对象之间的区别. (38认同)
  • 当我发布这个时,已接受的答案已经存在并被接受.它完美地回答了OP问题,所以我不会重复同样的事情.我发布我的答案主要是为了拓宽空/简单对象以外的主题.在这种情况下**是一个值得一提的重要区别. (16认同)
  • 这似乎是正确和更完整的答案. (14认同)
  • @Lobabob除了第一句话,这个答案实际上并没有提供有关OP问题的任何信息.它甚至不包含'new Object()`.坦率地说,我认为大卫先生误解了这个问题. (11认同)
  • 这个答案是偏离主题的.在您的代码中,Obj是一个继承自Object的独立类.使用对象文字表示法时,使用Object类,而不是Obj.当然,在其原型中使用方法设置类将使内存占用量小于创建大量普通对象并添加方法作为其属性,但这与此处提出的问题完全无关.这个问题的正确答案是"不,绝对没有区别(可能除了可读性)". (3认同)
  • 我找到了这个答案,基于一个类似于我的问题,但最终我正在学习我需要知道的内容.谢谢. (3认同)
  • 这实际上与这个问题没什么关系,因此只能引起混淆.将属性放在原型上与在对象本身上放置属性完全不同......无论您正在创建的属性是否为函数,这都适用.你实现这个就像是一个"方法与非函数属性"的东西,实际上函数和非函数值可以同等地分配给实际对象或对象的原型,并以任何方式将它分配给原型与这个问题无关. (2认同)
  • ^ tl; dr版本就是这个答案基本上是说"如果你做一些完全不同的事情会有所不同." (2认同)

kem*_*002 118

他们都做同样的事情(除非有人做了一些不寻常的事情),除了你的第二个创建一个对象添加一个属性.但是文字表示法在源代码中占用的空间更少.它清楚地可以识别出发生了什么,所以使用new Object(),你实际上只是打字更多(理论上,如果没有被JavaScript引擎优化)做一个不必要的函数调用.

这些

person = new Object() /*You should put a semicolon here too.  
It's not required, but it is good practice.*/ 
-or-

person = {
    property1 : "Hello"
};
Run Code Online (Sandbox Code Playgroud)

技术上不做同样的事情.第一个只是创建一个对象.第二个创建一个并分配一个属性.要使第一个相同,您需要第二步来创建和分配属性.

某人可以做的"不寻常的事情"是阴影或分配给默认的Object全局:

// Don't do this
Object = 23;
Run Code Online (Sandbox Code Playgroud)

在那个极不寻常的情况下,new Object会失败但{}会奏效.

在实践中,没有理由使用new Object而不是{}(除非你做了那个非常不寻常的事情).

  • 作者选择这个答案是正确的,但它是不完整的.请注意,进入内存分配时,两种语法之间存在差异. (10认同)
  • 没有区别。如果您指的是下面的答案之一,那么它就毫无意义,因为它是在谈论基于原型的对象模型和继承(那里的代码设置了从纯Object继承的Obj类)。这个问题不是关于创建某些自定义类的实例,而是关于创建Object的实例,并且对此问题的正确答案是“没有区别”。 (2认同)

Jam*_*man 53

在JavaScript中,我们可以通过两种方式声明一个新的空对象:

var obj1 = new Object();  
var obj2 = {};  
Run Code Online (Sandbox Code Playgroud)

我发现没有任何迹象表明这两者在幕后操作方面有任何显着差异(如果我错了请纠正我 - 我很想知道).但是,第二种方法(使用对象文字符号)提供了一些优点.

  1. 它更短(精确10个字符)
  2. 在运行中创建对象更容易,更有条理
  3. 如果一些小丑无意中覆盖了对象并不重要

考虑一个包含Name和TelNo成员的新对象.使用新的Object()约定,我们可以像这样创建它:

var obj1 = new Object();  
obj1.Name = "A Person";  
obj1.TelNo = "12345"; 
Run Code Online (Sandbox Code Playgroud)

JavaScript 的Expando Properties功能允许我们动态地以这种方式创建新成员,并且我们实现了预期的目标.但是,这种方式不是非常结构化或封装的.如果我们想在创建时指定成员,而不必依赖expando属性和赋值后创建,该怎么办?

这是对象文字符号可以帮助的地方:

var obj1 = {Name:"A Person",TelNo="12345"};  
Run Code Online (Sandbox Code Playgroud)

在这里,我们在一行代码中实现了相同的效果,并且显着减少了字符数.

进一步讨论上述对象构造方法可以在以下位置找到:JavaScript和面向对象编程(OOP).

最后,那个过度使用Object的白痴呢?你觉得这不可能吗?好吧,这个JSFiddle证明不是这样.使用对象文字符号可以防止我们对这个小丑犯罪.

(来自http://www.jameswiseman.com/blog/2011/01/19/jslint-messages-use-the-object-literal-notation/)


小智 41

在我使用Node.js的机器上,我运行了以下内容:

console.log('Testing Array:');
console.time('using[]');
for(var i=0; i<200000000; i++){var arr = []};
console.timeEnd('using[]');

console.time('using new');
for(var i=0; i<200000000; i++){var arr = new Array};
console.timeEnd('using new');

console.log('Testing Object:');

console.time('using{}');
for(var i=0; i<200000000; i++){var obj = {}};
console.timeEnd('using{}');

console.time('using new');
for(var i=0; i<200000000; i++){var obj = new Object};
console.timeEnd('using new');
Run Code Online (Sandbox Code Playgroud)

注意,这是这里找到的扩展:为什么arr = []比arr = new Array更快?

我的输出如下:

Testing Array:
using[]: 1091ms
using new: 2286ms
Testing Object:
using{}: 870ms
using new: 5637ms
Run Code Online (Sandbox Code Playgroud)

所以很明显{}和[]比使用new创建空对象/数组更快.

  • 我觉得这是问题真正寻找的答案,尽管我希望在具有一些属性的对象上进行额外的测试以确保. (3认同)
  • 有趣的数字。有些人需要意识到这一点,但是我认为即使分配一个微不足道的200,000个对象也只会花费我5.6毫秒,因此我不必担心。 (2认同)

Jer*_*ian 29

这里的每个人都在谈论两者的相似之处.我要指出差异.

  1. 使用new Object()允许您传递另一个对象.显而易见的结果是新创建的对象将被设置为相同的引用.这是一个示例代码:

    var obj1 = new Object();
    obj1.a = 1;
    var obj2 = new Object(obj1);
    obj2.a // 1
    
    Run Code Online (Sandbox Code Playgroud)
  2. 用法不限于OOP对象中的对象.其他类型也可以传递给它.该功能将相应地设置类型.例如,如果我们将整数1传递给它,将为我们创建一个number类型的对象.

    var obj = new Object(1);
    typeof obj // "number"
    
    Run Code Online (Sandbox Code Playgroud)
  3. new Object(1)如果向其添加属性,则使用上述方法()创建的对象将转换为对象类型.

    var obj = new Object(1);
    typeof obj // "number"
    obj.a = 2;
    typeof obj // "object"
    
    Run Code Online (Sandbox Code Playgroud)
  4. 如果对象是子类对象的副本,我们可以添加属性而不进行类型转换.

    var obj = new Object("foo");
    typeof obj // "object"
    obj === "foo" // true
    obj.a = 1;
    obj === "foo" // true
    obj.a // 1
    var str = "foo";
    str.a = 1;
    str.a // undefined
    
    Run Code Online (Sandbox Code Playgroud)

  • 我对最后两行非常困惑..为什么如果你将str.a赋值为1,str.a是未定义的?... @Jermin Bazazin (3认同)
  • @AndreaScarafoni因为`str`是`string`类型所以你不能为它分配属性.http://jsfiddle.net/grq6hdx7/1/ (3认同)

Md.*_*med 20

实际上,有几种方法可以在JavaScript中创建对象.当您只想创建一个对象时,使用" new "运算符创建" 基于构造函数 "的对象没有任何好处.它与使用" object literal "语法创建对象相同.但是,当您考虑" 原型继承 " 时,使用" new "运算符创建的" 基于构造函数的 "对象会出现令人难以置信的用途.您无法使用文字语法创建的对象维护继承链.但是您可以创建构造函数,将属性和方法附加到其原型.然后,如果使用" new "运算符将此构造函数赋值给任何变量,它将返回一个对象,该对象可以访问与该构造函数原型相关的所有方法和属性.

下面是使用构造函数创建对象的示例(请参阅底部的代码说明):

function Person(firstname, lastname) {
    this.firstname = firstname;
    this.lastname = lastname;
}

Person.prototype.fullname = function() {
    console.log(this.firstname + ' ' + this.lastname);
}

var zubaer = new Person('Zubaer', 'Ahammed');
var john = new Person('John', 'Doe');

zubaer.fullname();
john.fullname();
Run Code Online (Sandbox Code Playgroud)

现在,您可以通过实例化Person构造函数来创建任意数量的对象,并且所有这些对象都将从中继承fullname().

注意:" this "关键字将引用构造函数中的空对象,并且每当使用" new "运算符从Person创建新对象时,它将自动返回一个对象,该对象包含使用" this "关键字附加的所有属性和方法.并且这些对象肯定会继承附加了Person构造函数原型的方法和属性(这是这种方法的主要优点).

顺便说一句,如果你想用" object literal "语法获得相同的功能,你必须在所有对象上创建fullname(),如下所示:

var zubaer = {
    firstname: 'Zubaer',
    lastname: 'Ahammed',
    fullname: function() {
        console.log(this.firstname + ' ' + this.lastname);
    }
};

var john= {
    firstname: 'John',
    lastname: 'Doe',
    fullname: function() {
        console.log(this.firstname + ' ' + this.lastname);
    }
};

zubaer.fullname();
john.fullname();
Run Code Online (Sandbox Code Playgroud)

最后,如果你现在问为什么我应该使用构造函数方法而不是对象文字方法:

***Prototypal继承允许一个简单的继承链,它可以非常有用和强大.

***它通过继承构造函数原型中定义的常用方法和属性来节省内存.否则,您必须在所有对象中反复复制它们.

我希望这是有道理的.


小智 9

另外,根据一些O'Really javascript书籍....(引用)

使用文字而不是Object构造函数的另一个原因是没有范围解析.因为您可能已经创建了具有相同名称的本地构造函数,所以解释器需要从您调用Object()的位置一直查找作用域链,直到找到全局Object构造函数.

  • 等待O'Really是一个错字还是故意的双关语?他们应该用它来推销他们的书! (23认同)

Pir*_*App 5

2019年更新

我在 OSX High Sierra 10.13.6 节点版本 10.13.0 上运行了与 @rjloura 相同的代码,这些是结果

console.log('Testing Array:');
console.time('using[]');
for(var i=0; i<200000000; i++){var arr = []};
console.timeEnd('using[]');

console.time('using new');
for(var i=0; i<200000000; i++){var arr = new Array};
console.timeEnd('using new');

console.log('Testing Object:');

console.time('using{}');
for(var i=0; i<200000000; i++){var obj = {}};
console.timeEnd('using{}');

console.time('using new');
for(var i=0; i<200000000; i++){var obj = new Object};
console.timeEnd('using new');


Testing Array:
using[]: 117.613ms
using new: 117.168ms
Testing Object:
using{}: 117.205ms
using new: 118.644ms
Run Code Online (Sandbox Code Playgroud)