js之创建对象2

方法三:原型模式
1.试想一下,能不能把sayName拿出来放在一个公共区域里,这样举例子可能有些不合适,因为并不是说你用sayName的时候我就不可以用,我们想要的是不管谁去取,多少对象同时使用都可以,但是sayName只有一个。这样的想法就诞生原型模式,这个公共区域就是prototype。

如图所示,无论什么时候,只要创建一个新函数,就会根据一组特定的规则为该函数。

创建一个prototype属性,该属性指向函数的原型对象。而原型对象会获取一个constructor属性,该属性指向对应的构造函数。而对象的实例中则含有一个[[prototype]]的属性,它指向原型对象。这个属性对脚本是完全不可见的,但是可以通过isPrototypeOf()方法来确定对象之间是否存在这种关系,如果说[[prototype]]指向调用isPrototype()方法的对象(obj.prototype),这个方法就返回true:

alert(Person.prototype.isPrototypeOf(person1));//true

ECMAscript 5中新增加一个方法Object.getPrototypeOf(),返回[[Prototype]]的值:

alert(Object.getPrototypeOf(person1) == Person.prototype);//true
alert(Object.getPrototypeOf(person1).name);//Nicole

原型创建代码:

function Person(){

      }
      Person.prototype.name = "Nicole";
      Person.prototype.age = 12;
      Person.prototype.job = "software engnieer";
      Person.prototype.sayName = function(){
          alert(this.name);
      }

      var person1 = new Person();
      person1.sayName();//Nicole

      var person2 = new Person();
      person2.sayName();//Nicole

      alert(person1.sayName == person2.sayName);//true

2.更简单的原型语法:

前面例子每添加一个属性和方法就要敲一遍Person.prototype,很麻烦,可以使用字面量重写整个原型对象:

function Person(){

      }
      Person.prototype = {
          name:"Nicole",
          age:12,
          job:"software engnieer",
          sayName:function(){
              alert(this.name);
          }
      }

在这个例子中,我们将Person.prototype设置等于一个以字面量形式创建的新对象,最终结果相同,但是要注意的是,constructor不再指向Person,指向Object。

alert(Person.prototype.constructor == Person);//false

因此需要人工的配置constructor的指向:

Person.prototype = {
        constructor:Person,
         name:"Nicole",
          age:12,
          job:"software engnieer",
          sayName:function(){
              alert(this.name);
          }
     }

这样写依然有一个问题,就是重写prototype切断了,现有原型和重写前已经存在的实例的联系,它们引用的依然是最初的原型:

function Person(){

     }
     var person1 = new Person();

     Person.prototype = function(){
         constructor:Person,
         name:"Nicole"
     };

     alert(person1.name);//error

原型对象的缺点
共享是把双刃剑,它就带来了便利,也带来了麻烦,比方说:

function Person(){

     };

      Person.prototype = {
        constructor:Person,
         name:"Nicole",
          age:12,
          job:"software engnieer",
          friends:['hah','hhe'],
          sayName:function(){
              alert(this.name);
          }
     };
     var person1 = new Person();
     var person2 = new Person();


     person1.friends.push('black');

     alert(person2.friends);//'hah','hhe','black'

修改一个实例的原型方法或者属性,所有相关实例都会相应的变化。

方法四:组合使用构造函数模式和原型模式
为了解决原型模式的缺点,我们可以使用构造函数定义实例属性,用原型模式定义方法和共享的属性。

function Person(name,age,job){
         this.name = name;
         this.age = age;
         this.job = job;

         this.friends=["hello","world"];
     }

     Person.prototype = {
         constructor:Person;
         sayName:function(){
             alert(this.name);
         }
     }

     var person1 = new Person("Nicole",12,"software engnieer");
     var person2 = new Person("blue",14,"writer");
     
     person1.friends.push("!");

     alert(person1.friends);//"hello","world","!"
     alert(person2.friends);//"hello","world"

 

posted @ 2016-04-25 15:15  PhenixWL  阅读(132)  评论(0)    收藏  举报