• 【JavaScript回顾】对象创建的几种模式


    组合使用构造函数模式和原型模式

    创建自定义类型的常见方式,就是组合使用构造函数模式与原型模式。构造函数模式用于定义实 例属性,而原型模式用于定义方法和共享的属性。结果,每个实例都会有自己的一份实例属性的副本, 但同时又共享着对方法的引用,大限度地节省了内存。另外,这种混成模式还支持向构造函数传递参 数;可谓是集两种模式之长。

    <script>
            function Person(name, age, job) {
                this.name = name;
                this.age = age;
                this.job = job;
                this.friends = ["Shelby", "Sylvia"];
            }
    
            Person.prototype = {
                constructor: Person,
                showFriends: function () {
                    var message = this.name + ":";
                    this.friends.forEach(function (v, i, array) {
                        message += " " + v;
                    });
                    alert(message);
    
                }
            }
    
            var p1 = new Person("gck", 26, "senior software engineer");
            p1.friends.push("Carol");
            p1.showFriends();
    
            var p2 = new Person("gck", 26, "senior software engineer");
            p2.showFriends();
        </script>

    在这个例子中,实例属性都是在构造函数中定义的,而由所有实例共享的属性 constructor 和方 法 sayName()则是在原型中定义的。而修改了 person1.friends(向其中添加一个新字符串),并不 会影响到 person2.friends,因为它们分别引用了不同的数组。 这种构造函数与原型混成的模式,是目前在 ECMAScript中使用广泛、认同度高的一种创建自 定义类型的方法。可以说,这是用来定义引用类型的一种默认模式。

    动态原型模式

    function Person(name, age, job){  
        //属性    
          this.name = name;   
          this.age = age; 
          this.job = job;  
         //方法     
        if (typeof this.sayName != "function"){             
             Person.prototype.sayName = function(){            
                 alert(this.name);        
             };              
        } 
    }  
    var friend = new Person("Nicholas", 29, "Software Engineer");
     friend.sayName();                

      注意构造函数代码中加粗的部分。这里只在 sayName()方法不存在的情况下,才会将它添加到原 型中。这段代码只会在初次调用构造函数时才会执行。此后,原型已经完成初始化,不需要再做什么修 改了。不过要记住,这里对原型所做的修改,能够立即在所有实例中得到反映。因此,这种方法确实可 以说非常完美。其中,if 语句检查的可以是初始化之后应该存在的任何属性或方法——不必用一大堆 if 语句检查每个属性和每个方法;只要检查其中一个即可。对于采用这种模式创建的对象,还可以使 用 instanceof 操作符确定它的类型。

      

      注:使用动态原型模式时,不能使用对象字面量重写原型。前面已经解释过了,如果 在已经创建了实例的情况下重写原型,那么就会切断现有实例与新原型之间的联系。

    寄生构造函数模式

     function Person(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 friend = new Person("Nicholas", 29, "Software Engineer"); 
         friend.sayName(); //"Nicholas"

    在这个例子中,Person 函数创建了一个新对象,并以相应的属性和方法初始化该对象,然后又返 回了这个对象。除了使用 new 操作符并把使用的包装函数叫做构造函数之外,这个模式跟工厂模式其实 是一模一样的。构造函数在不返回值的情况下,默认会返回新对象实例。而通过在构造函数的末尾添加一个 return 语句,可以重写调用构造函数时返回的值。 这个模式可以在特殊的情况下用来为对象创建构造函数。假设我们想创建一个具有额外方法的特殊 数组。由于不能直接修改 Array 构造函数,因此可以使用这个模式。

     <script>
            function SpecialArray(){  
                //创建数组    
                var values = new Array();  
                //添加值     
                values.push.apply(values, arguments);  
                //添加方法    
                values.toPipedString = function() {
                             return this.join("|");
                };
                //返回数组
                return values;
            }
            var colors = new SpecialArray("red", "blue", "green");
            alert(colors.toPipedString()); //"red|blue|green"
        </script>

    在这个例子中,我们创建了一个名叫 SpecialArray 的构造函数。在这个函数内部,首先创建了 一个数组,然后 push()方法(用构造函数接收到的所有参数)初始化了数组的值。随后,又给数组实 例添加了一个 toPipedString()方法,该方法返回以竖线分割的数组值。后,将数组以函数值的形 式返回。接着,我们调用了 SpecialArray 构造函数,向其中传入了用于初始化数组的值,此后又调 用了 toPipedString()方法。 关于寄生构造函数模式,有一点需要说明:首先,返回的对象与构造函数或者与构造函数的原型属 性之间没有关系;也就是说,构造函数返回的对象与在构造函数外部创建的对象没有什么不同。为此, 不能依赖 instanceof 操作符来确定对象类型。由于存在上述问题,我们建议在可以使用其他模式的情 况下,不要使用这种模式。

     稳妥构造函数模式

     <script>
            function Person(name, age, job){          
                //创建要返回的对象   
                var o = new Object(); 
                //可以在这里定义私有变量和函数  
    
                //添加方法     
                o.sayName = function(){         alert(name);     };             
                //返回对象     
                return o;
            }
        </script>

    注意,在以这种模式创建的对象中,除了使用 sayName()方法之外,没有其他办法访问 name 的值。 可以像下面使用稳妥的 Person 构造函数。 
    var friend = Person("Nicholas", 29, "Software Engineer"); friend.sayName();  //"Nicholas"  这样,变量 friend 中保存的是一个稳妥对象,而除了调用 sayName()方法外,没有别的方式可 以访问其数据成员。即使有其他代码会给这个对象添加方法或数据成员,但也不可能有别的办法访问传 入到构造函数中的原始数据。稳妥构造函数模式提供的这种安全性,使得它非常适合在某些安全执行环境。

    注:与寄生构造函数模式类似,使用稳妥构造函数模式创建的对象与构造函数之间也 没有什么关系,因此 instanceof 操作符对这种对象也没有意义。

  • 相关阅读:
    当老板如何带团队?
    创业者第一法宝-了解自己
    交流才能交易,交易才能交心
    集合框架
    MySQL一些命令语法
    JS组成整理
    git中可以pull但是push提示Everything up-to-date的情况
    循环判断以及文件的使用--练习1
    Hello World !
    linux文件权限修改
  • 原文地址:https://www.cnblogs.com/guochenkai/p/4010920.html
Copyright © 2020-2023  润新知