由于写本文时全部是在编辑器中边写代码边写感想的,所以,全部思想都写在代码注释里面了

// 类继承

//todo.1 extends 关键字

class Animal {
constructor(name) {
this.speed = 0;
this.name = name;
}
run(speed) {
this.speed = speed;
console.log(`${this.name} runs with speed ${this.speed}`);
}
} // 如果“派生类”使用constructor函数,则必须在constructor调用this之前使用super来调用被继承类的constructor
// 如果“派生类”没有使用constructor函数,则默认会生成一个constructor,代码如下
/**
* constructor(...args) {
* super(...args)
* }
*/
// 为什么需要super() ?
// 因为“派生类(derived constructor)的构造函数与其他函数之间的区别在于其具有特殊的内部属性[[ConstructorKind]]:derived”
// 这个属性会影响new 的行为; 当通过new执行一个常规函数时,它将创建一个空对象,并将这个空对象赋值给this;
// 但是当继承的constructor执行时,它不会执行此操作,它期望父类的constructor来完成这项工作。因此派生类必须执行super才能执行
// 父类的constructor来完成这项工作,否则this指向的那个对象不会创建,并且程序会报错!
class Rabbit extends Animal {
constructor(name, color) {
super(name);
this.color = color;
}
} const rabbit = new Rabbit("兔子", "白色"); //todo.2 深入探究内部原理和[[HomeObject]]
// 让我们先来看一个例子。 const animal = {
name:'Animal',
eat() {
console.log('animal');
}
} const tiger = {
__proto__:animal,
name:'tiger',
eat() {
this.__proto__.eat.call(this);
}
} const youngTiger = {
__proto__:tiger,
name:'youngTiger',
eat() {
this.__proto__.eat.call(this);
}
} tiger.eat(); // animal
// youngTiger.eat(); // RangeError: Maximum call stack size exceeded // 为什么会报错?让我们来深入探究一下 /**
* 在youngerTiger.eat中
* this.__proto__.eat.call(this)
* 等于
* youngTiger.__proto__.eat.call(this)
* 等于
* tiger.eat.call(this)
* 在tiger.eat中
* this.__proto__.eat.call(this)
* 等于
* youngTiger.__proto__.eat.call(this)
* 等于
* tiger.eat.call(this)
*/ // 解决方案:[[HomeObject]] // 当一个函数被定义为类或者对象方法时,它的 [[HomeObject]] 属性就成为了该对象。
// 然后 super 使用它来解析(resolve)父原型及其方法。 let plant = {
name:'Plant',
grow() {
console.log(`${this.name} growing`);
}
} let flower = {
__proto__:plant,
grow() {
super.grow();
}
} let greenFlower = {
__proto__:flower,
grow() {
super.grow()
}
} greenFlower.grow();//Plant growing // [[HomeObject]]内置属性是被绑定到JavaScript对象上的,“方法”由哪个对象创建,则
// [[HomeObject]]指向哪个对象,并且[[HomeObject]]一旦创建就是不可变的
// 而且只能被super解析。注意:“方法”不是“函数属性”,
// “方法” {method(){}},“函数属性”{method:function(){}} // 解析,当对象嵌套继承时,为了避免Maximum call stack size exceeded错误,
// 我们可以使用super来代替 this.__proto__.method.call(this)方法,前提是
// [[HomeObject]]属性存在,并且__proto__存在

推荐阅读:《现代JavaScript教程》- 类继承

