ES6——class类继承(读书笔记)
前言
我一定是一个傻子,昨天这篇文章其实我已经写好了一半了,但是我没有保存
这是学习ES6的过程,我没有系统的看完阮大大的书。零零散散的,很多功能知道,但是没有实际的用过
看了几遍,总是看前面几章,所以这次我要立下flag 一定从头到尾学一遍ES6(有点讽刺 现在好像都有ES9了)
ES5与ES6 相差还是很大的
一、类
ES5 没有类这个说法,但是是可以实现类这样功能的,那就是构造函数
function Point (x,y){
this.x = x
this.y = y
} var a = new Point(1,2)
console.log(a.x) //
然后我在mdn上找到一个例子 详细的说了构造函数的原型 原型链
// 让我们从一个自身拥有属性a和b的函数里创建一个对象o:
let f = function () {
this.a = 1;
this.b = 2;
}
/* 这么写也一样
function f() {
this.a = 1;
this.b = 2;
}
*/
let o = new f(); // {a: 1, b: 2} // 在f函数的原型上定义属性
f.prototype.b = 3;
f.prototype.c = 4; // 不要在 f 函数的原型上直接定义 f.prototype = {b:3,c:4};这样会直接打破原型链
// o.[[Prototype]] 有属性 b 和 c
// (其实就是 o.__proto__ 或者 o.constructor.prototype)
// o.[[Prototype]].[[Prototype]] 是 Object.prototype.
// 最后o.[[Prototype]].[[Prototype]].[[Prototype]]是null
// 这就是原型链的末尾,即 null,
// 根据定义,null 就是没有 [[Prototype]]。 // 综上,整个原型链如下: // {a:1, b:2} ---> {b:3, c:4} ---> Object.prototype---> null console.log(o.a); //
// a是o的自身属性吗?是的,该属性的值为 1 console.log(o.b); //
// b是o的自身属性吗?是的,该属性的值为 2
// 原型上也有一个'b'属性,但是它不会被访问到。
// 这种情况被称为"属性遮蔽 (property shadowing)" console.log(o.c); //
// c是o的自身属性吗?不是,那看看它的原型上有没有
// c是o.[[Prototype]]的属性吗?是的,该属性的值为 4 console.log(o.d); // undefined
// d 是 o 的自身属性吗?不是,那看看它的原型上有没有
// d 是 o.[[Prototype]] 的属性吗?不是,那看看它的原型上有没有
// o.[[Prototype]].[[Prototype]] 为 null,停止搜索
// 找不到 d 属性,返回 undefined
看完这个例子,就大概知道原型 原型链 是怎样一层一层的找的(又有灵感 写一篇古风版的原型链了)
然后ES6 是怎么样的呢
class Point{
constructor(x,y){
this.x = x;
this.y = y;
}
toString(){
return "("+this.x+","+this.y+")"
}
}
上面代码定义了一个“类”,可以看到里面有一个constructor
方法,这就是构造方法
而this
关键字则代表实例对象。也就是说,ES5 的构造函数Point
,对应 ES6 的Point
类的构造方法。
使用的时候,也是直接对类使用new
命令,跟构造函数的用法完全一致。
class Bar {
doStuff() {
console.log('stuff');
}
} var b = new Bar();
b.doStuff() // "stuff"
类的所有方法都定义在类的prototype
属性上面。(继承) 在类的实例上面调用方法,其实就是调用原型上的方法。
class B {}
let b = new B(); b.constructor === B.prototype.constructor // true
prototype
对象的constructor
属性,直接指向“类”的本身,这与 ES5 的行为是一致的。
Point.prototype.constructor === Point // true
toString
方法是Point
类内部定义的方法,它是不可枚举的。这一点与 ES5 的行为不一致。
constructor
方法
constructor
方法是类的默认方法,通过new
命令生成对象实例时,自动调用该方法。一个类必须有constructor
方法,如果没有显式定义,一个空的constructor
方法会被默认添加。
class Point {
} // 等同于
class Point {
constructor() {}
}
- 类必须使用
new
调用,否则会报错。这是它跟普通构造函数的一个主要区别,后者不用new
也可以执行 constructor
函数返回一个全新的对象,结果导致实例对象不是Foo
类的实例。class Foo {
constructor() {
return Object.create(null);
}
} new Foo() instanceof Foo
// false- 类不存在变量提升(hoist),这一点与 ES5 完全不同。
{
let Foo = class {};
class Bar extends Foo {
}
}上面的代码不会报错,因为
Bar
继承Foo
的时候,Foo
已经有定义了。但是,如果存在class
的提升,上面代码就会报错,因为class
会被提升到代码头部,而let
命令是不提升的,所以导致Bar
继承Foo
的时候,Foo
还没有定义。- 由于本质上,ES6 的类只是 ES5 的构造函数的一层包装,所以函数的许多特性都被
Class
继承,包括name
属性name
属性总是返回紧跟在class
关键字后面的类名。class Point {}
Point.name // "Point"
- 如果某个方法之前加上星号(
*
),就表示该方法是一个 Generator 函数。 class Foo {
constructor(...args) {
this.args = args;
}
* [Symbol.iterator]() {
for (let arg of this.args) {
yield arg;
}
}
} for (let x of new Foo('hello', 'world')) {
console.log(x);
}
// hello
// world上面代码中,
Foo
类的Symbol.iterator
方法前有一个星号,表示该方法是一个 Generator 函数。Symbol.iterator
方法返回一个Foo
类的默认遍历器,for...of
循环会自动调用这个遍历器。- 在构造方法中绑定
this
,这样就不会找不到print
方法了。 不然就会this
会指向该方法运行时所在的环境(由于 class 内部是严格模式,所以 this 实际指向的是undefined
),从而导致找不到print
方法而报错。 - 另一种解决方法是使用箭头函数。
class Obj {
constructor() {
this.getThis = () => this;
}
} const myObj = new Obj();
myObj.getThis() === myObj // true
二、静态方法
类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static
关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
class Foo {
static classMethod() {
return 'hello';
}
} Foo.classMethod() // 'hello' var foo = new Foo();
foo.classMethod()
// TypeError: foo.classMethod is not a function
ES6——class类继承(读书笔记)的更多相关文章
- Java核心技术卷一基础知识-第5章-继承-读书笔记
第5章 继承 本章内容: * 类.超类和子类 * Object:所有类的超类 * 泛型数组列表 * 对象包装器和自动装箱 * 参数数量可变的方法 * 枚举类 * 反射 * 继承设计的技巧 利用继承,人 ...
- [转] 《ES6标准入门》读书笔记
来源:https://segmentfault.com/a/1190000005863641 let和const命令 ES6新增let命令,用于声明变量,是块级作用域. let声明的变量不会像var声 ...
- 线程阻塞工具类:LockSupport(读书笔记)
他可以在线程任意位置让线程阻塞, LockSupport的静态方法park()可以阻塞当前线程,类似的还有parkNanos() ParkUntil()等,他们实现了一个限时等待 public cl ...
- 《ES6标准入门》读书笔记 第5章 - 正则增强
第五章 - 正则增强 构造函数增强 允许覆写修饰符,如new RegExp(someRegex, 'ig') 字符串上的正则方法 原先match.replace等可以调用正则的方法在String的原型 ...
- 深入解析ES6 更易于继承的类语法的使用
和其它面向对象编程语言一样,ES6 正式定义了 class 类以及 extend 继承语法糖,并且支持静态.派生.抽象.迭代.单例等,而且根据 ES6 的新特性衍生出很多有趣的用法. 一.类的基本定义 ...
- 《C#图解教程》读书笔记之四:类和继承
本篇已收录至<C#图解教程>读书笔记目录贴,点击访问该目录可获取更多内容. 一.万物之宗:Object (1)除了特殊的Object类,其他所有类都是派生类,即使他们没有显示基类定义. ( ...
- 【读书笔记】【深入理解ES6】#9-JavaScript中的类
大多数面向对象的编程语言都支持类和类继承的特性,而JavaScript却不支持这些特性,只能通过其他方法定义并关联多个相似的对象.这个状态一直从ECMAScript 1持续到ECMAScript 5. ...
- 《C++ Primer Plus》读书笔记之十一—类继承
第十三章 类继承 1.类继承:扩展和修改类. 2.公有继承格式:冒号指出B类的基类是A,B是派生类. class B :public A { ... }: 3.派生类对象包含基类对象.使用公有派生,基 ...
- C++ primer plus读书笔记——第13章 类继承
第13章 类继承 1. 如果购买厂商的C库,除非厂商提供库函数的源代码,否则您将无法根据自己的需求,对函数进行扩展或修改.但如果是类库,只要其提供了类方法的头文件和编译后的代码,仍可以使用库中的类派生 ...
随机推荐
- js实现用户输入日期算出是今年的第几天
const rs = require("readline-sync"); // 根据用户输入的年月日输出第几天 // 欢迎 console.log("欢迎来到查询系统&q ...
- jQuery中的 AJAX
jQuery库中支持AJAX的操作,功能十分完善 详细请参考官方文档:https://www.jquery123.com/category/ajax/ 首先需要引入jquery文件!!! $.ajax ...
- FreeRTOS互斥信号量
API函数 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #define xSemaphoreCreateMutex() xQueueCreateMutex ...
- layui 单选框、复选框、下拉菜单 不显示问题 记录
1. 如果是 ajax嵌套了 页面, 请确保 只有最外层的页面引入了 layui.css 和 layui.js 内层页面 切记不要再次引入 2. layui.use(['form', 'upload ...
- InteiiJ IDEA中如何制定制定哪一个配置文件
项目下有好些application.property文件 彼此之间也不是什么 从application.property中指定dev就去对应dev的关系 就想用我本地的数据库 于是添加了一个appl ...
- h5中hash的用法实例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 通过mock-api模拟真实数据
一.什么是 mock-api mock-api(模客)是一个便捷的 REST 接口数据模拟工具,用于前后端隔离测试,开发调试. 二.mock-api 的使用 1.注册登录 http://mock-ap ...
- 网站检测空链、死链工具(Xenu)
网站常用检测空链.死链工具,Xenu是很小但是功能强大的检查网站404链接的软件,支持多线程,无需安装可直接打开使用.步骤如下: 网站的链接一般都成千上万,如果存在大量的空链接将大大的影响用户体验,怎 ...
- vue slot 插槽详解
插槽含义:就是引入子组件后,在插入子组件元素中添加信息或者标签,使得子组件的指定位置插入信息或者标签 插槽有三种:默认插槽.具名插槽.作用域插槽,由于vue2.6.0后对插槽进行修改,但是兼容2.6. ...
- .net System.IO.Stream 流操作类(FileStream等)
Stream 是所有流的抽象基类.流是字节序列的抽象概念. 流涉及到的3个基本操作: 读取流,读取是指从流到数据结构(如字节数组)的数据传输. 写入流,写入是指从数据结构到流的数据传输. 流查找,查找 ...