new

37 阅读2分钟

new 有啥用

  • 返回一个对象
  • 对象的原型链 proto 指向的是构造函数的 prototype
  • 对象会绑定到函数调用的 this

使用 new 调用函数时,该函数将被用作构造函数, 执行以下操作

1、创建一个空的简单 JavaScript 对象。方便起见,称之为 newInstance(实例) 2、如果构造函数的 prototype 属性是一个 对象Object,则将 newInstance 的 [[prototype]] 指向构造函数的 prototype 属性(也就是 newInstance 的 [[prototype]] 指向 对象 Object),否则 newInstance 将保持为一个普通对象,其[[prototype]] 为 Object.prototype

备注:因此,通过构造函数创建的所有实例,都可以访问添加到构造函数 prototype 属性中的属性/对象

// 定义一个函数
function Test() {}

// 通过 new 操作符调用,Test 被叫做构造函数
const test = new Test();
console.log("new:", test);

// 构造函数 Test的prototype 是对象Object
console.log("Test prototype:", Test.prototype);

3、使用给定参数执行构造函数,并将 newInstance 绑定为 this 的上下文(也就是,在构造函数中,所有 this 引用都指向 newInstance ) 4、如果构造函数返回 非原始值,则该返回值称为整个 new 表达式的结构。否则,如果构造函数未返回任何值或返回了一个原始值,则返回 newInstance。(通常构造函数不返回值,但可以选择返回值,以覆盖正常的对象创建过程)

function Car() {
  console.log("Car this", this); // 构造函数自己
}

car1 = new Car();
car2 = new Car();

console.log("car1:", car1); // 构造函数 Car 的实例化,赋值给 car1
console.log("car2:", car2); // 构造函数 Car 的实例化,赋值给 car2

console.log(car1.color1); // undefined

Car.prototype.color1 = "red"; // 给构造函数原型上增加属性 color1
console.log(car1.color1); // "red"

car1.color1 = "black"; // 给 实例car1 上添加属性 color1
console.log(car1.color1); // "black"

console.log(Object.getPrototypeOf(car1)); // {color1: 'red'}
console.log(Object.getPrototypeOf(car2)); // {color1: 'red'}

console.log(car1.color1); // 'black'
console.log(car2.color1); // 'red'

console.log(new Car()); // [[Prototype]]: Object{ color1: "red" }
console.log(car1); // { color1: 'black', [[prototype]]: { color1: "red"} }
console.log(car2); // {}

备注:虽然构造函数可以像任何常规函数一样被调用(既不使用 new 运算符),但这种情况下并不会创建一个新的对象,this 的值也不一样

写一个自己的 new

function lnew(Constructor, ...args) {
  let obj = {};
  Object.setPrototypeOf(obj, Object.prototype);
  // 也可以写成
  // let obj = Object.create(Object.prototype)
  console.log("Constructor:", Constructor);
  // 改变构造函数this指向
  Constructor.call(obj, ...args);
  return obj;
}

function testNew(name) {
  console.log("testNew:", name);
  this.name = name;
  console.log("this:", this);
}
const test = new lnew(testNew, "测试");
console.log(1, test); // {name: '测试'}