深入理解JavaScript中的类继承的更多相关文章

  1. 理解JavaScript中的原型继承(2)

    两年前在我学习JavaScript的时候我就写过两篇关于原型继承的博客: 理解JavaScript中原型继承 JavaScript中的原型继承 这两篇博客讲的都是原型的使用,其中一篇还有我学习时的错误 ...

  2. JavaScript中的类继承

    JavaScript是一个无class的面向对象语言,它使用原型继承而非类继承.这会让那些使用传统面向对象语言如C++和Java的程序员们感到困惑.正如我们所看到的,JavaScript的原型继承比类 ...

  3. 深入理解 JavaScript 中的 class

    在 ES6 规范中,引入了 class 的概念.使得 JS 开发者终于告别了,直接使用原型对象模仿面向对象中的类和类继承时代. 但是JS 中并没有一个真正的 class 原始类型, class 仅仅只 ...

  4. 深入理解JavaScript中创建对象模式的演变(原型)

    深入理解JavaScript中创建对象模式的演变(原型) 创建对象的模式多种多样,但是各种模式又有怎样的利弊呢?有没有一种最为完美的模式呢?下面我将就以下几个方面来分析创建对象的几种模式: Objec ...

  5. 深入理解JavaScript中的属性和特性

    深入理解JavaScript中的属性和特性 JavaScript中属性和特性是完全不同的两个概念,这里我将根据自己所学,来深入理解JavaScript中的属性和特性. 主要内容如下: 理解JavaSc ...

  6. 【干货理解】理解javascript中实现MVC的原理

    理解javascript中的MVC MVC模式是软件工程中一种软件架构模式,一般把软件模式分为三部分,模型(Model)+视图(View)+控制器(Controller); 模型:模型用于封装与应用程 ...

  7. 理解javascript中的策略模式

    理解javascript中的策略模式 策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换. 使用策略模式的优点如下: 优点:1. 策略模式利用组合,委托等技术和思想,有效 ...

  8. 全面理解Javascript中Promise

    全面理解Javascript中Promise 最近在学习Promise的时候,在网上收集了一些资料,发现很多的知识点不够系统,所以小编特意为大家整理了一些自认为 比较好的文章,供大家更好地学习js中非 ...

  9. JavaScript中的类

          JavaScript类的相关知识 1.例子 /* 例1 */// 定义一个构造函数function Range(from, to){ this.from = from; this.to = ...

随机推荐

  1. 干货!上古神器 sed 教程详解,小白也能看的懂

    目录: 介绍工作原理正则表达式基本语法数字定址和正则定址基本子命令实战练习 介绍 熟悉 Linux 的同学一定知道大名鼎鼎的 Linux 三剑客,它们是 grep.awk.sed,我们今天要聊的主角就 ...

  2. linux登陆欢迎信息及命令提示符修改

    登录信息修改 登陆信息显示数据 : /etc/issue and /etc/motd 登陆终端机的时候,会有几行提示的字符串,这些设置在/etc/issue里面可以修改,提示内容在/etc/motd中 ...

  3. 对象存储 COS 帮您轻松搞定跨域访问需求

    背景 早期为了避免 CSRF(跨站请求伪造) 攻击,浏览器引入了 "同源策略" 机制.如果两个 URL 的协议,主机名(域名/IP),端口号一致,则视为这两个 URL " ...

  4. 从synchronized和lock区别入手聊聊java锁机制

    写这篇文章之前,我去百度了一下啥叫锁,百度百科上写道:置于可启闭的器物上,以钥匙或暗码开启.确实我们一般理解的锁就是门锁,密码锁,但是在计算机科学中,锁又是啥,说实话,这个问题我也思考了很久,也没法很 ...

  5. Connections could not be acquired from the underlying database!

    Connections could not be acquired from the underlying database! 报错截图: 报错内容: Exception in thread &quo ...

  6. 详解Mybatis拦截器(从使用到源码)

    详解Mybatis拦截器(从使用到源码) MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能. 本文从配置到源码进行分析. 一.拦截器介绍 MyBatis 允许你在 ...

  7. Go RPC 框架 KiteX 性能优化实践 原创 基础架构团队 字节跳动技术团队 2021-01-18

    Go RPC 框架 KiteX 性能优化实践 原创 基础架构团队 字节跳动技术团队 2021-01-18

  8. JPEG解码——(3)文件头解析

    与具体的编码数据空间相比,jpeg文件头占据非常小乃至可以忽略不计的大小. 仍然拿JPEG解码--(1)JPEG文件格式概览中的<animal park>这张图片来举例,从跳过SOS(FF ...

  9. JasperReports 取消自动分页/忽略分页

    因为需要将合同比价单由PDF文档形式改为HTML页面方式,虽然转换文档类型了,但是发现HTML页面中间到了一定行数就出现了空行把Detail给隔开了.之前总想着怎样消除中间空行,以为是报表top页面边 ...

  10. 最简单直接地理解Java软件设计原则之依赖倒置原则

    理论性知识 定义 依赖倒置原则,Dependence Inversion Principle (DIP) 高层模块不应该依赖低层模块.二者都应该依赖其抽象. 抽象不应该依赖细节,细节应该依赖抽象. 针 ...