一起手写吧!ES5和ES6的继承机制!
原型
执行代码var o = new Object();
此时o对象内部会存储一个指针,这个指针指向了Object.prototype,当执行o.toString()等方法(或访问其他属性)时,o会首先查看自身有没有该方法或属性,如果没有的话就沿着内部存储的指针找到Object.prototype对象,然后查看Object.prototype对象是否有对应名称的方法或属性,如果有就调用Object.prototype的方法或属性。
我们把这个指针叫做o对象的原型。
ES3规范中定义了Object.prototype.isPrototypeOf()方法,该方法可以判断某个对象是不是另一个对象的原型。Object.prototype.isPrototypeOf(o)返回true值可以确定Object.prototype就是o对象的原型。
在ES3规范中,不能直接读取o对象的原型,也就是o对象的原型看不见摸不着的。ES5.1规范定义了Object.getPrototypeOf()方法,通过该方法可以获取对象的原型。我们可以通过Object.getPrototypeOf(o) === Object.prototype再次验证Object.prototype就是o对象的原型。
ES6规范更加直接,为对象添加了一个__proto__属性,通过这个属性就可以获得对象的原型,所以在支持__proto__的浏览器中,o.__proto__ === Object.prototype也会返回true。
当我们执行var x = new X();时,浏览器会执行x.__proto__ = X.prototype,会将实例化对象的原型设置为对应的类的prototype对象,这一点很重要。
原型链
我们执行如下代码:
function Person(){};
var p = new Person();
p.__proto__指向了Person.prototype,Person.prototype的原型是Person.prototype.__proto__,其指向了Object.prototype,Object.prototype.__proto__为null。
通过__proto__向上追踪形成了如下的链式结构:
p -> Person.prototype -> Object.prototype -> null
这一原型的链式结构就叫做原型链。Object.prototype的原型是null,也就是说Object.prototype没有原型。
JavaScript 对象有一个指向一个原型对象的链。当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依此层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。
JavaScript中的继承是通过原型实现的,虽然在ES6中引入了class关键字,但是它只是原型的语法糖,JavaScript继承仍然是基于原型实现的。
ES5寄生组合继承 (业内比较提倡的方法)
function inserit(son, father) {
var obj = Object.create(father.prototype);
son.prototype = obj;
obj.constructor = son
}
function SuperType(name, colors) {
this.name = name;
this.colors = colors;
}
SuperType.prototype.sayName = function () {
return this.name;
}
function SubType(job, name, color) {
SuperType.call(this, name, color);
this.job = job;
}
//核心方法
inserit(SubType, SuperType);
SubType.prototype.sayjob = function () {
return this.job;
}
var instance = new SubType("doctor", "John", ["red", "green"]);
console.log(instance.sayjob(), instance.sayName()) //doctor,John
ES6继承
ES6支持通过类来实现继承,方法比较简单,代码如下
class Point {
constructor(x, y) {
this.x = x
this.y = y
}
toString() {
return this.x + '' + this.y
}
}
class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y) //调用父类的constructor(x, y)
this.color = color
}
toString() {
return this.color + ' ' + super.toString() // 调用父类的toString()
}
}
var colorPoint = new ColorPoint('1', '2', 'red')
console.log(colorPoint.toString()) // red 12
一起手写吧!ES5和ES6的继承机制!的更多相关文章
- 详解ES5和ES6的继承
ES5继承 构造函数.原型和实例的关系:每一个构造函数都有一个原型对象,每一个原型对象都有一个指向构造函数的指针,而每一个实例都包含一个指向原型对象的内部指针, 原型链实现继承 基本思想:利用原型让一 ...
- ES5与ES6的继承
JavaScript本身是一种神马语言: 提到继承,我们常常会联想到C#.java等面向对象的高级语言(当然还有C++),因为存在类的概念使得这些语言在实际的使用中抽象成为一个对象,即面向对象.Jav ...
- ES5和ES6的继承
ES5继承 构造函数.原型和实例的关系:每一个构造函数都有一个原型对象,每一个原型对象都有一个指向构造函数的指针,而每一个实例都包含一个指向原型对象的内部指针, 原型链实现继承 基本思想:利用原型让一 ...
- ES5和ES6的继承对比
ES5的继承实现,这里以最佳实践:寄生组合式继承方式来实现.(为什么是最佳实践,前面有随笔讲过了,可以参考) function Super(name) { this.name = name; } Su ...
- ES5的继承和ES6的继承有什么区别?让Babel来告诉你
如果以前问我ES5的继承和ES6的继承有什么区别,我一定会自信的说没有区别,不过是语法糖而已,充其量也就是写法有区别,但是现在我会假装思考一下,然后说虽然只是语法糖,但也是有点小区别的,那么具体有什么 ...
- ES5和ES6中对于继承的实现方法
在ES5继承的实现非常有趣的,由于没有传统面向对象类的概念,Javascript利用原型链的特性来实现继承,这其中有很多的属性指向和需要注意的地方. 原型链的特点和实现已经在之前的一篇整理说过了,就是 ...
- ES6 class继承
ES6 class继承 class类的继承 class可以通过extends关键字实现继承,这笔ES5的通过修改原型连实现继承要清晰和方便很多. class Point{ } class ColorP ...
- 创建对象—从es5到es6
原文地址 本文主要讲述了使用JavaScript创建对象的几种方式,分别是传统的Object构造函数.对象字面量.工厂模式.构造函数模式.原型模式.组合模式,以及es6的class定义类.然后从bab ...
- 几道JS代码手写面试题
几道JS代码手写面试题 (1) 高阶段函数实现AOP(面向切面编程) Function.prototype.before = function (beforefn) { let ...
随机推荐
- oracle修改CHARACTERSET
[oracle@vm10-84-32-2 ~]$ sqlplus / as sysdba SQL*Plus: Release 11.2.0.4.0 Production on Thu Jun 11 1 ...
- 17.彻底解决Jmap在mac版本无法使用的问题
彻底解决Jmap在mac版本无法使用的问题 看了网上很多帖子,都说一半,说的都是大家说过的,根本没有解决问题.说jdk8不行,换成jdk9或者jdk11,我都试了,还是不行,最后说是mac的问题.换成 ...
- 大一C语言学习笔记(8)---指针篇--动态内存是什么?与静态内存有什么区别?怎么使用动态内存,有什么需要注意的地方?
静态内存指的是在编译时系统自动给其分配的内存,运行结束后会自动释放:静态内存是在栈中分配的: 动态内存是我们程序员手动分配的内存,正常情况下,程序运行结束后,也不会自动释放,所以为了避免发生未知的错误 ...
- 菜鸡的Java笔记 第二十九 - java 单例设计模式
SingleCase 单例设计模式 1.单例设计模式的特点 2.多例设计模式的特点 内容 单例设计模式 现在如果说有这么一个程序类 class S ...
- react之redux状态管理
1.传统MVC框架的缺陷 模型(model)-视图(view)-控制器(controller)的缩写 V即View视图:用户看到并与之交互的界面. M即Model模型是管理数据:很多业务逻辑都在模型中 ...
- WinForm训练一_改变窗体大小
1 //引用系统命名空间 2 using System; 3 //项目命名空间 4 using System.Collections.Generic; 5 using System.Component ...
- Spring Boot + MyBatis 多模块项目搭建教程
一.前言 1.开发工具及系统环境 IDE:IntelliJ IDEA 2020.2.2 系统环境:Windows 2.项目目录结构 biz层:业务逻辑层 dao层:数据持久层 web层:请求处理层 二 ...
- 关于 RocketMQ ClientID 相同引发的消息堆积的问题
首先,造成这个问题的 BUG RocketMQ 官方已经在 3月16号 的这个提交中修复了,这里只是探讨一下在修复之前造成问题的具体细节,更多的上下文可以参考我之前写的 <RocketMQ Co ...
- html+css第二篇
<img src="图片地址" alt="图片名"/> 图片(单标签)alt属性 是图片名字,是给百度搜索引擎抓取使用: a标签: 链接/下载/锚点 ...
- 最简单的Python3启动浏览器代码
#encoding=utf-8 from selenium import webdriver import time from time import sleep dr = webdriver.F ...