一、基本使用方法
prototype属性可算是JavaScript与其他面向对象语言的一大不同之处。prototype就是“一个给类的对象添加方法的方法”,使用prototype属性,可以给类动态地添加方法,以便在JavaScript中实现“继承”的效果。
具体来说,prototype 是在 IE 4 及其以后版本引入的一个针对于某一类的对象的方法,当你用prototype编写一个类后,如果new一个新的对象,浏览器会自动把prototype中的内容替你附加在对象上。这样,通过利用prototype就可以在JavaScript中实现成员函数的定义,甚至是“继承”的效果。
对于javascript本身而言是基于对象的,任何元素都可以看成对象。然而类型和对象是不同的,而我们所讲的prototype属性即是基于类型的一种属性。对于prototype的基本使用就如对象的创建及属性赋值一样的简单。直接通过赋值操作即可完成属性的创建。如:
var objectRef = new Object(); // 创建一个最基本的js对象
一个名为property的属性即可如下进行创建:
objectRef.property = 6;
objectRef["property"] = 6;
对于prototype的赋值也是类似,如下所示:
//首先创建一个基本的AClass类型
var AClass = function() {
this.property = 5;
};
//可以通过prototype属性来为该类型新增属性或方法
AClass.prototype.Method = function() {
alert(5);
}
所有对象本身都可以有prototype属性,它本身也是对象。如此循环下去就形成一个prototype链,这个链当遇到链中的prototype为null时即中止。(Object的默认prototype是null)。
如上代码var objectRef = new Object(),这个对象的prototyp是null, 所以objectRef的prototype链只包含一个对象Object.prototype。
分析如下的代码结构,可以看出类型MyClass2本身并没有定义testNumber,但通过prototype属性将MyClass1的所有定义都继承下来了,而且还继承了Object中的toString方法。因此该prototype的链包含3个。
<script>
var MyClass1 =function(formalParameter) {
this.testNumber =formalParameter;
};
var MyClass2 = function(formalParameter){
this.testString = formalParameter;
};
MyClass2.prototype = newMyClass1(9);
var myObject2 = newMyClass2("Hello World!");
alert(myObject2.testString);//Hello World!
alert(myObject2.testNumber); //9
alert(myObject2.toString); //function toString() {}
</script>
二、JS中的面向对象
JS中最简单的对象即为内嵌型的Object数据类型,如下所示,我们可以新建一个新的对象,并为其添加几个属性。
var obj = new Object();
obj.x = 1;
obj.y = 2;
可以用如下的图示来表示该对象。该对象中有两上属性,同时还包含一个隐含的prototype对象。
Obj
|
x
|
1
|
y
|
2
|
Object.prototype
|
constructor
|
Object
|
当然我们也可以构造如下带有构造函数的类,并生成其对象。
var AClass = function() {
this.x = 1;
this.y = 2;
}
var obj = new AClass();
此时,该对象的内部结构即如下图所示。其中包含了一个构造函数。
obj
|
x
|
1
|
y
|
2
|
AClass.prototype
|
constructor
|
AClass
|
Object.prototype
|
(constructor)
|
Object
|
在js中,每个对象都可以继承自另外一个其它的对象,我们可以称之为引用原型。当我们访问一个属性时,如果能通过对象本身直接找到,则返回,否则它会向引用原型中追溯,直到根部prototype(即object)。如下所示:
Object.prototype.inObj = 1;
var A = function() {
this.inA = 2;
}
A.prototype.inAProto = 3;
var B = function() {
this.inB = 4;
}
B.prototype = new A();
B.prototype.inBProto = 5;
var x = new B();
alert(x.inObj + “,” + x.inA + “,” + x.inAProto + “,” + x.inB + “,” +x.inBProto); //1, 2, 3, 4, 5
对于上述的代码,创建一个对象x,它所生成的prototype链结构如下:
对应生成的对象x的内部结构图如下所示:
x
|
inB
|
4
|
B.prototype
|
constructor
|
B
|
inA
|
2
|
inBProto
|
5
|
A.prototype
|
(constructor)
|
A
|
inAProto
|
3
|
Object.prototype
|
(constructor)
|
Object
|
inObj
|
1
|
三、prototype的继承使用
1、将ClassA的一个实例赋值给ClassB,则 ClassB就继承了ClassA的所有属性。
<script>
var ClassA = function() {
this.a = "a";
};
var ClassB = function() {
this.b= "b";
};
ClassB.prototype = new ClassA();
var objB = new ClassB();
alert(objB.a); // a
alert(objB.b); // b
</script>
从上述的变量输出结果,可以看出本身ClassB是没有属性a的,但在创建的对象中调用objB.a时却输出了a,说明在执行ClassB.prototype= new ClassA();后,ClassB继承了ClassA的所有属性。
2、js的原型继承是引用原型,而不是复制原型。当修改原型时会导致所有的实例变化。
<script>
var ClassA = function() {
this.a = "a";
};
var ClassB = function() {
this.b = "b";
};
ClassB.prototype = new ClassA();
var objB = new ClassB();
alert(objB.a); // a
ClassB.prototype.a ="changed";
alert(objB.a); //changed
</script>
由上述代码可以看出,即使对象创建于原型修改之前,但仍然会生效。这就印证了js是引用原型。即使是在对象创建之后修改,仍然会对之前生成的对象生效。
3、每个子类对象都执行同一个原型的引用,所以子类对象中的原型成员实际是同一个
<script>
var ClassA = function() {
this.a = "a";
this.Method = function() {
alert("ClassA");
}
};
var ClassB = function() {
this.b = "b";
};
ClassB.prototype = new ClassA();
var objB1 = new ClassB();
var objB2 = new ClassB();
alert(objB1.a == objB2.a); //true
alert(objB1.b == objB2.b); //true
alert(objB1.Method ==objB2.Method);
</script>
4、子类对象的写操作只访问子类对象的成员,相互之间不产生影响。写一定是写子类,读则要看是否子类中有,若有则读子类,若无则读原型。
<script>
var ClassA = function() {
this.a = "a";
};
var ClassB = function() {
this.b = "b";
};
ClassB.prototype = new ClassA();
var objB1 = new ClassB();
var objB2 = new ClassB();
objB1.a = "change";
alert(objB1.a); // change
alert(objB2.a); // a
</script>
由上述代码分析,其中由于进行了objB1.a进行了重新改变,所以其值在接下来进行了改变,但它不会影响到objB2对象。但若是原型发生了变化,则如2所示,它下面的所有实例均会发生变化。
5、构造子类时,原型的构造函数不会被执行
<script>
var ClassA = function() {
alert("ClassA");
this.a = "a";
};
var ClassB = function() {
alert("ClassB");
this.b = "b";
};
ClassB.prototype = new ClassA();// ClassA
var objB1 = new ClassB(); // ClassB
var objB2 = new ClassB(); // ClassB
</script>
由此可以看出,在构造子类时并没有象java中那样需要调用父类的构造函数。
6、在子类对象中访问原型的成员对象,会影响到其它对象
<script>
var ClassA = function() {
this.a = [];
};
var ClassB = function() {
this.b = "b";
};
ClassB.prototype = new ClassA();
var objB1 = new ClassB();
var objB2 = new ClassB();
objB1.a.push(1,2,3);
alert(objB2.a); // 1,2,3
</script>
由此可以看出,在子类对象中访问原型的成员对象后,由于采用的是引用原型方式,其实它和ClassB.a.push实现的是同样的功能。所以其它的子类也会跟着变化。
分享到:
相关推荐
Javascript面向对象 JavaScript面向对象的支持 JavaScript中支持面向对象的基础 jQuery、JSON超强组合 JSONG Private Members in JavaScript prototype手册 深入理解JavaScript闭包 悟透javascript(很好) 详解...
对于那些熟悉基于类的面向对象语言(Java 或者 C++)的开发者来说,JavaScript 的语法是比较怪异的,这是由于 JavaScript 是一门动态语言,而且它没有类的概念( ES6 新增了class 关键字,但只是语法糖,JavaScript ...
百度百科中,这样描述了property:在JavaScript中,prototype对象是实现面向对象的一个重要机制。每个函数就是一个对象(Function),函数对象都有一个子对象 prototype对象,类是以函数的形式来定义的。prototype...
潜意识里也就不会用面向对象的思想去编写JavaScript代码,也很少会去深入了解prototype, closures等概念。这导致书写的代码经常很糟糕。 对于JavaScript的学习,可能最重要的还是要从思想上认识到JavaScript不是...
Dojo是一个非常强大的、面向对象的、开源的JavaScript工具箱,它为开发富客户端Ajax应用提供了一套完整的小部件和一些特效操作。曾经有人这样说:“对于一个Web开发者而言,如果没有Dojo,他将是一个“残废”的...
前几天看了《再谈js面向对象编程》,当时就请教哈大神,发现文章有的地方可能会造成误导(或者说和ECMA有出入),后来自己翻一翻ECMA,总算找到“标准”的理解……本文适合初学者,特别是对构造函数、原型和原型链...
在Asp.net中如何用SQLDMO来获取SQL Server中的对象信息 使用Relations建立表之间的关系并却使用PagedDataSource类对DataList进行分页 通过作业,定时同步两个数据库 SQLSERVER高级注入技巧 利用反射实现ASP.NET控件和...
06/6.7.2.html 在JavaScript实现抽象类范例 06/6.8.3.html 给事件处理程序传递参数范例 06/6.8.4.html 使自定义事件支持多绑定范例 06/6.9/ 实例:使用面向对象思想处理cookie <br>第7章...
如果要学习QtScript,还需要了解JavaScript。 \本书的结构 \本书共21章,每章讨论一个专题。章节安排上基本采用循序渐进、由浅到深的原则。但最后的高级篇中的章节没有很强的关联,可以按照随意的顺序阅读。每章内容...
如果要学习QtScript,还需要了解JavaScript。 \本书的结构 \本书共21章,每章讨论一个专题。章节安排上基本采用循序渐进、由浅到深的原则。但最后的高级篇中的章节没有很强的关联,可以按照随意的顺序阅读。每章...