ES6-17【类、类的继承、类的实现、类的修饰】

本文围绕ES6/ES7中JavaScript的类与继承展开。介绍了类的基础、特殊写法、拓展及总结,如暂时性死区、公有属性不可枚举等;阐述了继承的基本情况和super方法的作用;说明了类的实现方式和源码;还提及类的修饰,包括基本用法、转译步骤和埋点操作,遵循开放封闭原则。

一.类

(1).基础

最简单的定义方式

class Person{}
log(new Person());//Person{}
log(typeof Person);function

标准写法

class Person{
    constructor(name = "zhangsan",age = "18"){
        //私有属性
        this.name = name;
        this.age = age;
    }
    //公有属性
    say(){
        log(`my name is ${this.name}`)
    }
}
console.log(new Person());
Person{
    age:"18"
    name:"zhangsan"
    __proto__
        constructor: class Person
        say: f say()
}

方法书写及调用

class Person{
    constructor(name = "zhangsan",age="18"){
        this.name = name;
        this.age = age;
    }
    say(){
        console.log(`my name is ${this.name},my age is ${this.age}`)
    }
    eat(){
        console.log('I can eat')
    }
    drink(){
        console.log('I can drink')
    }
}
new Person().eat();//I can eat
new Person().drink();//I can drink

通过assign来拓展原型属性

Object.assign(Person.prototype,{
    eat: function(){
        console.log('I can eat')
    },
    drink:function(){
        console.log('I can drink')
    }
},)
拓展出来的对象是可以枚举的
log(Object.keys(Person.prototype))//["say","eat","drink"]

class的属性内部的方法就是不可枚举的输出[]

constructor

实例化没有指定constructor系统默认指定

class Person{
    constructor(){
        
    }
}
log(new Person() instanceof Person);//true和之前一样,继承于Person

class Person{
    constructor(){
        return Object.create(null)
    }
}
log(new Person() instanceof Person);
如果返回新的对象则false

(2).特殊写法

可以用表达式的方式写class

let Person = class{
    say(){
        console.log(1)
    }
}
new Person.say()

执行方式必需为New 像直接立即执行函数就会报错,但是下面通过new就可以

let person = new class{
    say(){
        log(1)
    }
}()
person.say();//1

传参给constructor

let person = new class{
    constructor(name = 'zhangsan',age = '18'){
        this.name = name;
        this.age = age;
    }
    say(){
        log(1)
    }
}('lisi','19')

(3).拓展

暂时性死区TDZ

不像函数可以提升

console.log(new Person());
class Person{
    
}

构造器外声明属性

es7中你在外层直接申明属性,其实系统就是默认通过constror构建的私有属性

class Person{
    a = 1
    等价于
    constructor(){
        this.a = 1
    }
}

公有属性的私有方法

1.symbol

const eat = Symbol();
class Person{
    constructor(name,age){
        this.age = age;
        this.name = name;
    }
    say(){
        console.log(1);
    }
    [eat](){
        console.log(2)
    }
}
console.log(new Person().say());//1
console.log(new Person().eat())//报错

通过压缩后,方法名会变更,而普通的函数可以用.去访问,而symbol由于.是访问不到原本变量名的,所以就实现了公有函数的私有化

2.直接写在class外

class Person{
    constructor(name,age){
        this.age = age;
        this.name = name;
    }
    say(baz){
        children.call(this,baz)
    }
}
function children(baz){
    return this.bar = baz
}

3.静态方法

只可以通过类调用,不能通过类实例调用

class Person{
    static a(){
        log(1)
    }
}
console.log(Person.a)//打印1

静态属性

可能有兼容性的问题

只可以通过类调用,不能通过类实例调用

class Person{
   
    static name1 = 'cc';
}
var per = new Person()
console.log(Person.name1);//打印cc

class构造函数中也可定义取值存值函数

class Person{
    get a(){
        log(1)
    }
    set b(value){
        log(2)
    }
}
var person = new Person();
person.a; //1
person.b = 3;//2

