構造函數其實就是一個使用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
的新實例,這就避免了在全局對象上意外設置屬性。