摘要:继承可以使得子类具有父类别的各种属性和方法。继承是类与类之间的关系。继承的实质就是两次的原型搜索,像是实例属性而不是继承,才是继承。更多用法见继承。
前言
面试中最常会问到的问题:什么是继承?如何分别用 ES5 和 ES6 实现?想要学习继承,必须先学好原型与原型链,如果此部分还不清楚,请先学习此部分再来阅读本文,可参考我的文章JS之原型与原型链或浏览其他相关的学习网站。
定义继承到底是什么?维基百科是这样说的:继承(英语:inheritance)是面向对象软件技术当中的一个概念。如果一个类别B“继承自”另一个类别A,就把这个B称为“A的子类”,而把A称为“B的父类别”也可以称“A是B的超类”。继承可以使得子类具有父类别的各种属性和方法。详情点我。继承是类与类之间的关系。
var a = new Array() a.valueOf()
上面的a为什么可以使用valueOf方法?实际上是它是通过了原型链的搜索最终在Object.prototype里拿到了valueOf方法。
继承的实质就是两次的原型搜索,像a.push()是实例属性而不是继承,a.valueOf()才是继承。
自己实现原型链继承上面的结构就是我们要实现的,其中子类的Human和父类Object之间的继承是自带的,我们需要在Human后再加一个Man让person继承Human的属性和方法。
ES5实现继承1.把Human的自身的属性直接写在Man上:Human.call(this, name)
function Human(name) { // 创建一个 Human 构造函数 this.name = name } Human.prototype.run = function () { console.log("I can run") } function Man(name) { // 创建一个 Man 构造函数 Human.call(this, name) this.gender = "男" } Man.prototype.fight = function () { console.log("I can fight") } var dong = new Man("dong")
以上代码实现了上图的效果,但是我们并没有把Human也联系起来,我们想做的就是在第一第二层中加上Human这一层,即形成dong → Man → Human → Object 链式,也就是实现下图:
2.改变Man.prototype.__proto__的指向
所以我们只要把Man.prototype.__proto__的指向由Object.prototype变为指向Human.prototype即可,此时你可能觉得简单的加上一句Man.prototype.__proto__ = Human.prototype就可以改变它的指向,确实这种写法成功的改变了Man.prototype.__proto__的指向,但由于IE不支持这样的写法,所以我们要把代码修改为:
var f = function(){} f.prototype = Human.prototype Man.prototype = new f()
3.代码总结
function Human(name) { // 创建一个 Human 构造函数 this.name = name } Human.prototype.run = function () { console.log("I can run") } function Man(name) { // 创建一个 Man 构造函数 Human.call(this, name) this.gender = "男" } var f = function(){} f.prototype = Human.prototype Man.prototype = new f() //这里需要注意的问题是被修改的原型链的属性必须修改完后才能声明 //也就是这句话必须得写在fight 前,否则原型链一修改它里面的属性和方法就没了 Man.prototype.fight = function () { console.log("I can fight") } var dong = new Man("dong")ES6实现继承(class 和 extends)
class Human { constructor(name) { this.name = name } run() { console.log("I can run") } } class Man extends Human { //Man.prototype.__proto__ = Human.prototype constructor(name) { super(name) //Human.call(this,name) this.gender = "男" } fight(){ console.log("I can fight") } }
ES6中类的写法:自身属性name写在constructor里面,共有属性(原型链上的)run直接和他并列着写,而继承的写法:class后面是子类然后extends你的父类。更多用法见ES6继承。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/106598.html
摘要:在中必须调用方法,因为子类没有自己的对象,而是继承父类的对象,然后对其进行加工而就代表了父类的构造函数。虽然代表了父类的构造函数,但是返回的是子类的实例,即内部的指的是,因此在这里相当于。要求,子类的构造函数必须执行一次函数,否则会报错。 1.class ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES...
摘要:在中必须调用方法,因为子类没有自己的对象,而是继承父类的对象,然后对其进行加工而就代表了父类的构造函数。虽然代表了父类的构造函数,但是返回的是子类的实例,即内部的指的是,因此在这里相当于。要求,子类的构造函数必须执行一次函数,否则会报错。 1.class ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES...
摘要:返回布尔值,表示参数字符串是否在源字符串的头部。参考语法返回一个布尔值与的全等操作符比较兼容环境把对象的值复制到另一个对象里浅拷贝定义方法用于将所有可枚举的属性的值从一个或多个源对象复制到目标对象。语法要设置其原型的对象。 一步一步似爪牙。 前言 学习es6之前我们可能并不知道es6相比es5差距在哪, 但是这并不妨碍我们站在巨人的肩膀上; 程序员就是要乐于尝鲜; 学习es6最终目的是...
摘要:生成的类的原型会被自动调整,而你还能调用方法来访问基类的构造器。唯一能避免调用的办法,是从类构造器中返回一个对象。 起源 JS 从创建之初就不支持类,也没有把类继承作为定义相似对象以及关联对象的主要方式,这让不少开发者感到困惑。而从 ES1 诞生之前直到ES5 时期,很多库都创建了一些工具,让 JS 显得貌似能支持类。尽管一些 JS 开发者强烈认为这门语言不需要类,但为处理类而创建的代...
阅读 1103·2019-08-30 12:44
阅读 613·2019-08-29 13:03
阅读 2513·2019-08-28 18:15
阅读 2379·2019-08-26 10:41
阅读 3044·2019-08-26 10:28
阅读 2991·2019-08-23 16:54
阅读 1953·2019-08-23 15:16
阅读 764·2019-08-23 14:55