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

person = new Object()

...这个文字语法:

person = {
    property1 : "Hello"
};

看起来两者都做同样的事情,尽管JSLint更喜欢使用对象文字表示法。

哪个更好,为什么?


当前回答

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

其他回答

对于没有方法的简单对象(如您的示例)没有区别。 然而,当开始向对象添加方法时,就有很大的不同了。

文字:

function Obj( prop ) { 
    return { 
        p : prop, 
        sayHello : function(){ alert(this.p); }, 
    }; 
} 

原型:

function Obj( prop ) { 
    this.p = prop; 
} 
Obj.prototype.sayHello = function(){alert(this.p);}; 

这两种方法都允许像这样创建Obj实例:

var foo = new Obj( "hello" ); 

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

这里有很多很好的答案,但我想用我的50美分来回答。

所有这些答案所缺少的是一个简单的类比,它适用于刚开始学习编程语言的人。

希望我能用这个类比来填补这个空白:

对象文字创建vs基于构造函数的语法

感受句子创作的不同之处。

如果我有一句话“我喜欢奶酪”,我可以清楚响亮地(字面上,或逐字逐句地)告诉你:我喜欢奶酪。

这是我逐字逐句创造的句子。

所有其他的方法都是一些棘手的方法来让你理解我到底创造了什么句子。例如,我告诉你:

在我的句子中,主语是“I”,宾语是“cheese”,谓词是“to like”。 这是你学习同一句话的另一种方式,没有任何歧义:“我喜欢奶酪”。

Or,

我的句子有3个单词:第一个是英语字典里的第n个单词,第二个是英语字典里的第m个单词,最后一个是英语字典里的第l个单词。

在这种情况下,你也会得到同样的结果:你确切地知道这句话是什么。

你可以设计任何其他方法,这将不同于“逐字”的句子创建(字面),这将是间接(非字面,非逐字)的句子创建方法。

我认为这是这里的核心概念。

我发现ES6/ES2015有一个不同之处。不能使用简写箭头函数语法返回对象,除非用new object()包围对象。

> [1, 2, 3].map(v => {n: v});
[ undefined, undefined, undefined ]
> [1, 2, 3].map(v => new Object({n: v}));
[ { n: 1 }, { n: 2 }, { n: 3 } ]

这是因为编译器被{}括号搞糊涂了,认为n: i是一个label:语句结构;分号是可选的,所以它不会抱怨。

如果向对象添加另一个属性,它最终会抛出一个错误。

$ node -e "[1, 2, 3].map(v => {n: v, m: v+1});"
[1, 2, 3].map(v => {n: v, m: v+1});
                           ^

SyntaxError: Unexpected token :

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

var obj1 = new Object();  
var obj2 = {};  

我没有发现任何迹象表明这两家公司在幕后的运作方式有任何显著差异(如果我错了,请纠正我——我很想知道)。然而,第二种方法(使用对象文字表示法)提供了一些优点。

它更短(准确地说是10个字符) 动态创建对象更容易,也更结构化 如果某个小丑无意中覆盖了Object也没关系

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

var obj1 = new Object();  
obj1.Name = "A Person";  
obj1.TelNo = "12345"; 

JavaScript的Expando Properties特性允许我们以这种方式动态地创建新成员,我们实现了我们的意图。但是,这种方式不是非常结构化或封装的。如果我们希望在创建时指定成员,而不必依赖于expando属性和创建后赋值,该怎么办?

这就是对象文字表示法可以帮助的地方:

var obj1 = {Name:"A Person",TelNo="12345"};  

在这里,我们用一行代码和更少的字符实现了同样的效果。

关于上述对象构造方法的进一步讨论可以在:JavaScript和面向对象编程(OOP)中找到。

最后,那个覆盖Object的白痴呢?你觉得不可能吗?这个JSFiddle证明了事实并非如此。使用对象文字表示法可以防止我们犯这种错误。

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

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