js设计模式之路--原型对象
第一想法
创建一个人类,然后为其添加属性和方法,我最直接的想法:
1 function Person(name, age) { 2 this.name = name; 3 this.age = age; 4 this.sayName = function() { 5 alert("xxx"); 6 } 7 } 8 9 var p1 = new Person('z3', 20); 10 var p2 = new Person('z4', 18); 11 12 console.log(p1.sayName == p2.sayName);
测试结果: false
说明:
因为我们通过类实例化对象的时候,相当于复制了类中的共有属性和共有方法,创建了一个新的对象。每次通过new实例化的对象,都是独立的。因此我们打印p1.sayName和p2.sayName结果为false。
同时我们也发现类中sayName方法,是不变化的,即使alert也是打印的“xxx”。与name和age相比,name和age是接手实例化对象的时候,传入的参数,而sayName是不接收任何的,而且函数内容也是固定的。
这个固定的如果我们没次实例化的时候都创建一份的话,如果实例化对象的数量多的话,会导致资源浪费。像这种固定不变的,我们应该将其提出来,单独放在一个地方,需要的时候直接去拿来用就可以。不用在每个对象中都去实例化。
提出不变方法一
第一种处理办法是直接将方法提出来,然后在类中将这个方法的引用赋值给这个方法。
1 function sayName = function() { 2 alert("xxx"); 3 } 4 5 function Person(name, age) { 6 this.name = name; 7 this.age = age; 8 this.sayName = sayName; 9 } 10 11 var p1 = new Person('z3', 20); 12 var p2 = new Person('z4', 18); 13 14 console.log(p1.sayName == p2.sayName);
测试结果: true
说明:
通过结果我们看出,此时类中的sayName方法是同一个。这样我们不用重复创建不变的内容。只是将其放在哪里,然后要用直接去拿就可以。
但是这样我们将这个方法提出来是有问题的。这样操作,提出来的方法,作用在全局变了上。意思就是所有的方法都可以调用。而我们这个方法本身我们定义的时候就是为Person这个类服务的。别的类是不能拿去使用的。按现在这样定义的是处理不来这个方法的。这样容易造成全局变量污染。
绑定在原型上
prototype:创建每个对象的时候都有一个prototype属性,这是一个指针总是指向一个对象。而指向的这个对象的用途就是将特定不变的属性和方法包含在内,而可以被所有的实例对象所共有。
1 function Person(name, age) { 2 3 } 4 5 var obj = Person.prototype; 6 obj.name = 'z3'; 7 obj.age = 20; 8 9 var p1 = new Person(); 10 11 console.log(p1.name);
结果: z3
注意:
我们将name和age属性绑定在prototype上。这样所有通过new Person实例化的对象,也可以通过原型访问这些属性,但是有一点,我们也看到,这些属性绑定在原型上,赋的值都是固定的“z3”和20。因此印证了上面说的用途,就是将特定不变的属性和方法绑定在原型对象上。
此时我们对实例个对象,测试他们能否访问,访问的属相书否相等?
1 function Person(name, age) { 2 3 } 4 5 var obj = Person.prototype; 6 obj.name = 'z3'; 7 obj.age = 20; 8 9 var p1 = new Person(); 10 var p2 = new Person(); 11 12 console.log(p1.name); 13 console.log(p2.name); 14 console.log(p1.name == p2.name);
结果:
z3 z3 true
constructor
每个实例化的对象都有constructor属性,都执行对象的构造函数的。理清下思路:
- 1、构造函数.prototype = 原型对象
- 2、原型对象.constructor = 构造函数
- 3、实例对象的prototype = 原型对象 = 构造函数.prototype
注意:
这里检测第三点的时候,不能直接console.log()或者使用alert();来打印,如果打印的话结果也是 undefined。只能使用 isPrototytpeOf 来进行检测。
1 console.log(obj.isProtypeOf(p1));
结果; true
原型图例:

浙公网安备 33010602011771号