JavaScript高级程序设计笔记01,面向对象的程序设计

在JS中创建对象实例的几种方法

1.通过new关键字直接创建对象

这一种方法最为简单,容易理解,但是在日常使用中却用得最少,因此只做一个简单的示例。有以下代码:

var person = new Object(); //使用new关键字创建一个Object的实例person
person.name = "tom";
person.age = "25";
person.job = "programmer";
person.sayName = function(){
	alert(this.name);	//this.name将被解析为person.name
}

以上代码创建了一个名为person的对象,这个对象有属性也有方法,我们也可以使用以下代码达到同样的效果:

var person = {
	name: "tom",
	age: 29,
	job: "programmer"
	sayName: function() {
		alert(this.name);
	}
}

这里并没有通过new关键字创建对象,但是它却与上面的代码是一样的,拥有更简洁更JS的风格创建对象,同时它在转换成Json的时候也将更加直观,更利于存储和使用。

2.工厂模式创建对象

工程模式?什么是工厂模式呢?这里博主简单的谈一谈自己的看法。工厂模式就是指通过一些譬如函数的方法,在函数内部使用new关键字或者其他办法来创建对象,然后该函数将刚刚所创建的对象返回,这样能够通过这个函数直接得到对象的就是工厂函数。看以下代码:

function createObject() {
	var obj = new Object()
	return obj;
}

这一函数虽然没有实质性的作用,但是它确实是一个工厂函数,因为它在函数体内创建了对象obj并且最后又将它返回了出来。

3.构造函数模式

这种方法是目前JS创建对象比较受欢迎的方法。如果你熟悉使用JAVA或者C++那么你一定对构造函数有深刻映像吧。但是前者是出现在类里,JS的构造函数则与前者有一点点的不同。这里有一个简单的例子:

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

应该注意到,函数名P应该是大写字母。按照惯例,构造函数始终都应该以一个大写字母开头,而非构造函数应该以一个小写字母开头。这里的this则需要注意它所在的作用域。

Person("tom", 25, "programmer");
person1 = new Person("tom", 25, "programmer");
var person2 = new Object();
Person.call(person2, "tom", 25, "programmer");

以上代码对于函数Person来说都是可以正常调用的。只是我们要注意,函数体里的this它的作用域已经不同了。第一种是全局作用域window(因为是在全局作用域中调用,this对象总是指向Global对象);第二种则是作为构造函数调用,作用域为当前对象;最后一种则是在对象的作用域内调用函数Person,换句话来说,现在函数体内的this是指向对象person2的,亦即是说,在执行完3、4行代码后,name、age、job以及sayName都保存在了对象person2里面。

4.原型模式

我们创建的每个函数都有一个prototype(原型)属性。我们可以不用在构造函数中定义对象实例的信息,而是将这些信息都保存在原型对象中(因为信息都保存在了原型对象中,所以构造函数体在绝大部分的时间都是空的)。有以下例子:

function Person(){}
Person.prototype.name = "tom";
Person.prototype.age = "25";
Person.prototype.job = "programmer";
Person.prototype.sayName = function() {
	alert(this.name);
};

以上定义了一个Person的原型对象,里面包含了姓名、年龄以及工作等数据。但是这样写未免有些过于繁杂,增加了许多不必要的输入。为了减少不必要的输入,同时增加代码的简洁性及可读性,我们通过下面的方法来重写了原型对象:

function Person(){}
Person.prototype = {
	name: "tom",
	age: 25,
	job: "programmer",
	sayName: function() {
		alert(this.name);
	}
};

通过这样的方法,一是代码更加简洁明了,二是更容易与Json相互转换,便于数据的读取和存储。既然定义了原型对象,那么我们就可以直接实例化并且使用了。

var person1 = new Person();
alert(person1.name);	//"tom"来自原型

var person2 = new Person();
alert(person2.name);	//"tom"来自原型

person2.name = "mary";
alert(person2.name);	//"mary"来自实例
5.组合使用构造函数模式和原型模式(推荐)

但是通过这种方法创建的对象却有非常明显的缺点。它省略了为构造函数传递初始化参数这一环节,结果所有实例在默认情况下都将取得相同的属性值。这里我们可以组合使用构造函数模式和原型模式进行解决:

function Person(name, age, job){
	this.name = name;
	this.age = age;
	this.job = job;
	this.friends = ["mary", "tony"];
}

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

var person1 = new Person("tom", 25, "programmer");
var person2 = new Person("linuxlike", 26, "programmer");

person1.friends.push("lili");
alert(person1.friends);		//"mary","tony","lili"
alert(person2.friends);		//"mary","tony"

在这个例子中,实例属性都是在构造函数中定义的,而由所有实例共享的属性constructor和方法sayName()则是在原型中定义。而修改了person1.friends(向其中添加一个新字符串),并不会影响到person2.friends,因为它们分别引用了不同的数组。
可以看到上面的代码解决了构造函数无法传递参数,同时所有实例在初始情况下都将取相同值得问题。这种构造函数和原型混成的模式,是目前在ECMAScript中使用最广泛、认同度最高的一种创建自定义类型的方法。可以说,这是来定义引用类型的一种默认模式。

总结与参考

这里博主只是简单就《JavaScript高级程序设计》的第6.2章创建对象做了一个博主认为有必要的归纳。为了突出重点,省略了书中的很多部分。譬如动态原型模式、寄生构造函数模式、稳妥构造函数模式,这一些在书中都有讲到,但碍于篇幅,这里不再讲述。另外,原型模式中有一个原型链的知识点非常重要,书中用了大量文字与图片去描述,因为在下一小节的继承中,原型链将会是贯穿全局的一个知识点。最后,博主在写文章的时候,难免会有错误的地方,欢迎读者指出,博主可以进行及时的更正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值