JavaScript实现继承

以下内容均基于本人对《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. 无法在创建子类的实例时,给父类的构造函数传递参数(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 functiondog2.briefInfo();  //error: dog2.briefInfo is not a function 

存在的问题:

  1. 父类原型中定义的属性无法被继承

综合方式一方式二,一种很明显的方式呼之欲出了:

方式三:组合继承

实现方式:结合原型链继承和经典继承

子类

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}}//终于得到了预期的结果,算是较好的实现了继承。//但是,并不完美

存在的问题

  1. 父类的构造函数被调用了两次

为了引出下一个继承方式,先将函数的继承放在一边,看一下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继承了person

2. 寄生式继承

function createAnother(original) {  var clone = object(original);    //原型式继承定义的方法  //扩展对象  clone.sayHi = function() {    console.log('hi');  }  return clone;}

回到正题,接下来介绍一颗 “银弹”

方式四:寄生组合式继承

实现方式:

  1. 利用经典继承拷贝父类构造中的属性到子类

  2. 利用原型式继承创建一个继承父类原型的对象

  3. 将该对象的constructor属性指向子类的构造函数(寄生式继承:扩展对象)

  4. 将子类的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}}

关键字:JavaScript, 继承

版权声明

本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部