1. 简介:
封装是面向对象设计的基石,封装是什么,封装有何用,这些常识性的问题在这里不做介绍。尽管JS是一种面向对象的语言,但是它不具备用以将成员声明为公用或私用的任何内置机制。与上篇讲述的接口一样,我们将自己想办法实现这种特性。这里主要利用了JS的闭包。什么是闭包,这里也不作讨论,这不是一个讨论JS语法的总结。
2.JS创建自定义对象的基本方法
通过JS创建自定义对象主要有两种方法,一种是通过字面量对象,这种方法等价于实例化一个Object对象,给实例化的对象添加各种属性和方法; 第二种是通过构造函数的形式实例化对象。以下代码展示了这两种创建对象的方法。
/*通过字面量创建对象,等价于var obj=new Object(); obj.name='xxx', obj.age=23, obj.getName=function(){return this.name;}*/ var obj = { name: 'xxx', age: '23', getName:function(){ return this.name; }, .............. }; /*通过构造函数实例化一个对象*/ function Person(name, age){ this.name = name; this.age = age; this.getName=function(){ return this.name; }; } var obj_person = new Person('xxx', 23);
通过构造函数实例化对象,很显然,非常符合面向对象的特点,且我们可以通过该方法实现封装的特性。
3. 利用闭包和构造函数实现私有成员和特权方法
假设你想定义一个Person类,这个Person包含有name, age这两个属性,同时对age字段还提供了对应的get和set操作,而name字段我们不希望有人去更改他,只提供get方法,同时为了规范, 每个私有成员的命名都应该以'_'开头,很自然的,你可以这样定义构造函数:
function Person(name, age){ this._name = name; this._age = age; this.getAge = function(){ return this.age; }; this.setAge = function(value){ if(value < 0){ throw new Error("Age of a Person cannot be a minus"); //人的年龄是不能为负数的,在这里做个简单的值检验 } this.age = value; }; this.getName = function(){ return this.name };
只需 var obj = new Person(); obj._age = -10; 为了解决这类问题,我们可以按如下代码所示使用闭包实现私有成员:
function Person(name, age){ if (age < 0) { throw new Error("Age of a Person cannot be a minus"); } //私有成员,仅内部可见,只能通过特权方法访问 var _name = name, _age = age; //get和set特权方法 this.getName = function(){ return _name; }; this.getAge = function(){ return _age; }; this.setAge = function(value){ if (value < 0) { throw new Error("Age of a Person cannot be a minus"); } _age = value; }; }
//这里使用了一个自运行函数实现闭包 var Person = (function(){ var personNumbers = 0; //静态私有成员,记录实例化个数 function _checkAge(value){ //静态私有方法,检验年龄的合法性 if (value < 0) { throw new Error("Age of a Person cannot be a minus"); } } var cstor = function(name, age){ //将返回的构造函数 _checkAge(age); //私有成员,仅内部可见,只能通过特权方法访问 var _name = name, _age = age; ++personNumbers;//增加实例化个数 //get和set特权方法 this.getName = function(){ return _name; }; this.getAge = function(){ return _age; }; this.setAge = function(value){ _checkAge(age); _age = value; }; }; cstor.getPersonNumbers = function(){ //静态公有方法,返回实例化个数 return personNumbers; }; return cstor; })();