新操作符在JavaScript中是如何工作的?

新操作符在JavaScript中是如何工作的?,javascript,oop,object,new-operator,Javascript,Oop,Object,New Operator,可能是JavaScript中最难理解的部分,站在原型链旁边 所以问题是:如何 new dataObj(args); …实际创建一个对象,并定义其原型链/构造函数等 最好的方法是显示一个替代选项,以完全理解该关键字。表达式newc(arg1,arg2): 假设C是一个JavaScript函数(否则会出现错误): 创建新的空对象(无属性) 将新对象的原型设置为 C的“prototype”属性。 注意:函数的prototype的默认值是一个对象(在声明函数时自动创建),其原型设置为object.

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

所以问题是:如何

new dataObj(args); 
…实际创建一个对象,并定义其原型链/构造函数等

最好的方法是显示一个替代选项,以完全理解该关键字。

表达式
newc(arg1,arg2)

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

  • 创建新的空对象(无属性)
  • 将新对象的原型设置为
    C
    的“
    prototype
    ”属性。
    • 注意:函数的
      prototype
      的默认值是一个对象(在声明函数时自动创建),其原型设置为
      object.prototype
      ,并且
      构造函数
      属性指向函数
      C
    • 注意:术语可能会令人困惑。名为“prototype”的属性与对象的prototype不同。只有函数具有名为“prototype”的属性,但所有对象都具有prototype
  • 调用函数
    C
    ,将“
    this
    ”设置为新对象,并使用提供的参数
  • 如果调用函数
    C
    返回一个对象,则该对象是表达式的结果。否则,新创建的对象就是表达式的结果
  • ECMAScript 5中的
    new
    的替代方法是使用内置的
    Object.createObject
    方法

    新的C(arg1,arg2)
    相当于:

    var obj = Object.createObject(C.prototype);
    C.apply(obj, [arg1, arg2]);
    
    标准JavaScript不允许显式设置对象的原型,因此
    object.createObject
    无法在语言本身中实现。一些实现确实允许它通过非标准属性_uproto_;。在这种情况下,
    新C
    可以如下模拟:

    var obj = {};
    obj.__proto__ = C.prototype;
    C.apply(obj, [arg1, arg2]);
    

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

    • 初始化新的本机对象
    • 设置此对象的内部
      [[Prototype]]
      ,指向函数
      Prototype
      属性。
      • 如果函数的
        prototype
        属性不是对象(原语值,如数字、字符串、布尔值、未定义或Null),则使用
        object.prototype
    • 创建对象后,它调用函数,将对象作为其
      this
      值提供
    • 如果被调用函数的返回值是原语,则返回内部创建的对象
    • 否则,如果返回对象,则内部创建的对象将丢失
    new
    操作符的等效实现可以这样表示(假设ECMAScript 5
    Object.create
    方法可用):


    有点相关:用>var newObj={}替换Object.create(proto)是否安全;newObj.prototype=proto@pico.creator:不,当用作构造函数时,
    prototype
    属性仅对函数对象有意义,并且在我的示例实现
    new
    中使用构造函数时,无论如何都需要使用
    new
    操作符。。。唯一的其他解决方法是使用
    \uuuu proto\uuuu
    属性,但它是非标准的,正在被弃用。请参见,我在其中解释了函数对象的
    prototype
    属性与所有对象构成原型链的内部
    [[prototype]]]
    属性之间的区别。该术语的双重用法肯定令人困惑。然而,答案忽略了对象构造函数的设置;因为从我的实验来看,似乎构造函数被克隆、应用并添加到了结果中。构造函数值。我假设示例中的
    参数
    应该是
    f
    。。还是我遗漏了什么?请注意第2点:任何用户定义函数的
    prototype
    属性的默认值是一个包含
    构造函数
    属性的对象,该属性引用回函数本身,它继承自
    object.prototype
    。此对象在启动时初始化。关于
    Object.create
    ,它可以在ES3上进行部分仿真,设置
    [[Prototype]]]
    属性可以通过临时构造函数完成,但是是的,不可能完全仿真。干杯
    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