IT培訓(xùn)網(wǎng)
IT在線學(xué)習(xí)
面向?qū)ο蟮恼Z言有一個(gè)標(biāo)志,那就是它們都有類的概念,而通過類可 以創(chuàng)建任意多個(gè)具有相同屬性和方法的對(duì)象。前面提到過,ECMAScript 中沒有類的概念,因此它的對(duì)象也與基于類的語言中的對(duì)象有所不同。
ECMA把對(duì)象定義為:“無序?qū)傩缘募希鋵傩钥梢园局、?duì)象或者函數(shù)。對(duì)象的每個(gè)屬性或方法都有一個(gè)名字,而每個(gè)名字都映射到一個(gè)值。
我們之前在學(xué)習(xí)創(chuàng)建對(duì)象時(shí),使用字面量方式和Object構(gòu)造函數(shù)的方式都可以進(jìn)行創(chuàng)建對(duì)象,但是我們也發(fā)現(xiàn)了這兩種方式只適合用來創(chuàng)建單個(gè)對(duì)象,想要?jiǎng)?chuàng)建大量對(duì)象時(shí),一份代碼就要書寫多次,顯然的產(chǎn)生了代碼冗余。接下來來介紹幾種其他創(chuàng)建對(duì)象的方式。
工廠模式創(chuàng)建對(duì)象:
上面我們說使用Object構(gòu)造函數(shù)的方式進(jìn)行創(chuàng)建多個(gè)對(duì)象時(shí),會(huì)產(chǎn)生大量重復(fù)代碼,那自然而然我們就會(huì)想到將重復(fù)性的代碼封裝成為一個(gè)函數(shù),這個(gè)函數(shù)就是工廠函數(shù)。
- // 工廠模式實(shí)際上就是封裝函數(shù)
- function createStar(name, age, sex){
- // 1.創(chuàng)建一個(gè)空對(duì)象(原材料)
- var obj = {};
- // 2.添加屬性和方法(加工)
- obj.name = name;
- obj.age = age;
- obj.sex = sex;
- obj.skill = function(){
- console.log('sing dance');
- }
- // 3.返回出對(duì)象(出廠)
- return obj
- }
- // 創(chuàng)建對(duì)象
- var star1 = createStar('何美男',25,'boy');
- console.log(star1);
- star1.skill(); // sing dance
使用工廠模式創(chuàng)建對(duì)象雖然可以實(shí)現(xiàn)批量創(chuàng)建對(duì)象,但是卻出現(xiàn)了新的問題,即創(chuàng)建出的對(duì)象指向不明確。使用instanceof操作符檢測(cè)對(duì)象類型時(shí),都是屬于object。
- var star2 = createStar('大黃', 3, 'boy');
- console.log(star2);
- star2.skill();
- console.log(typeof star1, typeof star2); // object object
- console.log(star2 instanceof Object); // true
構(gòu)造函數(shù)創(chuàng)建對(duì)象:
構(gòu)造函數(shù)實(shí)際上就是一個(gè)函數(shù),只是這個(gè)函數(shù)是專門用來創(chuàng)建對(duì)象的,他的特點(diǎn):
1.構(gòu)造函數(shù)首字母大寫,為了區(qū)分普通函數(shù);
2.不需要?jiǎng)?chuàng)建對(duì)象,屬性和方法直接添加在this上,不需要return返回
3.構(gòu)造函數(shù)調(diào)用時(shí),一定要使用new;
- // 1.聲明構(gòu)造函數(shù)
- function Teacher(name, age, sex){
- // 添加屬性
- this.name = name;
- this.age = age;
- this.sex = sex;
- // 添加方法
- this.skill = function(){
- console.log('布置作業(yè)');
- }
- }
- // 2.實(shí)例化對(duì)象
- var t1 = new Teacher('小王',20,'girl');
- console.log(t1);
- t1.skill(); // 布置作業(yè)
- var t2 = new Teacher('小李', 25, 'boy');
- console.log(t2);
- t2.skill(); // 布置作業(yè)
我們需要明確 new操作符做了什么?
1.隱式的創(chuàng)建了一個(gè)對(duì)象;
2.讓this指向這個(gè)空對(duì)象;
3.讓實(shí)例對(duì)象的__ proto __指向構(gòu)造函數(shù)的prototype;
4.執(zhí)行代碼,給this添加屬性和方法;
5.隱式的返回創(chuàng)建好的對(duì)象;
所以在使用構(gòu)造函數(shù)創(chuàng)建對(duì)象時(shí)一定要使用new操作符。
使用構(gòu)造函數(shù)創(chuàng)建對(duì)象解決了創(chuàng)建出的對(duì)象指向不明確,構(gòu)造函數(shù)的主要問題就是每個(gè)方法都要在每個(gè)實(shí)例上重新創(chuàng)建一遍。在前面的例子中,t1 和 person2 都有一個(gè)名為 skill()的方法,但那兩個(gè)方法不是同一個(gè) Function 的實(shí)例。創(chuàng)建兩個(gè)完成同樣任務(wù)的 Function 實(shí)例的確沒有必要,我們可以通過代碼證實(shí):
- console.log(t1.skill() == t2.skill()); // false-比較的是地址
原型創(chuàng)建對(duì)象:
我們創(chuàng)建的每個(gè)函數(shù)都有一個(gè) prototype(原型)屬性,這個(gè)屬性是一個(gè)指針,指向一個(gè)對(duì)象, 而這個(gè)對(duì)象的用途是包含可以由特定類型的所有實(shí)例共享的屬性和方法。使用原型對(duì)象的好處是可以 讓所有對(duì)象實(shí)例共享它所包含的屬性和方法。換句話說,不必在構(gòu)造函數(shù)中定義對(duì)象實(shí)例的信息,而是 可以將這些信息直接添加到原型對(duì)象中,如下面的例子所示。
- function Stu(){}
- // 2.添加屬性和方法
- Stu.prototype.name = '小明';
- Stu.prototype.age = 18;
- Stu.prototype.skill = function(){
- console.log('沉迷敲代碼');
- }
- // 3.實(shí)例化對(duì)象
- var s1 = new Stu();
發(fā)現(xiàn)對(duì)象里邊是空的,打開可以看到所有的屬性和方法都在__proto__原型屬性上
理解原型對(duì)象
無論什么時(shí)候,只要?jiǎng)?chuàng)建了一個(gè)新函數(shù),就會(huì)根據(jù)一組特定的規(guī)則為該函數(shù)創(chuàng)建一個(gè)prototype 屬性,這個(gè)屬性指向函數(shù)的原型對(duì)象。在默認(rèn)情況下,所有原型對(duì)象都會(huì)自動(dòng)獲得一個(gè) constructor (構(gòu)造函數(shù))屬性,這個(gè)屬性包含一個(gè)指向 prototype 屬性所在函數(shù)的指針。
創(chuàng)建了自定義的構(gòu)造函數(shù)之后,其原型對(duì)象默認(rèn)只會(huì)取得 constructor 屬性;當(dāng)調(diào)用構(gòu)造函數(shù)創(chuàng)建一個(gè)新實(shí)例后,該實(shí)例的內(nèi)部將包含一個(gè)指針(內(nèi)部 屬性),指向構(gòu)造函數(shù)的原型對(duì)象。__proto__這個(gè)連接存在于實(shí)例與構(gòu)造函數(shù)的原型對(duì)象之間,而不是存在于實(shí)例與構(gòu)造函數(shù)之間。
針對(duì)上述原型模式創(chuàng)建對(duì)象的代碼,我們可以畫出它的圖例關(guān)系:
更多內(nèi)容
>>本文地址:http://www.yceu.cn/zhuanye/2021/69434.html
聲明:本站稿件版權(quán)均屬中公教育優(yōu)就業(yè)所有,未經(jīng)許可不得擅自轉(zhuǎn)載。
1 您的年齡
2 您的學(xué)歷
3 您更想做哪個(gè)方向的工作?