js 面向对象总结

面向对象的程序设计(Object-Oriented OO)

最近感受,不知道该学点什么,总是觉的本身什么都不会,又感受是会点什么,说是也知道面向对象,可是让系统的说一下这里面的东西,感受连不上线,成不了太系统的了解,因此就看了一下这的知识点,当本身的搬运工,伪装是发了一篇文章,等本身查看方便;bash

建立对象

1. 工厂模式:用函数来封装,以特定接口建立对象的细节

  1. 解决了建立多个类似对象的问题,
  2. 多用于建立多个含有相同属性,和方法的对象,避免代码的重复编写;
  3. 没有解决对象识别的问题(即怎么知道一个对象的类型)(它的 instanceof 只能是Object)
function creatPerson(name,age,job) {
        var o = new Object();
        o.name= name;
        o.age= age;
        o.job= job;
        o.sayName = function(){
            alert(this.name);
        };
        return o;
    }
    var p1 = creatPerson("hh",23,"worker");
    var p2 = creatPerson("xx",26,"worker1");
    p1.__proto__===p2.__proto__===Object.prototype;

    对象的constructor 属性最先是用来描述队形类型的,检测对象类型仍是 instanceof 更可靠
    工厂模式建立的对象,constructor只有Object,这样的实例没有特定的类型;

复制代码

2. 构造函数模式:

  1. 解决对象识别的问题(即怎么知道一个对象的类型)
  2. 缺点:每一个方法都在每一个实例上从新建立了一次,下面栗子中p1.sayName!=p2.sayName
  3. 解决方式:提出构造函数,在全局写一个函数申明;(这种解决方式的缺点:全局函数只是局部调用,方法过多就得建立多个全局函数,没什么封装性可言);
function Person(name,age,job){
        this.age = age;
        this.name = name;
        this.job = job;
        this.sayName = function(){
            alert(this.name)
        }
        //this.sayName = sayName;   //解决方式
    }
    var p1 = new Person("hh",23,"worker");
    var p2 = new Person("xx",26,"worker1");
        
        //function sayName(){alert(this.name)}  //解决方式


    new的执行:
        {
            var obj ={};
            obj.__proto__ = Person.prototype;
            Person.call(obj);
            return obj
        }
    p1 instanceof Person //true;
    p2 instanceof Person //true;
    p1 instanceof Object //true;
    p2 instanceof Object //true;
    这样是得p1和p2实例有了特定的类型, Person;

复制代码

3. 原型模式

  1. 优势:他省略了构造函数初始化参数这个环节,原型中全部属性都被不少实例共享,共享对函数很是合适,基本属性也还行 经过在实例上添加同名属性,可隐藏原型中的对应属性值;app

  2. 缺点: 他的共享属性,对于包含引用类型值的属性 若是实例从新赋值没什么影响,和基本类型同样,若是是操做修改 就有些问题了,会使得全部实例获取到的该属性都被修改, 因此也不单独使用函数

    function Person(){}
        Person.prototype={
            constructor:Person,
            name:"ss",
            friends:["s1","s2"],
            sayName:function(){alert(this.name)}
        }
        var p1= new Person();
        var p2= new Person();
        p1.name = "p1"
        console.log(p1.name) //p1
        console.log(p2.name) //ss
        p1.friends.push("s3");
        console.log(p1.friends) //["s1","s2","s3"]
        console.log(p2.friends) //["s1","s2","s3"]
    复制代码
  3. 用法:ui

    1. 通常用法:
      function Person(){}
          Person.prototype.name="ceshi"
          Person.prototype.age =12;
          Person.prototype.sayName = function(){
              alert(this.name)
          }
          //这样就是实现了代码的共享
      
      复制代码
    2. 简单写法
      更简单的写法:
              Person.prototype={
                  //constructor:Person,
                  name:"test",
                  age:12,
                  sayName:function(){alert(this.name)}
              }
          var friend = new Person();
          friend instanceof Object //true
          friend instanceof Person //true
          friend.constructor==Person //false
          friend.constructor==Object //true
      
          这种简单的写法constructor 属性就不在指向Person,而是指向Object构造函数;
          此时能够添加一个属性constructor( 如上面注释):可是此时的constructor 变成了可枚举的属性,原生是不可枚举的,能够考虑用Object.defineProperty()
      
      复制代码
    3. 原型动态:
      var p1 = new Person();
          <!-- 1 -->
              Person.prototype.hh="ss";
              p1.hh//ss 是能够先建立实例在改边原型在访问的;
              
          <!-- 2 -->
              Person.prototype={
                  name:"ss"
              }
              p1.__proto__!=Person.prototype;
              p1.name // undefined 
      
      复制代码
    4. 原生对象的原型:
      1. 能够给原生引用类型(Object、Array、String。。。)添加修改方法
        String.prototype.strarWith=function(tesx){return this.indexOf(text)==0}

4. 组合使用构造函数模式和原型模式:(定义引用类型的一种默认模式)

  1. 构造函数模式用于定义实例属性; 每一个属性在每一个实例上都从新建立了一次;即便引用类型的修改也不会影响其余实例
  2. 原型模式用于定义方法和共享属性;
function Person(age,name){
        this.name = name;
        this.age = age;
        this.friends=[1,2,3]
    }
    Person.prototype={
        constructor:Person,
        sayName:function(){
            alert(this.name)
        }
    }
    var p1 = new Person("ss",12);
    var p2 = new Person("ss3",123);
    p1.friends.push(2);
    console.log(p1.friends) // [1,2,3,2]
    console.log(p2.friends)// [1,2,3]
复制代码

