Javascript建構函式簡析
建構函式
根據調研,在使用new操作符通過建構函式執行個體化一個對象時,經過了以下過程:
建立一個Null 物件。
將這個Null 物件的__proto__成員指向了建構函式對象的prototype成員對象。
將建構函式的範圍賦給新對象,因此建構函式中的this指向新對象,然後再在該物件內容中調用建構函式。
返回新建立對象。注意:在JavaScript標準中,並沒有__prop__這個屬性,不過它現在已經是一些主流的JavaScript執行環境預設的一個標準屬性,用於指向建構函式的原型。該屬性是預設不可見的,而且在各執行環境中實現的細節不盡相同,例如IE瀏覽器中不存在該屬性。我們只要知道Javascript對象內部存在指向建構函式原型的指標就可以了,這個指標是在調用new運算式的時候自動賦值的,並且我們不應該去修改它。
function Person(msg){
//特權屬性(公有屬性)
this.myMsg = msg; //只在被執行個體化後的執行個體中可調用
this.address = '大連';
//私人屬性
var name = 'Sumer';
var age = 21;
var that = this;
//私人方法
function getName(){
alert(that.name);
}
//公有方法,能被外部公開訪問,這個方法每次執行個體化都要重新構造而prototype是原型共用,所有執行個體化後,都共同引用同一個
this.getAge = function(){
alert(age); //在公有方法中可以訪問私人成員
}
//私人和公有成員在函數的內部,在建構函式建立的每個執行個體中都會包含同樣的私人和公有成員的副本,因而執行個體越多佔用的記憶體越多
//而且私人成員僅僅是在對象建立時,由建構函式在物件內容下運行,不具有該對象的直接引用。
}
注意:由於JS函數的範圍特性,這些私人成員,被所有在建構函式中定義的公有方法所共用,而且僅被在建構函式中定義的公有方法所共用。這意味著,在prototype中定義的類成員將不能訪問在構造體中定義的私人成員。成員)。
//公有方法,適用於通過new關鍵字執行個體化的該對象的每個執行個體,向prototype中新增成員將會把新方法添加到建構函式的底層中去
Person.prototype.sayHello = function(){
alert('hello world!');
}
//靜態屬性
//適用於對象的特殊執行個體,就是作為Function對象執行個體的建構函式本身
Person.name = 'china';
//靜態方法
Person.alertname = function(){
alert(this.name);
}
//執行個體化
var m1 = new Person('me');
//---- 測試屬性 ----//
//console.log(Person.name); //china
//console.log(m1.name); //undefined, 靜態屬性不適用於一般執行個體
//console.log(m1.constructor.name); //china, 想訪問類的靜態屬性,先訪問該執行個體的建構函式,然後在訪問該類靜態屬性
//console.log(Person.address); //undefined, Person中的this指的不是函數本身,而是調用address的對象,而且只能是對象
//console.log(m1.address); //大連 此時this指的是執行個體化後的m1
//---- 測試方法 ----//
//Person.alertname(); //china,直接調用函數的類方法
//m1.alertname(); //FF: m1.alertname is not a function, alertname 是Person類的方法,和執行個體對象沒有直接關係
//m1.constructor.alertname(); //china, 調用該物件建構函數(類函數)的方法(函數)
//m1.sayHello(); //hello everyone, myObject類的prototype原型下的方法將會被執行個體繼承
//Person.sayHello(); //Person.sayHello is not a function,sayHello是原型方法,不是類的方法
//---- 測試prototype ----//
//console.log(m1.prototype); //undefined, 執行個體對象沒有prototype
//console.log(Person.prototype); //Object
//alert(Person.prototype.constructor); //console.log返回Person(msg),此時alert()更清楚,相當於Person
//console.log(Person.prototype.constructor.name); //china, 相當於Person.name;
由此分析可以清楚的瞭解到,使用私人成員,是以犧牲代碼可讀性為代價的。而且這種實現更多的是一種JavaScript技巧,因為它並不是語言本身具有的機制。不應該過多的應用在JS的模型構建中。公有成員的使用,更能提高我們代碼的可讀性,使我們構建的模型更加清晰。