`new Object()`和对象文字符号有什么区别?

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

person = new Object() 

…和这个字面语法:

 person = { property1 : "Hello" }; 

看来,两者都做同样的事情,虽然JSLint喜欢使用对象文字符号。

哪一个更好,为什么?

他们都做同样的事情(除非有人做了一些不寻常的事情),除此之外你的第二个创build一个对象, 添加一个属性。 但是文字符号在源代码中只占用较less的空间。 对于正在发生的事情,清楚地认识到,所以使用new Object() ,实际上只是input更多,并且(理论上,如果不是由JavaScript引擎优化的话)进行不必要的函数调用。

这些

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

在技​​术上不要做同样的事情。 第一个只是创build一个对象。 第二个创build一个并分配一个属性。 对于第一个是相同的,你需要第二步创build和分配属性。

有些人可以做的“不寻常的事情”是将影子或分配给默认的Object全局:

 // Don't do this Object = 23; 

在这种极不寻常的情况下, new Object将失败,但{}将工作。

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

没有方法的简单对象没有区别,如你的例子。 但是,当您开始向对象添加方法时,有一个很大的区别。

文字方式:

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

原型方式:

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

这两种方式都允许像这样创buildObj的实例:

 var foo = new Obj( "hello" ); 

但是,按照字面的方式,在对象的每个实例中都携带了sayHello方法的副本。 而在原型方法中,该方法在对象原型中定义并在所有对象实例之间共享。 如果你有很多的对象或者很多的方法,字面的方式会导致相当大的内存浪费。

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

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

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

  1. 它更短(精确的10个字符)
  2. dynamic创build对象更容易,更有条理
  3. 如果某个小丑无意中覆盖了Object,这并不重要

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

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

JavaScript的Expando Propertiesfunction使我们能够以这种方式即时创build新成员,并实现所期望的目标。 但是,这种方式并不是很结构化或封装。 如果我们想在创build时指定成员,而不必依靠expando属性和创build后的任务,会怎样?

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

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

在这里,我们已经在一行代码中实现了相同的效果,并且字符数量明显减less。

上面的对象构造方法的进一步讨论可以在JavaScript和面向对象编程(OOP)中find。

最后,那个超越Object的笨蛋呢? 你认为这是不可能的? 那么, 这个JSFiddle否则certificate。 使用对象字面符号可以防止我们从这个丑angular中脱身。

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

在我的机器上使用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'); 

请注意,这是在这里find的一个扩展: 为什么arr = []比arr = new Array更快?

我的输出是以下内容:

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

很明显{}和[]比使用new创build空对象/数组要快。

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

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

     var obj1 = new Object(); obj1.a = 1; var obj2 = new Object(obj1); obj2.a // 1 
  2. 用法不限于OOP对象中的对象。 其他types也可以传递给它。 该function将相应地设置types。 例如,如果我们将整数1传递给它,那么将为我们创build一个types编号的对象。

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

     var obj = new Object(1); typeof obj // "number" obj.a = 2; typeof obj // "object" 
  4. 如果该对象是对象的子类的副本,则可以添加该属性而不进行types转换。

     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 

实际上,有几种方法可以在JavaScript中创build对象。 当你只想创build一个对象时,使用“ new ”操作符创build“ 基于构造函数 ”的对象没有任何好处。 这与使用“ 对象字面量 ”语法创build对象相同。 但是当你考虑“ 原型inheritance ”时,用“ ”运算符创build的“ 基于构造函数 ”的对象变得难以置信。 你不能用用字面语法创build的对象维护inheritance链。 但是你可以创build一个构造函数 ,将属性和方法附加到它的原型。 然后,如果您使用“ new ”运算符将此构造函数分配给任何variables,它将返回一个对象,该对象将访问与该构造函数的原型附加的所有方法和属性。

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

 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构造函数来创build任意数量的对象,并且所有这些对象都将从其inheritancefullname()。

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

顺便说一句,如果你想获得与“ 对象字面量 ”语法相同的function,你将不得不在所有的对象,如下所示创buildfullname():

 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(); 

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

***原型inheritance允许一个简单的inheritance链,可以是非常有用和强大的。

***它通过inheritance构造函数原型中定义的常用方法和属性来节省内存。 否则,你将不得不一遍又一遍地在所有的对象中复制它们。

我希望这是有道理的。

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

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

我发现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是一个标签:语句构造; 分号是可选的,所以它不会抱怨。

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

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

如果创build10万个实例,则内存使用情况会有所不同 新的对象()只会保留一个副本,而{}将保留一万个副本。