JavaScript高级程序设计之什么是原型模式
原型模式:
我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象(原型对象),而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法,如果说的容易点就是,通过prototype. 声明的函数或则属性 都能给所有实例共享(当然必须是由此创建的对象);
eg:
function Person(){};
Person.prototype.name="Nicholas";
Person.prototype.sayName=function(){alert(this.name);}
var person1 = new Person();
var person2 = new Person();
person1.sayName == person2.sayName; //true
1,理解原型对象
上面说过,无论在什么时候创建一个函数,就会根据一组特定规则为该函数创建一个 prototype 属性,这个属性指向的函数原型的对象,而原型对象又会自动生成了一个constructor(构造函数)属性来回指向函数,就拿上面的来说:Person.prototype.constructor = Person;
最后,我们来根据构造函数来创建一个实例,而实例在建立之后,其内部将包含一个指针(是个内部属性,一般都是 __xx__ 来构成),这个指针指向的是原型对象 prototype ;
结论:通过上面说的,我们得到一个结论,那就是 实例 和 构造函数的原型之间 存在一种 连接。
附图:
2,如何判断 实例是否在其原型中
- isPrototypeOf() : 通过这个方法来确定 对象和构造函数之间是否存在关系,从字面理解,"isPrototypeOf" = "原型是来自"; 语句:Person.prototype.isPrototypeOf(person1); //true
- hasOwnProperty(): 拥有自己的属性。该方法可以检测一个属性是否存在一个 实例 中,还是存在于 原型 中。这个方法是从 Object继承而来。只在给定属性存 在于对象实例 中的时候,才会返回 true ; 语句:person1.hasOwnProperty("name"); //true
- in():在....; 有两种方式才会使用 in ,单独使用和for-in循环中。单独使用,in操作符通过对象能够访问给定属性时返回 true,无论属性是存在实例中还是原型中。语句:“name” in person1
结论: 使用 in 和 hasOwnProperty(),来判断给定的属性是存在于原型中还是实例中;
code:
function hasPrototypeProperty(object,name){ return !object.hasOwnProperty(name) && (name in object); }
3,更简单的原型语法
function Person(){} Person.prototype ={ name:"Nicholas", age:29, job:"sofware", sayName:function(){ alert(this.name); } }
看到这个代码,是不是感觉很优美?这种字面量的方法有个缺点,我们都知道 构造函数原型有个 constructor 属性指向构造函数。如果使用这个对象字面量方法来创建对象,那么 constructor 属性会指向Object ! 原因在于:我们在这里使用这个语法,本质上重写了默认的 prototype 对象,因此constructor 属性也变成了新对象 constructor属性。如果还是不理解的话,那么我们看下面变形的语法:
function Person(){} Person.prototype = prototypes; var prototypes = { name:"Nicholas", age:29, job:"sofware", sayName:function(){ alert(this.name); } }
看到了吗?对象字面量本来就是可以创建一个对象,那么我们的对象名字就是 Prototype
我们把本来要赋值给Person原型对象的 ,我们赋值给一个变量,再然后,把这个集合赋值给 person 原型对象,那么 Person.prototype.construtor = prototypes.prototype.construtor;
那么这个缺点该如何解决呢?
function Person(){} Person.prototype = { constructor: Person, name:"Nicholas", age:29, job:"sofware", sayName:function(){ alert(this.name); } }
只要给对象的属性指定 constructor 属性等于 Person就OK了,呵呵,再这里已经可以到 继承 的影子了。