前面咱們介紹了能夠經過Object構造函數或對象字面量均可以用來建立單個對象,可是若是須要建立多個對象的話,顯然不少冗餘代碼。javascript
接下來介紹幾種模式來建立對象。不過在此以前,咱們仍是先來了解下 typeof和instanceof 。html
//typeof主要用了檢查值類型數據,如: alert(typeof (1) + " " + typeof ("1") + " " + typeof (false) + " " + typeof (undefined)); //instanceof主要用了檢查對象,如: var arr = new Array(); alert((arr instanceof Object) + " " + (arr instanceof Array) + " " + (arr instanceof Number));//既是Object也是array,但不是Number
例:java
面試
下面咱們接着介紹數種建立對象的方式。瀏覽器
function createPerson(name) { var o = new Object(); o.name = name; o.sayName = function () { alert(this.name); }; return o; } var obj = createPerson("張三"); var obj2 = createPerson("李四"); alert(obj instanceof Object); alert(obj instanceof createPerson)
由上可知,工廠模式簡單、思路清晰、容易理解,也能夠建立對象,不過有個缺點不能肯定對象類型。由於它老是一個object類型,而不能斷定是createPerson類型。函數
例1:學習
this
var obj = { name: "李四" }; function Person(name) { this.name = name; this.sayName = function () { alert(this.name); }; } var per = new Person("張三"); per.sayName();//張三 var per2 = new Person("李四"); alert(per.sayName==per2.sayName);//false
其實,構造函數模式咱們在上篇博文就簡單介紹過了。一樣,構造函數模式也不完美,由於每一個實例化出來的對象所擁有的方法都是獨立的,而一個對象類型的方法徹底是能夠同享引用來節省內存空間。spa
例2:.net
由例2能夠看出,第二次彈出消息爲false,證實了每一個實例對象中的方法都是獨立的。 第三次彈出消息爲true,與上面的工廠模式不一樣,這裏經過構造函數建立的方法,能夠直接判斷對象類型了。
咱們說實例對象的方法應該是共享的,那麼咱們能夠用接下來的模式實現。
1.0在使用原型模式以前,咱們首先須要瞭解什麼是原型。個人理解就是,原始對象類型的模型。每一個對象都有一個屬性(prototype)指向對象的原型。
function Person() { this.sayHi1 = function () { } } Person.prototype.sayHi2 = function () { }; var per1 = new Person(); var per2 = new Person(); alert(per1.sayHi1 === per2.sayHi1);//每一個實例化出來的對象所獨有的,因此爲false alert(per1.sayHi2 === per2.sayHi2);//由於是同一個引用,因此爲true //咱們再次證實了構造函數中的屬性(或是方法、對象)是實例化對象獨有的,原型中的屬性(或是方法、對象)是共享的。
第一個比較是對象的屬性,因此每一個實例對象擁有獨立的方法,而第二個比較是原型方法,就算是實例對象,它們直接也是引用共享的。
例3:
咱們看到了 per1.sayHi2 === per2.sayHi2 比較是true。(===是全等的意思,不只比較值,還比較類型。)
咱們看到了 __proto__ 指向的就是咱們所謂的原型(只有Firefox、 Safari 和 Chrome瀏覽器有此屬性)。還有一個 constructor 指向咱們的構造函數。
1.1 __proto__ 和原型 prototype 的關係(其實__proto__並非一個js語言中規定的對象屬性,只是某些瀏覽器實現了)
function Person() { this.name1 = "張三", this.sayHi1 = function () { } } Person.prototype.sayHi2 = function () { }; var per1 = new Person(); var per2 = new Person(); alert(per1.constructor);//constructor指向了構造函數 alert(per1.constructor.prototype);//constructor.prototype 指向了構造函數的原型 alert(per1.constructor.prototype === per1.__proto__);//true 由此看出__proto__和原型的關係。(指向了構造函數的原型)
例:
1.2若是原型中的屬性和構造函數中的屬性重名,會優先訪問構造函數中的屬性
function Person(name) { this.name1 = name; }; Person.prototype.name1 = "test1"; Person.prototype.name2 = "test2"; var per1 = new Person("name1"); alert(per1.name1);//訪問到的是實例對象中的name1屬性「name1」 delete per1.name1;//刪除實例對象中的name1屬性 alert(per1.name1);//訪問類型原型中的name1屬性「test1」 alert(per1.name2);//訪問原型屬性「name2」 per1.name2 = "name2";//這裏並非修改了原型屬性「name2」的值,而是爲實例對象動態添加了一個「name2」的屬性,並賦值。 alert(per1.name2);//訪問實例屬性「name2」 delete per1.name2; alert(per1.name2);//訪問原型屬性「name2」
例:
如圖:
1.3使用字面量表示法爲原型統一添加方法和屬性
咱們上面看到定義原型的屬性和方法都是一個個定義的,看上去明顯感受雜亂。其實咱們也能夠經過字面量的方式爲原型添加屬性或方法,如:
function Person() { } Person.prototype = { name1: "張三", age: 23, sayHi: function () { alert(this.name1); } } var per1 = new Person(); per1.name1 = "李四" per1.sayHi()
缺點:這樣的定義,至關與重寫了對象類型的prototype屬性,也就是咱們再也訪問不到 constructor 屬性了。
固然,我也能夠手動設置,如:
function Person() { } Person.prototype = { constructor: Person,//手動設置constructor賦值Person name1: "張三", age: 23, sayHi: function () { alert(this.name1); } } var per1 = new Person(); per1.name1 = "李四" per1.sayHi()
咱們經過在構造函數中定義屬性,在原型中經過字面量表示法定義方法已經能夠很好的建立對象了。惟一的缺點就是分爲兩個步驟,那麼咱們下面試着所有封裝到構造函數中。如:
function Person(str1, str2, str3) { this.name1 = str1; this.name2 = str2; this.age = str3; //方法 if (typeof this.sayName != "function") {//只用判斷一個就能夠了,第一次構造的時候是不能有sayName方法的。 //在構造函數裏面貌似不能經過字面量來爲prototype統一賦值 Person.prototype.sayName = function () { alert(this.name1); }; Person.prototype.sayHi = function () { alert(this.name2); }; } } var per1 = new Person("張三","李四","12"); per1.sayName();
咱們平時經常使用的一些建立對象的方式就介紹到這裏了。
下一篇繼續分析對象的繼承,歡迎你們繼續關注。
這是學習記錄,不是教程。文中錯誤不免,您能夠指出錯誤,但請不要言辭刻薄。
原文連接:http://haojima.net/zhaopei/516.html
本文已同步至目錄索引:一步步學習javascript
歡迎上海「程序猿/媛」、"攻城獅"入羣:【滬猿】229082941 入羣須知
歡迎對我的博客感興趣的道友加入羣:【嗨-博客】469075305 入羣須知
若是您以爲文章對您有那麼一點點幫助,那麼麻煩您輕輕的點個贊,以資鼓勵。