ECMAScript中的構造函數可以用來創造特定類型的對象,Object和Array 是原生構造函數,在 運行時會自動出現在執行環境。也可以自定義構造函數,示例如下:
function Person(name,age,job){ this.name = name; this.age = age; this.job = job; this.sayName = function(){ alert(this.name); }; } var person1 = new Person("wsc",25,"software Engineer"); var person2 = new Person("yl",26,"Doctor");
注意:按照慣例,構造函數始終都應該以一個大寫字母開頭,而非構造函數則應該以一個小寫字母開頭,目的是區別ECMAScript中的其他函數,因為構造函數也是函數,只是配用來創建對象;
(1).創建Person新實例,必須使用new操縱符。這種方式調用構造函數實際上經歷一下4個步驟:
1.創建一個新對象;
2.將構造函數的作用域賦給新對象;
3.執行構造函數中的代碼;
4.返回新對象;
(2).構造函數都有一個構造函數屬性constructor,該屬性指向該對象所屬的實例,以前面的例子為准:
alert(person1.constructor == Person);//true
1.對象的constructor屬性主要目的是用來標識對象類型;
2.檢測對象類型主要是用instanceof,示例如下:
alert(person1 instanceof Object);//true 注意:所有的對象均繼承Object
alert(person1 instanceof Person);//true
3.創建自定義構造函數意味着將來可以將它的實力標識為一種特定的類型,這是構造模式勝過工廠模式的地方,
注意:以這種方式的構造函數是定義在Global對象中的;
(3).構造函數與其他函數的唯一區別是調用方式的不同:任何函數只要通過new操作符來調用,那么它就作為構造函數;任何函數如果不通過new操作符來調用,那么它就作為普通函數;
// 當作構造函數 var person = new Person("wsc",26,"Software Engineer"); person.sayName();//"wsc"; //普通函數 Person("wsc",26,"Software Engineer");//添加到window window.sayName()//"wsc" //在另一個對象的作用域中調用 var o = new Object(); Person.call(o,"wsc",26,"Software Engineer"); o.sayName();//"wsc"
(4).構造函數的問題
構造函數的主要問題是:每個方法都要在每個實例上重新創建一遍。
以上面的例子為例:從邏輯上,此時的構造函數還可以如下定義。
function Person(name,age,job){ this.name = name; this.age = age; this.job = job; this.sayName = new Function("alert(this.name)");//與聲明函數在邏輯上是等價的 } //在這里ECMAscript中的函數也是對象;
此種方式創建函數,會導致不同的作用域鏈和標識符解析,但在創建Function新實例的機制仍然是相同的。因此不同實例上同名的函數是不等的。
解決此問題的方式如下:
function Person(name,age,job){ this.name = name; this.age = age; this.job = job; this.sayName = sayName; } function sayName(){ alert(this.name); } var person1 = new Person("wsc",29,"software engineer"); var person2 = new Person("wife",26,"techer"); alert(person1.sayName === person2.sayName);//?
但此種方式,又會產生新的問題:全局函數只能被某個對象調用,如果對象需要定義很多方法,這就需要定義多個全局函數。如何解決呢?看原型