es6入门—类(class)、修饰器

class

对象原型的语法糖。使用class关键字定义类。
基础语法

let methodName = "getArea";
class Point{
    constructor(x,y){
        this.x = x;
        this.y = y;
    }
    toString(){
        return '('+this.x+','+this.y+')';
    }
    [methodName](){
        return "使用变量声明方法";
    }
}
typeof Point         //"function"
Point === Point.prototype.constructor      //true

//使用Object.assign()方法对一个类添加方法。

Object.assign(Point.prototype,{
    toValue(){}
});

1.定义类不需要加function保留字;
2.类中的方法不需要逗号分隔;
3.类的数据类型是函数,类本身就是构造函数;
4.类中定义的方法是定义在类的prototype属性上,调用实例方法就是调用原型上的方法。

类中定义的方法都是不可枚举的。

//不能枚举类中定义的toString方法及构造函数
Object.keys(Point.prototype);       //["toValue"]
//获取到所有的内部方法
Object.getOwnPropertyNames(Point.prototype);  
//["constructor","toString","toValue"]

实例调用
construct默认构造函数,绑定this对象;显示定义或者默认添加。
实例对象使用new命令,所有的实例对象共享一个原型对象。

let p1 = new Point(1,2);
let p2 = new Point(3,4);
p1.__proto__ === p2.__proto__;       //true
//this绑定到实例对象p1自身的属性,方法定义在原型上
p1.hasOwnProperty('x');            //true
p1.hasOwnProperty('toString');            //false
p1.__proto__.hasOwnProperty('toString');     //true

在实例上定义方法时,不要使用__proto__属性定义,所有的实例共享一个原型对象。

name属性总是返回class关键字的类名。

Point.name    //"Point"

可以使用表达式定义类

//类名时Myclass不是my,my供内部使用
const Myclass = class my{
    getClassName(){
        return my.name;
    }
}
//my可省略,可写出立即执行的类
const Myclass = new class{
    //...
}();

不存在变量提升。子类必须定义在父类后
类继承
使用extends关键字实现继承。

class ColorPoint extends Point{
    constructor(x,y,color){
        super(x,y);         //调用父类的构造函数
        this.color = color
    }
    toString(){
        return this.color+' '+super.toString();     //调用父类的toString()
    }
}

子类必须在construct方法中调用super方法;super指代父类的this对象。
子类没有自己的this对象,调用super方法得到父类的this对象。
子类只有调用了super方法后,才可以使用this关键字。

类的prototype属性和__proto__属性

每一个对象都有__proto__属性,指向对应的构造函数的prototype属性,class类同时存在这两条属性,存在两条继承链。
1.子类的__proto__属性表示构造函数的继承,总是指向父类。
2.子类prototype属性的__proto__属性表示方法的继承,总是指向父类的prototype属性。

//作为对象,子类的__proto__属性是父类
ColorPoint.__proto__ === Point       //true
//作为构造函数,子类的prototype原型__proto__属性是父类的实例
ColorPoint.prototype.__proto__ === Point.prototype    //true 

Object.getPrototypeOf();
//可以用于从子类上获取父类;判断一个类是否继承另一个类。
子类实例的__proto__属性的__proto__属性是父类实例的__proto__属性。
原生构造函数的继承
Boolean(),Number(),String(),Array(),Date(),Function(),RegExp(),Error(),Object()

    ES5是先新建子类的实例对象this,再将父类的属性添加到子类上,
    由于父类的内部属性无法获取,导致无法继承原生的构造函数。

    ES6允许继承原生构造函数定义子类。ES6先新建父类的实例对象this,然后再
    用子类的构造函数修饰this,这使得父类的所有属性都可以继承。

ES6可以在原生数据结构上定义自己的数据结构。
Class的静态方法,使用static关键字;表示该方法不会被实例继承,直接通过类调用该方法。
Class的静态属性,定义在实例对象上的属性。

    //目前支持的写法

    Point.name = "point";
    Point.name  //"point"
    //es7 
    class Point{
        name = "li";
        static age = "23";
    }

new.target属性,返回new命令所作用的构造函数。如果不是new命令调用的,则返回undefined。
可用于确定构造函数是怎么调用的。

    1.子类继承父类时new.target返回子类。
    2.可以用作父类不能独立使用,必须继承
    class Point{
        constructor(){
            if(new.target == Point){
                throw new Error("不能实例化");
            }
        }
    }
    3.在函数外部使用则会报错

Mixin模式,将多个类的接口“混入”另一个类。

function mix(...mixins){
    class Mix{}
    for(let mixin of mixins){
        copyProperties(Mix,mixin);
        copyProperties(Mix.prototype,mixin.prototype);
    }

    return Mix;
}
function copyProperties(target,source){
    for(let key of Reflect.ownKeys(source)){
        if(
            key!=="constructor"     
            &&key!=="prototype"
            &&key!=="name"       //类属性,返回class关键字后的类名。
        ){
            let desc = Object.getOwnPropertyDescriptor(source,key);
            Object.defineProperty(target,key,desc);
        }
    }
}

修饰器

是一个表达式,用于修改类的行为;是在编译时发生。ES7,使用Babel转码器

function decorator(target){
    target.name = "li";
}
@decorator
class User{}
User.name;     //"li"
//修饰器函数可接受三个参数,目标函数、属性名和该属性的描述对象(descriptor)
function decorator(name){
    return function(target){
        target.name = name;
    }
}
@decorator("lu")
class User{}
User.name;   //"lu"

方法的修饰

//name方法只读
class User{
    @readonly
    name(){return `$(this.name)`}
}
//三个参数,修改方法的默认行为
readonly(User.prototype,'name',descriptor);
function readonly(target,name,descriptor){
    /**
    {
        value:name,
        enumerable:false,
        configurable:true,
        writable:true
    }
    */
    descriptor.writable = false;
    return descriptor;
}

修饰器不能用于函数,函数存在提升。
可以使用第三方已经定义好的修饰器,core-decorator.js

    1.使用修饰器实现自动发布事件,在修饰器中定义事件,在对象的方法调用时自动发出。
    2.Mixin模式,在一个对象汇中混入另外一个对象的方法。对象继承的一种替代方案。
    3.Trait是一种修饰器,traits-decorator
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

heroboyluck

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值