JavaScript中的新关键字在第一次遇到时可能会非常令人困惑,因为人们倾向于认为JavaScript不是一种面向对象的编程语言。

这是怎么一回事?它解决了什么问题?什么时候合适,什么时候不合适?


当前回答

摘要:

new关键字在JavaScript中用于从构造函数创建对象。new关键字必须放置在构造函数调用之前,并将执行以下操作:

创建新对象将此对象的原型设置为构造函数的原型属性将this关键字绑定到新创建的对象并执行构造函数返回新创建的对象

例子:

功能狗(年龄){this.age=年龄;}const doggie=新狗(12);console.log(doggie);console.log(Object.getPrototypeOf(doggie)==Dog.prototype)//true

具体情况:

const doggie说:我们需要内存来声明变量。赋值运算符=表示:我们将使用=表达式是new Dog(12)。JavaScript引擎看到新关键字,创建一个新对象,并将原型设置为Dog.prototype执行构造函数时,将此值设置为新对象。在此步骤中,将年龄指定给新创建的小狗对象。新创建的对象被返回并分配给变量doggie。

其他回答

它做5件事:

它将创建一个新对象。此对象的类型只是对象。它将此新对象的内部、不可访问的[[prototype]](即__proto__)属性设置为构造函数的外部、可访问的原型对象(每个函数对象都自动具有原型属性)。它使该变量指向新创建的对象。每当提到这一点时,它都会使用新创建的对象来执行构造函数。它返回新创建的对象,除非构造函数返回非空对象引用。在这种情况下,将返回该对象引用。

注意:构造函数是指new关键字之后的函数,如

new ConstructorFunction(arg1, arg2)

完成此操作后,如果请求了新对象的未定义属性,脚本将检查对象的[[prototype]]对象的属性。这就是如何在JavaScript中获得类似于传统类继承的东西。

这方面最困难的部分是第2点。每个对象(包括函数)都有一个名为[[prototype]]的内部属性。只能在对象创建时使用new、object.create或基于文本(函数默认为Function.prototype,数字默认为Number.prototype等)设置它。只能使用object.getPrototypeOf(someObject)读取它。没有其他方法设置或读取此值。

除了隐藏的[[prototype]]属性外,函数还有一个名为prototype的属性,您可以通过它访问和修改,为所创建的对象提供继承的财产和方法。


下面是一个示例:

ObjMaker = function() {this.a = 'first';};
// ObjMaker is just a function, there's nothing special about it that makes 
// it a constructor.

ObjMaker.prototype.b = 'second';
// like all functions, ObjMaker has an accessible prototype property that 
// we can alter. I just added a property called 'b' to it. Like 
// all objects, ObjMaker also has an inaccessible [[prototype]] property
// that we can't do anything with

obj1 = new ObjMaker();
// 3 things just happened.
// A new, empty object was created called obj1.  At first obj1 was the same
// as {}. The [[prototype]] property of obj1 was then set to the current
// object value of the ObjMaker.prototype (if ObjMaker.prototype is later
// assigned a new object value, obj1's [[prototype]] will not change, but you
// can alter the properties of ObjMaker.prototype to add to both the
// prototype and [[prototype]]). The ObjMaker function was executed, with
// obj1 in place of this... so obj1.a was set to 'first'.

obj1.a;
// returns 'first'
obj1.b;
// obj1 doesn't have a property called 'b', so JavaScript checks 
// its [[prototype]]. Its [[prototype]] is the same as ObjMaker.prototype
// ObjMaker.prototype has a property called 'b' with value 'second'
// returns 'second'

这类似于类继承,因为现在,使用新的ObjMaker()创建的任何对象都似乎继承了“b”属性。

如果你想要一个类似子类的东西,那么你可以这样做:

SubObjMaker = function () {};
SubObjMaker.prototype = new ObjMaker(); // note: this pattern is deprecated!
// Because we used 'new', the [[prototype]] property of SubObjMaker.prototype
// is now set to the object value of ObjMaker.prototype.
// The modern way to do this is with Object.create(), which was added in ECMAScript 5:
// SubObjMaker.prototype = Object.create(ObjMaker.prototype);

SubObjMaker.prototype.c = 'third';  
obj2 = new SubObjMaker();
// [[prototype]] property of obj2 is now set to SubObjMaker.prototype
// Remember that the [[prototype]] property of SubObjMaker.prototype
// is ObjMaker.prototype. So now obj2 has a prototype chain!
// obj2 ---> SubObjMaker.prototype ---> ObjMaker.prototype

obj2.c;
// returns 'third', from SubObjMaker.prototype

obj2.b;
// returns 'second', from ObjMaker.prototype

