原创作者: sdcyst   阅读:14333次   评论:31条   更新时间:2011-06-01    

类变量/类方法/实例变量/实例方法
先补充一下以前写过的方法:
在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 条 请登录后发表评论
31 楼 xianxg 2011-10-08 16:03
结论:对象的constructor属性并非指向其构造器,而是指向其构造器的prototype属性的constructor属性

上面的结论应该是错的。

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
   [img][/img]
27 楼 hnzhoujunmei 2010-09-02 14:37
26 楼 wudiju 2010-04-28 16:16
每次看都有不同的体会,写的很好
25 楼 zxfjava2007 2010-04-25 17:11
我也有同感,都2遍了还是没能完全吸收,lz太牛了,佩服中....
24 楼 wudiju 2010-04-13 16:30
感觉自己的水平看一遍不行啊。。。
23 楼 moliu 2009-09-19 14:41
wzhc888 写道
throne212 写道

引用
PositionCircle.prototype = new Circle(); //设置PositionCircle的父类为Circle类 这句话有点没懂。为什么PositionCircle的原形就可以指定一个Circle的对象? 望哪位大牛解答一下。

看一下第四章的图,你就会明白了。

在未设置子、父关系之前,二者的地位是 一样的。我们在 安排它们,像上帝造人一样,我们有这个权利。
22 楼 nalan 2009-07-09 14:46
结论:对象的constructor属性并非指向其构造器,而是指向其构造器的prototype属性的constructor属性
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
pc.area()的执行路径:
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
throne212 写道

引用
PositionCircle.prototype = new Circle(); //设置PositionCircle的父类为Circle类 这句话有点没懂。为什么PositionCircle的原形就可以指定一个Circle的对象? 望哪位大牛解答一下。

看一下第四章的图,你就会明白了。
16 楼 zhzhy86 2009-05-04 12:00
very good
15 楼 biaowen 2009-05-03 12:04
alex09 写道

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
throne212 写道

引用
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
function Person(name,age) {  //定义方法  
    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
大开眼界!以前看JS的面向对象写法都不知所以然,受益匪浅!
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
throne212 写道

引用
PositionCircle.prototype = new Circle(); //设置PositionCircle的父类为Circle类 这句话有点没懂。为什么PositionCircle的原形就可以指定一个Circle的对象? 望哪位大牛解答一下。

第四章
引用
prototype属性在javascript中模拟了父类(超类)的角色,在js中体现面向对象的思想,prototype属性
是非常关键的

5 楼 alongsir 2008-12-26 00:13
看到第五节拉,,明天继续第六节 ^_^
很晚了,休息咯。。。
4 楼 throne212 2008-12-25 16:17
引用
PositionCircle.prototype = new Circle(); //设置PositionCircle的父类为Circle类


这句话有点没懂。为什么PositionCircle的原形就可以指定一个Circle的对象?

望哪位大牛解答一下。
3 楼 releaseyou 2008-12-22 14:40
2 楼 releaseyou 2008-12-22 14:40

发表评论

您还没有登录,请您登录后再发表评论

文章信息

Global site tag (gtag.js) - Google Analytics