ES6前
function Point(x, y) {//构造函数
this.x = x;
this.y = y;
}
Point.prototype.toString = function () {
return '(' + this.x + ', ' + this.y + ')';
};
var p = new Point(1, 2);
//ES6中
class Point {
constructor(x, y) {//构造函数
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
class Point {
// ...
}
typeof Point // "function"
Point === Point.prototype.constructor // true
//对比
class Point {
constructor() {
// ...
}
toString() {
// ...
}
toValue() {
// ...
}
}
// 等同于
Point.prototype = {
constructor() {},
toString() {},
toValue() {},
};
//对比
class B {}
let b = new B();
b.constructor === B.prototype.constructor // true
//同时添加多个方法
class Point {
constructor(){
// ...
}
}
Object.assign(Point.prototype, {
toString(){},
toValue(){}
});
//ES6内部方法不可枚举
class Point {
constructor(x, y) {
// ...
}
toString() {
// ...
}
}
Object.keys(Point.prototype)
// []
Object.getOwnPropertyNames(Point.prototype)
// ["constructor","toString"]
//constructor方法默认返回实例对象(即this),完全可以指定返回另外一个对象。
class Foo {
constructor() {
return Object.create(null);
}
}
new Foo() instanceof Foo
// false
类的实例
//与 ES5 一样,实例的属性除非显式定义在其本身(即定义在this对象上),否则都是定义在原型上(即定义在class上)。
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
var point = new Point(2, 3);
point.toString() // (2, 3)
point.hasOwnProperty('x') // true
point.hasOwnProperty('y') // true
point.hasOwnProperty('toString') // false
point.__proto__.hasOwnProperty('toString') // true
//与 ES5 一样,类的所有实例共享一个原型对象。
var p1 = new Point(2,3);
var p2 = new Point(3,2);
p1.__proto__ === p2.__proto__
//true
getter和setter
//存值函数和取值函数是设置在属性的 Descriptor 对象上的。
class CustomHTMLElement {
constructor(element) {
this.element = element;
}
get html() {
return this.element.innerHTML;
}
set html(value) {
this.element.innerHTML = value;
}
}
var descriptor = Object.getOwnPropertyDescriptor(
CustomHTMLElement.prototype, "html"
);
"get" in descriptor // true
"set" in descriptor // true
属性表达式
let methodName = 'getArea';
class Square {
constructor(length) {
// ...
}
[methodName]() {//方法名getArea,是从表达式得到
// ...
}
}
Class表达式
const MyClass = class Me {
getClassName() {
return Me.name;//类名只能在内部使用
}
};
// Class 表达式,可以写出立即执行的 Class。
let person = new class {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}('张三');
person.sayName(); // "张三"
注意点
\\1.类和模块的内部,默认就是严格模式
\\2类没有变量提升hoist
new Foo(); // ReferenceError
class Foo {}
\\3name属性,ES6 的类只是 ES5 的构造函数的一层包装
\\4Generator方法
class Foo {
constructor(...args) {
this.args = args;
}
* [Symbol.iterator]() {//Generator函数
for (let arg of this.args) {
yield arg;
}
}
}
for (let x of new Foo('hello', 'world')) {
console.log(x);
}
// hello
// world
\\5this的指向
class Logger {
printName(name = 'there') {
this.print(`Hello ${name}`);//this默认指向Logger类的实例
}
print(text) {
console.log(text);
}
}
const logger = new Logger();
const { printName } = logger;//this指向该方法运行时所在的环境
printName(); // TypeError: Cannot read property 'print' of undefined
\\解决1绑定this
class Logger {
constructor() {
this.printName = this.printName.bind(this);
}
// ...
}
\\解决2使用箭头函数
class Logger {
constructor() {
this.printName = (name = 'there') => {
this.print(`Hello ${name}`);
};
}
// ...
}
\\使用Proxy
function selfish (target) {
const cache = new WeakMap();
const handler = {
get (target, key) {
const value = Reflect.get(target, key);
if (typeof value !== 'function') {
return value;
}
if (!cache.has(value)) {
cache.set(value, value.bind(target));
}
return cache.get(value);
}
};
const proxy = new Proxy(target, handler);
return proxy;
}
const logger = selfish(new Logger());
静态方法
class Foo {
static classMethod() {
return 'hello';
}
}
Foo.classMethod() // 'hello'
var foo = new Foo();
foo.classMethod()
// TypeError: foo.classMethod is not a function
//this指向类
class Foo {
static bar() {
this.baz();
}
static baz() {
console.log('hello');
}
baz() {//baz方法可重名
console.log('world');
}
}
Foo.bar() // hello
//可继承
class Foo {
static classMethod() {
return 'hello';
}
}
class Bar extends Foo {
}
Bar.classMethod() // 'hello'
//super调用
class Foo {
static classMethod() {
return 'hello';
}
}
class Bar extends Foo {
static classMethod() {
return super.classMethod() + ', too';
}
}
Bar.classMethod() // "hello, too"
实例属性新写法
class IncreasingCounter {
_count = 0;//定义在类顶层
get value() {
console.log('Getting the current value!');
return this._count;
}
increment() {
this._count++;
}
}
静态属性
// 老写法
class Foo {
// ...
}
Foo.prop = 1;
// 新写法
class Foo {
static prop = 1;
}
new.target属性
//构造函数只能通过new命令调用
function Person(name) {
if (new.target !== undefined) {
this.name = name;
} else {
throw new Error('必须使用 new 命令生成实例');
}
}
// 另一种写法
function Person(name) {
if (new.target === Person) {
this.name = name;
} else {
throw new Error('必须使用 new 命令生成实例');
}
}
var person = new Person('张三'); // 正确
var notAPerson = Person.call(person, '张三'); // 报错
//返回子类
class Shape {
constructor() {
if (new.target === Shape) {
throw new Error('本类不能实例化');
}
}
}
class Rectangle extends Shape {
constructor(length, width) {
super();
// ...
}
}
var x = new Shape(); // 报错
var y = new Rectangle(3, 4); // 正确
私有方法属性
//方案一
class Widget {
// 公有方法
foo (baz) {
this._bar(baz);
}
// 私有方法加下划线_
_bar(baz) {
return this.snaf = baz;
}
// ...
}
//方案二
//索性将私有方法移出模块
class Widget {
foo (baz) {
bar.call(this, baz);
}
// ...
}
function bar(baz) {
return this.snaf = baz;
}
//方案三
const bar = Symbol('bar');
const snaf = Symbol('snaf');
export default class myClass{
// 公有方法
foo(baz) {
this[bar](baz);
}
// 私有方法
[bar](baz) {
return this[snaf] = baz;
}
// ...
};
const inst = new myClass();
Reflect.ownKeys(myClass.prototype)
// [ 'constructor', 'foo', Symbol(bar) ]
网友评论