obj2.a;
// returns 'first', from SubObjMaker.prototype, because SubObjMaker.prototype 
// was created with the ObjMaker function, which assigned a for us

在最后找到这一页之前,我读了大量关于这一主题的垃圾,在那里用漂亮的图表很好地解释了这一点。

除了丹尼尔·霍华德的回答之外,以下是new的作用(或者至少看起来是这样):

function New(func) {
    var res = {};
    if (func.prototype !== null) {
        res.__proto__ = func.prototype;
    }
    var ret = func.apply(res, Array.prototype.slice.call(arguments, 1));
    if ((typeof ret === "object" || typeof ret === "function") && ret !== null) {
        return ret;
    }
    return res;
}

虽然

var obj = New(A, 1, 2);

相当于

var obj = new A(1, 2);

假设您有此函数:

var Foo = function(){
  this.A = 1;
  this.B = 2;
};

如果将其作为独立函数调用,如下所示:

Foo();

执行此函数将向窗口对象(A和B)添加两个财产。它将其添加到窗口中,因为当您这样执行函数时,window是调用函数的对象,而函数中的this是调用该函数的对象。至少在JavaScript中。

现在,用新的:

var bar = new Foo();

当您向函数调用添加新对象时,将创建一个新对象(仅var bar=new object()),并且函数中的this指向您刚刚创建的新对象,而不是调用函数的对象。所以bar现在是一个具有财产A和B的对象。任何函数都可以是构造函数;这并不总是有意义的。

它有三个阶段:

1.创建:它创建一个新对象,并将此对象的[[prototype]]属性设置为构造函数的prototype属性。

2.执行:它指向新创建的对象并执行构造函数。

3.返回:在正常情况下,它将返回新创建的对象。但是,如果显式返回非空对象或函数,则会返回此值。需要提及的是,如果返回非空值,但它不是对象(例如Symbol value、undefined、NaN),则忽略该值并返回新创建的对象。

function myNew(constructor, ...args) {
  const obj = {}
  Object.setPrototypeOf(obj, constructor.prototype)
  
  const returnedVal = constructor.apply(obj, args)
  
  if (
    typeof returnedVal === 'function' 
    || (typeof returnedVal === 'object' && returnedVal !== null)) {
      return returnedVal
  }
  return obj
}

有关myNew的更多信息和测试,请阅读我的博客:https://medium.com/@magenta2127/how-does-the-new-operator-work-f7eaac692026

JavaScript不是面向对象编程(OOP)语言。因此,JavaScript中的查找过程使用委托过程,也称为原型委托或原型继承。

如果您试图从一个没有的对象中获取属性的值,JavaScript引擎会查找该对象的原型(以及它的原型,一步一步)。它是原型链,直到链结束为null,即Object.prototype==null(标准对象原型)。

此时,如果未定义属性或方法,则返回undefined。

重要的函数是一类对象。

函数=函数+对象组合框

FunctionName.prototype={共享子对象}

{
  // other properties
  prototype: {
   // shared space which automatically gets [[prototype]] linkage
      when "new" keyword is used on creating instance of "Constructor
      Function"
  }
}

因此,使用新关键字。,

手动创建对象,例如newObj。使用JavaScript规范[[prototype]](即proto)中的proto(AKA:dunderproto)创建隐藏键引用并将财产分配给newObj返回newObj对象。

所有操作都是手动完成的。

function CreateObj(value1, value2) {
  const newObj = {};
  newObj.property1 = value1;
  newObj.property2 = value2;
  return newObj;
}
var obj = CreateObj(10,20);

obj.__proto__ === Object.prototype;              // true
Object.getPrototypeOf(obj) === Object.prototype // true

JavaScript关键字new有助于自动化此过程:

创建了一个新的对象文本,其标识如下:{}引用并为此分配财产隐藏键创建[[prototype]](即proto)到Function.prototype共享空间。此对象{}的隐式返回

function CreateObj(value1, value2) {
  this.property1 = value1;
  this.property2 = value2;
}

var obj = new CreateObj(10,20);
obj.__proto__ === CreateObj.prototype             // true
Object.getPrototypeOf(obj) == CreateObj.prototype // true

调用不带new关键字的构造函数:

=>此:窗口

function CreateObj(value1, value2) {
  var isWindowObj = this === window;
  console.log("Is Pointing to Window Object", isWindowObj);
  this.property1 = value1;
  this.property2 = value2;
}
var obj = new CreateObj(10,20); // Is Pointing to Window Object false
var obj = CreateObj(10,20); // Is Pointing to Window Object true
window.property1; // 10
window.property2; // 20