美文网首页
JavaScript 面向对象(二)

JavaScript 面向对象(二)

作者: AlexLJS | 来源:发表于2020-02-27 20:20 被阅读0次

    JS的基本语法已经够让人自闭了,面向对象则更为与众不同。因为JS 的设计之初是不想引入 类似 “继承” 这样的功能, 后来还是加上了 原型模式 。


    准备工作

    原型模式

    定义:原型模式是一种创建型设计模式,Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建

    概括一下 :
    1、原型模式创建对象时使用
    2、原型模式出于优化性能而设计 ,且只有满足new对象结构比较复杂时才能优化性能(即构造函数复杂,例如 java 中 clone()方法 ,对于空构造方法比new对象更为费时间 )
    3、 发生在ram中, 有利有弊

    工厂模式

    比较常用的设计模式,在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。


    JavaScript 面向对象

    1、对象构造器(constructor)

    构造器穿件对象是改进自 工厂模式创建对象。

    fuction Person(name,age,job){
      this.name = name;
      this.age = age;
      this.job = job;
      this.sayName = sayName; 
    }
    function sayName(){
      alert(this.name);
    }
    var person1 = new Person("Alex", 24, "pg");
    

    注: 由于其“优秀”的设计,通用的方法this会bind到对象 , function写在外面 ,似乎不太合理?

    2、原型模式创建对象

    构造函数创建对象存在一个问题 : 构造函数中的每个方法都需要在实例对象中重新创建一遍,不能复用。所以使用原型模式创建对象似乎更合理。

    理解:
    原型指针 prototype 是Object 内置的一个指针(即 constructor),指向函数的原型对象。js 通过原型的方式 完成 对象的特殊继承。所有的对象最终指向Object。

    原型链 : 由于数据类型不受 原型的束缚, 所有对象的类型拥有 属性 proto 属性, 用于向上查找。通过 proto向上查找 形成 “原型链”

    fuction Person(){}
    
    Person.prototype.name = "Alex";
    Person.prototype.age = 24;
    Person.prototype.job = "pg";
    Person.prototype.sayName = function(){
        alert(this.name);
    }; 
    
    var person1 = new Person();
    
    

    即使不给初始属性值的,会用默认值!书上很长的篇幅讲解原理P150。

    3、(建议)使用原型模式 + 构造函数模式:

    原型模式还是存在弊端 , 这样下去,每new一个person对象,不仅默认值相同,如果要修改原型的话,另外对象的默认值也会发生影响。
    简化原型模式的写法。

    fuction Person(name,age,job){
      this.name = name;
      this.age = age;
      this.job = job;
      this.sayName = sayName; 
    }
    Person.prototype = {
         constructor : Person,
         sayName : function{
            alert(this.name);
        }
    }
    var person1 = new Person("Alex", 24, "pg");
    

    ps : 后面还有多种创建对象方式

    4、 继承

    js可以使用至少5、6种继承方式。
    https://www.cnblogs.com/ranyonsue/p/11201730.html
    举例 :借用构造函数继承

    fuction SuperType(name){
      this.name = name;
    }
    function SubType(){
      SuperType.call(this, "Alex");
      this.age = 24;
    }
    

    call将父类函数引到子类函数中。继承的同时传递参数,继承的同时添加属性。组合继承 参考 P169 。


    函数表达式、匿名函数、 闭包

    1、
    js 中函数是对象可以直接赋值给变量,无论有没有返回值。而变量只是表示一个地址。匿名函数被广泛使用,lambda表达式。

    var sayHi = function(){
      alert("hi");
    };
    // ==
    
    var sayHi = s => {
      alert(s);
    };
    sayHi("hi");
    
    

    注意: 区别函数与函数表达式。
    函数与函数表达式 作用域是不一样的,this 指向容易出现问题,重点注意使用 => 。 MDN 参考

    2、递归

    使用命名函数表达式 赋值给一个变量 :

    var factorial = (
          function f(num){
            if (num <= 1){
              return 1;
            } else {
              return num * f(num-1);
    }
        }
    );
    

    3、闭包

    你可以在一个函数里面嵌套另外一个函数。嵌套(内部)函数对其容器(外部)函数是私有的。它自身也形成了一个闭包。一个闭包是一个可以自己拥有独立的环境与变量的的表达式(通常是函数,因为ES6有了块级作用域的概念)。

    函数内部再构建一个函数 , 将子函数return。

    function outer() {
         var  a = '变量1'
         var  inner = function () {
                console.info(a)
         }
        return inner    // inner 就是一个闭包函数,因为他能够访问到outer函数的作用域
    }
    

    (实话我是不怎么理解, 大概是作用域的问题 。 es6 之后用 let const 也很少出现问题)

    4、模仿块作用区域

    (同上 , es6 之后也不需再需要了)

    (function(){
      //块作用区域
    })();
    

    用于处理一些临时变量 时, 相当于 {} , 第二个() 表示定义完 马上调用。

    4、静态私有变量 P184
    5、单例模式

    简单单例模式

    
    var Singleton = function(){
        this.instance = null;
    }
    
    Singleton.getInstance = function () {
        if(!this.instance){
          this.instance = new Singleton();
        }
        return this.instance;
    }
    
    

    透明单例、懒惰单例 , 就不再赘述了。

    相关文章

      网友评论

          本文标题:JavaScript 面向对象(二)

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