新操作员如何在JavaScript中工作?
可能是JavaScript最不理解的部分,站在原型链的旁边。
所以问题是:如何…
new dataObj(args);
…实际上创build一个对象,并定义其原型链/构造/ etc?
最好是展示一个替代scheme,充分理解这个关键字。
new
操作符使用内部[[Construct]]
方法,它基本上执行以下操作:
- 初始化一个新的本地对象
- 设置此对象的内部
[[Prototype]]
,指向Functionprototype
属性。- 如果函数的
prototype
属性不是一个对象(一个原始值,如数字,string,布尔值,未定义或空值),则使用Object.prototype
。
- 如果函数的
- 创build对象后,它调用该函数,提供该对象作为其值。
- 如果被调用函数的返回值是一个原语,则返回内部创build的对象。
- 否则,如果返回一个对象,则内部创build的对象将丢失。
new
运算符的等效实现可以像这样表示(假定ECMAScript 5 Object.create
方法可用):
function NEW(f) { var obj, ret, proto; // Check if `f.prototype` is an object, not a primitive proto = Object(f.prototype) === f.prototype ? f.prototype : Object.prototype; // Create an object that inherits from `proto` obj = Object.create(proto); // Apply the function setting `obj` as the `this` value ret = f.apply(obj, Array.prototype.slice.call(arguments, 1)); if (Object(ret) === ret) { // the result is an object? return ret; } return obj; } // Example usage: function Foo (arg) { this.prop = arg; } Foo.prototype.inherited = 'baz'; var obj = NEW(Foo, 'bar'); obj.prop; // 'bar' obj.inherited; // 'baz' obj instanceof Foo // true
expression式new C(arg1, arg2)
:
假设C是一个JavaScript函数(否则你会得到一个错误):
- 创build一个新的空对象(没有属性)
- 将新对象的原型设置为
C
的“prototype
”属性的值。- 注意:函数
prototype
的默认值是一个对象(声明函数时自动创build),其原型设置为Object.prototype
而constructor
属性指向函数C
- 注意:术语可能会令人困惑。 名为“prototype”的属性与对象的原型不一样。 只有函数具有名为“prototype”的属性,但所有对象都有一个原型。
- 注意:函数
- 使用设置为新对象的“
this
”和提供的参数调用函数C
- 如果调用函数
C
返回一个对象,则该对象是expression式的结果。 否则,新创build的对象是expression式的结果。
ECMAScript 5中new
的替代方法是使用内置的Object.createObject
方法。
new C(arg1, arg2)
将相当于:
var obj = Object.createObject(C.prototype); C.apply(obj, [arg1, arg2]);
标准的JavaScript不允许你明确地设置一个对象的原型,所以Object.createObject
不能用语言本身来实现。 有些实现允许通过非标准的属性__proto__。 在这种情况下,可以像这样模拟new C
:
var obj = {}; obj.__proto__ = C.prototype; C.apply(obj, [arg1, arg2]);