前端学习(五十九) JavaScript-class基本语法(javaScript)

class简介

类实际上是一个“特殊的函数”,就像能够定义函数表达式函数声明一样,另外class都必须遵循严格模式,类的语法有两个组成部分:

  • 类声明
  • 类表达式

类声明:

通过使用带有关键字class的类名(下例的类名就是ES6)来声明一个类后面加一对大括号

            class ES6{
            }

另外注意,类的定义不会提升,这个跟函数声明不一样,函数声明不管在哪定义,都可以在任意地方调用,而类的调用必须在类声明之后,否则会抛出一个ReferenceError异常。

类表达式:

类表达式是定义类的另一种方式,类表达式可以是被命名的表达式,也可以是匿名的。赋予一个命名类表达式的名称是类主体的本地名称

            //匿名类
            let a=class {
                constructor(a,b){
                    this.a=a;
                    this.b=b
                }
            }
            //命名类,这边的命名最好和主体的名字一致
            let a=class a{
                constructor(a,b){
                    this.a=a;
                    this.b=b
                }
            }

注意,类表达式也同样有声明提升的问题,调用必须在声明之后

constructor方法:是一个特殊的方法,一个class类只有一个constructor方法,这个方法用于创建和初始化

实例上

            //ES5以及之前
            function ES5(a,b) {
                this.a=a;
                this.b=b
            }
            ES5.prototype.func=function(){
                return this.a+this.b
            }
            let result=new ES5(1,2)

在ES6之前,都是通过构造函数实现的,到了ES6引入了类的概念,把上面的修改转到类的写法

            //ES6
            class ES6{
                constructor(a,b){
                    this.a=a;
                    this.b=b
                }
                func(){
                    return this.a+this.b
                }
            }
            let result=new ES5(1,2)

可以看出,constructor的作用就是构造函数的初始化,而原型上的方法也被写到了类里面(注意类的里面不需要写function),其他基本一致,从这看出,ES6的写法只是将对象原型的写法更在清晰,更像是面向对象编程的语法而已。

class特性

那么class的写法原型对象写法有什么共性和区别呢?

实例化

都是通过new关键字将对象实例化,例如

            let a=new ES5();
            let b=new ES6();

但是,原型对象可以不通过new来直接引用函数使用,而class而不行,会报错

            let a=ES5();     //直接调用
            let b=ES6();     //会直接报错    

等同于构造函数,通过下面的例子可以看出,class类和原型对象,其实基本就是一致的

            class g{
                constructor(){
                    this.ga = "a"
                    }
                newTest(){
                    console.log(this.ga
                    );
            }}
            console.log(typeof g);  //function
            console.log(g===g.prototype.constructor);   //true
            
            let h=new g();
            h.newTest();    //'a'
            console.log(h.constructor === g.prototype.constructor); //true

给类添加方法

Obeject.assign(target,a,b....n)

这个方法在对象中学过了,是将对象中的属性添加到目标对象中,如果属性已存在,会被覆盖

            class es1{}
            Object.assign(es1.prototype,{
                newTest(){},
                newtest2(){}
            })

class的属性都是不可枚举的,ES5中的构造函数则都可以枚举

            class es1{
                newTest(){};
                newtest2(){};
            }
            Object.assign(es1.prototype,{
                newTest3(){},
                newtest4(){}
            })
            console.log(Object.keys(es1.prototype));    //["newTest3", "newtest4"]
            console.log(Object.getOwnPropertyNames(es1.prototype)); //["constructor", "newTest", "newtest2", "newTest3", "newtest4"]

这例子可以看出,class本身的方法都是不可枚举的,只有使用getOwnPropertyNames获取;

另外,class内部定义的外部不能访问

            //命名类
            let esha=class ha{
                getName(){
                    console.log(ha.name);
                    
                }
            }
            let dd=new esha();
            dd.getName();   //ha
            //console.log(ha.name);   //报错,ha外部不能访问
             console.log(esha.name);    //可以访问,输出:ha

立即执行,立即执行和内部定义是比较常用的

             let hba=new class hb{
                constructor(name){
                    this.name =name
                    }
                newTest(){
                    console.log(this.name);
            }}("yzq")
            hba.newTest()

二次声明

ES5中,如果同一个函数名被多次声明不会报错的,但是在ES6中class的类名如果相同会直接报错;

静态方法

            let Es6a=class{
                constructor(){};
                static test(){
                    console.log('yzqa');
                    
                }
            }

静态方法无法被实例化后的实例调用,如果调用会直接报错

            let Es6a=class{
                constructor(){};
                static test(){
                    console.log('yzqa');
                    
                }
            }
            let Es6a1=new Es6a();
            console.log(Es6a1.test());  //报错

另外Static this指向的是类(个人理解就是优先指向同样是静态static的方法,如果方法名重复,都是static则是最后一个)

            let Es6a=class{
                constructor(){};
                static static getName(){return this.test()}
                 test(){
                    console.log('yzqa');
                    
                }
                test(){
                    console.log("new yzqa");
                    
                }
            }
            Es6a.getName()    //yzqa

继承

关键字是extends,通过继承来获得父类的属性和方法,包括静态方法

            let Es6b=class{
                constructor(){};
                static getName(){return 'yzqa';}
                static getNewname(){
                    console.log("why999");
                    
                }
            }
            class Es6b1 extends Es6b{
                static getName(){
                    console.log(super.getName()+"v5");
                    
                }
            }
            Es6b1.getName();    //yzqav5
            Es6b.getNewname();  //why999

super关键字,调用父级元素的方法

class中new.target指向的是当前的类,哪怕是继承的子类使用super调用父级的new.target,new.target指向的依旧是当前的子类,如下例

            class Es6c{
                constructor(){
                    console.log(new.target===Es6c ? "success" : "fail");
                    
                }
            }         
            class Es6c1 extends Es6c{
                constructor(){
                    super();
                }
            }
            let _es6c=new Es6c();   //success
            let _es6c_c=new Es6c1();    //fail

猜你喜欢

转载自blog.csdn.net/zy21131437/article/details/81408718