js笔记:类
es5的基础基本上学完了,继续学习es6中的类
简介
因为在js中生成实例对象的方法是直接通过构造函数,和c++和java有较大出入,所以es6提供了更接近传统语言的写法,通过class
关键字,可以直接定义类
不过这个class
只是一个语法糖,例如
1 | class Foo { |
可以知道其实类就是一个函数,类本身指向构造函数,而且定义在“类”上的方法其实也都是定义在构造函数的prototype
属性上
1 | class Foo { |
想往类添加其他的方法除了在使用class定义时也可以像原型与继承中Mixin模式那样直接使用Object.assign
进行添加
1 | class Foo { |
注意:和ES5不同的地方是类内部定义的方法是不可枚举的,而es5是可枚举的
1 | class Foo { |
还有个不同点是class
必须使用new
调用,否则会报错,这也是和普通构造函数不同的地方
constructor方法
用法在 js面向对象笔记 里写有。
constructor
方法如果没有显式定义,则会默认添加一个空的 constructor
constructor
默认返回实例对象,也就是 this
,也可以指定返回另一个对象,不过会导致实例对象不是该类。
类和普通的构造函数不一样的就是类必须要用 new
来调用否则报错。
类的实例
生成类的实例的写法,与ES5一样,需要用 new
,和上面说的一样如果不加 new
调用 class
会产生报错
和ES5差不多如果实例的属性除非是显式定义在其本身(即定义在 this
对象上),否则都是定义在原型上(即定义在 class
上)。
与 ES5 一样,类的所有实例共享一个原型对象。
1 | var p1 = new Point(2,3); |
__proto__
并不是语言本身的特性,这是各大厂商具体实现时添加的私有属性,虽然目前很多现代浏览器的 JS 引擎中都提供了这个私有属性,但依旧不建议在生产中使用该属性,避免对环境产生依赖。生产环境中,我们可以使用Object.getPrototypeOf
方法来获取实例对象的原型,然后再来为原型添加方法/属性。
但是一旦修改 __proto__
后可能会影响后面实例化的所有实例
getter和setter
在前面的es5里面有为单个实例对象添加getter和setter的方法:js笔记:对象
ES6和ES5差不多,可以在类内部使用 get
和 set
关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。
1 | class CustomHTMLElement { |
属性表达式
类的属性名,可以采用表达式
1 | let foo = 'getName' |
Class 表达式
类也可以像函数一样通过表达式赋值给变量
1 | const MyClass = class Me { |
上面代码使用表达式定义了一个类。需要注意的是,这个类的名字是Me,但是Me只在 Class 的内部可用,指代当前类。在 Class 外部,这个类只能用MyClass引用。
采用 Class 表达式,可以写出立即执行的 Class。
1 | let person = new class { |
注意点
严格模式
类和模块的内部,默认就是严格模式,所以不需要使用use strict指定运行模式。只要你的代码写在类或模块之中,就只有严格模式可用。考虑到未来所有的代码,其实都是运行在模块之中,所以 ES6 实际上把整个语言升级到了严格模式。
不存在提升
类不存在变量提升(hoist),这一点与 ES5 完全不同。
1 | new Foo(); // ReferenceError |
name 属性
由于本质上,ES6 的类只是 ES5 的构造函数的一层包装,所以函数的许多特性都被Class继承,包括name属性。
1 | class Point {} |
name属性总是返回紧跟在class关键字后面的类名。
Generator 方法
如果某个方法之前加上星号(*),就表示该方法是一个 Generator 函数。
1 | class Foo { |