new 运算符在 JavaScript 中是如何工作的?

Posted

技术标签:

【中文标题】new 运算符在 JavaScript 中是如何工作的?【英文标题】:How does the new operator work in JavaScript? 【发布时间】:2011-10-08 17:11:36 【问题描述】:

可能是 javascript 中最不被理解的部分,位于原型链旁边。

所以问题是:如何...

new dataObj(args); 

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

最好是显示一个替代方案,以完全理解这个关键字。

【问题讨论】:

相关类:***.com/questions/1646698/… 【参考方案1】:

new 运算符使用内部的[[Construct]] 方法,它基本上做了以下工作:

初始化一个新的原生对象 设置该对象的内部[[Prototype]],指向函数prototype属性。 如果函数的prototype 属性不是对象(原始值,例如数字、字符串、布尔值、未定义或空值),则使用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

【讨论】:

用 > var newObj = ; 替换 Object.create(proto) 是否安全? newObj.prototype = 原型; ? @pico.creator: 不,prototype 属性仅对 Function 对象有意义,当用作构造函数时,并且在我的 new 示例实现中使用构造函数时,需要使用new 运算符无论如何...唯一的其他方法是使用 __proto__ 属性,但它是非标准的,并且已被弃用。请参阅this answer,其中我解释了函数对象的prototype 属性与所有对象都具有形成原型链的内部[[Prototype]] 属性之间的区别。 这个词的双重用法确实令人困惑。但是答案忽略了对象构造函数的设置;由于我的实验,似乎构造函数被克隆、应用并添加到结果 .constructor 值中。 我假设示例中的 arguments 应该是 f.. 还是我遗漏了什么?【参考方案2】:

表达式new C(arg1, arg2)

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

    创建一个新的空对象(无属性) 将新对象的原型设置为 C 的“prototype”属性。 注意:函数的默认值prototype 是一个对象(在声明函数时自动创建),其原型设置为Object.prototypeconstructor 属性指向函数C。 注意:术语可能会造成混淆。名为“prototype”的属性与对象的原型相同。只有函数具有名为“原型”的属性,但所有对象都有原型。 调用函数C,并将“this”设置为新对象,并使用提供的参数。 如果调用函数C返回一个对象,这个对象就是表达式的结果。否则,新创建的对象就是表达式的结果。

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]);

【讨论】:

注意点#2:任何用户定义函数的prototype属性的默认值是一个包含constructor属性的对象,它引用了函数本身,并且它继承自Object.prototype。该对象在function objects are created 时初始化。关于Object.create,它可以在ES3 上部分模拟,设置[[Prototype]] 属性可以通过临时构造函数完成,但是是的,不可能完全模拟see more。干杯。

以上是关于new 运算符在 JavaScript 中是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 -1**2 在 JavaScript 中是语法错误?

javascript中new关键字详解

JavaScript24_旧类与new运算符

new运算符详解(JavaScript)

软工第一次作业

&在Java中是啥意思?