class

作者: 撑船的摆渡人 | 来源:发表于2019-02-15 09:12 被阅读0次

    ES6引入class(类)这个概念,通过class关键字可以定义类。该关键字的出现使得其在对象写法上更加清晰,更像是一种面向对象的语言。

    class Person { //定义了一个名字为Person的类
        constructor(name, age){ //constructor是一个构造方法,用来接收参数
            this.name = name; //this代表的是实例对象
            this.age = age;
        }
        say(){ //这是一个类的方法,注意千万不要加上function
            return `我叫${this.name},${this.age}岁了`
        }
    }
    let obj = new Person('andy',18);
    console.log(obj.say());
    

    类自身指向的就是构造函数,所以可以认为ES6中的类其实就是构造函数的另外一种写法。

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

    实际上类的所有方法都定义在类的prototype属性上

    class Person { //定义了一个名字为Person的类
        constructor(name, age){ //constructor是一个构造方法,用来接收参数
            this.name = name; //this代表的是实例对象
            this.age = age;
        }
        say(){ //这是一个类的方法,注意千万不要加上function
            return `我叫${this.name},${this.age}岁了`
        }
    }
    Person.prototype.say = function(){ //定义与类中相同名字的方法。
        return `覆盖类中的方法,我叫${this.name},${this.age}岁了`
    }
    let obj = new Person('andy',18);
    console.log(obj.say());
    

    也可以通过prototype属性对类添加方法

    Person.prototype.addFn=function(){
        return "我是通过prototype新增加的方法addFn";
    }
    let obj = new Person('andy',18);
    console.log(obj.addFn());
    

    还可以通过Object.assign方法来为对象动态添加方法

    Object.assign(Person.prototype,{
        getName:function(){
            return this.name;
        },
        getAge:function(){
            return this.age;
        }
    })
    let obj = new Person('andy',18);
    console.log(obj.getName());
    console.log(obj.getAge());
    

    constructor方法是类的构造函数的默认方法,通过new命令生成对象实例时,自动调用该方法。

    class Box {
        constructor(){
            console.log('实例化对象时,自动调用')
        }
    }
    let obj2 = new Box();
    

    constructor方法如果没有显示定义,会隐式生成一个constructor方法。所以即使你没有添加构造函数,构造函数也是存在的。constructor方法默认返回实例对象this,但是也可以指定constructor方法返回一个全新的对象,让返回的实例对象不是该类的实例。

    class Desk {
        constructor(){
            this.haha = '你好'
        }
    }
    class Body {
        constructor(){
            return new Desk();// 没有用this,直接返回一个全新的对象
        }
    }
    let obj3 = new Body();
    console.log(obj3.haha);
    

    constructor中定义的属性可以称为实例属性(既定义在this对象上),constructor外声明的属性都是定义在原型上的,可以称为原型属性(既定义在class上)。hasOwnProperty()函数用于判断属性是否是实例属性。其结果是一个布尔值,true说明是实例属性,false说不是实例属性。in操作符会在通过对象能够访问给定属性时返回true,无论该属性存在于实例中还是原型中。

    class Box{
        constructor(num1,num2){
            this.num1 = num1;
            this.num2 = num2;
        }
        sum(){
            return num1 + num2;
        }
    }
    let box = new Box(12,88);
    console.log(box.hasOwnProperty('num1'));
    console.log(box.hasOwnProperty('num2'));
    console.log(box.hasOwnProperty('sum'));
    console.log('num1' in box);
    console.log('num2' in box);
    console.log('sum' in box);
    console.log('say' in box);
    

    类的所有实例共享一个原型对象,他们的原型都是Person.prototype,所以proto属性时相等的

    class Person{
        constructor(m,n){
            this.m = m;
            this.n = n;
        }
        sum(){
            return m + n;
        }
    }
    

    p1与p2都是Person的实例,它们的proto都指向Person的prototype

    let p1 = new Person(1,2);
    let p2 = new Person(4,8);
    console.log(p1.__proto__,p1.__proto__ === p2.__proto__);
    

    由此,也可以通过proto来为类增加方法。使用实例的proto属性改写原型,会改变Class的原始定义,影响到所有实例,所以不推荐使用!

    p1.__proto__.sub = function(){
        return this.n - this.m
    }
    console.log(p1.sub());
    console.log(p2.sub());
    

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

    ES5可以先使用在定义,存在变量提升

    new A();
    function A(){
        console.log('ES5执行了')
    }
    

    ES6不能使用在定义,不存在变量提升,会报错

    new B();
    class B{
        constructor(){
            console.log('ES6执行时保错,B is not defined')
        }
    }
    

    相关文章

      网友评论

          本文标题:class

          本文链接:https://www.haomeiwen.com/subject/rqveeqtx.html