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


当前回答

新的操作符

用于从构造函数创建对象 新的关键字还执行构造函数

function Car() {
  console.log(this) // this points to myCar
  this.name = "Honda";
}

var myCar = new Car()
console.log(myCar) // Car {name: "Honda", constructor: Object}
console.log(myCar.name) // Honda
console.log(myCar instanceof Car) // true
console.log(myCar.constructor) // function Car() {}
console.log(myCar.constructor === Car) // true
console.log(typeof myCar) // object

Object.create

你也可以使用Object。Create创建一个新对象 但是,它不执行构造函数 对象。Create用于从另一个对象创建一个对象

const Car = {
  name: "Honda"
}

var myCar = Object.create(Car)
console.log(myCar) // Object {}
console.log(myCar.name) // Honda
console.log(myCar instanceof Car) // ERROR
console.log(myCar.constructor) // Anonymous function object
console.log(myCar.constructor === Car) // false
console.log(typeof myCar) // 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并不是特定的构造函数,但看起来像一个普通的单例对象。因此,使用这个方法,你可以从普通的普通对象构造和初始化。

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

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

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

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()函数。它解决了Crockfords的问题,也调用了init函数。

这是可行的:

var userBPrototype = {
    init: function(nameParam) {
        this.name = nameParam;
    },
    sayHello: function() {
        console.log('Hello '+ this.name);
    }
};


function UserB(name) {
    function F() {};
    F.prototype = userBPrototype;
    var f = new F;
    f.init(name);
    return f;
}

var bob = UserB('bob');
bob.sayHello();

这里UserB类似于Object。创造,但要适应我们的需要。

如果你愿意,也可以拨打:

var bob = new UserB('bob');

TL; diana:

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

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

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