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”?


当前回答

由于只有一个继承级别,您的示例可能不会让您看到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方法使用的语法创建一个对象文字。

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

其他回答

虽然Douglas Crockford曾经是Object.create()的狂热拥护者,而且基本上是他导致了这个构造实际上是在javascript中,但他不再有这种观点了。

他不再使用Object。创造,因为他完全停止使用这个关键字,因为它会带来太多麻烦。例如,如果不小心,它很容易指向全局对象,这可能会产生非常糟糕的后果。他声称不使用这个物体。创造已经没有意义了。

你可以看看2014年他在Nordic.js演讲的视频:

https://www.youtube.com/watch?v=PSGEjv3Tqo0

Object的另一种可能用法。Create是用一种廉价而有效的方式克隆不可变对象。

var anObj = {
    a: "test",
    b: "jest"
};

var bObj = Object.create(anObj);

bObj.b = "gone"; // replace an existing (by masking prototype)
bObj.c = "brand"; // add a new to demonstrate it is actually a new obj

// now bObj is {a: test, b: gone, c: brand}

Notes: The above snippet creates a clone of an source object (aka not a reference, as in cObj = aObj). It benefits over the copy-properties method (see 1), in that it does not copy object member properties. Rather it creates another -destination- object with it's prototype set on the source object. Moreover when properties are modified on the dest object, they are created "on the fly", masking the prototype's (src's) properties.This constitutes a fast an effective way of cloning immutable objects.

这里需要注意的是,这适用于创建后不应该修改的源对象(不可变)。如果源对象在创建后被修改,克隆的所有未屏蔽属性也将被修改。

这里(http://jsfiddle.net/y5b5q/1/)(需要对象。创建功能强大的浏览器)。

简介:

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创建对象,但仍然可以调用create方法。

例如:如果你想定义一个自定义元素,它必须派生自HTMLElement。

proto = new HTMLElement  //fail :(
proto = Object.create( HTMLElement.prototype )  //OK :)
document.registerElement( "custom-element", { prototype: proto } )

对象。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并不是特定的构造函数,但看起来像一个普通的单例对象。因此,使用这个方法,你可以从普通的普通对象构造和初始化。