摘要:以下內容均基于本人對高級程序設計第三版小節的理解先看一下父類私有受保護成員,只允許在父類的構造函數中賦值公有成員引用類型的成員構造函數中的方法,打印一些基本信息原型中的方法,將構造函數中的非函數成員以格式打印方式一原型鏈繼承實現方式子類的原
先看一下父類以下內容均基于本人對《JavaScript高級程序設計》第三版6.3小節的理解
function Animal(name) { var name = name; //"私有(受保護)"成員,只允許在父類的構造函數中賦值 this.food = undefined; //"公有"成員 //引用類型的成員 this.birthday = { year: undefined }; //構造函數中的方法,打印一些基本信息 this.greeting = function() { console.log("Hi, my name is {" + name + "} I like eat {" + this.food + "} and my birth year is {" + this.birthday.year + "}"); }; //原型中的方法,將構造函數中的非函數成員以JSON格式打印 Animal.prototype.briefInfo = function() { var brief = { name: name, food: this.food, birthday: this.birthday }; console.log(JSON.stringify(brief)); }; }方式一:原型鏈繼承
實現方式:子類的原型指向父類的實例
子類:
function Dog() {} Dog.prototype = new Animal(); //原型指向父類的實例
測試:
var dog1 = new Dog(); dog1.food = "shit"; dog1.birthday.year = 2015; var dog2 = new Dog(); dog2.food = "bones"; dog2.birthday.year = 2016; dog1.greeting(); //console: Hi, my name is {undefined} I like eat {shit} and my birth year is {2016} dog2.greeting(); //console: Hi, my name is {undefined} I like eat {bones} and my birth year is {2016} dog1.briefInfo(); //console: {"food":"shit","birthday":{"year":2016}} dog2.briefInfo(); //console: {"food":"bones","birthday":{"year":2016}} //以上, //birthday是引用類型的屬性,所以dog1的birthday.year被dog2覆蓋了; //無法給dog1和dog2的name賦值
存在的問題:
引用類型的對象會被子類的所有實例共享(1.1)
無法在創建子類的實例時,給父類的構造函數傳遞參數(1.2)
方式二:借用構造函數(偽造對象、經典繼承)實現方式:在子類的構造函數中利用call(或者apply)方法執行父類構造函數(問題1.2解決),將執行對象設為子類的this,相當于把父類構造函數中的成員拷貝了一份到子類(問題1.1解決)
子類
function Dog(name) { Animal.call(this, name); }
測試
var dog1 = new Dog("tom"); dog1.food = "shit"; dog1.birthday.year = 2015; var dog2 = new Dog("mike"); dog2.food = "bones"; dog2.birthday.year = 2016; dog1.greeting(); //console: Hi, my name is {tom} I like eat {shit} and my birth year is {2015} dog2.greeting(); //console: Hi, my name is {mike} I like eat {bones} and my birth year is {2016} //briefInfo是父類原型中的屬性,并沒有被繼承,以下語句會報錯 dog1.briefInfo(); //error: dog1.briefInfo is not a function dog2.briefInfo(); //error: dog2.briefInfo is not a function
存在的問題:
父類原型中定義的屬性無法被繼承
綜合方式一方式二,一種很明顯的方式呼之欲出了:
方式三:組合繼承實現方式:結合原型鏈繼承和經典繼承
子類
function Dog(name) { Animal.call(this, name); //經典繼承 } Dog.prototype = new Animal(); //原型鏈繼承
測試
var dog1 = new Dog("tom"); dog1.food = "shit"; dog1.birthday.year = 2015; var dog2 = new Dog("mike"); dog2.food = "bones"; dog2.birthday.year = 2016; dog1.greeting(); //console: Hi, my name is {tom} I like eat {shit} and my birth year is {2015} dog2.greeting(); //console: Hi, my name is {mike} I like eat {bones} and my birth year is {2016} dog1.briefInfo(); //console: {"name":"tom","food":"shit","birthday":{"year":2015}} dog2.briefInfo(); //console: {"name":"mike","food":"bones","birthday":{"year":2016}} //終于得到了預期的結果,算是較好的實現了繼承。 //但是,并不完美
存在的問題
父類的構造函數被調用了兩次
為了引出下一個繼承方式,先將函數的繼承放在一邊,看一下js中對象的繼承
(摘抄原文)
1. 原型式繼承
var person = { name: "martin" firend: ["bob", "steven"] }; function object(o) { function F() {}; F.prototype = o; return new F(); } var anotherPerson = object(person); //antherPerson繼承了person2. 寄生式繼承
function createAnother(original) { var clone = object(original); //原型式繼承定義的方法 //擴展對象 clone.sayHi = function() { console.log("hi"); } return clone; }
回到正題,接下來介紹一顆 “銀彈”
方式四:寄生組合式繼承實現方式:
利用經典繼承拷貝父類構造中的屬性到子類
利用原型式繼承創建一個繼承父類原型的對象
將該對象的constructor屬性指向子類的構造函數(寄生式繼承:擴展對象)
將子類的prototype指向該對象
子類
function Dog(name) { Animal.call(this, name); } function F() {} var supProto = Animal.prototype; F.prototype = supProto; var subProto = new F(); subProto.constructor = Dog; Dog.prototype = subProto;
測試
var dog1 = new Dog("tom"); dog1.food = "shit"; dog1.birthday.year = 2015; var dog2 = new Dog("mike"); dog2.food = "bones"; dog2.birthday.year = 2016; dog1.greeting(); //console: Hi, my name is {tom} I like eat {shit} and my birth year is {2015} dog2.greeting(); //console: Hi, my name is {mike} I like eat {bones} and my birth year is {2016} dog1.briefInfo(); //console: {"name":"tom","food":"shit","birthday":{"year":2015}} dog2.briefInfo(); //console: {"name":"mike","food":"bones","birthday":{"year":2016}}
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/79731.html
摘要:中的繼承并不是明確規定的,而是通過模仿實現的。繼承中的繼承又稱模擬類繼承。將函數抽離到全局對象中,函數內部直接通過作用域鏈查找函數。這種范式編程是基于作用域鏈,與前面講的繼承是基于原型鏈的本質區別是屬性查找方式的不同。 這一節梳理對象的繼承。 我們主要使用繼承來實現代碼的抽象和代碼的復用,在應用層實現功能的封裝。 javascript 的對象繼承方式真的是百花齊放,屬性繼承、原型繼承、...
摘要:和構造函數前面提到,是個內置隱藏屬性,雖然在可以通過訪問,但是其設計本意是不可被讀取和修改的,那么我們如何利用原型鏈來建立繼承關系提供了關鍵字。到這兒,思路就清晰了,怎么讓對象和對象的相連實現繼承只需把的構造函數的連接到就行了。 什么是繼承? 大多數人使用繼承不外乎是為了獲得這兩點好處,代碼的抽象和代碼的復用。代碼的抽象就不用說了,交通工具和汽車這類的例子數不勝數,在傳統的OO語言中(...
摘要:首先,需要來理清一些基礎的計算機編程概念編程哲學與設計模式計算機編程理念源自于對現實抽象的哲學思考,面向對象編程是其一種思維方式,與它并駕齊驅的是另外兩種思路過程式和函數式編程。 JavaScript 中的原型機制一直以來都被眾多開發者(包括本人)低估甚至忽視了,這是因為絕大多數人沒有想要深刻理解這個機制的內涵,以及越來越多的開發者缺乏計算機編程相關的基礎知識。對于這樣的開發者來說 J...
摘要:前言作為中最重要的內容之一,繼承問題一直是我們關注的重點。如果一個類別繼承自另一個類別,就把這個稱為的子類,而把稱為的父類別也可以稱是的超類。 前言 作為 JavaScript 中最重要的內容之一,繼承問題一直是我們關注的重點。那么你是否清晰地知道它的原理以及各種實現方式呢 閱讀這篇文章,你將知道: 什么是繼承 實現繼承有哪幾種方式 它們各有什么特點 這里默認你已經清楚的知道構造函...
摘要:繼承前言作為一門輕量級的腳本語言在和的橫空出世之后將其推向的新的高度雖然中出現的新的生成對象的類語法格式但依然為的語法糖而我們依然有必要從的原生實現入手來了解它的繼承實現方式給出了更加簡潔的固定的類聲明方式有興趣的可以查看阮一峰的入門下面給 javascript繼承 前言 javascript作為一門輕量級的腳本語言在ES6和node.js的橫空出世之后將其推向的新的高度,雖然 ES6...
閱讀 2242·2021-11-18 10:02
閱讀 3496·2021-11-15 11:36
閱讀 1122·2019-08-30 14:03
閱讀 738·2019-08-30 11:08
閱讀 2767·2019-08-29 13:20
閱讀 3293·2019-08-29 12:34
閱讀 1381·2019-08-28 18:30
閱讀 1646·2019-08-26 13:34