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 相关文章推荐
jQuery Tools tab(幻灯片)
Jul 14 Javascript
jquery改变disabled的boolean状态的三种方法
Dec 13 Javascript
javascript 使用for循环时该注意的问题-附问题总结
Aug 19 Javascript
jQuery实现选项联动轮播效果【附实例】
Apr 19 Javascript
Javascript实现图片不间断滚动的代码
Jun 22 Javascript
js移动焦点到最后位置的简单方法
Nov 25 Javascript
webpack3+React 的配置全解
Aug 21 Javascript
Vue.js组件间的循环引用方法示例
Dec 27 Javascript
浅谈webpack打包过程中因为图片的路径导致的问题
Feb 21 Javascript
微信小程序使用scroll-view标签实现自动滑动到底部功能的实例代码
Nov 09 Javascript
基于Taro的微信小程序模板消息-获取formId功能模块封装实践
Jul 15 Javascript
javascript 原型与原型链的理解及实例分析
Nov 23 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
php中的静态变量的基本用法
2014/03/20 PHP
php格式化时间戳显示友好的时间实现思路及代码
2014/10/23 PHP
PHP使用PDO调用mssql存储过程的方法示例
2017/10/07 PHP
php连接sftp的作用以及实例代码
2019/09/23 PHP
PHP获取php,mysql,apche的版本信息及更多服务器信息
2021/03/09 PHP
一个XML格式数据转换为图表的例子
2010/02/09 Javascript
jquery easyui的tabs使用时的问题
2010/03/23 Javascript
jquery 注意事项与常用语法小结
2010/06/07 Javascript
基于Jquery与WebMethod投票功能实现代码
2011/01/19 Javascript
说明你的Javascript技术很烂的五个原因
2011/04/26 Javascript
深入理解JavaScript系列(15) 函数(Functions)
2012/04/12 Javascript
IE8对JS通过属性和数组遍历解析不一样的地方探讨
2013/05/06 Javascript
js实现鼠标拖动图片并兼容IE/FF火狐/谷歌等主流浏览器
2013/06/06 Javascript
javascript自动给文本url地址增加链接的方法分享
2014/01/20 Javascript
用Jquery选择器计算table中的某一列某一行的合计
2014/08/13 Javascript
Sort()函数的多种用法
2016/03/20 Javascript
详解JS获取HTML DOM元素的8种方法
2017/06/17 Javascript
原生JS 购物车及购物页面的cookie使用方法
2017/08/21 Javascript
vue+mock.js实现前后端分离
2019/07/24 Javascript
JavaScript 函数用法详解【函数定义、参数、绑定、作用域、闭包等】
2020/05/12 Javascript
Vue使用预渲染代替SSR的方法
2020/07/02 Javascript
[49:35]2018DOTA2亚洲邀请赛3月30日 小组赛A组 KG VS TNC
2018/03/31 DOTA
浅谈pymysql查询语句中带有in时传递参数的问题
2020/06/05 Python
利用python对excel中一列的时间数据更改格式操作
2020/07/14 Python
html5移动端价格输入键盘的实现
2019/09/16 HTML / CSS
去加拿大的旅行和假期:Canadian Affair
2016/10/25 全球购物
写一个函数返回1+2+3+…+n的值(假定结果不会超过长整型变量的范围)
2014/09/05 面试题
岗位职责定义及内容
2013/11/08 职场文书
岗位职责的含义
2013/11/17 职场文书
银行员工职业规划范文
2014/01/21 职场文书
小学庆六一活动方案
2014/02/28 职场文书
岗位廉政承诺书
2014/03/27 职场文书
授权委托书格式范文
2014/08/02 职场文书
兵马俑的导游词
2015/02/02 职场文书
学校食堂管理制度
2015/08/04 职场文书
WINDOWS 64位 下安装配置mysql8.0.25最详细的教程
2022/03/22 MySQL