Using "Object.create" instead of "new"

Javascript 1.9.3 / ECMAScript 5 introduces , which Douglas Crockford amongst others has been advocating for a long time. How do I replace in the code below with ?Object.createnewObject.create

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

(Assume exists).MY_GLOBAL.nextId

The best I can come up with is:

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

There doesn't seem to be any advantage, so I think I'm not getting it. I'm probably being too neo-classical. How should I use to create user 'bob'?Object.create


答案 1

With only one level of inheritance, your example may not let you see the real benefits of Object.create.

This methods allows you to easily implement differential inheritance, where objects can directly inherit from other objects.

On your example, I don't think that your method should be public or even exist, if you call again this method on an existing object instance, the and properties will change.userBinitidname

Object.create lets you initialize object properties using its second argument, e.g.:

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

As you can see, the properties can be initialized on the second argument of , with an object literal using a syntax similar to the used by the and methods.Object.createObject.definePropertiesObject.defineProperty

It lets you set the property attributes (, , or ), which can be really useful.enumerablewritableconfigurable


答案 2

There is really no advantage in using over .Object.create(...)new object

Those advocating this method generally state rather ambiguous advantages: "scalability", or "more natural to JavaScript" etc.

However, I have yet to see a concrete example that shows that has any advantages over using . On the contrary there are known problems with it. Sam Elsamman describes what happens when there are nested objects and Object.create(...) is used:Object.createnew

var Animal = {
    traits: {},
}
var lion = Object.create(Animal);
lion.traits.legs = 4;
var bird = Object.create(Animal);
bird.traits.legs = 2;
alert(lion.traits.legs) // shows 2!!!

This occurs because advocates a practice where data is used to create new objects; here the datum becomes part of the prototype of and , and causes problems as it is shared. When using new the prototypal inheritance is explicit:Object.create(...)Animallionbird

function Animal() {
    this.traits = {};
}

function Lion() { }
Lion.prototype = new Animal();
function Bird() { }
Bird.prototype = new Animal();

var lion = new Lion();
lion.traits.legs = 4;
var bird = new Bird();
bird.traits.legs = 2;
alert(lion.traits.legs) // now shows 4

Regarding, the optional property attributes that are passed into , these can be added using Object.defineProperties(...).Object.create(...)