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

时间:2011-01-04 20:09:57

标签: javascript object jslint

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

person = new Object()

...和这个文字语法:

person = {
    property1 : "Hello"
};

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

哪一个更好,为什么?

12 个答案:

答案 0 :(得分:219)

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

文字方式:

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方法的副本。然而,使用原型方法,该方法在对象原型中定义并在所有对象实例之间共享。 如果你有很多对象或很多方法,那么字面上的方式会导致相当大的内存浪费。

答案 1 :(得分:113)

他们都做同样的事情(除非有人做了一些不寻常的事情),除了你的第二个创建一个对象添加一个属性。但是文字表示法在源代码中占用的空间更少。它可以清楚地识别出发生了什么,所以使用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"
};

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

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

// Don't do this
Object = 23;

极不寻常的案例中,new Object会失败,但{}会有效。

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

答案 2 :(得分:53)

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

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

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

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

    考虑一个包含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 and Object Oriented Programming (OOP).

    找到

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

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

答案 3 :(得分:39)

在使用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');

请注意,这是此处的内容的扩展:Why is arr = [] faster than arr = new Array?

我的输出如下:

Testing Array:
using[]: 1091ms
using new: 2286ms
Testing Object:
using{}: 870ms
using new: 5637ms

如此清楚{}和[]比使用new创建空对象/数组更快。

答案 4 :(得分:29)

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

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

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

    var obj = new Object(1);
    typeof obj // "number"
    
  3. 如果添加了属性,使用上述方法(new Object(1))创建的对象将转换为对象类型。

    var obj = new Object(1);
    typeof obj // "number"
    obj.a = 2;
    typeof obj // "object"
    
  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
    

答案 5 :(得分:17)

实际上,有几种方法可以在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();

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

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

顺便说一句,如果您希望使用“ 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();

最后,如果您现在问为什么我应该使用构造函数方法而不是 object literal 方法:

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

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

我希望这是有道理的。

答案 6 :(得分:8)

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

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

答案 7 :(得分:3)

对于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: ilabel: statement构造;分号是可选的,所以它不会抱怨它。

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

$ 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 :

答案 8 :(得分:0)

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

答案 9 :(得分:0)

我唯一使用“ new”键初始化对象的方法是内联箭头功能:

() => new Object({ key: value})

由于以下代码无效:

() => { key: value} //  instead of () => { return { key: value};}

答案 10 :(得分:0)

这里有很多很棒的答案,但我想带着我的 50 美分来。

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

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

对象字面量创建与基于构造函数的语法

感受造句的不同。

如果我有一个句子 "I like cheese",我可以清楚地大声告诉你(字面意思或逐字逐句):我喜欢奶酪。

这是我按字面意思(逐字逐句)创建的句子。

所有其他方式都是一些棘手的方式,可以让您理解我准确创建的句子。比如我告诉你:

  1. 在我的句子中,主语是"I",宾语是"cheese",谓语是"to like"。 这是您可以毫不含糊地学习相同句子的另一种方式:“我喜欢奶酪”。

或者,

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

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

您可以设计任何其他方法,这些方法不同于“逐字”造句 (LITERAL),也可以是 INDIRECT(非文字、非逐字逐字)造句方法。

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

答案 11 :(得分:-2)

如果您创建了1万个实例,则内存使用情况会有所不同。 new Object()只保留一份副本,{}将保留一万份。

相关问题