JavaScript中的几种继承方法示例


Posted in Javascript onDecember 06, 2020

1.原型链继承

原理: 子类原型指向父类实例对象实现原型共享,即Son.prototype = new Father()。

这里先简单介绍下原型

js中每个对象都有一个__proto__属性,这个属性指向的就是该对象的原型。js中每个函数都有一个prototype属性,这个属性指向该函数作为构造函数调用时创建的实例的原型。原型对象上有一个constructor属性,指向创建该对象的构造函数,该属性不可枚举。

var obj = {};
obj.__proto__ === Object.prototype; //true
console.log(Object.prototype.constructor) // ƒ Object

当我们访问一个对象的属性或者方法时,如果找不到,则会通过原型向上寻找,若原型上也未找到,则会去原型的原型上面去找。比如我要调用obj.toString方法时,在自身并未找到toString方法,则会去原型上去寻找,即在Object.prototype上去寻找,找到后运行该方法。

var obj = {};
obj.toString();
obj.__proto__.toString(); //obj.__proto__和Object.prototype指向的是一个对象,自然就能访问Object.prototype上的toString方法啦

注意:原型链的终点是null,使用bind方法返回的函数没有prototype属性。

var obj = {};
function fn(){};
fn.bind(obj).prototype; // undefined
Object.prototype.__proto__; // null

原型链接继承

function Father(age){
 this.age = age;
 this.color = ['red','pink']
}
Father.prototype.sayHello = function(){
 console.log('hello')
} 
function Son(sex){
 this.sex = sex
}
console.log(Son.prototype.constructor) // ƒ Son
Son.prototype = new Father(15) // 原型链继承关键
var son = new Son('男')
son.color.push('black')
var son2 = new Son('女')
son.sayHello() // hello
son.sayHello === son2.sayHello //true
console.log(son2.color) // ['red','pink','black']
console.log(Son.prototype.constructor) // ƒ Father

可以看到通过原型链实现继承,原型上引用类型的值会被所有实例共享。子类的constructor指向会发生改变,而且在创建子类实例时不可以向父类构造函数传递参数。可以手动把子类constructor属性指回其构造函数。

//写法一
Son.prototype.constructor = Son // 这种写法有点缺点,它会让constructor属性变的可以枚举。

//写法二
Object.defineProperty(Son.prototype,'constructor',{
 enumerable:false, // 设置不可枚举
 value:Son
})

2.构造函数继承

原理:在子类构造函数中通过apply或者call调用父类构造函数来继承属性或方法。

function Father(name){
 this.color = ['red']
 this.sayHello = function(){
  console.log('hello')
 }
}
Father.prototype.sayName = function(){
 console.log('zs')
}
function Son(num,name){
 Father.call(this,name) //实现继承的关键代码
 this.num = num
}
var son = new Son(10,'zs')
var son2 = new Son(15,'ls')
son.color.push('pink')
console.log(son2.color) // ['red']
son.sayName() //报错 son.sayName is not a function
console.log(son.sayHello === son2.sayHello) //false

可以看出通过构造函数实现继承,解决了原型链继承不能向父类传参以及引用类型值共享的问题。但这种继承方法却不能访问父类构造函数原型上的方法和属性,而且定义在父类构造函数中的方法也不能复用。

3.组合式继承

组合继承,有时候也叫伪经典继承,它是将原型链继承和构造函数继承结合到一起的一种继承模式。实现思路是通过原型链实现对原型属性和方法的继承,通过借用构造函数实现对实例属性的继承。

function Father(name){
 this.color = ['red']
}
Father.prototype.sayName = function(){
 console.log('zs')
}
function Son(num,name){
 Father.call(this,name) //继承实例属性
 this.num = num
}
Son.prototype = new Father() //继承原型上属性
Son.prototype.constructor = Son
var son = new Son(10,'zs')
var son2 = new Son(15,'ls')
son.color.push('pink')
console.log(son.color,son2.color) //['red','pink'] ['red']
son.sayName() // zs

组合式继承避免了原型链继承和构造函数继承的缺点,融合了它们的优点,成为JavaScript中常用的一种继承模式。

4.寄生式继承

寄生式继承与工厂模式类似,一般用来继承对象。即创建一个封装继承的函数,在函数内部复制一份该对象,对复制的对象进行处理,返回复制的对象。

function createAnother(obj){
  var clone = Object.create(obj)
  clone.name = 'zs'
  clone.sayHello = function(){
   console.log('hello')
  }
  return clone
}
var obj = {age:15}
var newObj = createAnother(obj) // 15
console.log(newObj.name) // zs
newObj.sayHello() // hello

5.寄生组合式继承

前面说到过组合式继承是Javascript中最常用的继承模式,不过这种模式也有自己的不足,它会调用两次父类构造函数。第一次是在将子类原型指向父类实例的时候,第二次是在子类构造函数中调用的。

function Father(name){
  this.name = name
 }
 function Son(num,name){
  Father.call(this,name) // 第二次调用
 }
 Son.prototype = new Father('ls') // 第一次调用
 var son = new Son(10,'zs')
 console.log(son)

在第一次调用的时候,Son.prototype会继承name这个属性,第二次调用时,实例对象会继承name。当我们获取实例对象的name属性时因为实例对象上有该属性,所以是不会去原型上去寻找的,相当于实例对象上的name属性把原型上的name属性给屏蔽掉了,所以原型上的这个属性是多余的。

