JavaScript中構建偽類子類的幾種錯誤方法

JavaScript中有幾種‘類’的構建模式:對象修飾、函數(shù)、原型绍赛、偽類,都相對比較好理解溃槐,總結構建偽類子類的幾種錯誤方法。

首先科吭,模擬一個場景昏滴,比如汽車,汽車有很多種对人,基于汽車的通用部分谣殊,我們創(chuàng)建父類(也可以叫做基類或者超類,以下都稱父類)Car牺弄,子類BMW姻几,實例mini和bus:

var Car = funciton(loc){
 this.loc = loc;
};
Car.prototype.move = function(){
 this.loc++;
};

var BMW = function(loc){
 //如何構造?下文代碼替換處
};

//調用
var bus = new Car(30);
bus.move();

var mini = new BMW(80);
mini.move();
mini.speedUp();
```


那么势告,該如何構造子類捏蛇捌?

### 不建議:直接重復

替換代碼:

   this.loc = loc;

這會在每一個實例中創(chuàng)建一個loc屬性,并且會指向對應的數(shù)字咱台。雖然可以達到效果络拌,但是有弊端:

1.失去了父類和子類的關系;
2.實際代碼中代碼邏輯要復雜的多回溺,那么需要重復的部分也很多盒音,冗余;
3.一旦需要修改馅而,那么需要修改多處,很容易遺忘&出錯譬圣;

### 錯誤:僅調用Car函數(shù)

替換代碼:

   new Car(loc);

除了在調用的時候創(chuàng)建的對象外(bus)瓮恭,這行代碼將會產(chǎn)生一個新的對象。

換一個角度厘熟,在BMW用new調用Car函數(shù)時屯蹦,Car函數(shù)中的this指向的是Car的一個全新的對象维哈。

帶關鍵字new運行任何函數(shù)的作用是在函數(shù)體中’隱藏的’添加了兩行代碼:

在第一行添加了:this = Object.create(Car.prototype);將this等同于一個全新的對象(規(guī)則上不允許在代碼中直接對this賦值,但在解釋器中可以運行)登澜;

在最后一行添加了:return this;

在這里阔挠,首先我們用new函數(shù)調用了BMW,已經(jīng)有一行’隱藏的‘:this = Object.create(BMW.prototype);這樣就有了兩個新對象脑蠕,然而我們不需要第二個购撼。

那么試著賦值給關鍵字this能否解決?

### 錯誤:給this賦值

替換代碼:

   this = new Car(loc);

規(guī)則錯誤谴仙,上面說過了~~在代碼里不能直接給this關鍵字賦值迂求。即使能,也依舊不能解決有兩個不同的對象的問題晃跺,有一個是不需要的揩局;

那么如果直接調用捏?

   Car(loc);

依舊不行~~

在調用的時候掀虎,Car中的this會指向global,也就是說凌盯,Car函數(shù)將會在全局作用域的上下文環(huán)境中運行(Car函數(shù)被作為一個自由函數(shù)調用,實際上將會綁定一個指向數(shù)字80的全局變量loc)烹玉,mini實例將完全不會被Car函數(shù)里的代碼影響驰怎;

### 推薦:使用call

替換代碼:

   Car.call(this,loc);

調用Car函數(shù),并且把參數(shù)綁定到mini上春霍,這樣只會創(chuàng)造一個實例砸西,并且使BMW在創(chuàng)建實例mini的時候調用了Car的構造器~~

### 原型鏈的處理

使用call雖然完成了子類的構造,但是此時可以發(fā)現(xiàn)址儒,mini.move()無法運行芹枷,這是因為mini是BMW的實例,原型鏈是委托在BMW.prototype上的莲趣,而BMW.prototype上并沒有定義move函數(shù)鸳慈,move函數(shù)是定義在car.prototype上的。(注:BMW.prototype是委托在Object.prototype上的)

因此喧伞,需要將BMW的原型委托到Car的原型上,同時不要忘了constructor~~

在代碼中添加:

   BMW.prototype = Object.create(Car.prototype);
   BMW.prototype.constructor = BMW; //否則實例的constructor會指向Car


這里有一個最常見的錯誤走芋,就是嘗試實例化父類構造器,作為委托給它原型的方法:
```javascript
var Car = function(loc){
 this.loc = loc;
};
Car.prototype.move = function(){
 this.loc++;
};

