淺談JavaScript對(duì)象與繼承
來源:易賢網(wǎng) 閱讀:650 次 日期:2016-07-29 14:03:20
溫馨提示:易賢網(wǎng)小編為您整理了“淺談JavaScript對(duì)象與繼承”,方便廣大網(wǎng)友查閱!

JavaScript是我在C語言之后接觸的第二門編程語言,大一暑假的時(shí)候在圖書館找了一本中國人寫的JavaScript程序設(shè)計(jì)來看。那個(gè)時(shí)候在編程方面幾乎還是小白,再加上那本書根本沒有提JavaScript的編程機(jī)制,又有一些誤導(dǎo)性的話,一直以來對(duì)JavaScript有很深的誤解,認(rèn)為JavaScript只是一門在瀏覽器上運(yùn)行的面向?qū)ο笳Z言,值此文來寫下JavaScript當(dāng)中很具有迷惑性和容易誤解的地方。當(dāng)然限于作者水平有限,也沒有什么開發(fā)經(jīng)驗(yàn),所以難免有疏漏之處,還望批評(píng)指正。

JavaScript的對(duì)象

對(duì)象是什么

JavaScript代碼當(dāng)中隨處可見new關(guān)鍵字,很容易讓人產(chǎn)生誤解,認(rèn)為JavaScript是Java一樣是基于類繼承的語言。但是事實(shí)并非如此,JavaScript當(dāng)中并沒有類,那JavaScript的對(duì)象不是類那又是什么呢?某種意義上說,JavaScript的對(duì)象就是Python當(dāng)中的字典(哈希表),其實(shí)也就是類似這樣的鍵值對(duì):

me={

  "fisrtName" : "seek",

  "lastName" : "truth" ,

  "getName" : function(){

    return this.firstName+this.lastName; //this相當(dāng)于指向這個(gè)對(duì)象的指針

  }

}

這是一個(gè)比較有誤解性的地方,初次看到時(shí)候覺得有點(diǎn)無法理解,但仔細(xì)用一用還是覺得合理,我們既可以像Python一樣用[]運(yùn)算符來獲取元素,也可以用.操作符來獲取元素:

me.firstName // => seek

me["lastName"] //=> truth

me.getName() // => seektruth

new運(yùn)算符

既然JavaScript當(dāng)中是沒有類的,那么new運(yùn)算符又是在干什么呢?這是JavaScript設(shè)計(jì)的最讓人誤解的地方之一。JavaScript是一門函數(shù)式編程語言,JavaScript當(dāng)中函數(shù)是一等公民,JavaScript當(dāng)中函數(shù)也是對(duì)象,函數(shù)對(duì)象在被創(chuàng)建的時(shí)候會(huì)被添加調(diào)用屬性,比較坑的是JavaScript函數(shù)有兩種調(diào)用方式,一種是加了new關(guān)鍵字的調(diào)用,一種是沒有new關(guān)鍵字的調(diào)用,前者會(huì)返回一個(gè)對(duì)象,后者會(huì)返回return語句當(dāng)中的內(nèi)容??紤]下面的一段函數(shù):

function Obj(name){

  this.name=name;

  return name;

}

如果我們用new運(yùn)算符來調(diào)用:

obj = new Obj("seektruth") //obj會(huì)是一個(gè)對(duì)象:{"name": "seektruth"}

如果我們直接調(diào)用:

obj = Obj("seektruth") //obj會(huì)是一個(gè)字符串:"seektruth"