JavaScript中的几种继承方法示例

为了解决这个问题,就有了寄生组合式继承。主要思路就是创建一个函数完成原型链继承和constructor的指向问题,然后通过构造函数继承属性。

// 复制一个父类的原型指向,将子类的原型指向复制的父类原型,达到不用调用父类构造函数就能继承其原型上的方法的效果。
 function inherit(Sup,Sub){
  var prototype = Object.create(Sup.prototype)
  Sub.prototype = prototype
  prototype.constructor = Sub
 }
 function Father(name){
  this.name = name
 }
 function Son(name){
 Father.call(this,name)
 }
 inherit(Father,Son)
 var son = new Son('zs')
 console.log(son)

JavaScript中的几种继承方法示例

以上就是JavaScript中常用的几种继承方式啦。

到此这篇关于JavaScript中的几种继承方法的文章就介绍到这了,更多相关JavaScript继承方法内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
json-lib出现There is a cycle in the hierarchy解决办法
Feb 24 Javascript
javascript使用数组的push方法完成快速排序
Sep 15 Javascript
使用JQ来编写最基本的淡入淡出效果附演示动画
Oct 31 Javascript
js判断一个字符串是否包含一个子串的方法
Jan 26 Javascript
快速解决js中window.location.href不工作的问题
Nov 02 Javascript
js实现鼠标左右移动,图片也跟着移动效果
Jan 25 Javascript
Node.js连接MongoDB数据库产生的问题
Feb 08 Javascript
vue.js $refs和$emit 父子组件交互的方法
Dec 20 Javascript
vue获取当前点击的元素并传值的实例
Mar 09 Javascript
手淘flexible.js框架使用和源代码讲解小结
Oct 15 Javascript
Vue 实现显示/隐藏层的思路(加全局点击事件)
Dec 31 Javascript
angular组件间传值测试的方法详解
May 07 Javascript
js调用网络摄像头的方法
Dec 05 #Javascript
浅谈Vue使用Elementui修改默认的最快方法
Dec 05 #Vue.js
vue+element_ui上传文件,并传递额外参数操作
Dec 05 #Vue.js
JavaScript实现浏览器网页自动滚动并点击的示例代码
Dec 05 #Javascript
解决vue下载后台传过来的乱码流的问题
Dec 05 #Vue.js
js获取图片的base64编码并压缩
Dec 05 #Javascript
js重写alert事件(避免alert弹框标题出现网址)
Dec 04 #Javascript
You might like
URL Rewrite的设置方法
2007/01/02 PHP
PHP性能分析工具XHProf安装使用教程
2015/05/13 PHP
070823更新的一个[消息提示框]组件 兼容ie7
2007/08/29 Javascript
关于文本框的一些限制控制总结~~
2010/04/15 Javascript
web网页按比例显示图片实现原理及js代码
2013/08/09 Javascript
js常用自定义公共函数汇总
2014/01/15 Javascript
JavaScript异步加载浅析
2014/12/28 Javascript
jquery滚动特效集锦
2015/06/03 Javascript
javascript+HTML5自定义元素播放焦点图动画
2016/02/21 Javascript
BootStrap下拉框在firefox浏览器界面不友好的解决方案
2016/08/18 Javascript
js插件Jcrop自定义截取图片功能
2016/10/14 Javascript
Bootstrap 模态框(Modal)插件代码解析
2016/12/21 Javascript
深入理解jquery中extend的实现
2016/12/22 Javascript
利用node.js实现反向代理的方法详解
2017/07/24 Javascript
基于JavaScript实现百度搜索框效果
2020/06/28 Javascript
详解vue 模拟后台数据(加载本地json文件)调试
2017/08/25 Javascript
JavaScript函数节流和函数去抖知识点学习
2018/07/31 Javascript
小程序实现多选框功能
2018/10/30 Javascript
[01:13:59]LGD vs Mineski Supermajor 胜者组 BO3 第三场 6.5
2018/06/06 DOTA
python通过文件头判断文件类型
2015/10/30 Python
Python实现的径向基(RBF)神经网络示例
2018/02/06 Python
python接口自动化(十六)--参数关联接口后传(详解)
2019/04/16 Python
美国最大的无人机经销商:DroneNerds
2018/03/20 全球购物
Saks Fifth Avenue澳洲/亚太地区:萨克斯第五大道精品百货店
2019/06/09 全球购物
门卫岗位职责
2013/11/15 职场文书
优秀辅导员事迹材料
2014/02/16 职场文书
环保项目建议书
2014/08/26 职场文书
农村党支部书记四风问题个人对照检查材料
2014/09/21 职场文书
2014县委书记党的群众路线教育实践活动对照检查材料思想汇报
2014/09/22 职场文书
教师节大会主持词
2015/07/06 职场文书
致运动员的广播稿
2015/08/19 职场文书
幼儿园迎新生欢迎词
2015/09/30 职场文书
大学组织委员竞选稿
2015/11/21 职场文书
Python-OpenCV实现图像缺陷检测的实例
2021/06/11 Python
关于nginx 实现jira反向代理的问题
2021/09/25 Servers
vue中 this.$set的使用详解
2021/11/17 Vue.js