es6 class 的 new 实例和 es5 的 new 实例有什么区别?
在ES6
中(和ES5
相比),class
的new
实例有以下特点:
class
的构造参数必须是new
来调用,不可以将其作为普通函数执行
es6
的class
不存在变量提升
- 最重要的是:es6 内部方法不可以枚举。es5 的
prototype
上的方法可以枚举。
为此我做了以下测试代码进行验证:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| console.log(ES5Class());
function ES5Class() { console.log("hello"); } ES5Class.prototype.func = function() { console.log("Hello world"); }; class ES6Class { constructor() {} func() { console.log("Hello world"); } } let es5 = new ES5Class(); let es6 = new ES6Class();
console.log("ES5 :"); for (let _ in es5) { console.log(_); }
console.log("ES6 :"); for (let _ in es6) { console.log(_); }
|
ES6 class 实现状态函数(static变量)
在C语言中,使用 static 关键字来增加函数变量的生命周期(不是范围),使其超出函数的调用范围。
在JS/TS中,也可以实现。通过class
:
1 2 3 4 5 6 7 8 9
| const { called } = new (class { count = 0; called = () => { this.count++; console.log("Called: ", this.count); }; })(); called(); called();
|
也可以用闭包:
1 2 3 4 5 6 7 8 9 10 11 12
| const { called: called2 } = (() => { var count = 0; return { called: () => { count++; console.log("Called: ", count); } }; })(); called2(); called2();
|
ES6 Class怎么把Class变成Iterator?
使用 class 的 name属性
+ generator 方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Foo { constructor(...args) { this.args = args; } *[Symbol.iterator]() { for (let arg of this.args) { yield arg; } } } var foo = new Foo(1, 2, 3); for (let x of foo) { console.log(x); }
|
ES6 Class 如何解决 this 指向问题?
问题描述:
1 2 3 4 5 6 7 8 9 10 11 12 13
| class Logger { constructor(name) { this.name = name; }
print() { console.log(this.name); } } const logger = new Logger('sysdesign.fun'); const { print } = logger; print();
|
解决1: 构建函数中,绑定 this
1 2 3 4 5 6 7
| class Logger { constructor(name) { this.name = name;
this.print = this.print.bind(this); } }
|
解决2: 使用 Proxy 自动绑定 this
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| function proxyClsThis(instance) { const cache = new WeakMap();
const proxy = new Proxy(instance, { get(target, propKey) { const val = Reflect.get(target, propKey); if (typeof val !== 'function') { return val; } if (!cache.has(val)) { cache.set(val, val.bind(target)); } return cache.get(val); }, });
return proxy; }
const logger = proxyClsThis(new Logger('sysdesign.fun')); const { print } = logger; print();
|
ES6 Class 如何解决私有属性问题?
准确来说,对象的操作,都可以通过Proxy来实现。具体可以见 [[ES6的Proxy,以及Reflect]] ,或者参考前面的解决2方案。
参考/推荐:《JavaScript 创建对象—从 es5 到 es6》