浅谈js中的三种继承方式及其优缺点


Posted in Javascript onAugust 10, 2016

第一种,prototype的方式:

//父类 
function person(){ 
  this.hair = 'black'; 
  this.eye = 'black'; 
  this.skin = 'yellow'; 
  this.view = function(){ 
    return this.hair + ',' + this.eye + ',' + this.skin; 
  } 
} 

//子类 
function man(){ 
  this.feature = ['beard','strong']; 
} 

man.prototype = new person(); 
var one = new man(); 

console.log(one.feature); //['beard','strong'] 
console.log(one.hair); //black 
console.log(one.eye); //black 
console.log(one.skin); //yellow 
console.log(one.view()); //black,black,yellow

这种方式最为简单,只需要让子类的prototype属性值赋值为被继承的一个实例就行了,之后就可以直接使用被继承类的方法了。

prototype 属性是啥意思呢? prototype 即为原型,每一个对象 ( 由 function 定义出来 ) 都有一个默认的原型属性,该属性是个对象类型。

并且该默认属性用来实现链的向上攀查。意思就是说,如果某个对象的属性不存在,那么将通过prototype属性所属对象来查找这个属性。如果 prototype 查找不到呢?

js会自动地找prototype的prototype属性所属对象来查找,这样就通过prototype一直往上索引攀查,直到查找到了该属性或者prototype最后为空 (“undefined”);

例如上例中的one.view()方法,js会先在one实例中查找是否有view()方法,因为没有,所以查找man.prototype属性,而prototype的值为person的一个实例,

该实例有view()方法,于是调用成功。

第二种,apply的方式:

//父类 
function person(){ 
  this.hair = 'black'; 
  this.eye = 'black'; 
  this.skin = 'yellow'; 
  this.view = function(){ 
    return this.hair + ',' + this.eye + ',' + this.skin; 
  } 
} 

//子类 
function man(){ 
  // person.apply(this,new Array()); 
  person.apply(this,[]); 
  this.feature = ['beard','strong']; 
} 

var one = new man(); 

console.log(one.feature); //['beard','strong'] 
console.log(one.hair); //black 
console.log(one.eye); //black 
console.log(one.skin); //yellow 
console.log(one.view()); //black,black,yellow

注意:如果apply参数为空,即没有参数传递,则通过 new Array() 、[] 来传递,null 无效。

第三种,call+prototype的方式:

//父类 
function person(){ 
  this.hair = 'black'; 
  this.eye = 'black'; 
  this.skin = 'yellow'; 
  this.view = function(){ 
    return this.hair + ',' + this.eye + ',' + this.skin; 
  } 
} 

//子类 
function man(){ 
  // person.apply(this,new Array()); 
  person.call(this,[]); 
  this.feature = ['beard','strong']; 
} 

man.prototype = new person(); 
var one = new man(); 

console.log(one.feature); //['beard','strong'] 
console.log(one.hair); //black 
console.log(one.eye); //black 
console.log(one.skin); //yellow 
console.log(one.view()); //black,black,yellow

call方式的实现机制却要多一条 man.prototype = new person(); 为啥呢?
那是因为call方法只实现了方法的替换而没有作对象属性的复制操作。
google Map API 的继承就是使用这种方式。

上面总结了三种继承方式的实现。但是每种方法都有其优缺点。

假如父类是这样的:

//父类 
function person(hair,eye,skin){ 
  this.hair = hair; 
  this.eye = eye; 
  this.skin = skin; 
  this.view = function(){ 
    return this.hair + ',' + this.eye + ',' + this.skin; 
  } 
}

子类应该如何设计,使子类man在创建对象的同时传递参数到父类person,prototype的继承方式就不适用了,
必须采用apply或者call的方式了:

//apply方式 
//子类 
function man(hair,eye,skin){ 
  person.apply(this,[hair,eye,skin]); 
  this.feature = ['beard','strong']; 
} 
//call方式 
//子类 
function man(hair,eye,skin){ 
  person.call(this,hair,eye,skin); 
  this.feature = ['beard','strong']; 
}

但是用apply方法也还是有缺点的,为什么?在js中,我们有个非常重要的运算符就是”instanceof”,该运算符用来比较某个对向是否为某种类型。

对于这个例子,one实例除了是man类型,也应该是person类型,但是apply方式继承之后,one却不属于person类型,即(one instanceof person)的值为false。

经此种种,最好的继承方式就是call+prototype方式了,之后你可以试一下(one instanceof BaseClass)的值是否为true。

第三种继承方式也有缺陷:子类new对象时要传一遍父类所需的参数,而且会重现父类中的属性和方法,下面这种继承方式才是完善的:

function Person(name){   
  this.name = name; 
} 

Person.prototype.getName = function() { 
  return this.name; 
} 

function Chinese(name, nation) { 
  Person.call(this, name); 
  this.nation = nation; 
} 

