JavaScript中对象的定义和继承的几种方式
2012-05-07 22:37 java线程例子 阅读(204) 评论(0) 编辑 收藏 举报前几天看张龙老师讲的JavaScript视频的时候,觉得老师讲的很好,继承和定义对象这很有意思,又查了几本书和一些资料,也慢慢的记住了这几种对象的定义方式和继承,但是日后,我可能会忘,所以写成博客和大家分享一下,并且做一下总结,我本来想看一看javascript高级程序设计这本书是怎么说的,可以图书馆刚上一天这书,就被人给借走了,只好等他换回去我在看了,我会慢慢的对这篇文章进行扩充。
定义对象的几种方式:
1)基于已有对象的扩充其属性和方法
这种方式是创建一个自定义对象的最简单方式,然后可以为他添加属性和方法,如下所示
var person = new Object(); person.name="Nicholas"; person.age = 29; person.job = "Software Engineer"; person.sayName = function(name) { this.name = name; alert(this.name); } object.sayName("lisi");
2)通过工厂方式
工厂模式是软件工程领域一种广为人知的模式,这种模式抽象了创建具体对象的过程,通过一种函数,用函数来封装以特定接口创建对象的细节。工厂方式的特点是通过特定的工厂方法创建特定类型的对象。以下是比较典型的实现代码。
//工厂方式创建对象 function createObject() { var object = new Object(); object.username = username; object.password = password; object.get = function() { alert(this.username+","+this.password); } } var object1 = createObject(); var object2 = createObject(); object1.get();
接下来给它加上参数
function createObject(username,password) { var object = new Object(); object.username = username; object.password = password; object.get = function() { alert(this.username+","+password); } return object; } var object = createObject("zhangsan","123"); object.get();
也可以让一个函数对象被多个对象所共享,而不是每一个对象拥有一个函数对象
function get() { alert(this.username+","+this.password); } function createObject(username,password) { var object = new Object(); object.username = username; object.password = password; object.get = get; return object; } var object = createObject("zhangsan","123"); var object2 = createObject("lisi","456"); object.get(); object2.get();
3)构造函数方式
构造函数的方式和工厂方式很像,通过构造函数的方式可以创建特定的对象,像Object和Array这样的原生构造函数,在运行时会自动出现在执行环境中,通过创建自定义的构造函数,从而自定义对象类型的属性和方法。
function Person() { this.username = "zhangsan"; this.password = "123"; this.getInfo = function() { alert(this.username+","+this.password); } } var person = new Person(); person.getInfo();
用的更多的是给他传递参数
function Person(username,password) { this.username = username; this.password = password; this.getInfo = function() { alert(this.username+","+this.password); } } var peron = new Person("zhangsan","123"); person.getInfo();
用构造函数的方式,按照惯例通长首字母大写,如Person中的P,而不是以一个小写的字母开头,这个做法鉴于其他OO语言,主要是为了区别。
构造函数方式和工厂方式都有一个不可忽略的弊端,就是每个对象被实例化时,都会实例化类中的方法,而这个弊端会造成每个对象都有独立的版本。
4)原型(“prototype”)方式
通过原型的方式我们可以避免这种弊端。我们创建的每个函数都有一个prototype属性,这个属性就是一个对象,它的用途是包含可以由特定类型的所有实例共享的属性和方法。
//使用原型的方式创建对象
function Person()
{
}
Person.prototype.username = "zhangsan";
Person.prototype.password = "123";
function.prototype.getInfo = functiion()
{
alert(this.username+","+this.password);
}
var person = new Person();
var person2 = new Person();
person.username = "lisi";
person.getInfo();
person2.getInfo();
对于原型方式来说,如果使用原型对象,那么生成的所有对象会共享原型中的属性,这样一个对象改变了该属性也会反映到其他对象中。
function Person() { } Person.prototype.username = new Array(); Person.prototype.password = "123"; Person.prototype.getInfo = function() { alert(this.username+","+this.password); } var person = new Person(); var person2 = new Person(); person.username.push("zhangsan"); person.username.push("lisi"); person.password = "456"; person.getInfo(); person2.getInfo();
单纯的使用原型方式定义对象无法再构造函数中为属性赋初值,只能在对象生成后再去改变属性值。
5)混合方式(原型+构造函数)
工厂方式、构造方式、原型方式都有一些缺陷,那种方式可以很好的实现对象的创建呢?使用原型+构造函数方式来定义对象,对象之间的属性互不干扰,各个对象间共享同一个方法。通过构造函数方式定义对象的所有非函数属性,用原型方式定义对象的函数属性,所有的属性都是单一对象私有的,而方法则是所有对象公有的。如下所示:
//使用原型+构造函数方式来定义对象 function Person()//构造函数定义对象的非函数属性 { this.username = new Array(); this.password = "123"; } Person.prototype.getInfo = function()//通过原型方式定义对象的函数 { alert(this.username+","+this.password); } var p = new Person(); var p2 = new Person(); p.username.push("zhangsan"); p2.username.push("lisi"); p.getInfo(); p2.getInfo();
6)通过动态原型方式
对于习惯了使用Java的人来说,面向对象的“封装”特征并没有体现在上述的代码中,混合方式并没有对对象的属性和方法进行严密封装。在JavaScript中,提供了一种动态原型的方式对对象的属性和方法进行严密的封装,在构造函数中通过一个 标志量让所有对象共享一个方法,而每个对象拥有自己的属性。
function Person()
{
this.username = "zhangsan";
this.password = "123";
if(typeof Person.flag == "undefined")
{
Person.prototype.getInfo = function()
{
alert(this.username+","+this.password);
}
Person.flag = true;
}
}
var p = new Person();
var p2 = new Person();
p.getInfo();
p2.getInfo();
JavaScript中的继承
和定义对象一样,在JavaScript中实现继承也有多种方式,javascript是弱类型的语言,有很多的地方没有明确的限制,挺多的时候都掌握在我们的手中。我们可以根据自己的方式来进行各种操作。
1)对象的冒充
使用对象的冒充的时候,必须使用构造函数,否则无法实现继承
//继承的第一种方式,对象的冒充 function Parent(username) { this.username = username; this.sayHello = function() { alert(this.username); } } function Child(username,password) { //下面的三行代码是最关键的代码 this.method = Parent; this.method(username); delete this.method; this.password = password; this.sayWorld = function() { alert(this.password); } } var parent = new Parent("zhangsan"); var child = new Child("lisi","1234"); parent.sayHello(); child.sayHello(); childsayWorld();
使用对象冒充的方式,可以实现多继承,让一个子类有多个父类,与单一的继承方式一样。
2)通过call方法
在Function对象中有两个方法可以实现继承,即call方法和apply方法。也正是因为这个我们所定义的每个函数都有call方法,我们可以通过函数名调用call方法,对于call方法的参数列表来说并不固定,根据实际的情况增加和减少。第一个参数是指调用当前的Function对象,并将它传递给函数中的this,而剩下的所有参数都是当前函数的参数。逐一赋值给函数中的参数。如下代码所示:
//使用call方法实现对象的继承 function Parent(username) { this.username = username; this.sayHello = function() { alert(this.username); } } function Child(username,password) { Parent.call(this,username);//在这里调用call方法,将Child对象通过this传递给父类的this,父类的this就代表了子类的对象 this.password = password; this.sayWorld = function() { alert(this.password); } } var parent = new Parent("zhangsan"); var child = new Child("lisi","123"); parent.sayHello(); child.sayHello(); child.sayWorld():
3)通过apply方法
apply方法也是Function对象里的方法,使用和call方法基本一致。唯一的区别就是apply方法的参数,call的方法的参数是不固定的,apply方法的参数只有两个,第一个是调用当前的Function对象,即this对象,第二个是传入参数的数组。如代码所示:
//使用apply方法实现对象继承 function Parent(username) { this.username = username; this.sayHello = function() { alert(this.username); } } function Child(username,password) { Parent.apply(this,new Array(username));//通过apply方法将Child对象传递给父类中的this,那么this就变成了子类的对象 this.password = password; this.sayWorld = function() { alert(this.password); } } var parent = new Parent("zhangsan"); var child = new Child("lisi","123"); parent.sayHello(); child.sayHello(); child.sayWorld();
4)原型链的方式
在之前的定义对象的时候使用了使用原型的方式创建对象,也可以通过原型的方式进行对象的继承。通常称作原型链。但是这种方式无法给构造函数传递参数。如代码所示:
//使用原型链方式实现对象继承 function Parent() { } Parent.prototype.hello = "hello"; Parent.prototype.sayHello = function() { alert(this.hello); } function Child() { } Child.prototype = new Parent();//通过这句话将子类的原型类设为了父类,从而实现了继承 Child.prototype.world = "world"; Child.prototype.sayWorld = function() { alert(this.world); } var child = new Child(); child.sayHello(); child.sayWorld();
5)混合方式
在JavaScript中最好的方式就是用混合方式实现对象间的继承。和定义对象一样,我们可以将属性和方法用不同的方式定义,用call或apply方式定义继承对象的属性,利用原型链的方式实现方法的继承。如下代码所示:
//使用混合的方式实现对象的继承 function Parent(hello) { this.hello = hello;//定义父类的属性 } Parent.prototype.sayHello = function()//定义父类的方法 { alert(this.hello); } function Child(hello,world) { Parent.call(this,hello);//继承父类的属性 this.world = world; } Child.prototype = new Parent();//继承父类的方法 Child.prototype.sayWorld = function() { alert(this.world); } var child = new Child("hello","world"); child.sayHello(); child.sayWorld();
以上的总结仅仅是我简单的总结,等日后学的比较深了会在扩充一下,希望大家理解一下。