javascript繼承—prototype屬性介紹(2)

來源:互聯網
上載者:User

js裡每一個function都有一個prototype屬性,而每一個執行個體都有constructor屬性,並且每一個function的prototype都有一個constructor屬性,這個屬性會指向自身。這會形成一個非常有意思的鏈式結構。舉例如下: function Person(){    this.name =12;}console.log(Person.prototype);console.log(Person.prototype.constructor);//輸出Person,指向自身console.log(Person.prototype.constructor.prototype.constructor);//輸出Person,指向自身/***再看一下這個類的輸出,則會出現如下情況**/function Person(){}Person.prototype.name = 'xiaoming';var p1 = new Person();console.log(p1);輸出結果如下: image 會把這個執行個體顯示出來,展開如下。p1有一個原型屬性,這個屬性有一個構造方法Person(),而這個構造方法又有prototype屬性,這個屬性有constructor方法… image 這裡主要讓我們瞭解一下prototype是屬於類(或者說函數function)的屬性,指向這個類的共有屬性和方法,而constructor是執行個體的屬性,指向它的建構函式(也可以說是類,js裡建構函式和類是一個概念)。 通過前面的兩篇文章 javascript繼承—繼承的實現原理(1) javascript建立對象的三種模式 我們知道用prototype來實現繼承可以使子類擁有父類的共有屬性和方法,其它兩種不行。所以這裡主要討論如何用prototype實現繼承。 由於採用prototype繼承父類的執行個體在javascript繼承—繼承的實現原理(1)中已有論述,下面著重介紹用prototype繼承實現的幾種方式。 方案一: 直接將父類的prototype屬性賦給子類,同時用call繼承父類的特權屬性,然後再修改子類prototype的constructor 複製代碼function Person(name,age){    this.name = name;    this.age = age;} Person.prototype = {    sayHi:function(){        alert('hi');    }} function Student(name,age,grade){    Person.call(this,name,age);    this.grade = grade;} Student.prototype = Person.prototype; //Student.prototype.constructor = Student;Student.prototype.study = function(){    alert('study');}var p1 = new Person('xiaoming',10);var s1 = new Student('xiaohong',9,3);//p1.study();// p1.study is not a function 說明Person的執行個體沒有study方法,即子類的共有方法沒有被父類共用console.log(p1);//Person { name="xiaoming", age=10, sayHi=function()}console.log(s1);//Student { name="xiaohong", age=9, grade=3, 更多...}console.log(p1.constructor);//Object() console.log(s1.constructor);//Object() 子類父類執行個體相同都為Object /**如果在原文中加上Student.prototype.constructor = Student;則console.log(p1.constructor);//Student() console.log(s1.constructor);//Student() 子類父類執行個體相同都為Student***/複製代碼這種方案經測試是行不通的,因為不管怎麼變,子類和父類的執行個體都會共有相同的constructor,這種情形下修改子類的共有方法,同時會修改了父類的共有方法,說明此法不通。 方案二: 將父類的執行個體賦給子類的原型對象,同時使用call方法使子類繼承父類的特權屬性。 複製代碼function Person(name,age){    this.name = name;    this.age = age;} Person.prototype = {    constructor:Person,    sayHi:function(){        alert('hi');    }} function Student(name,age,grade){    Person.call(this,name,age);    this.grade = grade;} Student.prototype = new Person();Student.prototype.constructor = Student;Student.prototype.study = function(){    alert('study');}var p1 = new Person('xiaoming',10);var s1 = new Student('xiaohong',9,3);//p1.study();// p1.study is not a function 說明Person的執行個體沒有study方法,即子類的共有方法沒有被父類共用console.log(p1);//Person { name="xiaoming", age=10, sayHi=function()}console.log(s1);//Student { name="xiaohong", age=9, grade=3, 更多...}console.log(p1.constructor);//Person(name,age) 父類的執行個體指向仍是父類console.log(s1.constructor);//Student(name,age,grade) //子類的執行個體指向仍是子類複製代碼得到的結果基本符合我們繼承的要求,但是這個繼承實現方式所繼承的是父類執行個體所有的屬性和方法,即執行個體方法(也可以說是特權方法),每建立一個子類對象都會把父類的特權方法,共有方法都複製一遍,這樣代碼區會出現大量重複。這時建立子類的執行個體就相當於javascript建立對象的三種模式 中的第二種建構函式模式。 方案三: 用prototype實現原型鏈繼承。 複製代碼function Person(name,age){    this.name = name;    this.age = age;}//第一種建立共有方法方式Person.prototype.sayHi = function(){    alert('hi');}//第二種建立共有方法方式/*--------------------------------------------------------Person.prototype = {    constructor:Person,    sayHi:function(){        alert('hi');    }}-------------------------------------------------------*/ function Student(name,age,grade){    Person.call(this,name,age);    this.grade = grade;} for(var i in Person.prototype){Student.prototype[i] = Person.prototype[i]}Student.prototype.study = function(){    alert('study');}var p1 = new Person('xiaoming',10);var s1 = new Student('xiaohong',9,3);//p1.study();// p1.study is not a function 說明Person的執行個體沒有study方法,即子類的共有方法沒有被父類共用console.log(p1);//Person { name="xiaoming", age=10, sayHi=function()}console.log(s1);//Student { name="xiaohong", age=9, grade=3, 更多...}console.log(p1.constructor);//Person(name,age) 父類的執行個體指向仍是父類console.log(s1.constructor);//Student(name,age,grade) //子類的執行個體指向仍是子類/*--------------------------------------------------------第二種方式console.log(p1.constructor);//Person() 父類的執行個體指向仍是Person-------------------------------------------------------*/複製代碼對於第二種建立共有方法,如果建立的時候不加constructor: Person,得到的父類執行個體會指向Object,是因為建立共有方法的時候直接將一個包含共有方法的Object對象賦給了父類的prototype屬性,將父類原有的constructor屬性Person修改為Object。所以會出現這種情形。 經過測試,這種繼承方式是可行的。使用這種方式繼承,可以看到基本實現了子類繼承父類的所有屬性和方法,並且子類的建構函式仍是子類,父類的建構函式是父類。自認為這是最佳方案。  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.