类变量/类方法/实例变量/实例方法
先补充一下以前写过的方法:
在javascript中,所有的方法都有一个call方法和apply方法.这两个方法可以模拟对象调用方法.它的第一个参数是对象,后面的
参数表示对象调用这个方法时的参数(ECMAScript specifies two methods that are defined for all functions, call()
and apply(). These methods allow you to invoke a function as if it were a method of some other object. The first
argument to both call() and apply() is the object on which the function is to be invoked; this argument becomes
the value of the this keyword within the body of the function. Any remaining arguments to call() are the values
that are passed to the function that is invoked).比如我们定义了一个方法f(),然后调用下面的语句:
f.call(o, 1, 2);
作用就相当于
o.m = f;
o.m(1,2);
delete o.m;
举个例子:
function Person(name,age) { //定义方法 this.name = name; this.age = age; } var o = new Object(); //空对象 alert(o.name + "_" + o.age); //undefined_undefined Person.call(o,"sdcyst",18); //相当于调用:o.Person("sdcyst",18) alert(o.name + "_" + o.age); //sdcyst_18 Person.apply(o,["name",89]);//apply方法作用同call,不同之处在于传递参数的形式是用数组来传递 alert(o.name + "_" + o.age); //name_89
---------------------------------
实例变量和实例方法都是通过实例对象加"."操作符然后跟上属性名或方法名来访问的,但是我们也可以为类来设置方法或变量,
这样就可以直接用类名加"."操作符然后跟上属性名或方法名来访问.定义类属性和类方法很简单:
Person.counter = 0; //定义类变量,创建的Person实例的个数 function Person(name,age) { this.name = name; this.age = age; Person.counter++; //没创建一个实例,类变量counter加1 }; Person.whoIsOlder = function(p1,p2) { //类方法,判断谁的年龄较大 if(p1.age > p2.age) { return p1; } else { return p2; } } var p1 = new Person("p1",18); var p2 = new Person("p2",22); alert("现在有 " + Person.counter + "个人"); //现在有2个人 var p = Person.whoIsOlder(p1,p2); alert(p.name + "的年龄较大"); //p2的年龄较大
prototype属性的应用:
下面这个例子是根据原书改过来的.
假设我们定义了一个Circle类,有一个radius属性和area方法,实现如下:
function Circle(radius) { this.radius = radius; this.area = function() { return 3.14 * this.radius * this.radius; } } var c = new Circle(1); alert(c.area()); //3.14
假设我们定义了100个Circle类的实例对象,那么每个实例对象都有一个radius属性和area方法,
实际上,除了radius属性,每个Circle类的实例对象的area方法都是一样,这样的话,我们就可以
把area方法抽出来定义在Circle类的prototype属性中,这样所有的实例对象就可以调用这个方法,
从而节省空间.
function Circle(radius) { this.radius = radius; } Circle.prototype.area = function() { return 3.14 * this.radius * this.radius; } var c = new Circle(1); alert(c.area()); //3.14
现在,让我们用prototype属性来模拟一下类的继承:首先定义一个Circle类作为父类,然后定义子类
PositionCircle.
function Circle(radius) { //定义父类Circle this.radius = radius; } Circle.prototype.area = function() { //定义父类的方法area计算面积 return this.radius * this.radius * 3.14; } function PositionCircle(x,y,radius) { //定义类PositionCircle this.x = x; //属性横坐标 this.y = y; //属性纵坐标 Circle.call(this,radius); //调用父类的方法,相当于调用this.Circle(radius),设置PositionCircle类的 //radius属性 } PositionCircle.prototype = new Circle(); //设置PositionCircle的父类为Circle类 var pc = new PositionCircle(1,2,1); alert(pc.area()); //3.14 //PositionCircle类的area方法继承自Circle类,而Circle类的 //area方法又继承自它的prototype属性对应的prototype对象 alert(pc.radius); //1 PositionCircle类的radius属性继承自Circle类 /* 注意:在前面我们设置PositionCircle类的prototype属性指向了一个Circle对象, 因此pc的prototype属性继承了Circle对象的prototype属性,而Circle对象的constructor属 性(即Circle对象对应的prototype对象的constructor属性)是指向Circle的,所以此处弹出 的是Circ. */ alert(pc.constructor); //Circle /*为此,我们在设计好了类的继承关系后,还要设置子类的constructor属性,否则它会指向父类 的constructor属性 */ PositionCircle.prototype.constructor = PositionCircle alert(pc.constructor); //PositionCircle
31 楼 xianxg 2011-10-08 16:03
上面的结论应该是错的。
constructor属性是构造函数的prototype属性中带有的属性,并且该constructor属性也指向构造函数自身。
new一个对象后如果没有特别赋予constructor属性的话,创建的对象是没有这个属性的。新建的对象带有__proto__属性,该属性是指向构造函数prototype属性的。因此新建的对象能找到这个constructor属性。
可以这样新建对象:
var obj = new Circle.prototype.constructor();
这个obj对象和下面创建的对象是一样的:(前提是prototype的constructor属性没有被赋其它值)
var obj = new Circle();
30 楼 tan4836128 2011-08-25 17:44
29 楼 dir_murong 2011-02-22 17:23
28 楼 liuyuanhui0301 2011-02-18 16:11
27 楼 hnzhoujunmei 2010-09-02 14:37
26 楼 wudiju 2010-04-28 16:16
25 楼 zxfjava2007 2010-04-25 17:11
24 楼 wudiju 2010-04-13 16:30
23 楼 moliu 2009-09-19 14:41
引用
PositionCircle.prototype = new Circle(); //设置PositionCircle的父类为Circle类 这句话有点没懂。为什么PositionCircle的原形就可以指定一个Circle的对象? 望哪位大牛解答一下。
看一下第四章的图,你就会明白了。
在未设置子、父关系之前,二者的地位是 一样的。我们在 安排它们,像上帝造人一样,我们有这个权利。
22 楼 nalan 2009-07-09 14:46
21 楼 nalan 2009-07-09 09:11
function Circle(radius){
this.radius = radius;
this.area = function(){
return "i am Circle"
}
}
Circle.prototype.area = function(){
return 3.14 * this.radius * this.radius;
}
function PositionCircle(x,y,radius){
this.x = x;
this.y = y;
// Circle.call(this,radius);
this.area = function(){
return "i am PositionCircle"
};
Circle.call(this,radius);
}
PositionCircle.prototype = new Circle();
PositionCircle.prototype.area = function(){
return "i am PositionCircle.prototype";
}
var pc = new PositionCircle(1,2,1);
alert(pc.area());
20 楼 nalan 2009-07-09 09:07
pc.area()的执行路径:
1、查找pc的属性area,如果有,返回;如果没有到第2步
2、查找pc.constructor.prototype.area属性,如果有,返回;如果没有到第3步
3、查找pc.constructor.prototype(现在prototype属性指向new Circle()对象),如果new Circle()对象有area属性,返回;如果没有到第4步(此处需说明:由于在PositionCircle的构造函数内执行了Circle.call(this,radius),如果Circle构造函数内有area属性,它将会给pc添加area属性,故此时参照第1步)
4、查找(new Circle()).constructor.prototype,如果有,返回;如果没有返回undefined
19 楼 nalan 2009-07-09 08:39
1、查找pc的属性area,如果有,返回;如果没有到第2步
2、查找pc.constructor.prototype(现在prototype熟悉指向new Circle()对象),如果new Circle()对象有area属性,返回;如果没有到第3步
3、查找(new Circle()).constructor.prototype,如果有,返回;如果没有返回undefined
18 楼 a_nuo 2009-06-05 13:09
17 楼 wzhc888 2009-05-04 17:15
引用
PositionCircle.prototype = new Circle(); //设置PositionCircle的父类为Circle类 这句话有点没懂。为什么PositionCircle的原形就可以指定一个Circle的对象? 望哪位大牛解答一下。
看一下第四章的图,你就会明白了。
16 楼 zhzhy86 2009-05-04 12:00
15 楼 biaowen 2009-05-03 12:04
throne212 写道
引用 PositionCircle.prototype = new Circle(); //设置PositionCircle的父类为Circle类 这句话有点没懂。为什么PositionCircle的原形就可以指定一个Circle的对象? 望哪位大牛解答一下。 这里将父类Circle的对象赋给了PositionCircle的prototype属性,相当于,将父类的属性和方法都赋给子类
看意思的确如您的解答,不过我注释掉这句话pc也可以正确调取Circle类的area方法和ridaus属性,疑惑???
//PositionCircle.prototype = new Circle();
14 楼 wdw8217 2009-04-29 08:49
13 楼 alex09 2009-04-13 21:20
引用
PositionCircle.prototype = new Circle(); //设置PositionCircle的父类为Circle类 这句话有点没懂。为什么PositionCircle的原形就可以指定一个Circle的对象? 望哪位大牛解答一下。
这里将父类Circle的对象赋给了PositionCircle的prototype属性,相当于,将父类的属性和方法都赋给子类
12 楼 sunwenran 2009-04-01 16:03
11 楼 nail2008 2009-03-02 15:40
this.name = name;
this.age = age;
}
function Person2(sex) { //定义方法
this.sex = sex;
}
var o = new Object(); //空对象
alert(o.name + "_" + o.age); //undefined_undefined
Person.call(o,"sdcyst",18); //相当于调用:o.Person("sdcyst",18)
alert(o.name + "_" + o.age); //sdcyst_18
Person2.call(o,1);
alert(o.name + "_" + o.age+"_"+o.sex);//sdcyst_18_1
10 楼 jiasky 2009-02-20 16:01
9 楼 lhy5201314 2009-01-20 10:23
8 楼 cobo85 2009-01-09 14:54
7 楼 youfengkai 2009-01-09 14:09
注意:在前面我们设置PositionCircle类的prototype属性指向了一个Circle对象,
因此pc的prototype属性继承了Circle对象的prototype属性,而Circle对象的constructor属 性(即Circle对象对应的prototype对象的constructor属性)是指向Circle的,所以此处弹出 的是Circ.
*/
alert(pc.constructor); //Circle
prototype属性的继承关系,怎么影响到constructor属性呢?不太清楚,请指点
6 楼 sytemper 2009-01-05 11:22
引用
PositionCircle.prototype = new Circle(); //设置PositionCircle的父类为Circle类 这句话有点没懂。为什么PositionCircle的原形就可以指定一个Circle的对象? 望哪位大牛解答一下。
第四章
是非常关键的
5 楼 alongsir 2008-12-26 00:13
很晚了,休息咯。。。
4 楼 throne212 2008-12-25 16:17
这句话有点没懂。为什么PositionCircle的原形就可以指定一个Circle的对象?
望哪位大牛解答一下。
3 楼 releaseyou 2008-12-22 14:40
2 楼 releaseyou 2008-12-22 14:40