this instanceof xx
在 JS
中一个实例对象的创建必须使用 new
操作符。但是限于 JS
的语法特征, 实际上 构造函数
同样可以像普通函数那样直接执行,这就使用了 函数作为构造函数的意义,为了避免这种情况的发生,很多 JS
库使用下面的这种方式:
function Person () {
if(!this instanceof Person){
console.warn('should be called with the new !')
}
}
为了了解这种方式的原理,我们先要理解当我们使用 new
时做了些什么。
当时用 new
操作符的时候,实际上会经历以下 4 个步骤:
- 创建一个新的对象。
- 将构造函数的作用域赋值给这个新对象。(this 指向该对象)。
- 执行构造函数中的代码。
- 返回新对象。
在执行了这四个步骤后,除了将作用域赋值给了新的对象,还将 够构造函数的 prototype
赋值给了 实例的 __proto__
,最终:
let person1 = new Person()
person1.__proto__ === Person.prototype //true
person instanceof Person // true
a instanceof A 用来检测 用来检测a 是否是 A 的实例
class new.target 属性
在 ES6
中,我们可以使用 class
关键词创建一个 类,每一个 class
类都有一个 new.target
属性,返回 new 命令所作用的构造函数。如果构造函数不是通过 new
操作符调用的, 那么 new.target
会返回 undefined
, 因此这个属性同样可以确保 构造函数必须是通过 new
调用的。
function Person () {
if(new.target !== Person){
console.warn('should be called with the new !')
}
}
class Person {
constructor(){
if(new.target !== Person){
throw new Error('should be called with the new !')
}
}
}