新运算符如何在JavaScript中运行?

时间:2011-07-19 16:48:57

标签: javascript oop object new-operator

可能是JavaScript中最不被理解的部分,站在原型链的旁边。

所以问题是:怎么做......

new dataObj(args); 

...实际创建一个对象,并定义其原型链/构造函数/ etc?

最好是展示另一种选择,以完全理解这个关键字。

2 个答案:

答案 0 :(得分:50)

new运算符使用内部[[Construct]]方法,它基本上执行以下操作:

  • 初始化新的原生对象
  • 设置此对象的内部[[Prototype]],指向Function prototype属性。
    • 如果函数的prototype属性不是对象(原始值,例如Number,String,Boolean,Undefined或Null),则使用Object.prototype
  • 创建对象后,它会调用该函数,并将该对象作为其this值。
  • 如果被调用函数的返回值是基元,则返回内部创建的对象。
  • 否则,如果返回一个对象,则内部创建的对象将丢失。

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

答案 1 :(得分:8)

表达式new C(arg1, arg2)

假设C是一个JavaScript函数(否则会出错):

  1. 创建一个新的空对象(无属性)
  2. 将新对象的原型设置为 prototype的“C”属性。
    • 注意:函数的默认值prototype是一个对象(在声明函数时自动创建),其原型设置为Object.prototypeconstructor属性指向函数C
    • 注意:术语可能令人困惑。名为“prototype”的属性与对象的原型相同。只有函数具有名为“prototype”的属性,但所有对象都有一个原型。
  3. 调用函数C,并将'this'设置为新对象,并使用提供的参数。
  4. 如果调用函数C返回一个对象,则该对象是表达式的结果。否则,新创建的对象是表达式的结果。
  5. 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]);