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