日期:2014-05-16  浏览次数:20367 次

TDD测试驱动的javascript开发(2) ------ 深入学习javascript中prototype

1. 原型模式

1.1 我们创建的每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。

简单的解释上面的话的意思就是:首先,我们要知道,面向对象的语言中类的存在,而javascript也是一门面向对象的语言(这句话说的可能有一些毛病,但是不影响),在javascript中定义一个类函数的时候,就默认创建了一个prototype属性,在这个prototype属性里的所有的属性和方法将被这个类的所有实例共享。看代码:

//创建一个Person类
function Person() {
}
//Person类prototype里包含了name、age属性和sayName()方法
Person.prototype.name = "defaultName";
Person.prototype.age = 29;
Person.prototype.sayName = function() {
	return this.name;
};

var person = new Person();
var person3 = new Person();
TestCase("test extends",{
	"test person.sayName() should be equals person3.sayName()" : function() {
		assertEquals(person.sayName(),person3.sayName()); 
	}
});

1.2 在默认的情况下,所有的原型对象都会自动获得一个constructor(构造函数)属性,这个属性包含一个指向prototype属性所在函数的指针。

Person.prototype.constructor  指向  Person

当为对象实例添加一个属性时,这个属性就会 屏蔽 原型对象中保存的同名属性(它只会阻止我们访问原型中的那个属性,并不会修改那个属性),不过我们可以使用delete操作符删除实例属性,让我们可以继续访问原型中的属性,看代码:

//创建一个Person类
function Person() {
}
//Person类prototype里包含了name、age属性和sayName()方法
Person.prototype.name = "defaultName";
Person.prototype.age = 29;
Person.prototype.sayName = function() {
	alert(this.name);
};

var person = new Person();
person.sayName();         // defaultName

var person2 = new Person();
person2.name = "person2";
person2.sayName();           //person2
//删除实例中的name属性
delete person2.name;
person2.sayName();          //defaultName
1.3 使用hasOwnProperty()方法可以检测一个属性是存在于实例中还是存在于原型中,只有在给定的属性是存在于对象的实例中才会返回true

function Person() {
}
//Person类prototype里包含了name、age属性和sayName()方法
Person.prototype.name = "defaultName";
Person.prototype.age = 29;
Person.prototype.sayName = function() {
	return this.name;
};

var person = new Person();

var person2 = new Person();
person2.name = "person2";

TestCase("test extends",{
	"test person should not be hasOwnProperty name" : function() {
		assertEquals(false,person.hasOwnProperty("name")); 
	},
	"test person2 should not be hasOwnProperty name" : function() {
		assertEquals(true,person2.hasOwnProperty("name")); 
	},
});


1.4 使用 in 操作符确定一个属性是原型中的属

in操作符只要通过对象能够访问到的属性就返回true,(hasOwnProperty()只在属性存在于实例中才返回true),因此,只要in操作符返回true,hasOwnProperty()返回false,就证明该属性是原型中的属性,看代码:

//创建一个Person类
function Person() {
}
//Person类prototype里包含了name、age属性和sayName()方法
Person.prototype.name = "defaultName";
Person.prototype.age = 29;
Person.prototype.sayName = function() {
	alert(this.name);
};

var person = new Person();

var person2 = new Person();
person2.name = "person2";
person2.color = "blue";

TestCase("test extends",{
	"test Person  person.hasOwnProperty(name)" : function() {
		assertEquals(false,person.hasOwnProperty("name")); //name是原型中的属性,实例中不存在
	},
	"test Person  name in person" : function() {
		assertEquals(true,"name" in person);
	},
	"test Person  person2.hasOwnProperty(name)" : function() {
		assertEquals(true,person2.hasOwnProperty("name"));//name是实例对象的属性
	},
	"test Person  Person2 name in person2" : function() {
		assertEquals(true,"name" in person2);
	},
	"test Person  person2.hasOwnProperty(color)&qu