美文网首页
类与继承

类与继承

作者: della岳 | 来源:发表于2022-01-27 13:52 被阅读0次

    一、es5的类与继承

    1. prototype原型对象

    每个函数(普通函数、构造函数)都有一个prototype原型对象,每个prototype都有constructor属性,constructor指向函数本身
    每个实例都有一个proto,指向构造函数的原型对象

    function getSum(a,b){
        console.log(a+b)
    }
    function People(name,age){
        this.name = name;
        this.age = age;
    }
    getSum(1,2);
    console.log(People.prototype.constructor)// People
    console.log(getSum.prototype.constructor)// getSum
    
    2. 静态方法和实例方法

    ① 在构造函数体中,this指向实例对象,通过this创建的属性属于实例属性
    ② 在构造函数原型对象上创建方法,方法内部this指向实例对象,属于实例方法
    ③ 直接挂在构造函数上的属性为静态属性、方法为静态方法,静态方法内的this指向构造函数本身
    ④ 直接调用构造函数,函数体内this指向调用时所处的作用域,即window

    // 声明构造函数People
    function People(name,age){
        console.log(this);// this指向实例对象
        this.name = name; //① 实例属性
        this.age = age; //① 实例属性
        People.count++;
    }
    // ② 实例方法,构造函数原型对象上的方法属于实例方法
    People.prototype.showName = function(){
        console.log('我的名字是',this.name)
    }
    // ③ 静态属性,构造函数上的属性属于静态属性
    People.count = 0;
    // ③ 静态方法,构造函数上的方法属于静态方法
    People.getCount = function(){ 
        console.log(this);// this指向构造函数本身
        console.log(this.count === People.count)//true ,此处等同于People
        console.log('目前共有',People.count,'个人')
    }
    
    let p1 = new People('xiaoyue1')
    console.log(p1);
    p1.showName();// 每个实例都能访问到原型对象上的方法和属性
    let p2 = new People('xiaoyue2')
    console.log(p2);
    p2.showName();// 每个实例都能访问到原型对象上的方法和属性
    
    console.log(People.count) //访问静态属性
    People.getCount(); //调用静态方法
    People('lily',18); // ④ 直接调用构造函数,函数题内部this指向当前作用域window
    
    // 常见静态方法和属性
    Math.max(1,2)
    Math.PI
    console.log(Math)// 查看Math上有哪些静态睡醒和静态方法
    // 常见实例方法和属性
    let arr = [1,2,3];
    console.log(arr.slice(1))// slice为实例方法,slice、push、pop等这些方法都是挂在Array的构造函数上的
    
    3. 类的继承,组合式继承

    ① 继承父类的属性:通过调用父类函数,call改变函数内this指向。People.call(this,name)
    ② 继承父类的方法:实例化一个父类的对象赋值给子类的原型对象,让子类实例通过自身的原型对象访问到父类的原型对象的方法。Student.prototype = new People();
    ③ 原型对象的constructor指回子类。Student.prototype.constructor = Student;

    function Student(name,hobby){
        People.call(this,name);//① 继承属性:执行People函数,改变this指向为当前Student实例
        this.hobby = hobby; //实例自身属性
    }
    // ②实例化一个People对象peo,peo赋值给Student原型对象,实例对象peo能访问到People原型对象上所有的方法, 因此Student原型对象也能访问到People原型对象上的所有方法。
    const peo = new People(); //实例化一个People对象peo
    Student.prototype = peo; //赋值给Student原型对象
    // Student.prototype = new People(); 或直接这样写
    // ③赋值前,Student的prototype的constructor指向Student。
    // ③赋值后,实例对象peo本身没有constructor,就会去new出它的构造函数People的原型对象上去找,但People的原型对象的constructor属性是指向People本身的。因此Student.prototype.constructor就会是People,得改回来,让它指回Student,如下。
    Student.prototype.constructor = Student; //③
    // 除了能访问到People的所有方法,还可以给Student原型对象添加属于自己的方法dance
    Student.prototype.dance = function(){ 
        console.log('dance')
    }
    let s1 = new Student('yoyo','跳舞');
    // console.log(Student.count) //undefined,继承不到静态属性和方法
    // console.log(Student.getCount()) //报错, 继承不到静态属性和方法
    console.log(s1)
    s1.showName()
    s1.dance()
    

    练习题

    console.log(s1.constructor === Student); //true
    console.log(s1.constructor === People); //false
    console.log(p1.constructor === People); //true
    console.log(p1.__proto__ === People.prototype); //true
    console.log(s1.__proto__ === Student.prototype); //true
    console.log(s1.__proto__.constructor === Student); //true
    

    二、es6的类与继承

    1. 类

    ① class 声明类
    ② constructor 函数体
    ③ static 声明静态方法,不能声明静态属性
    ④ set和get 实例属性声明的另一种方式,可用于属性的读与写时的拦截处理

    class People{ //①
        constructor(name){ //②函数体
            this.name = name; //实例属性
            this._sex = 0;
        }
        showName(){ //实例方法
            console.log(this.name)
        }
        // static count = 0; //会报错,es6还不支持这种static声明静态属性的写法!
        static getCount(){ //③静态方法
            // console.log(this) //静态方法this指向People,就是调用getCount时的.前面的那个对象
            console.log(this.count) //0
            console.log(this.count === People.count) //true
        }
        get sex(){ //④getter获取 
            if(this._sex === 0){
                return 'female'
            }else if(this._sex === 1){
                return 'male'
            }else{
                return 'error'
            }
        }
        set sex(val){ //④setter设置,只声明了set没声明get方法,设置时会报错
            if(val ===0 || val === 1){
                this._sex = val;
            }
        }
    }
    People.count = 0; //静态属性,目前只能这声明
    let p1 = new People('yoyo');
    console.log(p1);
    console.log(p1.sex)
    p1.sex = 1;
    console.log(p1.sex)
    
    2. 继承

    extends继承内容:实例属性、实例方法、静态属性、静态方法、get/set属性

    class Student extends People{
        constructor(name,hobby){
            super(name)
            this.hobby = hobby
        }
        study(){
            console.log('study')
        }
    }
    let s1 = new Student('yoyo','dance');
    console.log(s1) 
    console.log(s1.sex) //0 继承了get 和set声明的属性
    s1.showName(); //继承了实例方法
    console.log(Student.count) //0 继承了静态属性
    console.log(Student.getCount()) //true 继承了静态方法
    

    相关文章

      网友评论

          本文标题:类与继承

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