构造函数其实就是一个使用new 操作符调用的函数。当使用new 调用时,构造函数内用到的this 对象会指向新创建的对象实例,如下面的例子所示:
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
console.log(this)
}
var person = new Person("Nicholas", 29, "Software Engineer");
上面这个例子中,Person
构造函数使用this
对象给三个属性赋值:name
、age
和job
。当和new
操作符连用时,则会创建一个新的Person
对象,同时会给它分配这些属性。
问题出在当没有使用new
操作符来调用该构造函数的情况上。由于该this
对象是在运行时绑定的,所以直接调用Person()
,this
会映射到全局对象window
上,导致错误对象属性的意外增加。例如:
根据打印日志可以发现,此时this指向的是window,因为构造函数是作为普通函数调用的,所以原本针对Person 实例的三个属性被加到window 对象上。在这里this
被解析成了window
对象。这个问题的解决方法就是创建一个作用域安全的构造函数。
解决思路:
作用域安全的构造函数在进行任何更改前,首先确认this 对象是正确类型的实例。如果不是,那么会创建新的实例并返回:
function Person(name, age, job){
if (this instanceof Person){
this.name = name;
this.age = age;
this.job = job;
console.log('this 指向: ',this)
} else {
return new Person(name, age, job);
}
}
这样,调用Person
构造函数时无论是否使用new
操作符,都会返回一个Person
的新实例,这就避免了在全局对象上意外设置属性。