zoukankan      html  css  js  c++  java
  • ES6 的class类 笔记

    class Person{  
        // 构造  
        constructor(x,y){  
            this.x = x;  
            this.y = y;  
        }  
        toString(){  
            return (this.x + "的年龄是" +this.y+"");  
        }  
    }  
    export {Person};  
    //index.js  
    import {Person} from './Person';  
    let person = new Person('张三',12);  
    console.log(person.toString());</span>  

    1、class初始化定义:

       Person 是一个类 ,定义了属性(x,y)与方法 toString()

    console.log(typeof Person);//function  
    console.log(Person === Person.prototype.constructor);//true

    so: 类的数据类型就是函数,类本身就指向构造函数, 可以理解为:类就是构造函数 , 因为es5的中 【构造函数 === 构造函数.prototype.constructor】

    2、class类的修改与增加属性方法:

    构造函数的prototype属性,在ES6的“类”上面继续存在。事实上,类的所有方法都定义在类的prototype属性上面,通过以下方式可是覆盖类中的方法,当然定义类的时候也可以通过这个方式添加方法。

    Object.assign(Person.prototype,{  
        getWidth(){  
            console.log('12');  
        },  
        getHeight(){  
            console.log('24');  
        }  
    });  
    Person.prototype.sex = 'man' ;
    console.log(p.sex);  // man
    
    Person.prototype.sex = 'woman' ;
    console.log(p.sex);  //woman

    //class拥有保护机制,可以增加,或覆盖原来有属性,但是如下就不行
    Person.prototype == {}
    console.log(p.sex); //'woman';
    //sex属性还在,prototype从新赋空值这样是不生效的
     

    PS建议:class类已经定义完毕不可修改,不可直接修改Person.prototype,个别场景需要,应新建一个继承class上,然后再修改,拓展,新class继承老的class

    3、constructor构造函数:

    constructor方法是类的构造函数是默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个默认的constructor方法会被添加。所以即使你没有添加构造函数,也是有默认的构造函数的。一般constructor方法默认返回实例对象this,但是也可以指定constructor方法返回一个全新的对象,让返回的实例对象不是该类的实例。

    class AA {
        sayHello(){console.log('Hello')}
    }
    class BB{  
        // 构造
        constructor() {  
            this.x = 'x'
            return new AA();  
        }  
        sayX(){console.log(this.x)}
    }  
    let b = new BB();
    b.sayHello();  // hello
    b.sayX();  //TypeError: b.sayX is not a function

    4、类的构造函数,不使用new是没法调用的,使你使用实例对象去调用也是不行,这是它跟普通构造函数的一个主要区别。实例的属性除非显式定义在其本身(即定义在this对象上),否则都是定义在原型上(即定义在class上);

    class Person{  
        // 构造
        constructor(x,y){  
            this.x = x;  
            this.y = y;  
        }  
      
        toString(){  
            return (this.x + "的年龄是" +this.y+"岁");  
        }  
    }    
    let p = new Person('lis',8);  
    console.log(p.hasOwnProperty('x'));// true
    console.log(p.hasOwnProperty('toString'));//false  
    //x,y是定义在this对象上,toString定义在类上。

    4.1、类内部定义的方法(Person的toString方法),ES6中它是不可枚举的,这一点与ES5的行为不一致,ES5是可以枚举的。

    Object.assign(Person.prototype,{  
        getWidth(){  
            console.log('12');  
        },  
        getHeight(){  
            console.log('24');  
        }  
    });  
    
    //ES5  
    console.log(Object.keys(Person.prototype));//["toString", "getWidth", "getHeight"]  
    console.log(Object.getOwnPropertyNames(Person.prototype));//["constructor", "toString", "getWidth", "getHeight"]  
      
    //ES6  
    console.log(Object.keys(Person.prototype));//["getWidth", "getHeight"]  没有toString 可以用getOwnPropertyNames
    console.log(Object.getOwnPropertyNames(Person.prototype));//["constructor", "toString", "getWidth", "getHeight"]
    //
    //Object.keys(obj),返回数组里是该obj可被枚举的所有属性。Object.getOwnPropertyNames(obj),返回数组里是该obj上所有的实例属性。

    5、可以通过实例的__proto__属性为Class添加方法(绝不推荐)

    let person1 = new Person('李四',13);  
    person1.__proto__.getH = function (){  
        return "Height";  
    };   
    console.log(person1.getH());

    6、class不存在变量提升,需要先定义再使用,因为ES6不会把类的声明提升到代码头部,但是ES5就不一样,ES5存在变量提升,可以先使用,然后再定义。

    new A();  
    function A(){  
      
    }//ES5可以先使用再定义,存在变量提升  
    //错误  
    new B();  
    class B{  
      
    }//B is not a constructor  
    //ES6不能先使用再定义,不存在变量提升

    7、const Expression = class Expre  谁才是真的class名,下边这个类的名字是Expression而不是Expre,Expre只在Class的内部代码可用,指代当前类。

    const Expression = class Expre{  
        static getAge(){  
            return '12';  
        }  
        getClassName(){  
            return " ClassName1= " +Expre.name + " ClassName2= " +Expression.name;  
        }  
    };  
      
    let exp = new Expression();  
    //let exp = new Expre();错误  
    //bundle.js:7935 Uncaught ReferenceError: Expre is not defined  
    console.log(exp.getClassName());//ClassName1= Expre ClassName2= Expre  
    //console.log(Expre.getAge());错误  
    //bundle.js:7935 Uncaught ReferenceError: Expre is not defined  
    console.log(Expression.getAge())
    
    //也可以这么写
    //说明:如果省略了class后面的那个名字Expre,MyExpre.name返回的就是MyExpre,如果没有省略MyExpre.name返回就是class后面的那个名字Expre。
    const MyExpre = class{ getClassName(){ return MyExpre.name; } };

    8、采用Class表达式,可以写出立即执行的Class

    let person = new class{  
        // 构造  
        constructor(props) {  
            this.props = props;  
        }  
        getProps(){  
            return this.props;  
        }  
    }('构造函数的参数');  
    console.log(person.getProps());//构造函数的参数

    9、私有方法的需求:

    私有方法是常见需求,但ES6不提供,只能通过变通方法模拟实现。一种做法是在命名上加以区别,在方法前面加上_(下划线),表示这是一个只限于内部使用的私有方法。但是,这种命名是不保险的,在类的外部,还是可以调用到这个方法。另一种方法就是索性将私有方法移出模块,因为模块内部的所有方法都是对外可见的。

    export default class PrivateMethod{  
        // 构造  
        constructor() {  
        }  
        getName(){  
            priName();  
        }  
    }  
      
    function priName(){  
        console.log('私有方法测试');  
    }  
    //index.js  
    import PriMe from './PrivateMethod';  
    let prime = new PriMe();  
    prime.getName();

    10、类内部this指向问题:

    类的方法内部如果含有this,它默认指向类的实例。getName方法中的this,默认指向ThisStu类的实例。但是,如果将这个方法提取出来单独使用,this会指向该方法运行时所在的环境,因为找不到name方法而导致报错。

    class ThisStu{  
        getName(){  
            return this.name();  
        }  
        name(){  
            return '王五';  
        }  
    }  
    
    let thisStu = new ThisStu();  
    console.log(thisStu.getName());  //王五
    const {getName} = thisStu;  
    getName();  //Cannot read property 'name' of undefined

    一个比较简单的解决方法是,在构造方法中绑定this,这样就不会找不到name方法了。

    class ThisStu{  
        constructor() {  
            this.getName = this.getName.bind(this);  
        }  
        getName(){  
            return this.name();  
        }  
        name(){  
            return '王五';  
        }  
    }  
    
    //或者 用剪头函数  在构造函数,直接给当前实例的getName赋值
    class ThisStu1{  
        constructor() {  
            this.getName = ()=>{  
                return this.name();  
            }  
        }  
        name(){  
            return '王五';  
        }  
    }  

    11、Class类的静态方法  static的定义

    类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。

    //定义静态方法  
    static getAge(){  
     return '获取Age的静态方法';  
    }  
    //通过类名直接调用  
    console.log(StaticMethod.getAge());

    如果StaticMethod继承StaticMethodParent,StaticMethodParent的静态方法,可以被StaticMethod继承。

    export default class StaticMethodParent{  
        static getCommon(){  
            return '父类的静态方法';  
        }  
    }  
    //通过子类直接调用  
    console.log(StaticMethod.getCommon());  
    如果StaticMethod继承StaticMethodParent,StaticMethodParent的静态方法,可以在StaticMethod中用super调用。  
    //定义静态方法  
    static getAge(){  
        //子类可以调用父类的静态方法  
        console.log(super.getCommon());  
        return '获取Age的静态方法';  
    }

    说明:静态方法只能在静态方法中调用,不能再实例方法中调用。

    参考资料地址:https://blog.csdn.net/pcaxb/article/details/53759637

    http://es6.ruanyifeng.com/#docs/class

  • 相关阅读:
    jenkins GitHub 自动触发
    rabbitmq web管理
    系统编码,文件编码,python编码
    反转二叉树
    从右边看二叉树
    python pyenv
    js 闭包
    git review & devops过程
    centos7搭建自己的yum源
    优先级队列PriorityQueue 测试,会自动排序
  • 原文地址:https://www.cnblogs.com/liujinyu/p/9075949.html
Copyright © 2011-2022 走看看