js高级之面向对象三大特征以及原型链

526 阅读3分钟

面向对象三大特征

  • a.封装:将某个具体功能封装在对象中,(把代码放入对象的方法中)只对外部暴露指定的接口,外界在使用的时候,只考虑接口怎么用,不用考虑内部怎么实现

  • b继承:一个对象拥有其他对象的属性和方法

  • c.多态:一个对象在不同情况下的多种状态

    • js基本不涉及多态

继承的三种实现方式

1.混入式继承 : 遍历 父对象 的所有属性值,添加给 子对象

  • 特点:每继承一次,就要执行一次循环 应用场景:单个对象继承

示例如下:

 for (let key in father){
        father[key] = son[key]
    }
    console.log ( son )

2.替换原型继承 : 将 父对象 作为 子对象构造函数的原型

  • 特点:会丢失原型之前的成员变量 应用场景:多个对象继承
  • 原型继承之后,由于父对象覆盖原来的子对象构造函数原型,就会导致constructor消失
  • 解决办法:手动添加(对开发几乎没有影响,也可以不加) Son.prototype.constructor = Son

示例如下:

 let father = {
        house:{
            address:'北京一环',
            price:100000000
        },
        car:{
            brand:'劳斯莱斯',
            price:5000000
        }
    }

    function Son (name,age  ) {
        this.name = name
        this.age = age
    }

    Son.prototype.sayHi = function(){
        console.log('你好')
    }
    

    //让父对象成为子对象构造函数的原型
    Son.prototype  = father

    //实例化对象
    let son1 = new Son('小张',30)
    console.log ( son1 )
    let son2 = new Son('小王',20)
    console.log ( son2 )
    

3.混合式继承 : 混入式 + 替换原型

  • 特点 : 遍历 父对象 所有的属性值,添加给 子对象构造函数 的原型

示例如下:

 let father = {
        house:{
            address:'北京一环',
            price:100000000
        },
        car:{
            brand:'劳斯莱斯',
            price:5000000
        }
    }

    function Son (name,age  ) {
        this.name = name
        this.age = age
    }

    Son.prototype.sayHi = function(){
        console.log('你好')
    }

   //将父对象的所有属性添加到子对象构造函数的原型中
    for(let key in father){
        Son.prototype[key] = father[key];
    }

    //实例化对象
    let son1 = new Son('小张',30)
    console.log ( son1 )
    let son2 = new Son('小王',20)
    console.log ( son2 )

原型链

原型链的定义

原型链的定义 :每一个对象,都有__proto__指向自身的原型。 而原型也是对象,也有自己的__proto__指向原型的原型,以此类推形成链式结构,称之为原型链。(原型链的终点是null)

对象访问原型链中成员的规则

对象访问原型链中成员的规则 :就近原则

  • 当访问对象的成员,先看自己有没有。有则访问,没有则看原型有没有。

  • 原型有则访问, 没有则访问原型的原型,没有则继续往上找。

  • 以此类推,一直找到原型链终点 : null.

  • 还没有, 如果是属性 : 则获取undefined 如果是方法 ,则报错xxx is not function 示例如下:

image.png

//1.构造函数
        function Person(name, age) {
            this.name = name;
            this.age = age;
        };

        //2.原型对象:存储具有共同特征的属性
        Person.prototype.sayHi = function () {
            console.log('人生若只如初见,何事秋风悲画扇');
        };

        Person.prototype.type = '人类';

        //3.实例化对象
        let p1 = new Person('大美女', 18);
        console.log(p1);

        //请说出以下代码执行结果
        console.log(p1.name); //大美女      p1自己有name属性
        console.log(p1.type); //人类  p1自己没有type,但是p1的原型有
        console.log(p1.hobby); //undefined p1自己没有hobby,原型也没有
        p1.sayHi(); // 人生若只如初见,何事秋风悲画扇   p1自己没有这个方法,原型有
        // p1.eat();//报错 xxx is not function    p1自己没有这个方法,原型也没有

        //为什么不报错?  p1自己没有这个方法,原型也没有这个方法,但是原型的原型有
        p1.toString();

        //查看p1的原型链
        console.log(p1.__proto__.constructor); //Person
        console.log(p1.__proto__ === Person.prototype); //true

        //查看p1的原型的原型
        console.log(p1.__proto__.__proto__.constructor); //Object
        console.log(p1.__proto__.__proto__ === Object.prototype); //true

        //查看p1的原型的原型的原型
        console.log(p1.__proto__.__proto__.__proto__); //null
        

DOM对象原型链

image.png

示例代码如下:

 /*查看内置对象的原型链*/

    //1.Array
    let arr = new Array(10,20,30);
    console.log ( arr );
    //查看arr的原型
    console.log ( arr.__proto__.constructor );//Array
    console.log ( arr.__proto__ === Array.prototype );
    //查看arr的原型的原型
    console.log ( arr.__proto__.__proto__.constructor );//Object
    console.log ( arr.__proto__.__proto__ === Object.prototype );//true

    //2.Date
    let date1 = new Date();
    //细节:日期对象直接console.log会转成string,查看对象需要使用console.dir打印
    console.dir(date1);
    console.log ( date1.__proto__ === Date.prototype );//true
    console.log ( date1.__proto__.__proto__.constructor );//Object
    console.log ( date1.__proto__.__proto__ === Object.prototype );//true

    //3.String
    let str = new String('123');
    console.log ( str );
    console.log ( str.__proto__ === String.prototype );//true
    console.log ( str.__proto__.__proto__.constructor );//Object
    console.log ( str.__proto__.__proto__ === Object.prototype );//true

    //4.界面元素
    let div1 = document.getElementById('div1');
    let p1 = document.getElementById('p1');