• 面向对象及构建函数


    1.工厂模式

    《Javascript 高级程序设计(第3版)》 用了寥寥十多行介绍了工厂模式。我找了一些相关资料,想确定一下这种模式的具体适用场景和优势。按照资料中的说法,是考虑到 ECMAScript 无法创建类,所以:

    创建一个对象,紧接着描述对象的属性和方法,最后用另一个对象把它们封装起来当作接口。

    按照上面描述的,工厂函数是用来在 Javascript 中实现类似于 Java 中类的功能。通过调用工厂函数,可以创建多个相似的对象实例。

        简单工厂模式:使用一个类(通常为单体)来生成实例。
        复杂工厂模式:使用子类来决定一个成员变量应该是哪个具体的类的实例。

    关于 Javascript 使用工厂模式的优点,根据网上的总结,大概有以下几点:

    a. 消除对象之间的耦合(这个不太明白,消除谁与谁的耦合?);

    b. 在进行批次相关设置时,把所有实例化的代码都集中在一个位置,有助于创建模块化的代码,减少代码量;

    c.  用于许多小型对象组成一个大对象。

    缺点:

    a. 没有解决对象识别的问题。

    .....这个模式先留着吧,没太搞透彻优势在哪。以后领悟了的话再来补充。引用《Javascript 设计模式与开发实践》P5中的一段话:

    “而在 Javascript 这种类型模糊的语言中,对象多态性是天生的,一个变量既可以指向一个类,又可以随时指向另外一个类。Javascript 不存在类型耦合问题,自然也没有必要刻意把对象“延迟”到子类创建,也就是说,Javascript 实际上是不需要工厂方法模式的。 模式的存在首先是能为我们解决什么问题,这种牵强的模拟只会让人觉得设计模式既难懂又没什么用。”

    2. 构造函数模式

    关于封装: 在 Javascript 中,可以将一些属性和方法封装到构造函数内;

    关于多态:在 Javascript 中不存在重载的概念,但可以通过参数个数和类型判断来模拟重载,但是 Javascript 中多态是与生俱来的。一个最简单的栗子:

    同一个构造函数实例化得到的两个对象实例,可以给它们传入不同的参数,这两个对象实例是不同的。这就是面向对象编程的多态。

    利用构造函数模式,可以创建多个实例,这些实例都被标定为了特定的类型。构造函数模式相比于工厂模式更为简单且易于实现,但也存在缺点:

    复制代码
    function Person(name,age,job){
        this.name = name;
        this.age = age;
        this.job = job;
        this.arr = [];
        this.sayName = function(){
            alert(this.name);
        };
    }
    var person1 = new Person("Nicholas",29,"Software Engineer");
    var person2 = new Person("Greg",27,"Doctor");
    
    console.log(person1.sayName==person2.sayName);//false
    person1.arr.push(1);
    console.log(person1.arr);//1
    
    person2.arr.push(2);
    console.log(person2.arr);//2
    复制代码

    利用构造函数每实例化一个实例对象,构造函数内的方法都要在实例上重新创建一次。通过 person1.sayName==person2.sayName 返回的返回结果可以看到两个实例引用的方法是不同的。

    注意:这一点也适用于数组。

    可以通过将构造函数的方法放在外部,使得对象实例每次都引用同一个方法。

    复制代码
    function 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("Nicholas",29,"Software Engineer");
    var person2 = new Person("Greg",27,"Doctor");
    
    console.log(person1.sayName==person2.sayName);//true
    复制代码

    通过将构造函数的方法提到外部作为:特权方法。可以使实例获得相同的方法引用。

    但是这种方法也存在一些问题:将方法提到外部作为特权方法使得封装性变差。如果构造函数内部有很多个方法,这样做后果更为明显。

    另外再看一个问题:如果构造函数内有多个固定属性,并且存在多个方法。实例化的时候要为每个对象都复制相同的固定属性,如果将方法放在构造函数内部,这些方法也要复制,即使都作为特权函数,也存在弊端。

    总结,构造函数模式存在两点不足:1. 浪费内存;2. 可能会使封装性变差。

    3.原型模式

    原型模式的出现,解决了构造函数实例化过程中对固定属性个方法重复深复制的问题。

    对于相同的属性和方法,只要在构造函数的原型对象上申明一次,构造函数的实例就可以共享同一个属性和方法。

    复制代码
    function Person(){
    
    }
    
    Person.prototype.name = "Nicholas";
    Person.prototype.sayName = function(){
        console.log(this.name);
    }
    
    var person1 = new Person();
    var person2 = new Person();
    
    console.log(person1.sayName===person2.sayName);//true
    console.log(person1.name===person2.name);//true
    复制代码

     4.组合使用构造函数模式和原型模式(混合模式)

    但是可以看到,虽然原型模式能够解决固定属性和方法多次复制的问题,如果属性要根据不同实例对象改变,这时候最好还是把会随实例对象改变的属性放置在构造函数内部,这又用到了构造函数模式。将构造函数模式和原型模式相结合,就能利用这两个模式的优势。

    复制代码
    function Person(name,age){
        //会随实例对象改变的属性
        this.name = name;
        this.age = age;
    }
    //不变的属性或者是方法
    Person.prototype.job = "Soft Engineer";
    Person.prototype.sayName = function(){
        console.log(this.name);
    }
    
    var person1 = new Person("Nicholas",28);
    var person2 = new Person("Shelby",25);
    复制代码
  • 相关阅读:
    UVM训练场
    无法解析具体reference那个同名文件
    Verdi技巧
    verilog disable 用法 (易错!)
    Unicode 和 UTF-8 有何区别?
    gcc编译过程简述
    js对象中什么是可枚举性(enumerable)?
    JSON.stringify 语法实例讲解
    ECMAScript5 Object的新属性方法
    Can someone explain Webpack's CommonsChunkPlugin
  • 原文地址:https://www.cnblogs.com/zouyun/p/7662137.html
Copyright © 2020-2023  润新知