javascript Prototype Pattern

Prototype :和java 类中定义static方法一样,表示类方法,所有对象使用同一方法。

                    java中的原型:就像电影里一个真人,然后有许多真人复制品。

                                            就是用new建立一个对象(原xi),然后建立其它对象不用new,直接复制以前建立的属性和方法。

           因此java和javascript的Prototype不一样。                                           

一、构造函数的问题

   1、建立一个实例,相应的建立一个方法.因此不同的实例,同名的方法名,但是方法的实例不一样。

       尽管构造函数模式是有用的,但是有一些缺点。 主要的缺点,建立一个实例,相应的建立一个方法. 记住,函数在in ECMAScript里是对象, 

 因此,每当一个函数被定义,实际上被实例化了一个对象。逻辑上, 构造器看起来像这样:
function Person(name, age, job){
     this.name = name;
    this.age = age;
    this.job = job;

   this.sayName = new Function(“alert(this.name)”); //logical equivalent

 //this.sayName = function(){ alert(this.name); }

}

         类:Function:

      实例:new Function

构造函数:Function(“ ”);

  上面表示定义一个Function的实例,哪么

   var person1 = new Person(“Nicholas”, 29, “Software Engineer”);
   var person2 = new Person(“Greg”, 27, “Doctor”);

   new Person 一次,sayName ()实例一次,所以同名的函数sayName ()的实例对象不一样。

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

  做同一件事情,有两个Function实例是无意义的,所以大家都希望建立一个类的无数对象,可以只用一个方法。

2、把函数写在构造函数外面,哪么多个实例只用一个方法,但是缺点是外面有可能写很多方法。

例子:

function Person(name, age, job){

this.name = name;
this.age = age;
this.job = job;
this.sayName = sayName;
}
function sayName(){
   alert(this.name);g;;;
}

var person1 = new Person(“Nicholas”, 29, “Software Engineer”);
var person2 = new Person(“Greg”, 27, “Doctor”);

  在这个例子中,sayName() 函数时定义在构造函数外面. 在构造函数里面sayName 属性等于全局 sayName() 函数. 因此sayName属性现在包含一个指向函数的指针,
   person1, person2  共享 在全局作用域里的sayName() 函数 . 这个解决了上面做同一件事情重复函数的问题,

  但是 也不好.如果对象需要多个方法,需要建立多个全局函数, 这些问题由Prototype Pattern 解决  

二、The Prototype Pattern:就是解决多个实例使用同一个方法的问题。
     用一个prototype 属性建立每一个函数,包含属性和方法。一旦构造函数被调用, 对象的原型被建立
     使用prototype 的好处是所有的properties和methods 是被所有实例共享,例子

1、prototype的建立
     例如:Person:大写表示是一个类,prototype定义其公共属性和方法

    发现这种方法,只建立一个Person prototype原型。

   function Person(){ }
     c.name = “Nicholas”;
     Person.prototype.age = 29;
     Person.prototype.job = “Software Engineer”;
     Person.prototype.sayName = function(){
        alert(this.name);
     };

    var person1 = new Person();
        person1.sayName(); //”Nicholas”

   var person2 = new Person();

       person2.sayName(); //”Nicholas”

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

   上面,属性和sayName()方法时直接加到Person的prototype属性上,留下空的构造函数. 上面person1,person2 实例调用同一方法,结果一样。

2、Prototypes 工作过程:

     每建立一个函数,它的 prototype 属性同时建立,同时建立一个Person Prototype类, 所有的Person prototypes自动的得到一个constructor属性,值指向类Person的prototype属性. 在上面例子中, 例如,Person.prototype.constructor指向Person.
     当定义一个自己的构造函数Person 时,Person  prototype仅默认的得到constructor属性,所有其它方法来自父类Object.每次构造函数被调用去建立一个新实例,实例有一个有一个内部指针指向属性 constructor. 

       实例(person1,person2)和Person prototype直接相连

但是实例(person1,person2)和构造函数(Person)不相连。

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

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

    Person.prototype.isPrototypeOf(obj)方法:判断person1的实例是否和Person prototype对象相连

    Object.getPrototypeOf(person1) :返回person1里面[[Prototype]]值。

2.1、查找对象属性的过程

      调用 person1.sayName()时, 有两步,

          第一: the JavaScript engine 问, “实例 person1,你有一个叫sayName属性吗?” no,因此它继续别找边问,

           第二:Person Prototype,你有一个叫sayName属性吗?”,yes,因此存贮在prototype 的函数被访问。

      person2.sayName()被调用, 会得到同样的结果,在多个对象中, 利用prototypes会共享属性和方法

3、解决实例属性和prototype属性名字一样的问题。

function Person(){
}
Person.prototype.name = “Nicholas”;
Person.prototype.age = 29;
Person.prototype.job = “Software Engineer”;
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
var person2 = new Person();
person1.name = “Greg”;
alert(person1.name); //”Greg” - from instance
alert(person2.name); //”Nicholas” - from prototype

 因为实例person1查找name时,从实例对象开始找,找到,则停止

person2没找到,去Prototype里面去找。

 可以删除person1中属性name,

 delete person1.name;
