Javascript 1.9.3 / ECMAScript 5引入了Object。这是Douglas Crockford等人长期以来一直倡导的。我如何在下面的代码替换新的对象。创建?

var UserA = function(nameParam) {
    this.id = MY_GLOBAL.nextId();
    this.name = nameParam;
}
UserA.prototype.sayHello = function() {
    console.log('Hello '+ this.name);
}
var bob = new UserA('bob');
bob.sayHello();

(假设MY_GLOBAL。nextId存在)。

我能想到的最好的是:

var userB = {
    init: function(nameParam) {
        this.id = MY_GLOBAL.nextId();
        this.name = nameParam;
    },
    sayHello: function() {
        console.log('Hello '+ this.name);
    }
};
var bob = Object.create(userB);
bob.init('Bob');
bob.sayHello();

似乎没有任何优势,所以我想我没有得到它。我可能太新古典主义了。我应该如何使用Object。创建创建用户“bob”?


当前回答

它的优点是。在大多数浏览器中,Create通常比new慢

在这个jsperf示例中,在Chromium浏览器中,browser new的速度是Object.create(obj)的30倍,尽管两者都非常快。这很奇怪,因为new要做更多的事情(比如调用构造函数),而Object。create应该只是创建一个新的对象,并将传入的对象作为原型(crockford语言中的秘密链接)

也许浏览器在创建Object时还没有跟上进度。创造更有效的方法(也许他们是基于新的方法……甚至在本地代码中)

其他回答

对象。create在一些浏览器上还不是标准的,比如IE8, Opera v11.5, Konq 4.3都没有。你可以使用Douglas Crockford的Object版本。为这些浏览器创建,但这不包括在CMS的回答中使用的第二个“初始化对象”参数。

对于跨浏览器代码,同时进行对象初始化的一种方法是自定义Crockford的object .create。这里有一个方法:-

Object.build = function(o) {
   var initArgs = Array.prototype.slice.call(arguments,1)
   function F() {
      if((typeof o.init === 'function') && initArgs.length) {
         o.init.apply(this,initArgs)
      }
   }
   F.prototype = o
   return new F()
}

这维护了Crockford原型继承,也检查对象中的任何init方法,然后用参数运行它,比如说new man('John','Smith')。然后你的代码变成:-

MY_GLOBAL = {i: 1, nextId: function(){return this.i++}}  // For example

var userB = {
    init: function(nameParam) {
        this.id = MY_GLOBAL.nextId();
        this.name = nameParam;
    },
    sayHello: function() {
        console.log('Hello '+ this.name);
    }
};
var bob = Object.build(userB, 'Bob');  // Different from your code
bob.sayHello();

所以bob继承了sayHello方法,现在拥有自己的属性id=1和name=' bob '。当然,这些属性既可写又可枚举。这也是一种比ECMA Object简单得多的初始化方法。创建,特别是当您不关心可写、可枚举和可配置属性时。

对于没有init方法的初始化,可以使用以下Crockford mod

Object.gen = function(o) {
   var makeArgs = arguments 
   function F() {
      var prop, i=1, arg, val
      for(prop in o) {
         if(!o.hasOwnProperty(prop)) continue
         val = o[prop]
         arg = makeArgs[i++]
         if(typeof arg === 'undefined') break
         this[prop] = arg
      }
   }
   F.prototype = o
   return new F()
}

这将使用Object填充userB自己的属性,按照它们定义的顺序。在userB参数之后从左到右生成参数。它使用for(prop in o)循环,因此,根据ECMA标准,属性枚举的顺序不能保证与属性定义的顺序相同。然而,在(4)主要浏览器上测试的几个代码示例显示,如果使用hasOwnProperty过滤器,它们是相同的,有时甚至不使用。

MY_GLOBAL = {i: 1, nextId: function(){return this.i++}};  // For example

var userB = {
   name: null,
   id: null,
   sayHello: function() {
      console.log('Hello '+ this.name);
   }
}

var bob = Object.gen(userB, 'Bob', MY_GLOBAL.nextId());

我想说的是比Object简单一些。因为userB不需要init方法。此外,userB并不是特定的构造函数,但看起来像一个普通的单例对象。因此,使用这个方法,你可以从普通的普通对象构造和初始化。

TL; diana:

new Computer()将调用构造函数Computer(){}一次,而Object.create(Computer.prototype)则不会。

所有的优势都是基于这一点。

关于性能的附加说明:像new Computer()这样的构造函数调用被引擎大量优化,因此它可能比Object.create还要快。

简介:

object. create()是一个Javascript函数,它接受2个参数并返回一个新对象。 第一个参数是一个对象,它将是新创建对象的原型 第二个参数是一个对象,它将是新创建对象的属性

例子:

Const proto = { Talk: () => console.log('hi') } Const props = { 年龄:{ 可写:没错, 可配置:没错, 价值:26 } } let Person = Object。创建(原型、道具) console.log (Person.age); Person.talk ();

实际应用:

The main advantage of creating an object in this manner is that the prototype can be explicitly defined. When using an object literal, or the new keyword you have no control over this (however, you can overwrite them of course). If we want to have a prototype The new keyword invokes a constructor function. With Object.create() there is no need for invoking or even declaring a constructor function. It can Basically be a helpful tool when you want create objects in a very dynamic manner. We can make an object factory function which creates objects with different prototypes depending on the arguments received.

我认为问题的重点是理解new和Object之间的区别。创建方法。根据这个答案和这个视频,new关键字做了下面的事情:

创建新对象。 将新对象链接到构造函数(原型)。 使此变量指向新对象。 使用new对象执行构造函数,隐式执行返回this; 将构造函数函数名赋给新对象的属性构造函数。

对象。Create只执行第1和第2步!

在代码示例中提供的问题,这不是什么大问题,但在下一个例子中,它是:

var onlineUsers = [];
function SiteMember(name) {
    this.name = name;
    onlineUsers.push(name);
}
SiteMember.prototype.getName = function() {
    return this.name;
}
function Guest(name) {
    SiteMember.call(this, name);
}
Guest.prototype = new SiteMember();

var g = new Guest('James');
console.log(onlineUsers);

作为副作用的结果将是:

[ undefined, 'James' ]

因为盖斯特。prototype = new SiteMember(); 但是我们不需要执行父构造函数方法,我们只需要使方法getName在Guest中可用。 因此我们必须使用Object.create。 如果替换Guest。prototype = new SiteMember(); 来的客人。prototype = Object.create(sitember .prototype);结果是:

[ 'James' ]

由于只有一个继承级别,您的示例可能不会让您看到Object.create的真正好处。

该方法允许您轻松实现差异继承,其中对象可以直接从其他对象继承。

在你的userB的例子中,我不认为你的init方法应该是公共的,甚至不存在,如果你在一个现有的对象实例上再次调用这个方法,id和name属性将会改变。

对象。Create允许你使用它的第二个参数初始化对象属性,例如:

var userB = {
  sayHello: function() {
    console.log('Hello '+ this.name);
  }
};

var bob = Object.create(userB, {
  'id' : {
    value: MY_GLOBAL.nextId(),
    enumerable:true // writable:false, configurable(deletable):false by default
  },
  'name': {
    value: 'Bob',
    enumerable: true
  }
});

如您所见,属性可以在Object的第二个参数上初始化。使用类似于object . defineproperties和object . defineproperty方法使用的语法创建一个对象文字。

它允许您设置属性属性(可枚举、可写或可配置),这非常有用。