浅谈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 相关文章推荐
让js弹出窗口居前显示的实现方法
Jul 10 Javascript
JS+CSS实现的日本门户网站经典选项卡导航效果
Sep 27 Javascript
使用RequireJS库加载JavaScript模块的实例教程
Jun 06 Javascript
js中获取 table节点各tr及td的内容简单实例
Oct 14 Javascript
JQuery中解决重复动画的方法
Oct 17 Javascript
Vue.js第四天学习笔记
Dec 02 Javascript
基于jQuery实现的查看全文功能【实用】
Dec 11 Javascript
基于JS实现仿百度百家主页的轮播图效果
Mar 06 Javascript
使用vue制作滑动标签
Sep 21 Javascript
jQuery 判断元素是否存在然后按需加载内容的实现代码
Jan 16 jQuery
原生js拖拽实现图形伸缩效果
Feb 10 Javascript
vue3中的组件间通信
Mar 31 Vue.js
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
文件上传类
2006/10/09 PHP
php数组函数序列 之shuffle()和array_rand() 随机函数使用介绍
2011/10/29 PHP
PHP导出EXCEL快速开发指南--PHPEXCEL的使用详解
2013/06/03 PHP
PHP strip_tags保留多个HTML标签的方法
2016/05/22 PHP
PHP获取指定时间段之间的 年,月,天,时,分,秒
2016/06/05 PHP
Yii实现复选框批量操作实例代码
2017/03/15 PHP
几个比较经典常用的jQuery小技巧
2010/03/01 Javascript
javascript getElementsByTagName
2011/01/31 Javascript
Javascript Web Slider 焦点图示例源码
2013/10/10 Javascript
js页面跳转的常用方法整理
2013/10/18 Javascript
基于JS实现EOS隐藏错误提示层代码
2016/04/25 Javascript
jquery制做精致的倒计时特效
2016/06/13 Javascript
Angularjs 动态改变title标题(兼容ios)
2016/12/29 Javascript
js编写简单的聊天室功能
2017/08/17 Javascript
Vue 全局loading组件实例详解
2018/05/29 Javascript
详解React 的几种条件渲染以及选择
2018/10/23 Javascript
javascript动态创建对象的属性详解
2018/11/07 Javascript
JavaScript实现猜数字游戏
2020/05/20 Javascript
python模块之sys模块和序列化模块(实例讲解)
2017/09/13 Python
你眼中的Python大牛 应该都有这份书单
2017/10/31 Python
Python判断两个对象相等的原理
2017/12/12 Python
python 将字符串转换成字典dict的各种方式总结
2018/03/23 Python
简单实现Python爬取网络图片
2018/04/01 Python
python opencv 检测移动物体并截图保存实例
2020/03/10 Python
python开发前景如何
2020/06/11 Python
Python实时监控网站浏览记录实现过程详解
2020/07/14 Python
使用jupyter notebook运行python和R的步骤
2020/08/13 Python
原生 JS+CSS+HTML 实现时序图的方法
2019/07/31 HTML / CSS
英国最大的宠物食品和宠物用品网上零售商: Zooplus
2016/08/01 全球购物
武汉东之林科技有限公司机试
2013/09/17 面试题
风险评估实施方案
2014/03/09 职场文书
单位工作证明格式模板
2014/10/04 职场文书
2014年文秘工作总结
2014/11/25 职场文书
先进工作者申报材料
2014/12/23 职场文书
电力培训学习心得体会
2016/01/11 职场文书
公司趣味运动会开幕词
2016/03/04 职场文书