5. 动态原型模式:

  1. 原型和狗仔函数独立开,感受和其余语言的OO不同,动态原型就是把全部的信息都封装在构造函数中;
  2. 在构造函数中检查某个应该从在的方法是否有效,来以为是否是初始化原型,其实就是初始化一次原型
function Person(name,age){
        this.name = name;
        this.age = age;
        if(typeof this.sayName !="function"){//sayName没初始化 这里对一个方法判断就能够,而后初始化全部的,不必都每一个方法都判断

            Person.prototype.sayName=function(){alert(this.name)}
            Person.prototype.sayAge=function(){alert(this.age)};
            .....
        }
  ****注意****:此处不能使用对象字面量形式重写原型, 由于这中写法是先建立的实例,而后在修改的原型,要是用对象字面量重写原型,会切断现有实例和新原型之间的联系, 致使方法实例上无此方法;
    }

复制代码

6. 寄生构造函数模式:

  1. 和工厂模式差很少,只是用了new 初始化实例;
  2. 它返回的对象与构造函数和构造函数的原型没有任何关系;
function Person(name,age){
        var o = new Object();
        o.name=name;
        o.age=age;
        o.sayName=function(){
            alert(this.name)
        };
        return o;
    }
    var friends = new Person("xiaoming",12)
    friends.asyName()  // xiaoming

复制代码

7. 稳妥构造函数模式:

稳妥对象: 没有公共属性,而且其方法中不引用this的对象;this

function Person(name,age){
        var o = new Object();
        o.sayName=function(){
            alert(name)
        };
        return o;
    }
    var friends = new Person("xiaoming",12)
    friends.asyName()  // xiaoming
复制代码

继承 :

  1. 继承通常包括: 接口继承:继承方法和签名; 实现继承:继承实际的方法;ECMAScript 只支持实现继承spa

  2. js主要经过原型链实现继承,原型链的构建是经过将一个类型的实例赋值给另外一个构造函数的原型实现的prototype

继承方式

1. 原型链(不多单独使用)
  1. 问题:操做引用类型的数据(从新赋值不影响,至关于子类添加隐藏父类),会被全部实例共享受
  2. 问题er: 建立子类时候不能向父类的构造函数传递参数;???
Son.prototype = new Father();
    
    //此时Son.constructor 被改写为了 Father;
    Son.prototype.constructor = Son;
    
    //给子类修改或者是添加方法的时候,要放在替换语句,改版子类原型语句以后, 
    //原型继承时,不能使用字面量方式建立原型方法,这样就从新写了原型链了
    Son.prototype.getName=function(){alert(this.name)};

复制代码
2. 构造函数绑定: call ,apply 继承:(不多单独使用)
  1. 问题: 父函数原型(prototype)中的方法,子类是不能够见的
  2. 问题兔:方法属性都是在构造函数中定义的,每一个实例和方法都从新建立一次,没有复用之说z
function Son(){
        Father.call(this,arguments)
    }
复制代码
3. 组合继承:(经常使用继承模式)
  1. 这样可使得实例分别拥有各自的属性(包括引用类型的,实例间互补影响),又可使用相同的方法;
  2. 缺陷: 不管什么状况下,都会调用两次父类的构造函数;
function Father(){
        this.name ="ss";
        this.friends=[1,2,3,4]
    }
    function Son(){
        Father.call(this);
    }
    Son.prototype = new Father(); // Son 原型得到Father上的属性,name和friends


    var son1 = new Son(); // 此时调用Son构造函数为son1 实例上添加了属性(name和friends), 这些属性就屏蔽了原型中的同名属性;
    // 调用两次Father构造函数的结果就是有两组属性,一组在实例上,一组在原型上;

复制代码
4. 原型式继承:
  1. 在不必兴师动众建立构造函数,而是只想让一个对象与另外一个对象保持相似的状况,可使用, 相似钱拷贝;
function object(o){
        function F(){};
        F.prototype = o;
        return new F();
    }
    // 和 Object.creat() 传递一个参数时候相同
复制代码
5. 寄生式继承:
  1. 继承origin 的属性和方法;
  2. 同时还有本身的方法;
function creat(origin){
        var clone = object(origin); // 能够是任何返回新对象的函数
        clone.sayName(){alert("name")}; //这里的函数每次都建立,不存在复用一说,
        return clone;
    }
复制代码
6. 寄生组合式:(理想的继承实现方式)
  1. 解决组合继承中的缺陷,生成两组属性,只在实例上生成原型;
  2. 经过构造函数来继承属性,经过原型链的混成形式来继承方法(就是给子类原型,指定一个父类的副本便可)
function inherit(son,father){

        var prototype = object(father.prototype); 
            // 上句话,建立父类原型的副本,prototype.__proto__ = Father.prototype;
            // prototype 继承constructor prototype.constructor 取的是原型链上,原型的Father.prototype.constructor, 为 Father();即:prototype.constructor == prototype.__proto__.constructor  // true
            // prototype.hasOwnPrototyoe("constructor") //false
        

        prototype.constructor = son; // 弥补重写原型形成的默认属性的修改;
            //此时是给prototype 添加了constructor 属性,赋值为son, 屏蔽了原型上的constructor属性
            // prototype.hasOwnPrototype("constructor") // true
            // prototype.constructor = son;
            // prototype.__proto__.constructor = father
        son.prototype  = prototype;
            // 给子类原型赋值为父类原型的副本;
    }

    //使用:
    function Father(){
        this.name="11";
        this.age=12;
    }
    Father.prototype.sayName=function(){
        alert(this.name);
    }
    function Son(){
        Father.call(this);
        this.age=23;
    }
    inherit(Son,Father);
    Son.prototype.sayAge=function(){
        alert(this.age)
    }

复制代码
相关文章
相关标签/搜索