讀古今文學網 > 編寫高質量代碼:改善JavaScript程序的188個建議 > 建議77:推薦作用域安全的構造函數 >

建議77:推薦作用域安全的構造函數

構造函數其實是一個使用new運算符的函數。當使用new調用時,構造函數的內部用到的this對像會指向新創建的實例。


function Person(name,age,job){

this.name=name;

this.age=age;

this.job=job;

}

var person=new Person("Nicholas",34,'software Engineer');


在沒有使用new運算符來調用構造函數的情況下,由於該this對象是在運行時綁定的,因此直接調用Person會將該對像綁定到全局對像window上,這將導致錯誤屬性意外增加到全局作用域上。這是由於this的晚綁定造成的,在這裡this被解析成了window對象。

解決這個問題的方案是創建一個作用域安全的構造函數。首先確認this對象是否為正確的類型實例,如果不是,則創建新的實例並返回。


function Person(name,age,job){

//檢測this對象是否是Person的實例

if(this instanceof Person){

this.name=name;

this.age=age;

this.job=job;

}else{

return new Person(name,age,job);

}

}


如果使用的構造函數獲取繼承且不使用原型鏈,那麼這個繼承可能就被破壞。


function Polygon(sides){

if(this instanceof Polygon){

this.sides=sides;

this.getArea=function{

return 0;

}

}else{

return new Polygon(sides);

}

}

function Rectangle(width,height){

Polygon.call(this,2);

this.width=width;

this.height=height;

this.getArea=function{

return this.width*this.height;

};

}

var rect=new Rectangle(5,10);

alert(rect.sides);//undefined


Rectangle構造函數的作用域是不安全的。在新創建一個Rectangle實例後,這個實例通過Polygon.call繼承了sides屬性,但由於Polygon構造函數的作用域是安全的,this對象並非是Polygon的實例,因此會創建並返回一個新的Polygon對象。

由於Rectangle構造函數中的this對象並沒有得到增長,同時Polygon.call返回的值沒有被用到,所以Rectangle實例中不會有sides屬性。構造函數配合使用原型鏈可以解決這個問題。


function Polygon(sides){

if(this instanceof Polygon){

this.sides=sides;

this.getArea=function{

return 0;

}

}else{

return new Polygon(sides);

}

}

function Rectangle(width,height){

Polygon.call(this,2);

this.width=width;

this.height=height;

this.getArea=function{

return this.width*this.height;

};

}

//使用原型鏈

Rectangle.prototype=new Polygon;

var rect=new Rectangle(5,10);

alert(rect.sides);//2


這時構造函數的作用域就很有用了。