如何寫乙個作用域安全的建構函式

2021-09-28 18:54:47 字數 2246 閱讀 9205

建構函式本質上就是乙個使用new操作符呼叫的函式,使用new呼叫時,建構函式內用到的this物件會指向新建立的物件例項:

function girlfriend(name, age, height) 

// 使用new操作符來分配這些屬性

var girlfriend = new girlfriend("ying", 23, 170);

平時寫變數時,如果因為失誤忘記使用new操作符時,會造成乙個糟糕的影響————因為this物件是在執行時繫結的,直接呼叫建構函式,this會對映到全域性物件window上,導致錯誤物件屬性的增加,增添不必要的變數到全域性物件中:

var girlfriend = new girlfriend("ying", 23, 170);

console.log(window.name); // "ying"

console.log(window.age); // 23

console.log(window.height); // 170

特別的,當你自己建構函式內的某些變數名與window變數名重名時(像一些常用變數名name、length等),對這些屬性的偶然覆蓋就很可能導致其他地方出錯,並且這個bug還相當難找!

在這種情況下構造乙個作用域安全的建構函式就顯得很有必要:

function girlfriend(name, age, height)  else 

}var girlfriend1 = girlfriend("ying", 23, 170); // "new" "created"

console.log(window.name); // ""

console.log(girfriend1.name); // "ying"

var girlfriend2 = new girlfriend("lin", 22, 165); // "created"

console.log(girfriend1.name); // "lin"

girlfriend1背後建構函式先new了乙個例項並返回例項(列印「new」),再對例項進行賦值(列印「created」)。

girlfriend2自己就先new了乙個例項,直接對該例項進行賦值(只列印「created」)。

這樣在任何情況下就都可以返回乙個安全作用域的例項了。

使用上面新增乙個檢查的方法可以建立乙個作用域安全的建構函式,但如果有的函式竊取該函式的繼承且沒有使用原型鏈,那這個繼承將被破壞不生效:

function bmi(***, weight=1, height=1) ;

} else

}function people(height, weight)

var guy = new people(1.75, 68); // 單位是m和kg

console.log(guy.***) // undefined

bmi建構函式作用域是安全的,但people並不是。新建立乙個people例項後,這個例項準備通過bmi.call()來繼承bmi的***屬性,但由於bmi的作用域是安全的,this物件並非是bmi的例項,所以bmi會先自己建立乙個新的bmi物件,不會把新的bmi物件的值傳遞到people中去。

這樣people中的this物件並沒有得到增長,同時bmi.call()返回的值也沒有用到,所以people例項中就不會有***、weight、height屬性和getbmi()函式。

解決辦法:建構函式結合使用原型鏈或寄生組合:

function bmi(***, weight=1, height=1) ;

} else

}function people(height, weight)

people.prototype = new bmi(); // 重點

var guy = new people(1.75, 68);

console.log(guy.***) // "male"

這樣寫的話,乙個people的例項同時也是乙個bmi的例項,所以bmi.call()才會去執行,為people例項新增上屬性和函式。

當多個人一同構建乙個專案時,作用域構安全函式就非常必要,對全域性物件意外的更改可能就會導致一些常常難以追蹤的錯誤,這和平常設定空變數和空函式一樣避免因為其他人可能發生的錯誤而阻塞程式執行。

更多專業前端知識,請上

【猿2048】www.mk2048.com

作用域安全的建構函式

一般建構函式定義和呼叫如下 function person name,age,job var person new person thinksley 24,web developer console.log person.name thinksley 而如果例項化物件的時候不用new的話,this會...

作用域安全的建構函式

眾所周知,建構函式一般用new去呼叫,比如 function person name,age var xiaoming new person xiaoming 21 因為使用new 呼叫建構函式,所有建構函式內部使用的this會指向新建立的物件的例項,但是,如果沒有用new去呼叫建構函式,情況會怎麼...

如何寫乙個Stack?

1.棧是陣列 2.先進後出 3.出棧 4.入棧 手寫乙個雙向鍊錶 棧 public class stackpopandpush public stackpopandpush int lens 返回元素個數 public intsize 返回陣列長度,容量,棧資料長 private intcapaci...