面向对象编程

86 阅读2分钟

类和继承

  • ES6 class,extends;

面向过程和面向对象

OOP:Object Oriented Programming

从面向过程的角度

step1();
step2();
step3();
……
finish();

从面向对象的角度

面向对象 —— 一切皆对象 finish => step(xxx) something.deal(finish)

函数式编程

something.step1().step2().step3()......

[1,2,3,4,5].map(item => item * 2).filter(item => item > 10).join(',')

JS对象的创建

创建一个对象有哪些方法

  • Object.create()
    • Object.create() 创建了一个对象;
    • let p = Object.create(q) => p.ptoto = q
  • new Function();
    • 创建了一个对象;
    • 该对象的原型只想了这个Function(构造函数)的prototype
    • 该对象实现了这个构造函数的方法;
    • 跟据一些特定情况返回对象
      • 如果没有返回值,则返回创建的对象;
      • 如果有返回值,是一个对象,则返回该对象;
      • 如果有返回值,不是一个对象,则返回创建的对象
    function newObj(Father){
        if(typeof Father !== 'function'){
            throw new Error('new operator function the frist param must be a function')
        }
        
        var obj = Object.create(Father.prototype);
        var result = Father.apply(obj, Array.prototype.slice.call(arguments,1));
        return result && typeof result === 'object'&& result !== null ? result :obj;
    }
    let p = new Person() //Person 是构造函数
    
    p.__proto__ = Person.prototype;
    Person.prototype.constructor =Person;
    p.constructor =Person;
  • var obj={};
    • obj.proto = Object.prototype; let p = Object.create({}) 相当于: let p = Object.create(obj); 相当于: p.proto = obj;

继承

实现一个继承主要是两个部分:

  • 使用父类的构造函数的方法;
  • 让对象的原型链指向父类;

原型链继承

    function Parent(){
        this.name = 'father';
    }
    
    Parent.prototype.getName = function(){
        console.log(this.name);
    }
    
    function Child(){};
    
    //Child.__proto__ = Parent.prototype
    
    Child.prototype =new Parent();
    Child.prototype.constructor = Child;
    
    //存在问题:
    //1.如果有属性是引用类型,一旦某个实例修改了这个属性,所有的都会改变;
    //2. 创建 Child 的时候不能传参

构造函数继承

    //想办法把Parent上的属性和方法添加到Child上面去,而不是都存在在原型对象上,防止被实例共享;
    
    function Parent(action,name){
        this.action = ['a','b','c'];
        this.name = 'parentName';
    }
    
    function Child(play){
        Parent.apply(this,Array.prototype.slice.call(arguments,1));
        this.play = play;
    }
    
    //存在问题:
    // 1.属性或者方法想被继承的话,只能在构造函数中定义
    // 2.如果方法在构造函数中定义了,每次创建实例都会创建一遍方法
    

组合继承

     function Parent(action,name){
        this.action = ['a','b','c'];
        this.name = 'parentName';
    }
    
    Parent.prototype.work = function(){
        console.log('hi'+ this.name )
    }
    
    function Child(play){
        Parent.apply(this,Array.prototype.slice.call(arguments,1));
        this.play = play;
    }
    
    Child.prototype = new Parent();
    Child.prototype.constructor = Child;

组合寄生式继承

    function inherit(p){
        if(p == null) throw TypeError() //p是一个对象,不能为null
         if(Object.create) return Object.create(p);
         var t = typeof p;
         if(t !== 'object' && t !=='function') throw TypeError()
         function f(){
         };
         f.prototype = p;
         return new f();
    }
    function Parent(action,name){
        this.action = ['a','b','c'];
        this.name = 'parentName';
    }
    
    Parent.prototype.work = function(){
        console.log('hi'+ this.name )
    }
    
    function Child(play){
        Parent.apply(this,Array.prototype.slice.call(arguments,1));
        this.play = play;
    }
    
    //Child.prototype = new Parent();
    Child.prototype = inherit(Parent.prototype);
    Child.prototype.constructor = Child;

es6继承

    class A{
    
    }
    
    class B extends A{
        constructor(){
            super()
        }
    }
    
    //super 作为函数调用时,要求必须执行一次
    //因为子类自己的this对象,必须通过父类的构造函数完成
    //es6继承会继承静态的方法和属性