摘要:繼承傳統(tǒng)的面向?qū)ο笳Z(yǔ)言,繼承是類與類之間的關(guān)系。原型繼承原型定義原型就是指構(gòu)造函數(shù)的屬性所引用的對(duì)象。創(chuàng)建構(gòu)造函數(shù)創(chuàng)建的實(shí)例對(duì)象張三李四就是對(duì)象的原型也是的原型在原型上創(chuàng)建一個(gè)屬性運(yùn)行和,并對(duì)比是否為同一個(gè)方法。
原文鏈接:http://www.hansmkiii.com/2018/07/06/javascript-node-1/
" 面向?qū)ο蟆⒃?、繼承 "
1、面向?qū)ο?/b> 1.1 什么是面向?qū)ο蟪绦蛟O(shè)計(jì)為了了解 面向?qū)ο?/strong> 與 面向過程 的區(qū)別,我們先看案例1。
案例1:一輛汽車以60km/h,在一條長(zhǎng)度1200km的公路上行駛,求其行駛完全程需要的時(shí)間。
/* 面向過程 */ var time = 1200 / 60; // 計(jì)算汽車行駛時(shí)間 console.log(time); // 打印結(jié)果
/* 面向?qū)ο?*/ // 創(chuàng)建公路對(duì)象 var road = { long: 1200 // 公路長(zhǎng)度 }; // 創(chuàng)建小汽車對(duì)象 var car = { speed: 60, // 汽車速度 road: road, // 汽車在公路上行駛,與公路對(duì)象關(guān)聯(lián)(road已聲明) run: function(){ // 汽車行駛的方法,返回行駛速度 return this.road.long / this.speed; } } var r = car.run(); // 執(zhí)行汽車行駛的方法,返回行駛速度 console.log(r); // 打印結(jié)果(30)
雖然看上去面向?qū)ο蟊让嫦蜻^程要復(fù)雜了很多,但是如果考慮到以后可能會(huì)改變某個(gè)變量(公路長(zhǎng)度或汽車行駛速度),面向過程需要修改運(yùn)算過程中的值,而面向?qū)ο笾恍枰趫?zhí)行運(yùn)算方法之前通過car.speed = 40修改 car 對(duì)象的 speed 屬性即可,可以有效避免修改錯(cuò)誤和修改多處。
當(dāng)程序復(fù)雜程度到達(dá)一定的量級(jí),面向?qū)ο罂梢蕴岣叱绦虻目删S護(hù)性。
如果后面我們的需求改變了,依舊需要汽車對(duì)象,但是要返回汽車的顏色。
如果是面向過程開發(fā),我們需要?jiǎng)h除掉面向過程的所有代碼,重新寫代碼返回汽車的顏色。而面向?qū)ο髣t不需要?jiǎng)h除原來定義的對(duì)象,只需要給 car 對(duì)象增加一個(gè) color 屬性,擴(kuò)展 car 對(duì)象。
所以,面向?qū)ο蟪绦蛟O(shè)計(jì)的優(yōu)勢(shì)有:
提高代碼的可維護(hù)性
提高代碼的可擴(kuò)展性
1.2 面向?qū)ο蟮姆绞讲僮鱀OMHTML
111222333444
JS
// 給div添加背景顏色 // 面向過程 var divs = document.getElementsByTagName("div"); for (var i=0; i如果多處需要相同的功能,面向?qū)ο蟮姆椒梢蕴岣叽a的復(fù)用性。
2、繼承傳統(tǒng)的面向?qū)ο笳Z(yǔ)言,繼承是 類 與 類 之間的關(guān)系。而JS中,由于沒有 類 的概念。所以是 對(duì)象 與 對(duì)象 之間的關(guān)系。
定義:在JS中,繼承就是指使一個(gè)對(duì)象有權(quán)去訪問另一個(gè)對(duì)象的能力。
2.1 原型繼承 原型
比如:對(duì)象A能繼承對(duì)象B的成員(屬性和方法),那么,對(duì)象A就繼承于對(duì)象B。定義:原型就是指構(gòu)造函數(shù)的prototype屬性所引用的對(duì)象。
目的:解決同類對(duì)象數(shù)據(jù)共享問題。示例:
// 創(chuàng)建構(gòu)造函數(shù) Person function Person(name, age){ this.name = name; this.age = age; this.say = function(){ console.log("hello!") } } // 創(chuàng)建 Person 的實(shí)例對(duì)象 var p1 = new Person("張三", 19); var p2 = new Person("李四", 20); // Person.prototype 就是對(duì)象 p1 的原型 // p1.__proto__ 也是 p1 的原型 console.log(Person.prototype === p1.__proto__); // true此時(shí),p1和p2都有繼承了構(gòu)造函數(shù) Person 的 say 屬性,在控制臺(tái)打印查看:
p1.say(); // hello! p2.say(); // hello!這是 構(gòu)造函數(shù)繼承,那么 p1 的 say 和 p2 的 say 是不是同一個(gè)方法呢?
// 打印查看 console.log(p1.say === p2.say); // false查看結(jié)果發(fā)現(xiàn)兩個(gè) say 方法并不是同一個(gè),所以在創(chuàng)建實(shí)例對(duì)象的時(shí)候開辟了兩塊內(nèi)存分別存放了 p1.say 和 p2.say,這就導(dǎo)致了內(nèi)存的浪費(fèi),所以我們需要通過原型共享數(shù)據(jù)來解決這個(gè)問題。
// 創(chuàng)建構(gòu)造函數(shù) Person function Person(name, age){ this.name = name; this.age = age; } // 創(chuàng)建 Person 的實(shí)例對(duì)象 var p1 = new Person("張三", 19); var p2 = new Person("李四", 20); // Person.prototype 就是對(duì)象 p1 的原型 // p1.__proto__ 也是 p1 的原型 // 在原型上創(chuàng)建一個(gè) say 屬性 Person.prototype.say = function(){ console.log("hello!"); } // 運(yùn)行 p1.say 和 p2.say,并對(duì)比是否為同一個(gè)方法。 p1.say(); // hello! p2.say(); // hello! console.log(p1.say === p2.say); // true如此便通過原型繼承實(shí)現(xiàn)了數(shù)據(jù)共享。
構(gòu)造函數(shù)中可以顯式的指定return語(yǔ)句,但是如果返回的數(shù)據(jù)類型為簡(jiǎn)單數(shù)據(jù)類型,或者null undefined值都會(huì)被忽略,依舊返回的是構(gòu)造函數(shù)的實(shí)例對(duì)象2.2 類式繼承類式繼承通過call(this, ... , ...)或apply(this, arguments)方法改變this指向?qū)崿F(xiàn)繼承。
// 創(chuàng)建 Person 構(gòu)造函數(shù) function Person(name, age) { this.name = name; this.age = age; } // 創(chuàng)建 Student 構(gòu)造函數(shù) function Student(name, age, id){ this.name = name; this.age = age; this.id = id; }Student對(duì)象是 Person 對(duì)象的一個(gè)分支,可以繼承Person的屬性。
所以Student 屬性可以這樣寫:function Student(name, age, id){ Person.call(this, name, age); this.id = id; } var s = new Student("張三","20","123456789"); console.log(s); // {name: "張三", age: "20", id: "123456789"}或者
function Student(name, age, id){ Person.apply(this, arguments); // arguments 是一個(gè)數(shù)組 也可以寫成 [name, age] this.id = id; } var s = new Student("張三","20","123456789"); console.log(s); // {name: "張三", age: "20", id: "123456789"}2.3 組合繼承通過前面對(duì) 原型繼承 和 類式繼承 的了解,我們發(fā)現(xiàn) 原型繼承 用于繼承靜態(tài)數(shù)據(jù), 類式繼承 用于繼承動(dòng)態(tài)參數(shù),所以我們有時(shí)候需要同時(shí)使用 原型繼承 和 類式繼承,也就是 組合繼承。
function Person(name, age) { this.name = name; this.age = age; } // 類式繼承 function Student(name, age, id){ Person.call(this, name, age); this.id = id; } // 原型繼承 Student.prototype.class = function(){ console.log("English"); } var s = new Student("張三", 20, "123456"); s.class();2.4 extend方法var a = { name: "g" }; var b = { print: function() { console.log("Hello,JS!") } } // 將 parent 對(duì)象上的成員賦值給 child function extend(child, parent) { for (var pro in parent) { // child[pro] = parent[pro]; // 缺點(diǎn):會(huì)將parent對(duì)象的原型上的成員一同復(fù)制過來,所以需要先判斷屬性是否為parent私有的 if (parent.hasOwnProperty(pro)){ child[pro] = parent[pro]; } } } extend(a,b); a.print();以上四種繼承方式是開發(fā)過程中最常見的幾種,具體應(yīng)用場(chǎng)景視情況而定,甚至可以多個(gè)組合使用
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/96051.html
摘要:此時(shí)的原型對(duì)象包括一個(gè)指向另一個(gè)原型的指針,相應(yīng)的,另一個(gè)原型中的指向另一個(gè)構(gòu)造函數(shù)。這種關(guān)系層層遞進(jìn),就通過一個(gè)原型對(duì)象鏈接另一個(gè)構(gòu)造函數(shù)的原型對(duì)象的方式實(shí)現(xiàn)了繼承。 讀這篇之前,最好是已讀過我前面的關(guān)于對(duì)象的理解和封裝類的筆記。第6章我一共寫了3篇總結(jié),下面是相關(guān)鏈接:讀《javaScript高級(jí)程序設(shè)計(jì)-第6章》之理解對(duì)象讀《javaScript高級(jí)程序設(shè)計(jì)-第6章》之封裝類 一...
摘要:使用時(shí),會(huì)自動(dòng)創(chuàng)建對(duì)象,其類型為構(gòu)造函數(shù)類型,指向?qū)ο髮?shí)例缺少關(guān)鍵字,指向全局對(duì)象。構(gòu)造函數(shù)本身也具有屬性指向原型對(duì)象。 在JavaScript面向?qū)ο缶?一)中講解了一些與面向?qū)ο笙嚓P(guān)的概念和方法,這篇講講原型和繼承。 構(gòu)造函數(shù)和原型對(duì)象 構(gòu)造函數(shù)也是函數(shù),用new創(chuàng)建對(duì)象時(shí)調(diào)用的函數(shù),與普通函數(shù)的一個(gè)區(qū)別是,其首字母應(yīng)該大寫。但如果將構(gòu)造函數(shù)當(dāng)作普通函數(shù)調(diào)用(缺少new關(guān)鍵字...
摘要:繼承和前面兩篇文章中的知識(shí)非常相關(guān),如果對(duì)函數(shù)創(chuàng)建原理和原型鏈不熟悉,請(qǐng)猛戳高級(jí)程序設(shè)計(jì)筆記創(chuàng)建對(duì)象高級(jí)程序設(shè)計(jì)筆記原型圖解繼承,通俗的說,就是將自身不存在的屬性或方法,通過某種方式為自己所用文章分別介紹原型鏈繼承繼承借用構(gòu)造函數(shù)繼承組合繼 繼承和前面兩篇文章中的知識(shí)非常相關(guān),如果對(duì)函數(shù)創(chuàng)建原理和原型鏈不熟悉,請(qǐng)猛戳:《javascript高級(jí)程序設(shè)計(jì)》筆記:創(chuàng)建對(duì)象《javascri...
摘要:上一篇你不知道的筆記寫在前面這是年第一篇博客,回顧去年年初列的學(xué)習(xí)清單,發(fā)現(xiàn)僅有部分完成了。當(dāng)然,這并不影響年是向上的一年在新的城市穩(wěn)定連續(xù)堅(jiān)持健身三個(gè)月早睡早起游戲時(shí)間大大縮減,學(xué)會(huì)生活。 上一篇:《你不知道的javascript》筆記_this 寫在前面 這是2019年第一篇博客,回顧去年年初列的學(xué)習(xí)清單,發(fā)現(xiàn)僅有部分完成了。當(dāng)然,這并不影響2018年是向上的一年:在新的城市穩(wěn)定、...
摘要:即另外,注意到構(gòu)造函數(shù)里的屬性,都沒有經(jīng)過進(jìn)行初始化,而是直接使用進(jìn)行綁定。并且在模式下,構(gòu)造函數(shù)沒有使用進(jìn)行調(diào)用,也會(huì)導(dǎo)致報(bào)錯(cuò)。調(diào)用構(gòu)造函數(shù)千萬(wàn)不要忘記寫。 1. 基礎(chǔ) JavaScript不區(qū)分類和實(shí)例的概念,而是通過原型來實(shí)現(xiàn)面向?qū)ο缶幊?。Java是從高級(jí)的抽象上設(shè)計(jì)的類和實(shí)例,而JavaScript的設(shè)計(jì)理念,聽起來就好比Heros里的Peter,可以復(fù)制別人的能力。JavaS...
閱讀 2633·2021-11-19 09:56
閱讀 886·2021-09-24 10:25
閱讀 1653·2021-09-09 09:34
閱讀 2211·2021-09-09 09:33
閱讀 1066·2019-08-30 15:54
閱讀 552·2019-08-29 18:33
閱讀 1278·2019-08-29 17:19
閱讀 516·2019-08-29 14:19