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中的其餘函數,由於構造函數也是函數,只是配用來建立對象;this
(1).建立Person新實例,必須使用new操縱符。這種方式調用構造函數實際上經歷一下4個步驟:
1.建立一個新對象;spa
2.將構造函數的做用域賦給新對象;code
3.執行構造函數中的代碼;對象
4.返回新對象;blog
(2).構造函數都有一個構造函數屬性constructor,該屬性指向該對象所屬的實例,之前面的例子爲準:繼承
alert(person1.constructor == Person);//trueip
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);//?
但此種方式,又會產生新的問題:全局函數只能被某個對象調用,若是對象須要定義不少方法,這就須要定義多個全局函數。如何解決呢?看原型