浅谈 js中的几种模式 (一)

  今天看了《JavaScript 高级程序设计》(第三版)这本书,颇有收获,总想写点什么,只恨自己菜鸟一只写不出什么真知灼见,只能。。。。。。好了废话不多说,开篇了。

  大家都知道在js中可以用Object构造函数和对象字面量这两种方式创建对象

            //利用Object构造函数创建对象
            var person=new Object();
            person.name="DJL";
            person.age=22;
            //利用对象字面量创建对象
            var person2={
                name:"DJL",
                age:22
            }
            
            alert(person.name);//DJL
            alert(person2.name);//DJL            

  但是上诉两种创建对象的方法都有一个明显的缺点那就是使用同一个接口创建很多对象会产生很多重复的代码。为了解决这个问题js引入了工厂模式:

      function createPerson (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 person1=createPerson ("DJL1",22,"student1");
        var person2=createPerson ("DJL2",22,"student2");

        alert(typeof createPerson ("DJL2",22,"student2"));//object

 

  

  这样我们在利用createPerson这个函数接口创建很多对象时,就不用每个都要去写o.name=name;o.age=age;这些重复的代码。工厂模式创建对象就在于在这个函数接口内部利用Object构造函数又创建了一个新的对象,然后return出来。但是,但是,但是,这种模式也是有问题的-----你怎么用instanceof ,即你怎么知道某个对象的具体类型,这样吗

alert(person1 instanceof createPerson);//这肯定是false啦

  为了解决这个问题,构造函数模式出来了

      function CreatePerson (name,age,job) {                
                this.name=name;
                this.age=age;
                this.job=job;
                this.sayName=function(){
                    alert(this.name);
                }                    
            }
            
            var person1= new CreatePerson ("DJL1",22,"student1");
            var person2= new CreatePerson ("DJL2",22,"student2");
            alert(person1 instanceof CreatePerson);//true

与工厂模式不同的是:1  没有显示的创建新对象  2  直接将属性和方法赋值给了this对象  3  没有return 语句  4  函数名首字母大写

要创建CreatePerson的实例必须要使用关键字new。以这种方式新建对象会经历如下有如下4个过程

  1 创建新的对象

  2 将构造函数的作用域赋给新对象(因此this就指向了新对象)

  3 执行构造函数中的代码

  4 返回新对象

  利用构造函数模式,我们可以将来将他的实例标识为一种特定的类型。然而这种模式也是有缺点的,上例中我们创建了person1和person2这两个实例,有相同的方法名sayName,但是这两个同名函数却不是相等的

  

alert(person1.sayName==person2.sayName)  //false

但是有时我们同一个构造函数不同实例中的同名函数来共同完成一件事情怎么办,下面这是一种办法

      function CreatePerson (name,age,job) {                
                this.name=name;
                this.age=age;
                this.job=job;           
                this.sayName=sayName;
            }
            
            function sayName(){
                //toDo
            }
            
            var person1= new CreatePerson ("DJL1",22,"student1");
            var person2= new CreatePerson ("DJL2",22,"student2");

我们把sayName函数的定义转移到了构造函数外部,而在构造函数内部我们把sayName设置成了全局变量。这样person1 和person2就共享了在全局域中定义的sayName()函数。这样做确实解决了共享性问题,但是如果有很多个这样的函数呢,那边要定义多个全局函数,那么封装性就不言而喻了。为了解决这个问题,原型模式就脱颖而出了。

  我们创建的每一个函数都有一个prototype属性,该属性是一个指针,指向一个对象。这个对象包含了所有实例共享的属性和方法。使用原型对象的好处就是可以让所有对象实例共享它所包含的属性和方法。我们不必在构造函数中去定义对象实例的信息,而是可以将这些信息添加到原型对象中。

       function CreatePerson () {
                
            }
            
            CreatePerson.prototype.name="DJL";
            CreatePerson.prototype.age=22;
            CreatePerson.prototype.job="student";
            CreatePerson.prototype.sayName=function(){
                alert(this.name);
            }
            
            var person1= new CreatePerson ();
            person1.sayName();
            var person2= new CreatePerson ();
            person2.sayName();
       alert(person1.sayName==person2.sayName);//true

  此时我们仍然可以通过CreatePerson这个构造函数来创建实例,并且能够访问sayName这个函数,与构造函数模式的区别就是,此时sayName()是共享型的, person1和person2 访问的是同一个sayName函数。

  好吧今天就先写到这里,明天继续补上,不然寝室该停电了,那就恐怖了,以上所写是对《JavaScript高级程序设计》这本书就行了提炼和少许自己的见解,如果大家有什么不理解的欢迎讨论,当然更建议大家去买这本书(纸质书),我刚刚看了2天,就觉得受益匪浅,好了,撤了。

  

原文地址:https://www.cnblogs.com/djlxs/p/5097401.html