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: '测试'}