javascirpt 面向对象编程、原型原型链你会了吗

68 阅读2分钟

面向对象编程

  • 什么是对象,为什么要面向对象 对象指的是某一类物体的简单抽象,对象是容器,属性表示对象的状态,方法表示对象的能力或者行为。面向对象从逻辑上迁移更加灵活、代码复用性更高、高度的模块化。
    const Course = {
        teacher: 'lelei',
        leader: 'hanmeimei',
        startCourse: function() {
            console.log(`开始上课,有请${this.teacher}老师`)
        }
    }

构造函数

  • 什么是构造函数 构造函数是用来生成一类物体的函数 js本质上就是基于构造函数和原型链
     function Course() {
        this.teacher = 'yunyin';
        this.leader = 'xh';
        this.startCourse = name => {
            return `开始${name}课`;
        }
    }

    const course = new Course(args);

Course就是构造函数

  • 构造函数内部的this指向所要生成的实例
  • 构造函数的实例用 new 生成
  • 构造函数可以初始化传参
function Course(teacher, leader) {
        this.teacher = teacher;
        this.leader = leader;
        this.startCourse = name => {
            return `开始${name}课`;
        }
    }

    const course = new Course('li lei', 'han mei mei');
  • new 是什么,做了什么
    1. 结构上:创建了一个空对象,作为返回的对象实例
    1. 属性上:将生成空对象的原型对象指向了构造函数的prototype属性
    1. 关系上:将当前实例对象赋给了内部的this
    1. 生命周期上:执行了构造函数的初始化代码
  • 实现一个new
    function myNew(obj, ...args) {
       const newObj = Object.create(obj.prototype);
        const result = obj.apply(newObj, args);

        return typeof result === 'object' ? result : newObj;

    }

原型与原型链

  • 原型 prototype 每个实例都一个__proto__属性指向构造函数的protoType
  • 原型链 每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针,当访问实例的某个属性时如果该实例上没有,就会从原型对象上寻找,如果原型对象上没有,就会从原型对象的原型对象上寻找,如此层层递进,就构成了实例与原型的链条,这个链条就是原型链

image.png

继承

  • 原型链继承
    function Game() {
        this.name = 'LOL'
        this.skin = ['s']
    }
    Game.pototype.getName = function() {
        return this.name
    }
    function LOL(){}
    LOL.prototype = new Game()
    LOL.prototype.constructor = LOL
    const game1 = new LOL();
    const game2 = new LOL();
    game1.skin.push('ss')
    //原型链继承的缺点
    1、父类属性一旦赋值给到子类的原型属性,此时属性属于子类的共享属性了
    2、实例化子类时,无法向父类进行传参
    // 解决办法 => 构造函数继承
     function Game(arg) {
        this.name = 'lol';
        this.skin = ['s'];
    }
    Game.prototype.getName = function() {
        return this.name;
    }

    function LOL(arg) {
        Game.call(this, arg);
    }

    const game3 = new LOL('arg');
    // 解决了共享属性问题和子向父传参问题
    

原型链上共享方法无法被读取继承, 如何解决=> 组合继承

  • 组合继承
 function Game(arg) {
        this.name = 'lol';
        this.skin = ['s'];
    }
    Game.prototype.getName = function() {
        return this.name;
    }

    function LOL(arg) {
        Game.call(this, arg);
    }
    LOL.prototype = Object.create(Game.prototype);
    LOL.prototype.constructor = LOL;
    const game5 = new LOL('arg');