alert(person1.name); //”Nicholas” - from the prototype
alert(person1.hasOwnProperty(“name”)); //false,实例1是否建立属性name.

   person1.hasOwnProperty(“name”)
 方法:

  1、hasOwnProperty:只在实例person1上有用

  2、“name” in person1:在实例person1上有用,在Prototype 上也有用,所以只要name存在一方,会显示true

  3、 一个对象的属性是否存在prototype 上,通过 hasOwnProperty()和in结合来判断。

      function hasPrototypeProperty(object, name){
        return !object.hasOwnProperty(name) && (name in object);

 4、Object.keys(p1):得到p1实例的所有属性和方法名

      var keys = Object.getOwnPropertyNames(Person.prototype);
      alert(keys); //”constructor,name,age,job,sayName”

function Person(){
}
Person.prototype.name = “Nicholas”;
Person.prototype.age = 29;
Person.prototype.job = “Software Engineer”;
Person.prototype.sayName = function(){
alert(this.name);
};
    var p1 = new Person();
     p1.name = “Rob”;
    p1.age = 31;
    var p1keys = Object.keys(p1);
    alert(p1keys); //”name,age”


四、上面prototype重复太多,声明简单写法 ,只有一个prototype,

          

function Person(){
}
Person.prototype = {
        name : “Nicholas”,
           age : 29,
        job : “Software Engineer”,
        sayName : function () {
      alert(this.name);
    }
};

上面有一个异常: the constructor 属性不再指向 Person对象。

所以你不能用constructor 来确定对象类型
var friend = new Person();
alert(friend instanceof Object); //true
alert(friend instanceof Person); //true
alert(friend.constructor == Person); //false
alert(friend.constructor == Object); //true

 1、更改方法1,直接加属性,如果你需要constructor来判断对象类型  

function Person(){
}
Person.prototype = {
         constructor: Person,
           name : “Nicholas”,
         age : 29,
          job : “Software Engineer”,
         sayName : function () {
       alert(this.name);
}
};
2、用  ECMAScript 5 新增的规范

function Person(){
}
Person.prototype = {
    name : “Nicholas”,
    age : 29,
    job : “Software Engineer”,
    sayName : function () {
           alert(this.name);
     }
};
//ECMAScript 5 only – restore the constructor
Object.defineProperty(Person.prototype, “constructor”, {
enumerable: false,
value: Person
});



五、 Dynamic Nature of Prototypes
   但是Person Prototype 出现两个,一个是Person Prototype,一个是新的Person Prototype。


var friend= new Person();
   Person.prototype.sayHi = function(){
      alert(“hi”);
         };
friend.sayHi(); //”hi” - works!

下面例子:  

 类:Person

   实例:friend

  原型:Person.prototype   

  流程: friend.sayHi() 被调用时,执行new Person();。建立Person,Person Prototype,实例friend,

             1、浏览器去实例friend找属性sayHi,没有找到,出现错误。

             2、然后执行重写Person Prototype,建立一个新Person Prototype,

  

function Person(){
}
    var friend = new Person();
       Person.prototype = {//这是建立固定值对象的标准方式,会建立Person Prototype原型。
           constructor: Person,
                   name : “Nicholas”,
                      age : 29,
                       job : “Software Engineer”,
                      sayName : function () {
                       alert(this.name);
                  }
       };
friend.sayName(); //error

      在这个例子中,当调用 friend.sayName() 时,一个新的Person 实例被建立,然后prototype objec是重写。
这将引起一个错误,因为friend 指向的原型并没有包含name属性,

  举例如下:

     1、在原型赋值前,建立Person实例friend ,自动建立一个Person Prototype 原型,属性值为空。


 2、在原型赋值后,比上面多一个新的Person Prototype 原型,以前的指向变化的是,Person的prototype属性改指向new Person Prototype。而new Person Prototype里面的constructor 指向Person构造函数,我喜欢叫Person类。

    

在构造函数上重写属性意味着新的实例将引用新的prototype ,而以前的实例指向不变。

六、Combination Constructor/Prototype Pattern

      这也许是最好的一种方式,和一个java类一样,分类级别(所有对象共享属性和方法)的和实例级别(属性和方法给特定的对象用)。
   

function Person(name, age, job){
  this.name = name;
  this.age = age;
  this.job = job;
  this.friends = [“Shelby”, “Court”];
}
Person.prototype = {
        constructor: Person,
       sayName : function () {
       alert(this.name);
}
};
var person1 = new Person(“Nicholas”, 29, “Software Engineer”);
var person2 = new Person(“Greg”, 27, “Doctor”);
person1.friends.push(“Van”);
alert(person1.friends); //”Shelby,Court,Van”
alert(person2.friends); //”Shelby,Court”
alert(person1.friends === person2.friends); //false
alert(person1.sayName === person2.sayName); //true










    








  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
社会发展日新月异,用计算机应用实现数据管理功能已经算是很完善的了,但是随着移动互联网的到来,处理信息不再受制于地理位置的限制,处理信息及时高效,备受人们的喜爱。所以各大互联网厂商都瞄准移动互联网这个潮流进行各大布局,经过多年的大浪淘沙,各种移动操作系统的不断面世,而目前市场占有率最高的就是微信小程序,本次开发一套基于微信小程序的生签到系统,有管理员,教师,学生三个角色。管理员功能有个人中心,学生管理,教师管理,签到管理,学生签到管理,班课信息管理,加入班课管理,请假信息管理,审批信息管理,销假信息管理,系统管理。教师和学生都可以在微信端注册和登录,教师可以管理签到信息,管理班课信息,审批请假信息,查看学生签到,查看加入班级,查看审批信息和销假信息。学生可以查看教师发布的学生签到信息,可以自己选择加入班课信息,添加请假信息,查看审批信息,进行销假操作。基于微信小程序的生签到系统服务端用Java开发的网站后台,接收并且处理微信小程序端传入的json数据,数据库用到了MySQL数据库作为数据的存储。这样就让用户用着方便快捷,都通过同一个后台进行业务处理,而后台又可以根据并发量做好部署,用硬件和软件进行协作,满足于数据的交互式处理,让用户的数据存储更安全,得到数据更方便。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值