js的new关键字(面试高频考点)

100 阅读4分钟

new 运算符 --------创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。

new constructor[([arguments])]:
    constructor:一个指定对象实例的类型的类或函数。
    arguments:一个用于被constructor调用的参数列表
//例如:   
function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}
const car1 = new Car('Eagle', 'Talon TSi', 1993);
console.log(car1.make);/  Eagle




new关键字会进行如下的操作:
    1.  创建一个空的简单JS对象(即{});
    2.  为步骤 1 新创建的对象添加属性__proto__,将该属性链接至构造函数的原型对象;
    3.  将步骤 1 新创建的对象作为this的上下文;
    4.  如果该函数没有返回对象,则返回this。
    (关于对象的constructor,参见Object.prototype.constructor)


创建一个用户自定义的对象需要两步:
    1.  通过编写函数来定义对象类型。
    2.  通过new来创建对象实例。


创建一个对象类型,需要创建一个指定其名称和属性的函数;对象的属性可以指向其他对象.
    当代码new Foo(...)执行时,会发生以下事情:
        1.  一个继承自Foo.prototype的新对象被创建。
        2.  使用指定的参数调用构造函数Foo,并将this绑定到新创建的对象。new Foo等同于new Foo(),也就是没有指定参数列表,Foo不带任何参数调用的情况。
        3.  由构造函数返回的对象就是new表达式的结果。如果构造函数没有显式返回一个对象,则使用步骤 1 创建的对象。(一般情况下,构造函数不返回值,但是用户可以选择主动返回对象,来覆盖正常的对象创建步骤)
    你始终可以对已定义的对象添加新的属性。例如,car1.color = "black"语句给car1添加了一个新的属性color,并给这个属性赋值 "black"。
    但是,这不会影响任何其他对象。要将新属性添加到相同类型的所有对象,你必须将该属性添加到Car对象类型的定义中。
    你可以使用Function.prototype属性将共享属性添加到以前定义的对象类型。这定义了一个由该函数创建的所有对象共享的属性,而不仅仅是对象类型的其中一个实例。

    //下面的代码将一个值为null的color属性添加到car类型的所有对象,然后仅在实例对象car1中用字符串 "black" 覆盖该值。详见prototype。
    function Car() {}
    car1 = new Car();
    car2 = new Car();
    console.log(car1.color);    // undefined

    Car.prototype.color = "original color";//将该属性添加到Car对象类型的定义中,将共享给所有对象
    console.log(car1.color);    // original color

    car1.color = 'black';
    console.log(car1.color);   // black

    console.log(car1.__proto__.color) //original color,
    console.log(car2.__proto__.color) //original color,
    console.log(car1.color)  // black
    console.log(car2.color) // original color

   如果你没有使用new运算符,构造函数会像其他的常规函数一样被调用,并不会创建一个对象。在这种情况下,this的指向也是不一样的。

1. 对象类型和对象实例-----对象类型就是函数,对象实例就是new出来的对象

//假设你要创建一个汽车的对象类型,叫做 car,这个类型具备 make, model, year 等属性:
    function Car(make, model, year) {
       this.make = make;
       this.model = model;
       this.year = year;
    }


//现可创建一个mycar的对象,创建了mycar并给他的属性指定值,mycar.make的值为"Eagle",mycar.year的值为1993等
    var mycar = new Car("Eagle", "Talon TSi", 1993);
    
    
//可通过调用 `new` 来创建任意个汽车对象。例如:
    var kenscar = new Car("Nissan", "300ZX", 1992);

2. 对象属性为其他对象

//假设你定义了一个对象叫做person:
function Person(name, age, sex) {
   this.name = name;
   this.age = age;
   this.sex = sex;
}


//然后实例化两个新的person对象如下:
var rand = new Person("Rand McNally", 33, "M");
var ken = new Person("Ken Jones", 39, "M");


//然后你可重写car的定义,添加一个值为person对象的owner属性,如下:
function Car(make, model, year, owner) {
   this.make = make;
   this.model = model;
   this.year = year;
   this.owner = owner;
}


//实例化新的对象,你可以用如下代码:
var car1 = new Car("Eagle", "Talon TSi", 1993, rand);
var car2 = new Car("Nissan", "300ZX", 1992, ken);


//创建对象时,并没有传字符串或数字给owner,而是传了对象rand和ken。这个时候,你可以这样来获取car2的owner的 name:
car2.owner.name