//继承方法 
function inherit(subClass, superClass) { 
  function F() {} 
  F.prototype = superClass.prototype; 
  subClass.prototype = new F(); 
  subClass.prototype.constructor = subClass.constructor; 
} 

inherit(Chinese, Person); 

Chinese.prototype.getNation = function() { 
  return this.nation; 
}; 

var p = new Person('shijun'); 
var c = new Chinese("liyatang", "China"); 

console.log(p); // Person {name: "shijun", getName: function} 
console.log(c); // Chinese {name: "liyatang", nation: "China", constructor: function, getNation: function, getName: function} 


console.log(p.constructor); // function Person(name){} 
console.log(c.constructor); // function Chinese(){} 

console.log(c instanceof Chinese); // true 
console.log(c instanceof Person); // true

以上这篇浅谈js中的三种继承方式及其优缺点就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
更优雅的事件触发兼容
Oct 24 Javascript
js控制table合并具体实现
Feb 20 Javascript
JS简单计算器实例
Jan 20 Javascript
jQuery的css() 方法使用指南
May 03 Javascript
javascript实现可键盘控制的抽奖系统
Mar 10 Javascript
轻松实现js弹框显示选项
Sep 13 Javascript
基于js的变量提升和函数提升(详解)
Sep 17 Javascript
微信小程序实现人脸识别
May 25 Javascript
vue-router实现编程式导航的代码实例
Jan 19 Javascript
详解关于webpack多入口热加载很慢的原因
Apr 24 Javascript
微信小程序如何访问公众号文章
Jul 08 Javascript
在vue中实现给每个页面顶部设置title
Jul 29 Javascript
jQuery+HTML5+CSS3制作支持响应式布局时间轴插件
Aug 10 #Javascript
基于js中的原型、继承的一些想法
Aug 10 #Javascript
新入门node.js必须要知道的概念(必看篇)
Aug 10 #Javascript
jQuery制作圣诞主题页面 更像是爱情影集
Aug 10 #Javascript
jquery实现拖动效果
Aug 10 #Javascript
JS弹出新窗口被拦截的解决方法
Aug 09 #Javascript
只要1K 纯JS脚本送你一朵3D红色玫瑰
Aug 09 #Javascript
You might like
使用php计算排列组合的方法
2013/11/13 PHP
php中opendir函数用法实例
2014/11/15 PHP
php计算给定时间之前的函数用法实例
2015/04/03 PHP
php实现的中文分词类完整实例
2017/02/06 PHP
PHP将数据导出Excel表中的实例(投机型)
2017/07/31 PHP
Laravel 模型关联基础教程详解
2019/09/17 PHP
PHP设计模式之数据访问对象模式(DAO)原理与用法实例分析
2019/12/12 PHP
javascript网页关键字高亮代码
2008/07/30 Javascript
javascript 获取所有id中包含某关键字的控件的实现代码
2010/11/25 Javascript
带左右箭头图片轮播的JS代码
2013/12/18 Javascript
jquery动态添加option示例
2013/12/30 Javascript
jquery插件开发之实现md5插件
2014/03/17 Javascript
javascript DIV实现跟随鼠标移动
2020/03/19 Javascript
关于JS 预解释的相关理解
2016/06/28 Javascript
JS实现图片高斯模糊切换效果的焦点图实例
2017/01/21 Javascript
Bootstrap图片轮播效果详解
2017/10/17 Javascript
vue响应式系统之observe、watcher、dep的源码解析
2019/04/09 Javascript
vue项目创建并引入饿了么elementUI组件的步骤
2019/04/11 Javascript
javaScript把其它类型转换为Number类型
2019/10/13 Javascript
Vue实现剪贴板复制功能
2019/12/31 Javascript
解决vue 给window添加和移除resize事件遇到的坑
2020/07/21 Javascript
17个Python小技巧分享
2015/01/23 Python
Python实现单词拼写检查
2015/04/25 Python
从列表或字典创建Pandas的DataFrame对象的方法
2019/07/06 Python
基于MSELoss()与CrossEntropyLoss()的区别详解
2020/01/02 Python
python实现串口通信的示例代码
2020/02/10 Python
利用 Python ElementTree 生成 xml的实例
2020/03/06 Python
查看已安装tensorflow版本的方法示例
2020/04/19 Python
python virtualenv虚拟环境配置与使用教程详解
2020/07/13 Python
Ooni英国官网:披萨烤箱
2020/05/31 全球购物
工程师求职简历的自我评价分享
2013/10/10 职场文书
国旗下的演讲稿
2014/05/08 职场文书
植树节口号
2014/06/21 职场文书
村主任“四风”问题个人对照检查材料思想汇报
2014/10/02 职场文书
晚自修旷课检讨书怎么写
2014/11/17 职场文书
走进毛泽东观后感
2015/06/04 职场文书