JavaScript面向?qū)ο缶幊?/h1>

JavaScript的面向?qū)ο缶幊毯痛蠖鄶?shù)其他語言如Java辽幌、C#的面向?qū)ο缶幊潭疾惶粯印?br> 類和實例是大多數(shù)面向?qū)ο缶幊陶Z言的基本概念涌攻。
不過山橄,在JavaScript中墙歪,這個概念需要改一改听系。JavaScript不區(qū)分類和實例的概念,而是通過原型prototype來實現(xiàn)面向?qū)ο缶幊?br> 原型是指 當我們想要創(chuàng)阿金xiaoming這個具體的學生時,我們并沒有一個Student類型可用,那怎么辦,恰好有這么一個現(xiàn)成的對象:

var robot = {
    name: 'Robot',
    height: 1.6,
    run: function () {
        console.log(this.name + ' is running...');
    }
};
我們看robot對象有名字,有身高,還會跑,有點像小明,干脆就根據(jù)它來創(chuàng)建小明得了.
于是我們把它改名為Student,然后創(chuàng)建出xiaoming:
var Student = {
    name: 'Robot',
    height: 1.2,
    run: function () {
        console.log(this.name + ' is running...');
    }
};
var xiaoming = {
    name: '小明'
};
xiaoming.__proto__ = Student

注意最后一行代碼把xiaoming的原型指向了對象Student,看上去xiaoming放佛是從Student繼承下來的
xiaoming.name; // '小明'
xiaoming.run(); // 小明 is running...
xiaoming有自己的name屬性,但并沒有定義run()方法虹菲。不過靠胜,由于小明是從Student繼承而來,只要Student有run()方法,xiaoming也可以調(diào)用:
JavaScript的原型鏈和Java的Class區(qū)別就在浪漠,它沒有“Class”的概念陕习,所有對象都是實例,所謂繼承關系不過是把一個對象的原型指向另一個對象而已址愿。
要注意:上述代碼僅用于演示目的,在編寫JavaScript代碼時,不要直接用obj.proto去改變一個對象的原型,并且,低版本的IE也無法使用proto
Object.create()方法可以傳入一個原型對象,并創(chuàng)建一個基于該原型的新對象,但是新對象什么屬性都沒有,因此,我們可以編寫一函數(shù)來創(chuàng)建xioaming
原型對象:

var Student = {
    name:'Robot',
    height:1.2,
    run: function () {
        console.log(this.name + 'is running...')
    }
};
function createStudent(name){
//基于Student原型創(chuàng)建一個新對象
var s = Object.create(Student);
//初始化新對象
s.name = name;
return s;
}
var xiaoming = createStudent('小明');
xiaoming.run();
xiaoming.__proto__ === Student;//true

創(chuàng)建對象
JavaScript對每個創(chuàng)建的對象都會設置一個原型该镣,指向它的原型對象。
當我們用obj.xxx訪問一個對象的屬性時必盖,JavaScript引擎先在當前對象上查找該屬性拌牲,如果沒有找到,就到其原型對象上找歌粥,如果還沒有找到,就一直上溯到Object.prototype對象拍埠,最后失驶,如果還沒有找到,就只能返回undefined枣购。
容易想到嬉探,如果原型鏈很長,那么訪問一個對象的屬性就會因為花更多的時間查找而變得更慢棉圈,因此要注意不要把原型鏈搞得太長涩堤。

構造函數(shù)
除了直接用{...}創(chuàng)建一個對象外,JavaScript還可以用一種構造函數(shù)的方法來創(chuàng)建對象。它的用法是分瘾,先定義一個構造函數(shù):

function Student(name) {
    this.name = name;
    this.hello = function () {
        alert('hello, ' + this.name + '!');
    }
}

這不是一個普通函數(shù)嗎胎围?這確實是一個普通函數(shù),但是在JavaScript中德召,可以用關鍵字new來調(diào)用這個函數(shù)白魂,并返回一個對象:
var xiaoming = new Student('小明');
xiaoming.name; // '小明'
xiaoming.hello(); // Hello, 小明!
注意: 如果不寫new,這就是一個普通的函數(shù),它返回undefined.但是如果寫了new,它就變成了一個構造函數(shù),它綁定的this指向新創(chuàng)建的對象,并默認返回this,
也就是說,不需要再最后寫return this;
新創(chuàng)建的xiaoming的原型鏈是:xiaoming ----> Student.prototype ----> Object.prototype ----> null
用new Student()創(chuàng)建的對象還從原型上獲得了一個constructor屬性,它指向函數(shù)Student本身.

image.png

紅色箭頭是原型鏈上岗。注意福荸,Student.prototype指向的對象就是xiaoming、xiaohong的原型對象肴掷,這個原型對象自己還有個屬性constructor敬锐,指向Student函數(shù)本身。

另外呆瞻,函數(shù)Student恰好有個屬性prototype指向xiaoming台夺、xiaohong的原型對象,但是xiaoming栋烤、xiaohong這些對象可沒有prototype這個屬性谒养,不過可以用proto這個非標準用法來查看。

現(xiàn)在我們就認為xiaoming、xiaohong這些對象“繼承”自Student买窟。

xiaoming.name; // '小明'
xiaohong.name; // '小紅'
xiaoming.hello; // function: Student.hello()
xiaohong.hello; // function: Student.hello()
xiaoming.hello === xiaohong.hello; // false

xiaoming和xiaohong各自的name不同丰泊,這是對的,否則我們無法區(qū)分誰是誰了始绍。