確實(shí)設(shè)計(jì)的挺坑的,我們?cè)谡{(diào)用的時(shí)候需要分清楚是否需要使用new,一般來說需要用new關(guān)鍵字來調(diào)用的函數(shù)會(huì)采用大寫開頭。

還有更坑的是如果返回的返回值是一個(gè)對(duì)象:

function Obj(name){

  this.name=name;

  return {};

}

這樣無論我們是否用new運(yùn)算符來調(diào)用都會(huì)返回return語句里的值:

new Obj("seektruth") //=> {}

Obj("seektruth") //=> {}

設(shè)計(jì)的是什么鬼......

對(duì)象繼承

原型

前面已經(jīng)說到過JavaScript當(dāng)中是沒有類的,那JavaScript又是怎么來實(shí)現(xiàn)繼承的呢?答案是通過原型鏈。在JavaScript當(dāng)中,每個(gè)對(duì)象都會(huì)有一個(gè)原型,在創(chuàng)建對(duì)象的時(shí)候,如果不加說明的話,對(duì)象繼承的原型是Object.prototype,函數(shù)對(duì)象會(huì)繼承Function.prototype(Function.prototype繼承Object.prototype):

Object.prototype // => {}

Function.prototype // => [Function]

我們可以通過對(duì)象的__proto__熟悉來查看對(duì)象的原型:

a={}

a.__proto__ // => {}

JavaScript通過指定對(duì)象的原型來實(shí)現(xiàn)繼承,指定對(duì)象的原型主要有三種方式,一是在構(gòu)造函數(shù)當(dāng)中指明原型,二是直接修改對(duì)象的__proto__屬性,三是利用Object.create函數(shù),下面我們依次來看一看

在構(gòu)造函數(shù)當(dāng)中指定原型

我們可以在構(gòu)造函數(shù)當(dāng)中指定對(duì)象的原型:

me={

  "firstName" : "seek",

  "lastName" : "truth" ,

  "getName" : function(){

    return this.firstName+this.lastName; //this相當(dāng)于指向這個(gè)對(duì)象的指針

  }

}

function Obj(name){

  this.firstName = name;

  this.__proto__ = me; //指定原型為me對(duì)象

}

指定了原型之后,我們新建了對(duì)象之后就可以訪問原型的屬性:

obj = new Obj("foo"); // => { firstName: 'foo' }

obj.firstName // => foo

obj.lastName // => truth

obj.getName() // => "footruth"

當(dāng)訪問一個(gè)對(duì)象的時(shí)候,首先會(huì)嘗試在改對(duì)象當(dāng)中尋找該屬性,如果沒有就回到原型當(dāng)中尋找,直到Object.prototype。如果我們?cè)谛碌膶?duì)象當(dāng)中重寫了原型當(dāng)中的屬性(方法),那么實(shí)際使用的時(shí)候我們新寫的屬性(方法)會(huì)覆蓋掉原型當(dāng)中的定義,這有點(diǎn)像基于類的語言的函數(shù)重載。

注意如果原型me對(duì)象的lastname屬性有改變,因?yàn)閛bj對(duì)象是在原型當(dāng)中尋找屬性,那么這個(gè)obj對(duì)象的lastname屬性也會(huì)改變:

me.lastName = "me"

obj.lastName // => "me"

obj.getName() // => "foome"

直接改變對(duì)象的原型

我們也可以直接指定(改變)對(duì)象的原型:

obj2 = {}

obj2.__proto__ = me

obj2.firstName // => seek

obj2.lastName // => "me"

obj2.getName() // => "seekme"

使用Object.create函數(shù)

盡管說前兩種方法可以解決問題,但是這兩種寫法并不優(yōu)雅,因?yàn)镴avaScript并不是基于類的語言,第一寫法很容易給人以誤解,JavaScript語言精粹的作者Crockford認(rèn)為new就不應(yīng)該出現(xiàn)在JavaScript語言當(dāng)中,而推薦使用Object.create函數(shù)來基于原型來創(chuàng)建對(duì)象。Object.create函數(shù)的用法很簡單:

obj3 = Object.create(me) // 以me為原型創(chuàng)建新的對(duì)象

obj3.firstName // => seek

obj3.lastName // => "me"

obj3.getName() // => "seekme"

obj3 = Object.create(me) 與obj2 = {};obj2.proto = me是等價(jià)的,但是前一種寫法更優(yōu)雅也更易于理解。

總結(jié)

JavaScript作為一門基于原型的,函數(shù)式的編程語言在設(shè)計(jì)上有很多優(yōu)雅與強(qiáng)大之處,但同時(shí)又有很多糟粕和坑,正式如此,JavaScript也是被誤解最多語言。學(xué)習(xí)了JavaScript的對(duì)象繼承機(jī)制,感覺自己的水平還是大有長進(jìn)的。

以上這篇淺談JavaScript對(duì)象與繼承就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考

更多信息請(qǐng)查看網(wǎng)絡(luò)編程
易賢網(wǎng)手機(jī)網(wǎng)站地址:淺談JavaScript對(duì)象與繼承
由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢回復(fù)僅供參考,敬請(qǐng)考生以權(quán)威部門公布的正式信息和咨詢?yōu)闇?zhǔn)!

2025國考·省考課程試聽報(bào)名

  • 報(bào)班類型
  • 姓名
  • 手機(jī)號(hào)
  • 驗(yàn)證碼
關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 新媒體/短視頻平臺(tái) | 手機(jī)站點(diǎn) | 投訴建議
工業(yè)和信息化部備案號(hào):滇ICP備2023014141號(hào)-1 云南省教育廳備案號(hào):云教ICP備0901021 滇公網(wǎng)安備53010202001879號(hào) 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號(hào)
云南網(wǎng)警備案專用圖標(biāo)
聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關(guān)注公眾號(hào):hfpxwx
咨詢QQ:1093837350(9:00—18:00)版權(quán)所有:易賢網(wǎng)
云南網(wǎng)警報(bào)警專用圖標(biāo)