構造函數(shù)的作用域還有安全這么一說蹈矮。很多人估計都不知道砰逻,下面通過一個例子來說明,什么是作用域不安全的構造函數(shù)泛鸟。
//大眾化的造人函數(shù)
function Person(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
}
var xiaoming = new Person("小明","20","boy"); //造了個小明 這樣做是不會有問題的
var kangkang = Person("康康","21","boy"); //這樣寫就會出問題了 大問題
console.log(this.name); //康康
以上代碼的輸出在部分人看來或許是沒錯啊 構造函數(shù)中把name
的值賦給this
了蝠咆。控制臺輸出的也是之前賦的值北滥。但是刚操,請注意這邊的this
并不是 kangkang
這個新的對象 而是 window
對象 相當于把要給新對象的屬性值 加到了全局對象上了。導致了新建的對象在取屬性值時報錯再芋,而且在全局對象上新增了屬性(方法)造成了污染菊霜。
以上說了那么多,就是想說像上面第二種方法實例化對象的時候济赎,由于沒有new
關鍵字鉴逞,導致操作的this
并不是新的實例而是全局對象记某,從而可能引起頁面的問題。如:別的函數(shù)可能誤用這些變量构捡;造成全局對象過于龐大辙纬,影響訪問速度(因為變量的取值是需要從原型鏈上遍歷的)
以下是處理的辦法
//還是那個造人函數(shù)
function Person(name,age,sex){
if (this instanceof Person){
this.name = name;
this.age = age;
this.sex = sex;
}else{
return new Person(name, age, job);
}
}
var xiaoming = new Person("小明","20","boy"); //造了個小明 這樣做是不會有問題的
var kangkang = Person("康康","21","boy"); //這樣寫就會出問題了 大問題
console.log(this.name); //undefined
如此就能確保不管有沒有 new 關鍵字都能正確的生成我們想要的對象實例。
當然以上修改后一定程度上解決了以上的問題叭喜。但是,若使用了構造函數(shù)竊取模式(個人理解:構造函數(shù)B中用call調用A構造函數(shù) 想使B中的this 帶有A構造函數(shù)中的屬性或方法)的繼承且不使用原型鏈蓖谢,那么就可能會破壞這個繼承捂蕴。
//還是那個造人函數(shù)
function Person(name,age,sex){
if (this instanceof Person){
this.name = name;
this.age = age;
this.sex = sex;
}else{
return new Person(name, age, job);
}
}
function Programmer(skill){
Person.call(this,"xiaoming","20","boy");
this.skill = skill;
}
var xiaoming = new Programmer("java"); //造了個會java的小明
console.log(xiaoming .name); //undefined
相信很多人都找到了問題的關鍵所在。在實例化時由于this
繼承的并不是 Person 所以用 call
調用的時候 返回的對象是新的 Person對象(執(zhí)行else里面的) this也是新的實例的 而不是屬于Programmer構造函數(shù)中的this闪幽,新生成的Programmer實例并沒有得到增長 call 調用后返回的值也沒用到 所以得到的值會是undefined啥辨;
若使用原型鏈就可以解決上面的問題了。
......省略上面的兩個構造函數(shù)
Programmer.prototype = new Person()// ******這里的代碼是關鍵******
//以上代碼會使一個Programmer實例同時也是Person的實例盯腌。this就能通過if判斷
var xiaoming = new Programmer("java"); //造了個會java的小明
console.log(xiaoming .name); //xiaoming
作用域安全的構造函數(shù)在很多看來并沒多少用處溉知,但是為了避免造成一些難以追蹤的問題,特別是在多人協(xié)同編寫功能的情況下腕够,還是推薦使用作用域安全的構造函數(shù)级乍。
2017.03.02