xiaoming和xiaohong各自的hello是一個函數(shù)瞳购,但它們是兩個不同的函數(shù),雖然函數(shù)名稱和代碼都是相同的亏推!

如果我們通過new Student()創(chuàng)建了很多對象学赛,這些對象的hello函數(shù)實際上只需要共享同一個函數(shù)就可以了,這樣可以節(jié)省很多內(nèi)存吞杭。

要讓創(chuàng)建的對象共享一個hello函數(shù)盏浇,根據(jù)對象的屬性查找原則,我們只要把hello函數(shù)移動到xiaoming芽狗、xiaohong這些對象共同的原型上就可以了绢掰,也就是Student.prototype:

image.png

修改代碼如下:

function Student(name) {
    this.name = name;
}

Student.prototype.hello = function () {
    alert('Hello, ' + this.name + '!');
};

忘記寫new怎么辦

如果一個函數(shù)被定義為用于創(chuàng)建對象的構造函數(shù),但是調(diào)用時忘記了寫new怎么辦童擎?

在strict模式下滴劲,this.name = name將報錯,因為this綁定為undefined顾复,在非strict模式下班挖,this.name = name不報錯,因為this綁定為window芯砸,于是無意間創(chuàng)建了全局變量name萧芙,并且返回undefined,這個結(jié)果更糟糕乙嘀。

所以末购,調(diào)用構造函數(shù)千萬不要忘記寫new。為了區(qū)分普通函數(shù)和構造函數(shù)虎谢,按照約定盟榴,構造函數(shù)首字母應當大寫,而普通函數(shù)首字母應當小寫婴噩,這樣擎场,一些語法檢查工具如jslint將可以幫你檢測到漏寫的new。

最后几莽,我們還可以編寫一個createStudent()函數(shù)迅办,在內(nèi)部封裝所有的new操作。一個常用的編程模式像這樣:

function Student(props) {
    this.name = props.name || '匿名'; // 默認值為'匿名'
    this.grade = props.grade || 1; // 默認值為1
}

Student.prototype.hello = function () {
    alert('Hello, ' + this.name + '!');
};

function createStudent(props) {
    return new Student(props || {})
}

這個createStudent()函數(shù)有幾個巨大的優(yōu)點:一是不需要new來調(diào)用章蚣,二是參數(shù)非常靈活站欺,可以不傳,也可以這么傳:

var xiaoming = createStudent({
    name: '小明'
});

xiaoming.grade; // 1

如果創(chuàng)建的對象有很多屬性,我們只需要傳遞需要的某些屬性矾策,剩下的屬性可以用默認值磷账。由于參數(shù)是一個Object,我們無需記憶參數(shù)的順序贾虽。如果恰好從JSON拿到了一個對象逃糟,就可以直接創(chuàng)建出xiaoming。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者

  • 序言:七十年代末蓬豁,一起剝皮案震驚了整個濱河市绰咽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌地粪,老刑警劉巖取募,帶你破解...
    沈念sama閱讀 212,029評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異驶忌,居然都是意外死亡矛辕,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評論 3 385
  • 文/潘曉璐 我一進店門付魔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人飞蹂,你說我怎么就攤上這事几苍。” “怎么了陈哑?”我有些...
    開封第一講書人閱讀 157,570評論 0 348
  • 文/不壞的土叔 我叫張陵妻坝,是天一觀的道長。 經(jīng)常有香客問我惊窖,道長刽宪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,535評論 1 284
  • 正文 為了忘掉前任界酒,我火速辦了婚禮圣拄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘毁欣。我一直安慰自己庇谆,他們只是感情好,可當我...
    茶點故事閱讀 65,650評論 6 386
  • 文/花漫 我一把揭開白布凭疮。 她就那樣靜靜地躺著饭耳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪执解。 梳的紋絲不亂的頭發(fā)上寞肖,一...
    開封第一講書人閱讀 49,850評論 1 290
  • 那天,我揣著相機與錄音,去河邊找鬼新蟆。 笑死觅赊,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的栅葡。 我是一名探鬼主播茉兰,決...
    沈念sama閱讀 39,006評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼欣簇!你這毒婦竟也來了规脸?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,747評論 0 268
  • 序言:老撾萬榮一對情侶失蹤熊咽,失蹤者是張志新(化名)和其女友劉穎莫鸭,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體横殴,經(jīng)...
    沈念sama閱讀 44,207評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡被因,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,536評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了衫仑。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片梨与。...
    茶點故事閱讀 38,683評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖文狱,靈堂內(nèi)的尸體忽然破棺而出粥鞋,到底是詐尸還是另有隱情,我是刑警寧澤瞄崇,帶...
    沈念sama閱讀 34,342評論 4 330
  • 正文 年R本政府宣布呻粹,位于F島的核電站,受9級特大地震影響苏研,放射性物質(zhì)發(fā)生泄漏等浊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,964評論 3 315
  • 文/蒙蒙 一摹蘑、第九天 我趴在偏房一處隱蔽的房頂上張望筹燕。 院中可真熱鬧,春花似錦纹蝴、人聲如沸庄萎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,772評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽糠涛。三九已至,卻和暖如春兼犯,著一層夾襖步出監(jiān)牢的瞬間忍捡,已是汗流浹背集漾。 一陣腳步聲響...
    開封第一講書人閱讀 32,004評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留砸脊,地道東北人具篇。 一個月前我還...
    沈念sama閱讀 46,401評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像凌埂,于是被迫代替她去往敵國和親驱显。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,566評論 2 349

推薦閱讀更多精彩內(nèi)容