首页 > JavaScript > 面向对象的 JavaScript 代码

面向对象的 JavaScript 代码

2009年2月19日

本篇文章节选自:http://lijing.9966.org/jayli/yshare/p1/code.html   原文作者:jay

JavaScript是基于原型的编程语言,但也有完整的面向对象特性。同时其书写风格灵活多变,包括函数式编程、原型风格编程和面向对象风格编程。

从代码风格来看,封装类型分为类式的封装和原型式的封装。
这里我们使用“人”(Person)的例子,构造一个“人”的类,人有名字,人可以“吃饭”、“睡觉”、“走路”等等

1,类式封装

最直接最简单的封装方法是将人名,吃饭,睡觉等属性和动作封装在Person类中.
<script>
/*定义一个"人"的类,人有名字,人也可以吃饭,睡觉,走路
*我们用类式封装来实现
*但是所有成员都是公有的,任何人都能够在外部访问name,eat,sleep,walk
*/

//Person类
var Person = function(name){

//公有成员
this.name = name;

//公有方法
this.eat = function(){
alert(this.name+’ is eating sth’);
};
this.sleep = function(){
alert(this.name+’ is sleeping’);
};
this.walk = function(){
alert(this.name+’ is walking’);
};
};

var jay = new Person(’jay’);
</script>

可以通过firebug看到“jay”的成员和属性。

但这样的代码有一个问题:不安全,因为类成员在任意命名空间都可以访问到。我们需要做改进:增加私有成员和私有方法。

通常约定私有成员变量用"_"开始,比如_value表示这是一个私有变量。

<script>
/*定义一个"人"的类,人有名字,人也可以吃饭,睡觉,走路
 *针对类式封装,增加私有成员,私有方法
 *这里增加的_setNickName和_getNickName只是说明私有方法的用法,实际中可以完全省略
 */

var Person = function(name){

	//私有成员
	var _nickname = 'nothing';
	//公有成员
	this.name = name;

	//私有方法
	var _setNickName = function(nickname){
		_nickname = nickname;
	};
	var _getNickName = function(){
		return _nickname;
	};

	//公共方法
	this.eat = function(){
		alert(this.name+' is eating sth');
	};
	this.sleep = function(){
		alert(this.name+' is sleeping');
	};
	this.walk = function(){
		alert(this.name+' is walking');
	};
	this.setNickName = function(nickname){//接口
		_setNickName(nickname);
	};
	this.getNickName = function(){//接口
		return _getNickName();
	};
};

var jay = new Person('jay');
</script>

这样就可以通过Person提供的接口对私有成员进行访问。

类式封装的优点:思路很清晰,适合那些有c++或java编程经验的人。

类式封装的缺点:内存利用不科学,因为每个实例都拥有各自的成员方法,而各自的方法是一样的,我们希望每个实例都共享一个方法。而成员受运行时影响比较大,则希望每个实例的成员可以占据单独的内存。原型式封装弥补了这个缺陷,原型使得每个实例都共享一份原型方法。

2,原型式封装

<script>
/*定义一个"人"的类,人有名字,人也可以吃饭,睡觉,走路
 *
 *原型式封装,每个实例都共享一份原型,(jjb.eat == jay.eat) = true
 */

var Person = function(name){
	var _nickname = 'nothing';
	this.name = name;

	this.setNickName = function(nickname){//接口方法
		_nickname = nickname;
	};
	this.getNickName = function(){//接口方法
		return _nickname;
	};
};

//原型
Person.prototype = {
	eat:function(){
		alert(this.name+' is eating sth');
	},
	sleep:function(){
		alert(this.name+' is sleeping');
	},
	walk:function(){
		alert(this.name+' is walking');
	}
};

var jay = new Person('jay');
var jjb = new Person('jjb');
</script>

这样jjb.eat == jay.eat,说明实例的eat是到Person的prototype.eat的引用.

原型式封装的优点:内存利用合理,缺点:初学难理解。

这种编码风格要注意的:1,方法在原型中定义,成员在类中定义,2,私有变量和接口函数写在类定义中,因为接口通常使用到私有变量。

3,静态变量

在C++,JAVA和C#中有类静态变量,如何在js中实现?

<script>
/*
 * 给“人”中定义一个静态变量“人数”,这样每个“人”的实例都共享一个“人”的名为“人数”的成员
 */

var Person = (function(){

	//私有静态成员
	var numOfPersons = 0;

	return function(name){
		//公有成员
		this.name = name;
		//私有成员
		var _nickname = 'nothing';

		//接口方法
		this.setNickName = function(nickname){
			_nickname = nickname;
		};
		this.getNickName = function(){
			return _nickname;
		};
		this.setNum = function(num){
			numOfPersons = num;
		};
		this.getNum = function(){
			return numOfPersons;
		};
	};

})();

//原型
Person.prototype = {
	eat:function(){
		alert(this.name+' is eating sth');
	},
	sleep:function(){
		alert(this.name+' is sleeping');
	},
	walk:function(){
		alert(this.name+' is walking');
	}
};

var jay = new Person('jay');
var jjb = new Person('jjb');

</script>

在这个例子中,jjb.getNum() = 0;jjb.setNum(3);jay.getNum() = 3;

kingabird JavaScript

  1. kingabird
    2009年2月19日13:10 | #1

    呵呵,测试下我的头像是什么。

  1. 本文目前尚无任何 trackbacks 和 pingbacks.