var BMW = function(){
 Car.call(this,loc);
};
BMW.prototype = new Car();
```
這幾乎和Object.create方法實現(xiàn)了相同的效果潘鲫,但是唯一的區(qū)別是它在創(chuàng)建這個新對象的時候運行了Car函數(shù)翁逞,這點不太好~~

Object.create并不是一個很新的語言特性。

常見做法規(guī)定設置BMW.prototype等于一個新的Car實例溉仑,但是這樣會引起很多問題挖函,每次我們構造一個類似BMW的子類或者其他Car的子類,都會調用Car這個函數(shù)作為整個過程的一部分浊竟,父類構造函數(shù)在執(zhí)行時也許要求一些參數(shù)(比如loc)怨喘,但是沒有任何方式傳遞他們津畸,因為新的Car的原型并沒有實際意義上的位置屬性,唯一擁有有意義的位置屬性的實物是Car或者BMW的實例必怜,所有的BMW在抽象概念上沒有一個有意義的位置肉拓,因此在這里傳遞loc輸入變量是沒什么用的,這個函數(shù)運行的時候會把他的所有輸入綁定為undefined梳庆。

如果代碼行需要處理這些輸入暖途,比如這個點訪問:

```javascript
var Car = function(loc){
 this.loc = loc.valueOf();
}
```

那么loc是undefined,所以undefined.valueOf()將會導致一個錯誤……

構造一個足夠強健的構造器去避免這種錯誤是非常難的靠益,實際工作中的代碼邏輯也很復雜丧肴,著實沒必要,用Object.create就行~

最后完整的代碼:
```javascript
var Car = funciton(loc){
 this.loc = loc;
};
Car.prototype.move = function(){
 this.loc++;
};

var BMW = function(loc){
 Car.call(this,loc);
};
BMW.prototype = Object.create(Car.prototype);
BMW.prototype.constructor = BMW; 

//調用
var bus = new Car(30);
bus.move();

var mini = new BMW(80);
mini.move();
mini.speedUp();
```

就醬~
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末胧后,一起剝皮案震驚了整個濱河市芋浮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌壳快,老刑警劉巖纸巷,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異眶痰,居然都是意外死亡瘤旨,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門竖伯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來存哲,“玉大人,你說我怎么就攤上這事七婴∷钔担” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵打厘,是天一觀的道長修肠。 經(jīng)常有香客問我,道長户盯,這世上最難降的妖魔是什么嵌施? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮莽鸭,結果婚禮上吗伤,老公的妹妹穿的比我還像新娘。我一直安慰自己硫眨,他們只是感情好足淆,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般缸浦。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上氮兵,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天裂逐,我揣著相機與錄音,去河邊找鬼泣栈。 笑死卜高,一個胖子當著我的面吹牛,可吹牛的內容都是我干的南片。 我是一名探鬼主播掺涛,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼疼进!你這毒婦竟也來了薪缆?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤伞广,失蹤者是張志新(化名)和其女友劉穎拣帽,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嚼锄,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡减拭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了区丑。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拧粪。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖沧侥,靈堂內的尸體忽然破棺而出可霎,到底是詐尸還是另有隱情,我是刑警寧澤正什,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布啥纸,位于F島的核電站,受9級特大地震影響婴氮,放射性物質發(fā)生泄漏斯棒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一主经、第九天 我趴在偏房一處隱蔽的房頂上張望荣暮。 院中可真熱鬧,春花似錦罩驻、人聲如沸穗酥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽砾跃。三九已至骏啰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間抽高,已是汗流浹背判耕。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留翘骂,地道東北人壁熄。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像碳竟,于是被迫代替她去往敵國和親草丧。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內容