浅谈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 相关文章推荐
[原创]图片分页查看
Aug 28 Javascript
jQuery 前的按键判断代码
Mar 19 Javascript
从QQ网站中提取的纯JS省市区三级联动菜单
Dec 25 Javascript
js解析json读取List中的实体对象示例
Mar 11 Javascript
浅谈利用JavaScript进行的DDoS攻击原理与防御
Jun 04 Javascript
Node.js开发教程之基于OnceIO框架实现文件上传和验证功能
Nov 30 Javascript
手机软键盘弹出时影响布局的解决方法
Dec 15 Javascript
使用vue.js实现checkbox的全选和多个的删除功能
Feb 17 Javascript
基于vue2实现左滑删除功能
Nov 28 Javascript
详解React中传入组件的props改变时更新组件的几种实现方法
Sep 13 Javascript
vue 开发之路由配置方法详解
Dec 02 Javascript
微信小程序基于movable-view实现滑动删除效果
Jan 08 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中使用addslashes函数报错问题的解决方法
2013/02/06 PHP
CI框架源码阅读,系统常量文件constants.php的配置
2013/02/28 PHP
PHP数字字符串左侧补0、字符串填充和自动补齐的几种方法
2014/05/10 PHP
PHP中spl_autoload_register()和__autoload()区别分析
2014/05/10 PHP
CodeIgniter中实现泛域名解析
2014/07/19 PHP
php中curl使用指南
2015/02/05 PHP
php获取本周星期一具体日期的方法
2015/04/20 PHP
PHP脚本自动识别验证码查询汽车违章
2016/12/20 PHP
php实现和c#一致的DES加密解密实例
2017/07/24 PHP
jquery+json 通用三级联动下拉列表
2010/04/19 Javascript
JavaScript实现弹出子窗口并传值给父窗口
2014/12/18 Javascript
jQuery中has()方法用法实例
2015/01/06 Javascript
javascript实现炫酷的拖动分页
2015/05/11 Javascript
C#中使用迭代器处理等待任务
2015/07/13 Javascript
CSS3实现动态背景登录框的代码
2015/07/28 Javascript
深入理解JS中的substr和substring
2016/04/26 Javascript
canvas时钟效果
2017/02/16 Javascript
浅谈JavaScript中的apply/call/bind和this的使用
2017/02/26 Javascript
VUE利用vuex模拟实现新闻点赞功能实例
2017/06/28 Javascript
Angular2环境搭建具体操作步骤(推荐)
2017/08/04 Javascript
解决Vue中mounted钩子函数获取节点高度出错问题
2018/05/18 Javascript
Pyinstaller将py打包成exe的实例
2018/03/31 Python
浅谈Python小波分析库Pywavelets的一点使用心得
2019/07/09 Python
Tensorflow模型实现预测或识别单张图片
2019/07/19 Python
TensorFlow基于MNIST数据集实现车牌识别(初步演示版)
2019/08/05 Python
python调用Matplotlib绘制分布点图
2019/10/18 Python
如何用Anaconda搭建虚拟环境并创建Django项目
2020/08/02 Python
美国最顶级的精品店之一:Hampden Clothing
2016/12/22 全球购物
美国波道夫·古德曼百货官网:Bergdorf Goodman
2017/11/07 全球购物
机电专业大学生求职信
2013/10/04 职场文书
2014信息公开实施方案
2014/02/22 职场文书
普希金诗歌赏析(6首)
2019/08/22 职场文书
68句权威创业名言
2019/08/26 职场文书
使用Html+Css实现简易导航栏功能(导航栏遇到鼠标切换背景颜色)
2021/04/07 HTML / CSS
Python使用sql语句对mysql数据库多条件模糊查询的思路详解
2021/04/12 Python
python和Appium的移动端多设备自动化测试框架
2022/04/26 Python