类中默认开启的严格模式

(4).总结

  1. 有暂时性死区TDZ
  2. 公有属性不可枚举
  3. 默认严格模式
  4. 必需通过new方式来执行
  5. 类中会有默认的constructor

二.继承

(1).基本

静态属性访问不到会报错,所以继承的还是原型上的

class Parent{
    constructor(name = 'zhangsan'){
        this.name = name;
    }
    say(){
        console.log(1)
    }
}
class Child extends Parent{
    constructor(age = '19')
        this.age = age;
    }
}
console.log(new Child().age)

会报错

必需指定super,在派生类里面this的指向并不是当前对象

这时候可以通过super把父级的整个实例继承过来,才能用父类的this

class Child extends Parent{
    constructor(age = '19')
        super('lisi');
        this.age = age;
    }
}
console.log(new Child())
child{
    age:"19"
    name:"lisi"
}

(2).super方法

1.继承原型里的属性的

2.在对象当中拿到原型对象

let proto = {
    y: 20,
    z: 40
}
let obj = {
    x: 10,
    foo(){
        log(super.y)
    }
}
Object.setPrototypeOf(obj,proto);
obj.foo();20

3.在静态方法,指向自己的父类

三.类的实现

(1).实现方式

//1.TDZ :通过函数表达式接收

//2.只能通过new实例化调用属性或方法 :通过传入当前作用域 和本函数 来通过instanceof来判断

//3.严格模式 :‘use strict’

//4.公有方法不可枚举: 通过传入得第二个参数设置属性描述符

//5.默认constructor :通过difineProperty实现

(2).class源码

"use strict"
function _classCallBack(instance,Constructor){
    if(!(instance instanceof Constructor)){
        throw new TypeError('Cannot call a class as a function')
    }
}
var _createClass = function(){
    function defineProperties(target,props){
        for(var i = 0; i<props.length;i++){
            var descriptor = props[i];
            descriptor.enumerable = descriptor.enumerable || false;
            descriptor.configurable = true;
            if("value" in descriptor) descriptor.writable = true;
            Object.defineProperty(target,descriptor.key,descriptor)
        }
        return function(Constructor,protoProps,staticProps){
            if(protoProps) defineProperties(Constructor.prototype,protoProps)
            if(staticProps) defineProperties(Constructor,staticProps)
            return Constructor;
        }
    }
}();
var Person = function(){
    function Person(){
        var name = arguments[0] !== undefined && arguments.length > 1 ? arguments[0]:'xx';
        var test = arguments[0] !== undefined && arguments.length > 1 ? arguments[1]:'dd';
        _classCallBack(this,Person)
        this.name = name
        this.age = age
    }
    _createClass(Person,[{
        key:"test",
        value:function test(){
            console.log('hahahahahha');
        }
    }],[{
        key:'fuck',
        value:function fuck(){
            console.log(2);
        }
    }])
    return Person;
// }();

四.类的修饰

可以在类或类的方法上拓展自己的方法

(1).基本

@+修饰

class Person{
    @readOnly()
    say(){
        console.log('ad is show');
        
    }
}
function readOnly(target,name,descriptctor){
    三个参数打印如下
    类本体,指定属性名称,属性描述符
}


(2).转译

1.安装插件

 

2.可以通过淘宝镜像下载(把这个放在屁股后面)

 

3.添加插件

 

4.修饰符使用

index页面引用bundle.js编译后的,这样就可以通过浏览器语法编译了

(3).埋点操作

用于记录动作

let log = (type) =>{
    return function(target,name,descriptor){
        let src_methiod = descriptor.value;
        descriptor.value = (...arg)=>{
            src_methiod.apply(target,arg);
            console.log(type);
            
        }
    }
}
class Person{
    @log('show')
    say(){
        console.log('ad is show');
        
    }
    @log('click')
    click(){
        console.log('ad is click');
        
    }
}
ad is show
show
ad is click
click

总结:对拓展开放,对修改封闭。遵循了开放封闭原则

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值