Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1176405
  • 博文数量: 252
  • 博客积分: 5421
  • 博客等级: 大校
  • 技术积分: 2418
  • 用 户 组: 普通用户
  • 注册时间: 2007-06-17 12:59
文章分类

全部博文(252)

文章存档

2017年(3)

2016年(18)

2015年(31)

2014年(18)

2013年(7)

2012年(8)

2011年(12)

2010年(30)

2009年(32)

2008年(57)

2007年(36)

分类: 系统运维

2010-03-06 22:28:17

在js中利用new、this和prototype三个关键字可以实现完备的面向对象特征。而创建一个新的对象new关键字是不可缺少的。

只用new创建一个最简单的对象:(1)

var t = new Object;
t.a = 'test'
;
t.b = function (){alert(t.a)};
t.b();

弹出“test”

再利用new和this关键字改进:(2)

var t = new Object;
t.a = 'test'
t.b = function (){alert(this.a)};
t.b();

弹出“test”,但仍不能实现重复建立多个实例。

改进:(3)

function test()
{
    this.a = 'test';
    this.b = function (){alert(this.a)};
    return 1;
}
var t = test();
alert(a);
b();
alert(t);
alert(t.a);
t.b();

依次,弹出test、弹出test、弹出1、undefined、对象不支持此属性或方法。可见,直接调用函数时,t只是函数的返回值,并不是需要的对象。由于test是由window对象调用的,this指代了window对象,把a和b赋给了window对象。

加上new:(4)

function test()
{
    this.a = 'test';
    this.b = function (){alert(this.a)};
    return 1;
}
var t = new test();
alert(t);
alert(t.a);
t.b();
alert(a);
b();

依次,弹出[object Object]、弹出test、弹出test、编译错误'a'未定义、停止执行。可见,用new运算符时,调用test函数的对象被赋给了t,this指代t对象,函数返回值被忽略。a和b()在window上未定义。

也可以采用函数返回值的方式建立对象:(5)

function test()
{
    var t = new Object;
    t.a = 'test';
    t.b = function (){alert(this.a)};
    return t;
}
var t1 = test();
alert(t1);
alert(t1.a);
t1.b();
var
t2 = test();
t2.a =
'test2';
t2.b;

alert(Object.a);
Object.b();

以上依次,弹出[object Object]、弹出test、弹出test、弹出test2、弹出undefined、编译错误:对象不支持此属性或方法,停止执行。可见,在函数内部new操作符新建了个基本对象并返回,两个test实例不相互影响,也不影响Object对象。

但是上面的4和5的例子都有个弊端就是b方法其实只是一个函数指针,两个指针所指向的函数在调用构造函数时即时创建,并非为同一个程序实例,造成存储空间浪费。
一种改进方案是:(6)

var test_b = function (){alert(this.a)};
function test()
{
    var t = new Object;
    t.a = 'test';
    t.b = test_b;
    return t;
}
var t1 = test();
t1.b();
var t2 = test();
t2.a = 'test2';
t2.b();

这样两个实例的b属性为同一个值test_b指针,都指向同一个函数。

除了这种方式还有一种办法做到,那就是js内置于每个对象中的对象类型原型的引用prototype属性。
用prototype属性提供对象的类的一组基本功能,对象的新实例“继承”赋予该对象原型的操作。
看示例:(7)

function test()
{
    this.a = 'test';
}
test.prototype.b = function (){alert(this.a)};
test.prototype.c = new Array();

test.prototype.d = 5;
var t1 = new test();
t1.b();
var t2 = new test();
t2.a = 'test2';
t2.b();
//////
t1.c = [1,2];

alert(t1.c);
t2.c[1] = 4;

alert(t2.c);
alert(t1.c);

//////

t2.d = 6;
alert(t2.d);
alert(t1.d);

依次,弹出test、弹出test2、弹出1,2,弹出1,4,弹出1,2,弹出6,弹出5。可见,目的达到了,后面的示例说明:当prototype的属性为对象的引用时,它为指向对象的指针,和普通变量一样被每个实例继承。另外,prototype属性在对象被实例化前创建。也不可以放在函数内因为那样每次实例化对象时,都会为prototype的属性重新赋值,那样仍然没达到目地。


在看下js中的继承:(8)

function test()
{
    this.a = 'test';
    this.b = function (){alert(this.a)};
}
function subTest()
{
    this.peraP = test;
    this.peraP();
    this.subName = 'subTest';
}
var t1 = new test();
t1.b();
var t2 = new subTest();
t2.b();
alert(t2.subName);

依次输出:弹出test、弹出test、弹出subTest。在子类的构造函数内,用this调用父类构造函数,实现继承。

当类的构造函数不需要传递参数时,也可以使用原型链实现继承。
例:(9)

function test()
{
    this.a = 'test';
}
test.prototype.b = function (){alert(this.a)};

function subTest()
{
    this.subName = 'subTest';
}
subTest.prototype = new test;
subTest.prototype.showName = function (){alert(this.subName)};

var t1 = new test();
t1.b();
var t2 = new subTest();
t2.b();
t2.showName();

依次输出:弹出test、弹出test、弹出subTest。当父类的构造函数不需要传递参数时,可以用subClass.prototype = new ParentClass;的方式覆盖子类的prototype原型,子类的新原型属性放在后面添加。



附录:
new 运算符

new
运算符执行下面的任务:
1、创建一个没有成员的对象。
2、为那个对象调用构造函数,传递一个指针给新创建的对象作为 this 指针。
3、然后构造函数根据传递给它的参数初始化该对象。


this 语句

指当前对象。
this
.property
必选的 property 参数指的是对象的属性。

说明
this 关键字通常在对象的构造函数中使用,用来引用对象。
对于 JScript 的客户版本,如果在其他所有对象的上下文之外使用
this,则它指的是 window 对象。


prototype 属性

返回对象类型原型的引用。
objectName
.prototype
objectName
参数是对象的名称。

说明
prototype 属性提供对象的类的一组基本功能。对象的新实例“继承”赋予该对象原型的操作。所有 JScript 内部对象都有 prototype 属性。

阅读(10285) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~