ES6:他来了,class他来了!

ES6:class的引入

概要

  • ES6的class语法仅仅只是一个语法糖,在ES5中同样可以实现,新的class语法只是为了让对象原型的写法更加清晰,更像面向对象编程语法。
class Point{
    
    
    constructor(x,y){
    
    
        this.x = x;
        this.y = y;
    }
    toString(){
    
    
        console.log( '(' + this.x + ',' + this.y + ')');
    }
}

// 调用
let a = new Point(1,2);
a.toString();

//输出
(1,2)
  • 在类的实例上调用方法,实际上就是在调用原型的方法;

  • 类内部定义的方法都是不可枚举的;

  • 类必须使用new来调用,否则会报错;

class表达式

  • 与函数一样,class也可以用表达式的形式定义;
const myclass = class me{
    
    
    getClassName(){
    
    
        return me.name;
    }
}

let a = new myclass();
a.getClassName();

// 输出
"me"
  • 从上面的例子可以看出,me只在内部class中有用,外部调用时还是利用变量名称myclass;

不存在变量提升

  • 类不存在变量提升,因此在类定义之前不能够调用它;

私有方法和属性

  • 在ES6的class中没有提供private关键字,但目前有一种提案,采用#作为私有标志
class Me{
    
    
    #name
    #age = 20
    // #getmoney() {return 100}
    constructor(name){
    
    
        this.#name = name;
    }
    getit(){
    
    
        console.log('age:' + this.#age);
    }

}

let a = new Me('yivi');
a.getit();

//输出
age:20


//如果尝试访问私有属性
a.#name;
//报错
“Private field '#name' must be declared in an enclosing class

this的指向

  • 类的内部若含有this,他将默认指向类的实例。但有时单独使用该方法可能会报错。
class Logger{
    
    
    printName(name = 'yivi'){
    
    
        this.print(`${
      
      name},yyds!`);
    }
    
    print(text){
    
    
        console.log(text);
    }
}

const logger = new Logger();
const {
    
    printName}  = logger;
printName(); 	//报错
  • 上述代码中,this的指向默认指向实例,但如果提取出来单独使用,则this会指向当前的运行环境;
  • 解决方法是:在定义类时将this存储起来;
//方法1

class Logger{
    
    
    constructor(){
    
    
        // 将当前this绑定到printName函数上
        this.printName = this.PrintName.bind(this);
    }
    
    printName(name = 'yivi'){
    
    
        this.print(`${
      
      name},yyds!`);
    }
    
    print(text){
    
    
        console.log(text);
    }
}

const logger = new Logger();
const {
    
    printName}  = logger;
printName(); 	//“yivi,yyds!”
  • 还可以用箭头函数
// 方法2
class Logger{
    
    
    constructor(){
    
    
        this.printName = (name = 'yivi')=>{
    
    
            this.print(`${
      
      name},yyds!`)
        }
    }
}

getter和setter

  • 类的内部也可以设置get和set关键字对某个属性设置存值函数和取值函数。
class Myclass{
    
    
    constructor(){
    
    }
    get prop(){
    
    
        return 'i am getter!';
    }
    set prop(val){
    
    
        console.log("prop set as "+ val);
    }
}

let init = new Myclass();
init.prop =  123;
init.prop;

//prop set as 123
//i am getter

静态方法和静态属性

  • 类相当于实例的原型,在类的函数前添加static关键字,代表静态方法,只能通过类访问,实例将不会继承其方法。
class Foo{
    
    
    static mymethod(){
    
    
        console.log('i am static!');
    }
}

let a = new Foo();
Foo.mymethod();
a.mymethod();

// i am static!
// TypeError: foo.mymethod is not a function
  • 父类的静态方法可以被子类继承!子类可通过super调用父类方法。
class Father{
    
    
    static mymethod(){
    
    
        console.log('i am static!');
    }
}

class Son extends Father{
    
    
    static sonmethod(){
    
    
        console.log('hello!' + super.mymethod() );
    }
}

Son.mymethod();
// i am static!

Son.sonmethod();
// hello!i am static!
  • 静态属性和静态方法相同,也是在属性前添加static关键字。

new.target属性

  • ES6在类的内部定义了一个new.target属性,返回new命令锁作用的构造函数
class Person{
    
    
    name;
    constructor(name){
    
    
        if(new.target == Person){
    
    
            this.name = name;
        }else{
    
    
            throw new Error('请使用new生成实例');
        }
    }
}

let a = new Person('yivi');
  • 子类继承父类时,new.,target会返回子类!
class father{
    
    
    constructor(){
    
    
        console.log(new.target == father);
    }
}

class son extends father{
    
    
    constructor(){
    
    
        super();
    }
}

let a = new son();
// false;

关于子类的this

  • 子类的构造函数中,必须调用了super后,在可以使用this关键字,否则会报错;这是因为子类没有自己的this对象,只有继承父类的this对象。
  • 如果子类没有定义constructor,那么会自动添加包含super关键字的constructor。
class Father{
    
    }
class Son extends Father{
    
    
    constructor(...args){
    
    
        //自动添加
        super(...args);
    }
}

let a = new Son();
a instanceof Father;
a instanceof Son;

// true
// true

super关键字

  • super()这个方法只能用在子类的constructor属性中,用在其他地方会报错!

  • super关键字作为对象在普通方法中指向父类的原型对象,在静态方法中指向父类。

class A{
    
    
    constructor(){
    
    
        this.p = 123;
    }
}

class B extends A{
    
    
    constructor(){
    
    
        super();
        // 这里的super指向A.prototype
        console.log(super.p);
    }
    get m(){
    
    
        // 这里的super指向A
        console.log(super.p);
    }
}

let a = new B();
a.m;
// 123
// undefined
  • Es6规定,通过super调用父类方法时,super会绑定子类的this。也就是说,此时的super就是子类的this
class A{
    
    
    constructor(){
    
    
        this.x = 1;
    }
    print(){
    
    
        console.log(this.x);
    }
}


class B extends A{
    
    
    constructor(){
    
    
        super();
        this.x = 2;
    }
    getx(){
    
    
        super.print();
    }
}

let a = new B();
a.getx();
// 2;

类的prototype和__proto__属性

  • 子类的__proto__属性表示构造函数的继承,指向父类;
  • 子类的prototype属性的__proto__属性表示方法的继承,指向父类的prototype;
class A{
    
    }
class B extends A{
    
    }

B.__proto__ === A	//true
B.prototype.__proto__  === A.prototype	//true

猜你喜欢

转载自blog.csdn.net/yivisir/article/details/108781805