Object.create 在一些浏览器上还不是标准的,例如 IE8、Opera v11.5、Konq 4.3 都没有。您可以为这些浏览器使用 Douglas Crockford 的 Object.create 版本,但这不包括 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.create 更简单的初始化方法,尤其是在您不关心可写、可枚举和可配置属性的情况下。
对于没有 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()
}
这将按照定义的顺序填充 userB 自己的属性,在 userB 参数之后从左到右使用 Object.gen 参数。它使用 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.build 更简单一些,因为 userB 不需要 init 方法。userB 也不是专门的构造函数,但看起来像一个普通的单例对象。因此,使用这种方法,您可以从普通的普通对象构造和初始化。