ES6的class混乱的笔记

1)class是原型的语法糖
class相当于声明一个对象,内部的方法相当于原型中的函数或属性。
class声明的类的原型是不可枚举的,但是可以通过Object.getOwnPropertyNames()得到所有的属性方法,ES5原型中的属性和类除了constructor都是可枚举的。
Object.keys()能得到所有可枚举属性。
Object.getOwnPropertyNames()在ES5中遍历不到constructor,在ES6里可以
2)class声明的类必须用new构造,否则报错
constructor中返回自定义对象,导致原型的constructor属性不等于构造函数。
如果属性没有显示的定义在this上,就在原型上即class上,定义在this上的可以用hasOwnProperty判断为true,没有用this即在原型上的用hasOwnProperty判断为false
3) 尽量不要用实例的proto属性,否则单方面改变原型的方法,影响别的实例使用。
4) 表达式定义的class 类名只能在class内部起作用 在类外访问不到类的name属性
非表达式定义的calss 类名可在外部通过class的构造函数名.name读取
5) 匿名类 let person = new class {}
6) class不存在变量提升
7) class私有方法
class的私有方法只能模拟,但是在类外还能访问到,解决办法有两种:
1.将私有方法移出class 变为模块的私有方法
2.symbol定义方法名,定义在内部,第三方无法访问
8)类方法内部的this指向类的实例 将类内部的方法单独在环境中调用,this又指向运行环境,解决方法有三个:
a. 构造函数中用箭头函数保存this

constructor() {
    this.printName = (name = ‘there’) => {
        this.print(‘${name}’);
    }
}

b. Proxy
c. 在构造函数中为内部方法绑定this
class Logger {
constructor() {
this.print = this.printName.bind(this);
}
}
9)class内部的属性拦截
get和set是设置在Descriptor属性上的,
通过Object.getOwnPropertyDescriptor(Book.prototype, ‘age’) 得到该对象,与ES5一致。

class Book {
    constructor() {
    }
    set age(value) {
        console.log('setter ' + value);
    }
    get age() { 
        return 'getter';
    }
}

10)class的遍历器

*[Symbol.iterator] () {
    for(let arg of this.args) {
        yield arg;
    }
}

11)class的静态方法:不能被实例调用,不被实例继承
但是父类的静态方法可以被子类继承,可通过super调父类静态方法
静态属性 提案
实例属性 提案

class Foo {
    static classMethod() {
        return 'hello';
    }
}
console.log(Foo.classMethod());   // hello
class FooChild extends Foo {
}
console.log(FooChild.classMethod());   // hello
// 静态属性
Foo.prop = 2;

12)new.target属性
确保构造函数只能通过new调用
子类继承父类,父类内部的new.target指向子类的构造。可用该属性实现不能独立使用,必须继承后才能使用的类。

class Shape {
    constructor(length) {
        if(new.target === Shape) {     // 通过子类调用该构造不会报错
            throw new Error('不能直接使用该类');
        }
    }
}
class circle extends Shape {
    constructor(r) {
        super(); // 调用父类构造函数成功
    }
}

13)class继承 子类的构造函数中必须调用super,否则实例化时报错。子类没有this,必须调用父类构造函数得到父类的this。所以在子类中要使用this必须先super(),否则报错。
14)ES5与ES6继承的区别
ES5先构造子类this,将父类方法加到子类this上
ES6构造父类,将父类this给子类
15)判断继承Object.getPropertyOf(child) === parent
16) 子类调super,super虽然代表父类构造函数,但返回子类实例,父类构造函数内部的this指的是子类构造。类似java父类引用指向子类对象。
17) super()用于构造只能在构造函数中调用,不能在其它函数中调用,否则报错。
当做父类的引用,可在普通函数中使用
super.*() 调用父类的方法,此时super相当于parent.prototype。
【注意】super访问不到父类实例上的属性和方法。即父类通过this.定义的。只能访问父类通过原型定义的属性,即parent.prototype.color = ‘red’; 这样子类在函数中通过super.color可访问到。
18) 关于this指向变化的问题,子类调用super父类方法内部的this就变成子类的this了。
子类中的super在静态方法中指向父类,在普通方法中指向父类的原型对象。
使用super必须显示指定 是当做方法使用还是当做原型使用的。
19)类的prototype和proto
子类的proto指向父类构造
子类的prototype的proto指向父类prototype
// B extends A 的实现原理

// B的实例继承A的实例
Object.setPrototypeOf(B.prototype, A.prototype);
// B的实例继承A的静态属性
Object.setPrototypeOf(B,A);
const b = new B();

Object.setPrototypeOf = function(obj, proto) {
    obj.__proto__ = proto;
    return obj;
}   

20)普通对象直接继承Function.prototype

class A{}
A.__proto__  ===  Function.prototype
A.prototype.__proto__  ===  Object.prototype (A构造返回一个空对象)

class A extends null {}
A.__proto__  ===  Function.prototype
A.prototype.__proto__  ===  undefined
// (A构造返回一个undefined内部Object.create(null))

21)ES6可以继承原生数据结构,自定义子类。
因为ES6的继承是先构造父类的,所以ES6可以取得父类的内部this,实现该功能。
ES5通过绑定this无法实现继承原生数据结构,原生的数据结构忽略绑定this,也不能得到内部this。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值