中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

js中創建對象的幾種方式

發布時間:2020-08-23 15:41:06 來源:腳本之家 閱讀:150 作者:Claiyre 欄目:web開發

前言

不管是哪門語言,千變萬化不離其宗,深入理解其本質,方能應用自如。對應到js,閉包,原型,函數,對象等是需要花費大功夫思考、理解的。本文穿插了js原型和函數的相關知識,討論了批量創建對象的幾種方式以及它們的優缺點。

正文

說起創建對象,最容易想到的便是通過對象字面量方式直接定義一個對象吧,但這種方式只能創建少量,單獨且相互間無聯系的對象。若要批量創建對象,該如何?

工廠模式

工廠模式非常直觀,將創建對象的過程抽象為一個函數,用函數封裝以特定接口創建對象的細節。如下所示:

function createStudent(name,sex,grade){       
 var o = new Object();
 o.name = name;
 o.sex = sex;
 o.grade = grade;

 o.sayName = function(){
 console.log(this.name);
 }
 return o;
}
var s1 = createStudent('Claiyre','famale',1);

通俗地講,工廠模式就是將創建對象的語句放在一個函數里,通過傳入參數來創建特定對象,最后返回創建的對象。

工廠模式雖然可以創建多個相似的對象,但卻不能解決對象標識的問題,即怎樣知道一個對象的類型。構造函數模式應運而生。

構造函數模式

構造函數模式是java語言創建對象的通用方式。兩種語言用構造函數創建對象的方式略有不同,注意區別。

在JavaScript中沒有類的概念,函數即為一等公民,因此,不必顯式聲明某個類,直接創建構造函數即可,類的方法和屬性在構造函數中(或原型對象上)處理。構造函數模式的示例代碼如下:

function Student(name,sex,grade){       
 this.name = name;
 this.sex = sex;
 this.grade = grade;
 this.sayName = function(){
 console.log(this.name);
 }
}
var s2 = new Student('孫悟空','male',2);

細心的朋友一定發現了構造函數的函數名首字母是大寫的,而普通函數首字母則是小寫,這是眾多OO語言約定俗成的規定,雖然大多數情況下不大寫也不會報錯,但是為了代碼的規范性和可讀性,還是應該將構造函數的首字母大寫,與普通函數區別開。

與工廠模式相比,用構造模式創建對象有以下幾點不同:

  • 沒有顯示地創建對象
  • 直接將屬性和方法賦給this對象
  • 沒有return語句

此外,還應注意到要創建Student的實例,必須要使用new操作符,創建的實例對象將有一個constructor(構造器)屬性,指向Person構造函數。調用構造函數創建對象經過了以下幾個過程:

  • 創建一個新對象
  • 將構造函數的作用域賦給新對象(因此this就指向了這個新對象)
  • 執行構造函數中的代碼
  • 返回新對象(不需要顯式返回)

構造函數雖好用,但也不是沒有缺點。使用構造函數的主要問題是:每個方法都要在每個實例上創建一遍。在ECMAScript中,函數即對象,因此每定義一個函數,也就是實例化了一個對象。下面的例子證明了這個缺點。

var s3 = new Student('唐僧','male',3);
var s4 = new Student('白骨精','female',4);
s3.sayName();
s4.sayName();
console.log(s3.sayName == s4.sayName);

運行結果:

js中創建對象的幾種方式

也就是說通過構造函數實例化的多個對象的方法,是多個不同的方法,但它們內部的代碼以及實現的功能是相同的,這就造成了一定的資源浪費。

幸運的是,這個問題可以用原型模式來解決。

原型模式

js中,每個函數都有一個prototype屬性,它是一個指針,指向一個對象,叫做原型對象,原型對象包含了可以由特定類型的所有實例對象共享的屬性和方法。此外,這個對象有一個與生自來的屬性constructor,指向創建對象的構造方法。

使用原型模式可以讓所有的實例共享原型對象中的屬性和方法,也就是說,不必再構造函數中定義對象實例的信息。用代碼表示如下:

function Student_1(){
}
Student_1.prototype.name = 'Claiyre';
Student_1.prototype.sex = 'female';
Student_1.prototype.class = 5;
Student_1.prototype.sayName = function (){
 console.log(this.name);
}
var s5 = new Student_1();       s5.sayName(); //Claiyre
var s6 = new Student_1();
s6.sayName(); //Claiyre

一張圖勝過千言萬語,下圖清楚地闡釋了各個對象和原型對象間的關系:

js中創建對象的幾種方式

了解過原型后,可以繼續在實例對象上增添屬性或方法:

s6.name = 'John';      
s6.sayName(); //John

當要讀取某個對象的屬性時,都會執行一次搜索,搜索首先從對象實例本身開始,如果在實例中找到了這個屬性,則搜索結束,返回實例屬性的值;若實例上沒有找到,則繼續向對象的原型對象延伸,搜索對象的原型對象,若在原型對象上找到了,則返回原型上相應屬性的值,若沒有找到,則返回undefined。因此,實例對象屬性會覆蓋原型對象上的同名屬性,所以上面第二行代碼輸出的是John。

  • Object.getPrototypeOf(object)方法返回參數對象的原型對象。
  • Object.keys(object)方法返回對象上課枚舉的實例屬性。

原型中的所有屬性都是被所有實例所共享的,這種共享對于函數來說非常合適,對于包含基本值的屬性也說的過去(實例屬性會覆蓋原型同名屬性),但對于那些包含引用類型的屬性,可有大麻煩了

Student_1.prototype.friends = ['aa','bb'];
console.log('s6的朋友' + s6.friends);
s5.friends.push('cc');
console.log('s5的朋友' + s5.friends);
console.log('s6的朋友' + s6.friends);

運行結果:

js中創建對象的幾種方式

問題來了,我們只想改變s5的朋友列表,但由于原型模式的共享本質,s6的朋友列表也隨之改變了。

因此,很少單獨使用原型模式。

組合使用構造函數和原型模式

構造函數模式用于定義實例屬性,原型模式則用于定義方法和共享的屬性。這種混合模式不僅支持向構造函數傳入參數,還最大限度地節約了內存,可謂是集兩模式之長。示例代碼如下:

function Student(name,sex,grade){       
 this.name = name;
 this.sex = sex;
 this.grade = grade;
}
Student.prototype.sayName = function(){
 console.log(this.name);
}
Student.prototype.school = 'Joooh school';

其他模式

除了以上幾種常見的模式外,批量創建對象的方式還有

  • 動態原型模式:僅在第一次調用構造函數時,將方法賦給原型對象的相應屬性,其他示例的處理方式同構造函數模式
  • 寄生構造函數模式:僅僅封裝創建對象的代碼,然后再返回新創建的對象,仍使用new操作符調用
  • 穩妥構造函數模式:沒有公共屬性,只有私有變量和方法,以及一些get/set方法,用以處理私有變量。

結語

每種模式都有各自的優缺點,具體要使用哪種,還需結合實際場景,深入理解,靈活運用。

以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持億速云!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

南丹县| 德昌县| 郴州市| 诏安县| 岳普湖县| 汝州市| 巴塘县| 宜良县| 青海省| 榆社县| 靖州| 张家口市| 棋牌| 江孜县| 无棣县| 东乌珠穆沁旗| 诏安县| 卓尼县| 榆林市| 衡东县| 汾西县| 上思县| 黎城县| 祥云县| 霸州市| 始兴县| 南郑县| 内丘县| 新野县| 剑河县| 泸西县| 津南区| 乌兰浩特市| 酒泉市| 灵丘县| 和硕县| 永宁县| 开平市| 武义县| 东光县| 都匀市|