new
2023年06月15日
一、认识
二、语法
三、属性
3.1 new.target
ES6
为new
命令引入了一个new.target
属性,该属性一般用在构造函数之中,返回new
命令作用于的那个构造函数。如果构造函数不是通过new
命令或Reflect.construct()
调用的,new.target
会返回undefined
,因此这个属性可以用来确定构造函数是怎么调用的。注意,在函数外部,使用new.target
会报错。
语法
-
类: 类 内部调用
new.target
, 返回当前类 ; 子类继承父类时,父类内部调用new.target
, 返回子类class Point {
constructor() {
console.log(new.target);
}
}
const point = new Point(); // [class Point]class Point {
constructor() {
console.log(new.target);
}
}
class ThreePoint extends Point {
constructor() {
super();
console.log(new.target);
}
}
const point = new Point(); // [class Point]
const threePoint = new ThreePoint(); // [class ThreePoint extends Point] // [class ThreePoint extends Point] -
构造函数: 如果构造函数不是通过
new
命令或Reflect.construct()
调用的,new.target
会返回undefined
function Point(name) {
console.log(new.target);
}
Point(); // undefined
const point = new Point(); // Point
四、场景
4.1 必须继承
方法一、通过 new.target
class Point {
constructor() {
if (new.target === Point) {
throw new Error('本类不能实例化');
}
}
}
class ThreePoint extends Point {
constructor() {
super();
}
}
// const point = new Point();
const threePoint = new ThreePoint();
4.2 必须 new
方法一、通过 instanceof
function Point() {
if (!(this instanceof Point)) {
console.log('必须通过 new 调用');
return;
}
console.log('new 调用之后');
}
Point(); // 必须通过 new 调用
const point = new Point(); // new 调用之后
方法二、通过 new.target
function Point() {
if (new.target !== Point) {
console.log('必须通过 new 调用');
return;
}
console.log('new 调用之后');
}
Point(); // 必须通过 new 调用
const point = new Point(); // new 调用之后
五、原理 Polyfill
-
创建一个空的简单JavaScript对象(即)
-
为新创建的对象添加属性
__proto__
,将该属性链接至构造函数的原型对象prototype
-
将构造函数内部
this
绑定到新创建的对象 , 执行构造函数 -
如果构造函数没有显式返回一个对象,则返回新创建的对象。(一般情况下,构造函数不返回值,但是用户可以选择主动返回对象,来覆盖正常的对象创建步骤)
function myNew(constructor, ...argArray) {
const newObj = {};
Object.setPrototypeOf(newObj, constructor.prototype);
const result = constructor.call(newObj, ...argArray);
if (
(typeof result === "object" && result !== null) ||
typeof result === "function"
) {
return result;
} else {
return newObj;
}
}
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.getName = function () {
return this.name;
};
const person = myNew(Person, "柏拉图", 23);
console.log(person);
console.log(person.getName());