JavaScript面向?qū)ο罄^承原理與實(shí)現(xiàn)方法分析
本文實(shí)例講述了JavaScript面向?qū)ο罄^承原理與實(shí)現(xiàn)方法。分享給大家供大家參考,具體如下:
1、構(gòu)造函數(shù)、原型和實(shí)例的關(guān)系
構(gòu)造函數(shù)有一個(gè)原型屬性prototype
指向一個(gè)原型對(duì)象。
原型對(duì)象包含一個(gè)指向構(gòu)造函數(shù)的指針constructor
。
實(shí)例包含一個(gè)指向原型對(duì)象的內(nèi)部指針[[prototype]]
。
2、通過原型鏈實(shí)現(xiàn)繼承
基本思想:利用原型讓一個(gè)引用類型繼承另一個(gè)引用類型的屬性和方法,子類型可以訪問超類型的所有屬性和方法。原型鏈的構(gòu)建是將一個(gè)類型的實(shí)例賦值給另一個(gè)構(gòu)造函數(shù)的原型實(shí)現(xiàn)的。實(shí)現(xiàn)的本質(zhì)是重寫原型對(duì)象,代之以一個(gè)新類型的實(shí)例。
function Person(name) { this.name = name; } Person.prototype.sayHello = function() { alert("Hello, " + this.name); } var person = new Person("Alice"); person.sayHello(); // Hello, Alice function Student() { } Student.prototype = new Person("Bruce"); Student.prototype.id = 16; Student.prototype.showId = function() { alert(this.id); } var student = new Student(); student.sayHello(); // Hello, Bruce student.showId(); // 16
注意:不能用對(duì)象字面量創(chuàng)建原型方法,這樣會(huì)重寫原型鏈,導(dǎo)致繼承無效。
function Person(name) { this.name = name; } Person.prototype.sayHello = function() { alert("Hello, " + this.name); } var person = new Person("Alice"); person.sayHello(); // Hello, Alice function Student() { } Student.prototype = new Person("Bruce"); Student.prototype.id = 16; Student.prototype = { showId: function() { alert(this.id); } }; var student = new Student(); student.sayHello(); // 報(bào)錯(cuò):student.sayHello is not a function student.showId(); // 16
student指向Student的原型,Student的原型又指向Person的原型。
student.sayHello()
原型鏈搜索機(jī)制:
1)搜索student實(shí)例中是否有sayHello()
2)搜索Student.prototype
是否有sayHello()
3)搜索Person.prototype
是否有sayHello()
子類型有時(shí)候需要覆蓋超類型的某個(gè)方法,或者需要添加超類型中不存在的某個(gè)方法。
function Person(name) { this.name = name; } Person.prototype.sayHello = function() { alert("Hello, " + this.name); } var person = new Person("Alice"); person.sayHello(); // Hello, Alice function Student() { } Student.prototype = new Person("Bruce"); Student.prototype.id = 16; Student.prototype.showId = function() { alert(this.id); } Student.prototype.sayHello = function() { alert("Hi, " + this.name); } var student = new Student(); student.sayHello(); //Hi, Bruce student.showId(); // 16
注意:給原型覆蓋或添加方法的代碼一定要放在替換原型的語句之后。
function Person(name) { this.name = name; } Person.prototype.sayHello = function() { alert("Hello, " + this.name); } var person = new Person("Alice"); person.sayHello(); // Hello, Alice function Student() { } Student.prototype.sayHello = function() { alert("Hi, " + this.name); } Student.prototype = new Person("Bruce"); Student.prototype.id = 16; Student.prototype.showId = function() { alert(this.id); } var student = new Student(); student.sayHello(); // Hello, Bruce student.showId(); // 16
確定實(shí)例和原型的關(guān)系:
(1)instanceof
alert(student instanceof Object); // true alert(student instanceof Student); // true alert(student instanceof Person); // true
(2)isProtptypeOf
alert(Object.prototype.isPrototypeOf(student)); // true alert(Student.prototype.isPrototypeOf(student)); // true alert(Person.prototype.isPrototypeOf(student)); // true
(3)getPrototypeOf
Object.getPrototypeOf(student1) == Student.prototype
使用原型鏈實(shí)現(xiàn)繼承的問題:
(1)引用類型的屬性會(huì)被實(shí)例共享,原型實(shí)現(xiàn)繼承時(shí),原型會(huì)變成另外一個(gè)類型的實(shí)例,實(shí)例的屬性則變成了現(xiàn)在的原型屬性,從而被共享。
function Person(name, age) { this.friends = ["Cindy","David"]; } function Student() { } Student.prototype = new Person(); var student1 = new Student(); student1.friends.push("Bruce"); alert(student1.friends); // "Cindy","David","Bruce" var student2 = new Student(); alert(student1.friends); // "Cindy","David","Bruce"
(2)在創(chuàng)建子類型的實(shí)例時(shí),不能向超類型的構(gòu)造函數(shù)中傳遞參數(shù),實(shí)際上,應(yīng)該是沒有辦法在不影響所有對(duì)象實(shí)例的情況下,給超類型的構(gòu)造函數(shù)傳遞參數(shù)。
實(shí)際中很少單獨(dú)使用原型鏈實(shí)現(xiàn)繼承。
3、通過構(gòu)造函數(shù)實(shí)現(xiàn)繼承
基本思想:在子類型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型構(gòu)造函數(shù)。通過使用apply()
和call()
方法也可以在新創(chuàng)建的對(duì)象上執(zhí)行構(gòu)造函數(shù)。
function Person(name, age) { this.name = name; this.age = age; } function Student() { Person.call(this,"Alice",22); // 繼承了構(gòu)造函數(shù)Person,同時(shí)還傳遞了參數(shù) this.id = 16; // 實(shí)例屬性 } var student = new Student(); alert(student.name); // "Alice" alert(student.age); // 22 alert(student.id); // 16
使用構(gòu)造函數(shù)實(shí)現(xiàn)繼承的問題:
(1)在超類型的原型中定義的方法,對(duì)子類型而言是不可見的,結(jié)果所有類型都只能使用構(gòu)造函數(shù)模式。
(2)要想子類能夠訪問超類定義的方法,方法只能在構(gòu)造函數(shù)中定義,但方法在構(gòu)造函數(shù)中定義時(shí),函數(shù)復(fù)用無從談起。
function Person(name, age) { this.name = name; this.age = age; } Person.prototype.showName = function() { alert(this.name); }; function Student() { Person.call(this,"Alice",22); this.id = 16; } var student = new Student(); alert(student.showName()); // 報(bào)錯(cuò):student.showName is not a function
實(shí)際中很少單獨(dú)使用使用構(gòu)造函數(shù)實(shí)現(xiàn)繼承。
4、組合使用原型鏈和構(gòu)造函數(shù)實(shí)現(xiàn)繼承
思路:使用原型鏈繼承共享的屬性和方法,使用構(gòu)造函數(shù)繼承實(shí)例屬性。
效果:既通過在原型上定義方法實(shí)現(xiàn)了函數(shù)復(fù)用,又能夠保證每個(gè)實(shí)例都有自己的屬性。
function Person(name, age) { this.name = name; this.age = age; this.friends = ["Cindy","David"]; } Person.prototype.sayHello = function() { alert("Hello, " + this.name); } function Student(name, age, id) { Person.call(this, name, age); this.id = id; } Student.prototype = new Person(); Student.prototype.showId = function() { alert(this.id); } var student1 = new Student("Alice", 22, 16); student1.friends.push("Emy"); alert(student1.friends); // "Cindy","David","Emy" student1.sayHello(); // Hello, Alice student1.showId(); // 16 var student2 = new Student("Bruce", 23, 17); alert(student2.friends); // "Cindy","David" student2.sayHello(); // Hello, Bruce student2.showId(); // 17
更多關(guān)于JavaScript相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《javascript面向?qū)ο笕腴T教程》、《JavaScript錯(cuò)誤與調(diào)試技巧總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》及《JavaScript數(shù)學(xué)運(yùn)算用法總結(jié)》
希望本文所述對(duì)大家JavaScript程序設(shè)計(jì)有所幫助。
相關(guān)文章
微信小程序?qū)崿F(xiàn)拍照和相冊(cè)選取圖片
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)拍照和相冊(cè)選取圖片,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-05-05JavaScript實(shí)現(xiàn)PC端橫向輪播圖
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)PC端橫向輪播圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-02-02基于Bootstrap下拉框插件bootstrap-select使用方法詳解
這篇文章主要為大家詳細(xì)介紹了基于Bootstrap下拉框插件bootstrap-select的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-08-08利用進(jìn)制轉(zhuǎn)換壓縮數(shù)字函數(shù)分享
本文主要介紹了進(jìn)制轉(zhuǎn)換函數(shù),用于壓縮數(shù)字,比如Date.now()這樣的長數(shù)字,用62進(jìn)制表示,就更短,大家參考使用吧2014-01-01JavaScript實(shí)現(xiàn)移動(dòng)端彈窗后禁止?jié)L動(dòng)
這篇文章主要介紹了JavaScript實(shí)現(xiàn)移動(dòng)端彈窗后禁止?jié)L動(dòng),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05深入理解ES6 Promise 擴(kuò)展always方法
本篇文章主要介紹了ES6 Promise 擴(kuò)展always方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-09-09