浅谈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正则匹配换行问题实现代码
Dec 10 Javascript
javascript动态判断html元素并执行不同的操作
Jun 16 Javascript
深入理解JavaScript系列(46):代码复用模式(推荐篇)详解
Mar 04 Javascript
jQuery实现文本展开收缩特效
Jun 03 Javascript
Javascript连接Access数据库完整实例
Aug 03 Javascript
javascript数组去重的六种方法汇总
Aug 16 Javascript
jquery实现全选、反选、获得所有选中的checkbox
Sep 13 Javascript
jQuery时间插件jquery.clock.js用法实例(5个示例)
Jan 14 Javascript
JS Array创建及concat()split()slice()的使用方法
Jun 03 Javascript
AngularJS执行流程详解
Feb 17 Javascript
vue 虚拟dom的patch源码分析
Mar 01 Javascript
electron 安装,调试,打包的具体使用
Nov 06 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
虫族 ZERG 概述
2020/03/14 星际争霸
PHP fopen 读取带中文URL地址的一点见解
2012/09/25 PHP
php中数字、字符与对象判断函数用法实例
2014/11/26 PHP
JavaScript中的对象化编程
2008/01/16 Javascript
jquery中常用的SET和GET
2009/01/13 Javascript
使用IE6看老赵的博客 jQuery初探
2010/01/17 Javascript
fancybox modal的完美解决(右上的X)
2012/10/30 Javascript
提取jquery的ready()方法单独使用示例
2014/03/25 Javascript
javascript实现鼠标拖动改变层大小的方法
2015/04/30 Javascript
js实现Select列表内容自动滚动效果代码
2015/08/20 Javascript
跟我学习javascript的全局变量
2015/11/16 Javascript
实例讲解jquery与json的结合
2016/01/07 Javascript
Javascript的表单与验证-非空验证
2016/03/18 Javascript
浅析JSONP技术原理及实现
2016/06/08 Javascript
从0开始学Vue
2016/10/27 Javascript
Vue.js 2.0学习教程之从基础到组件详解
2017/04/24 Javascript
利用纯JS实现像素逐渐显示的方法示例
2017/08/14 Javascript
浅谈React 服务器端渲染的使用
2018/05/08 Javascript
bootstrap里bootstrap动态加载下拉框的实例讲解
2018/08/10 Javascript
微信小程序HTTP接口请求封装的实现
2019/02/21 Javascript
详解vue2.6插槽更新v-slot用法总结
2019/03/09 Javascript
Vue自定义组件双向绑定实现原理及方法详解
2020/09/03 Javascript
[02:53]2018年度DOTA2最佳战队-完美盛典
2018/12/17 DOTA
python修改注册表终止360进程实例
2014/10/13 Python
django 自定义用户user模型的三种方法
2014/11/18 Python
Python 转义字符详细介绍
2017/03/21 Python
python生成不重复随机数和对list乱序的解决方法
2018/04/09 Python
浅析python继承与多重继承
2018/09/13 Python
Python flask框架post接口调用示例
2019/07/03 Python
使用python客户端访问impala的操作方式
2020/03/28 Python
python Paramiko使用示例
2020/09/21 Python
耐克中国官方商城:Nike中国
2018/10/18 全球购物
PHP数据运算类型都有哪些
2013/11/05 面试题
毕业生的自我评价分享
2013/12/18 职场文书
促销活动总结模板
2014/07/01 职场文书
英语导游欢迎词
2015/09/30 职场文书