ES6中的类

186 阅读3分钟

ES5和ES6创建类

//ES5
function Point(x,y){
    this.x = x;
    this.y = y;
}
Point.prototype.getPostion = function(){
    return '(' + this.x + ',' + this.y')'
}

var p1 = new Point(2,3);
console.log(p1) // Point {x:2,y:3}
console.log(p1.getPostion()) //(2,3)

//ES6
class Point{
    constructor(x,y){
        this.x = x;
        this.y = y;
    }
    getPostion () {
        return `(${this.x},${this.y})`
    }
}

var p1 = new Point(2,3);
console.log(p1) // Point {x:2,y:3}
console.log(p1.getPostion()) //(2,3)
console.log(p1.hasOwnProperty('x')) // true
console.log(p1.hasOwnProperty('getPostion')) //false
console.log(p1.__proto__.hasOwnProperty('getPostion')) //true getPostion是定义在类的prototype上的

取值函数 存值函数

// ES5
var info = {
    _age:18, //私有变量
    set age(newValue){
        if (newValue > 18){
            console.log('哭~~~')
        } else {
            console.log('笑~~~')
        }
    },
    get age(){
        console.log('秘密~~~~')
        return this._age
    }
}
console.log(info.age) //获取age的时候就会触发 get age()
// 返回 你问我年龄干嘛
info.age = 17 //返回 我还年轻

// ES6
class Info(){
    constructor(age){
        this._age = age
    }
    set age (newAge){
        console.log('new age is:' + newAge)
        this._age = newAge
    }
    get age(){
        return this._age
    }
}
const infos = new Info(18)
infos.age = 17
// new age is: 17
console.log(infos.age) // 17

class表达式

const Func = function(){}
function Func(){}

//ES6
const Infos = class{}
class Infos = {}

静态方法

class Point {
    z = 0;
    constructor(x,y){
        this.x = x;
        this.y =y;
    }
    static getClassName(){
        return Point.name
    }
}

Point.getClassName() // Point
const p = new Point()
// Point {z: 0, x: undefined, y: undefined}

私有变量

//第一种
class Point{
    _name(){
        //私有方法 只是约定 还是可以被外部调用
    }
}
//第二种
const _fn = () => {}
class Point{
    fn1(){
        _fn.call(this)
    }
}
// export default Point 只暴露这个类外部就没办法访问到_fn

//第三种
//a.js
const fn = Symbol('fn');
export default class Point{
    
}
//b.js
import Point from './a.js'
//只可以访问point

//第四种
class Point {
    #oenProp = 12
}

new target

function Point(){
    console.log(new.target)
}
const p = new Point();
/*
输出 f Point(){
    console.log(new.target)
}
*/
function Point(){
    constructor(){
        console.log(new.target)
    }
}
const p = new Point();
/*
输出 f Point(){
    constructor(){
        console.log(new.target)
    }
}*/
function Parent(){
    constructor(){
        console.log(new.target)
    }
}
class Child extends Parent{
    constructor(){
        super()
    }
}
/*
输出 class Child extends Parent(){
    constructor(){
        console.log(new.target)
    }
}

继承

//ES5的继承
function Food(){
    this.type = 'food'
}
Food.prototype.getType = function(){
    return this.type
}

function Vegetables(name){
    this.name = name
}

//继承
Vegetables.prototype = new Food();
const tomato = new Vegetables('tomato')
console.log(tomato.getType())
// food

class Parent{
    constructor(name){
        this.name = name
    }
    getName(){
        return this.name
    }
}

class Child{
    constructor(name,age){
        super(name) //继承至父类
        this.age = age
    }
}
const c = new Child('kimi',18)
console.log(c) 
// Child {name:'kimi',age:18}
console.log(c.getName())
// kimi
console.log(c instanceof Child) //true
console.log(c instanceof Farent) //true
//既是子类的实例也是父类的实例

console.log(Object.getPrototypeOf(Child) === Parent) //true
//Child的原型就是Parent类

super

//super 做为函数 指向父类的构造函数constructor
class Parent {
    constructor(name){
        this.name = name
    }
    getName(){
      return this.name
    }
    static getNames (){
        return this.name
        // this 指向的是Child类
    }
}
class Child extends Parent{
    constructor(name,age){
        super(name) //必须调用super才可以使用this
        this.age = age
    }
}
const c = new Child('kimi',18)
console.log(c.name) // kimi
console.log(Child.getNames()) 
// 父类的static getNames(){return this.name}
// 这里的this指向Child类
// Child

// super 做为对象 指向的是父类的原型对象
// super 静态方法 指向父类
class Parent{
    constructor(){
        this.type = 'parent'
    }
    getName(){
        return this.type
    }
}
Parent.getType = () => {
    return 'is parent'
}

class Child extends Parent{
    constructor(){
        super()
        console.log('constructor:' + super.getName())
        // parent
    }
    getParentName(){
        console.log(super.getName)
    }
    getParentType(){
        console.log(super.getType())
    }
    static getParentType(){
        console.log(super.getType())
    }
}

const c = new Child()
c.getParentName() // parent
c.getParentType() // TypeError 无法访问到父类的静态方法

Child.getParentType() // is parent
class Parent{
    constructor(){
        this.name = 'parent'
    }
    print(){
        console.log(this.name)
    }
}
class Child extends Parent{
    constructor(){
        super()
        this.name = 'child'
    }
    childPrint(){
        super.print() 
        // 这里的super指向的是父类的原型对象
        // 单独使用super会报错
    }
}

const c = new Child()
c.childPrint() // child 父类里面的this指向的是子类的实例

proto

var objs = new Object()
console.log(objs.__proto__ === Object.prototype) // true
// 子类的__proto__指向的是父类本身
// 子类的prototype属性的__proto__指向父类的prototype属性
// 实例的__proto__属性的__proto__指向父类实例的__proto__

原生实例的继承

class CustomArray extends Array{
    constructor(...args){
        super(...args)
    }
}

const arr = new CustomArray(3,4,5)
console.log(arr.fill(0)) // [0,0,0]
console.log(arr) // CustomArray(3) [3,4,5]
// 可以继承Array的方法

为什么super 必须在this之前

  • 普通的构造函数执行时,会创建一个空对象作为this
  • 继承构造函数,需要父类完成这件事情,只有调用super 才会创建空对象 才会又this 负责就会报错