如何确保你的构造函数只能被new调用,而不能被普通函数调用?
js中的函数一般有两种形式 new Fun()、fun(); 但是js内部并没有作区分;
- 所以人为规定构造函数名首字母要大写作为区分;
- 可以利用instanceof检测某个对象是不是另外一个对象的实例 new Person() instanceof Person --> true
- 使用new调用函数和普通调用函数的最大区别是在于函数内部的this指向不同;new调用后this指向实例、普通调用则会指向window
function Person(){
console.log(this)
}
console.log( new Person() instanceof Person) //true
Person() //window
const p = new Person() //Person{}
第一种方法:instanceof 判断
function Person(){
if(!(this instanceof Person)){
throw new TypeError('普通函数调用')
}else{
console.log('new调用')
}
}
Person() // Uncaught TypeError: 普通函数调用
new Person() // new调用
//此方法有点瑕疵,可以通过call、apply改变this指向骗过以上if判断
Person.call(new Person())
第二种方法:new.target ES6中引入的属性,如果构造函数不是通过 new
命令或 Reflect.construct()
调用的,new.target
会返回 undefined
function Person(){
if(!(new.target)){
throw new TypeError('普通函数调用')
}else{
console.log('new调用')
}
}
Person() // Uncaught TypeError: 普通函数调用
new Person() // new调用
第三种方法:class、类的构造器必须使用new调用
class Person{
constructor(name){
this.name = name
}
}
//Person()//test.html:15 Uncaught TypeError: Class constructor Person cannot be invoked without 'new'
const person = new Person('zhangsan')
console.log(person.name)//zhangsan