ES6 Class类

ES6 Class类

ES6中class是基于原型的继续的语法糖,供应越发清楚的语法来建立对象和原型。

声明和定义

es5 声明一个组织函数:

function Student(name, age) {
    this.name = name;
    this.age = age;
}

Student.prototype.getInfo = function() {
    return '{name:' + this.name + ',age:' + this.age + '}';
}

Student.prototype.setInfo = function(name, age) {
    this.name = name;
    this.age = age;
}

var p = new Student('nico', 1);
p.getInfo(); //{name:nico,age:1}
p.setInfo('siip', 10);
p.getInfo(); //{name:siip,10}

es6 声明一个类:

class Student {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    getInfo() {
        return `{name:${this.name},age:${this.age}}`;
    }
    setInfo(name, age) {
        this.name = name;
        this.age = age;
    }
}
let p = new Student('nico', 1);
p.setInfo('siip', 10);
p.getInfo();//{name:siip,10}

以上二者相比之下,很能够看出,es6类函数比es5组织函数,代码量更少,而且构造条理越发简洁清楚明了。

有些处所须要注重的是:

  1. es5存在变量提拔(var xxx,function xxx(){})
  2. es6不存在变量提拔(const,let,class)

Class 要领

constructor

constructor是默许的要领,就算在声明类函数时没有写constructor要领,在实例化时会自动增加上一个空的constructor

class Student {
    constructor() {
        this.desc = 'test';
    }
}

经由过程babel转码:

   function _classCallCheck(instance, Constructor) {
        if (!(instance instanceof Constructor)) {
            throw new TypeError("Cannot call a class as a function");
        }
    }

    var Student = function Student() {
        _classCallCheck(this, Student);//类不能直接被挪用,只能经由过程new实例化

        this.desc = 'test';
    };

constructor要领指向本身,在一个类中只能有一个名为 “constructor” 的特别要领。

Student === Student.prototype.constructor;//true

static

简述:望文生义这是一个静态要领,就是不须要实例化类就可以够挪用的要领, 实例化对象不能继续静态要领。

class Student {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    static ageFilter(...args) {
        let stuAge = args;
        let arr = [];

        for (let i = 0; i < stuAge.length; i++) {
            if (stuAge[i].age > 12) {
                arr.push(stuAge[i])
            }
        }
        return arr;
    }
    getInfo() {
        return `{name:${this.name},age:${this.age}}`;
    }
    setInfo(name, age) {
        this.name = name;
        this.age = age;
    }
}
Student.ageFilter({
    name: 'a',
    age: 1
}, {
    name: 'b',
    age: 14
});//{name: "a", age: 14}

静态函数的this指向类函数本身,当this没有指明被谁挪用时,this为undefined

我们将上面代码用babel编译,从效果上看:

    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;
        };
    }();

从代码能够看出,静态要领与类函数要领的区别是:当用Object.defineProperty去定义对象属性时传入的对象差别,一个传入的是组织函数的原型,另一个是传入组织函数。

es6当前还不支撑静态属性

extends

关键字在类声明或类表达式中用于建立一个类作为另一个类的一个子类

class Student {
    constructor(name = null, age = null) {
        this.name = name;
        this.age = age;
    }
    getInfo() {
        return `{name:${this.name},age:${this.age}}`;
    }
    setInfo(name, age) {
        this.name = name;
        this.age = age;
    }
}

class Citizen extends Student {
    constructor(name, age) {
        super(name, age);
        this.name = 123;
    }
}
let stu = new Citizen('siip', '25');
stu.getInfo(); //{name:siip,age:25}

能够看到子类能够挪用父类上的要领和属性,当运用extends继续父类时,子类constructor和super和被默许增加上,而且在组织函数内,只要挪用了super函数后才运用this,否则会抛出ReferenceError毛病

     constructor() {
        this.name = 'xxx'
         super()
      }//ReferenceError

super

  • super可作为一个函数运用
  • super可作为一个对象运用

下面一个子类继续父类的Math的要领:

function MathFns() {
    this.status = 'Father'
}
MathFns.prototype = Math;

class Max extends MathFns {
    constructor() {
        super();
    }
    static base() {
        return super.max();
    }
}
let m = new MathFns();
m; //{status: "Father"}
m.max(1, 2);//2

我们能够经由过程babel编译,尝试去明白es6的继续,

function _inherits(subClass, superClass) {
    if (typeof superClass !== "function" && superClass !== null) {
        throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
    }
    subClass.prototype = Object.create(superClass && superClass.prototype, {
        constructor: {
            value: subClass,
            enumerable: false,
            writable: true,
            configurable: true
        }
    });

    if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;

}

这个封装继续函数,重要完成的功用是,子类原型指向父类,原型组织器指向本身,然后再经由过程隐式原型链指向父类函数,如许子类被实例化后的对像就可以运用父类原型链上的要领以及经由过程隐式原型链访问到父类的属性。

总结

总的来看,es6的class类实际上是基于原型链和继续做的一层封装,它的构造条理相对于es5原型链写法越发清楚清楚明了,代码量更少。class类重要内容是组织函数、静态要领、继续。

  1. 组织函数

    • 一个类里,必有一个constructor函数,默许。
    • 类不存在变量提拔
    • 一个类里只能有一个constructor函数
    • constructor函数指向类本身
  2. 静态要领

    • 静态函数的this指向类函数本身,当this没有指明被谁挪用时,this为undefined
    • 在同一个类中的一个静态要领挪用另一个静态要领
    • 类实例化对象不能挪用类静态要领
  3. 继续

    • 子类继续父类的属性和要领
    • 在子类继续父类,子类的组织函数中要先挪用super函数,才运用this
    • super能够作为函数或对象挪用,但指向都是子类
    原文作者:NicolaChin
    原文地址: https://segmentfault.com/a/1190000013220367
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