JavaScript中的私有成员


Posted in Javascript onSeptember 18, 2006

JavaScript是世界上是被误解得最厉害的编程语言。有些人认为它不具备“信息隐藏”的能力,因为JavaScript的对象没有私有变量和方法。这是误解。JavaScript对象可以拥有私有成员,下面我们来看看怎么做。(SharkUI.com注:JavaScript并不是真正拥有私有、公有等等OOP的特性,这篇译文中提到的这些私有、公有、特权等特性,是利用JavaScript的其他特性(参看本文的“闭包”一节)“模拟”出来的。感兴趣的话可以搜索相关的文章来看,当然也可以不管这些,就当它是真正的OOP来用。Have fun!)

对象

JavaScript是建立在对象之上的。数组(Array)是对象,函数(Function)是对象,对象(Objects)当然也是对象。那什么是对象呢?对象是一组“名称:值”对(name-value pair)的集合。名称是字符串,值却可以是字符串、数值、布尔或对象(包括数组和函数)。对象通常是用哈希表来实现的,以便可以快速地取值。

如果值是一个函数,我们就可以把它当作一个“方法”。当对象的一个方法被执行,变量this就被设为对象本身。如此,方法就可以通过this变量来访问对象的实例。

对象可以通过“构造器(constructor)”来创建。构造器是一个拥有初始化对象的函数。构造器提供了类似其他语言中的“类(class)”所提供的特性和功能,包括静态变量和方法。

公有

对象的所有成员都是公有成员。任何函数都可以访问、修改或者删除这些成员,当然也可以添加新的成员。给对象添加成员的两种主要方法:

通过构造器

这种方法一般用来初始化对象实例的公有变量。构造器的this变量被用来给对象添加成员:

function Container(param) {
  this.member = param;
}

构造一个新的对象:

var myContainer = new Container('abc');

然后,公有变量 myContainer.member 就拥有了值 'abc'。

通过原型(prototype)

这种方法通常用来添加公有方法。在对象本身搜寻一个成员但没有找到时,就使用构造器的原型(prototype)成员。这种原型机制实现了面向对象所谓的 “继承(inheritance)”,同时也节省了内存。给创建自同一个构造器的所有的对象加上一个方法,只需要给构造器的prototype增加一个函数:

Container.prototype.stamp = function (string) {
  return this.member + string;
}

然后我们就可以调用这个方法:

myContainer.stamp('def')

返回'abcdef'。

私有

私有(Private)成员是由构造器创建的。通常构造器中用var声明的变量和函数参数成为私有成员。

function Container(param) {
  this.member = param;
  var secret = 3;
  var self = this;
}

这个构造器创建了三个私有的实例变量:param,secret和self。

function Container(param) {
  function dec() {
   if (secret > 0) {
     secret -= 1;
     return true;
   } else {
     return false;
   }
  }

  this.member = param;
  var secret = 3;
  var self = this;
}

私有方法dec会检查实例变量secret,如果它大于0,自减1并返回true;如果它小于0,返回false。这样就实现了由这个架造器所创建对象的dec函数只能用三次的功能。

按惯例,我们创建了一个私有变量self。私有方法可以通过它来访问到对象本身。但这只是一种权宜之计,因为《ECMAScript Language Specification》中有一个错误,使得内部函数的this变量被设置成一个错误值。

公有方法(SharkUI.com注:即上文说的通过prototype创建的方法)是无法调用私有方法的,所以为了能使用私有方法,我们需要引入特权方法(privileged method)。

特权

一个特权方法可以访问私有变量和方法,而它本身可以被公有方法和外界访问。你可以删除或替换一个特权方法,但不能修改它,也不能强制它放弃自己的密秘(SharkUI.com注:原文如此,可能是指它的特权,关于这点请高手指教)。

特权方法是在构造器内部通过this来创建的。

function Container(param) {
  function dec() {
   if (secret > 0) {
     secret -= 1;
     return true;
   } else {
     return false;
   }
  }

  this.member = param;
  var secret = 3;
  var self = this;

  this.service = function () {
   if (dec()) {
     return self.member;
   } else {
     return null;
   }
  };
}

service是一个特权方法。前三次调用myContainer.service()将返回'abc',之后将返回null。service通过调用私有方法dec来访问私有变量secret。对于其他对象和方法来说,可以访问到service,但不能直接访问到私有的成员。

闭包

这种公有、私有和特权成员模式的存在是由于JavaScript的内在机制:闭包。这意味着一个内部函数永远可以访问它外部函数的变量和参数,即使外部函数已经返回。这是JavaScript语言非常强大的一个特性。目前还没有关于JavaScript编程的书籍展示了如何来利用它,它们甚至都没有提到这一点。

私有和特权成员只能在对象初始化的时候创建,而公有成员可以被随时添加进来。

模式

公有
function Constructor(...) {
  this.membername = value;
}
Constructor.prototype.membername = value;
私有
function Constructor(...) {
  var self = this;
  var membername = value;
  function membername(...) {...}
}

注:这句代码:

function membername(...) {...}

事实上是以下代码的简略写法

var membername = function membername(...) {...};
特权
function Constructor(...) {
  this.membername = function (...) {...};
}

后记

Douglas Crockford的这篇文章为我们写出更优美的JavaSciprt程序奠定了基础,为我们创建出更合理的面向对象应用和框架带来了可能。在这篇译文快要完成的时候,惊诧的发现作者网站上出现了一个本文中文版的链接。好事!有越来越多的中国人开始关注这些“边边角角”的技术。虽然做了重复工作,但一样希望各位能从这篇文章中有所收益。也希望有更多的人能投入到原创和翻译前端技术文章中来,在多数人浮躁的时候,我们需要更多基础性的工作。一周一篇不多,一年一篇不少,只要开始了就行!

Javascript 相关文章推荐
用于判断用户注册时,密码强度的JS代码
Jan 01 Javascript
javascript 一些用法小结
Sep 11 Javascript
jQuery 翻牌或百叶窗效果(内容三秒自动切换)
Jun 14 Javascript
JQuery之focus函数使用介绍
Aug 20 Javascript
jquery快捷动态绑定键盘事件的操作函数代码
Oct 17 Javascript
JavaScript 判断用户输入的邮箱及手机格式是否正确
Dec 08 Javascript
javascript实现简单的进度条
Jul 02 Javascript
js实现的万能flv网页播放器代码
Apr 30 Javascript
温习Javascript基础语法之词法结构
May 31 Javascript
jQuery插件 Jqplot图表实例
Jun 18 Javascript
微信小程序左滑删除效果的实现代码
Feb 20 Javascript
微信公众平台 客服接口发消息的实现代码(Java接口开发)
Apr 17 Javascript
javascript的事件描述
Sep 08 #Javascript
由浅到深了解JavaScript类
Sep 08 #Javascript
js常用函数 不错
Sep 08 #Javascript
Javascript 不能释放内存.
Sep 07 #Javascript
一些有关检查数据的JS代码
Sep 07 #Javascript
Mozilla中显示textarea中选择的文字
Sep 07 #Javascript
showModelessDialog()使用详解
Sep 07 #Javascript
You might like
PHP_MySQL教程-第一天
2007/03/18 PHP
php设计模式 Composite (组合模式)
2011/06/26 PHP
PHP获取当前日期所在星期(月份)的开始日期与结束日期(实现代码)
2013/06/18 PHP
一个简单的JavaScript 日期计算算法
2009/09/11 Javascript
30个最佳jQuery Lightbox效果插件分享
2011/04/11 Javascript
jQuery学习笔记 操作jQuery对象 文档处理
2012/09/19 Javascript
详解js跨域原理以及2种解决方案
2015/12/09 Javascript
详解Javascript模板引擎mustache.js
2016/01/20 Javascript
JS使用onerror捕获异常示例
2016/08/03 Javascript
微信小程序 触控事件详细介绍
2016/10/17 Javascript
基于Node.js + WebSocket打造即时聊天程序嗨聊
2016/11/29 Javascript
关于BootStrap modal 在IOS9中不能弹出的解决方法(IOS 9 bootstrap modal ios 9 noticework)
2016/12/14 Javascript
Vue2.0实现将页面中表格数据导出excel的实例
2017/08/09 Javascript
详解Webpack+Babel+React开发环境的搭建的方法步骤
2018/01/09 Javascript
利用js实现简易红绿灯
2020/10/15 Javascript
[02:03]《现实生活中的DOTA2》—林书豪&DOTA2职业选手出演短片
2015/08/18 DOTA
Python中的startswith和endswith函数使用实例
2014/08/25 Python
在Django中管理Users和Permissions以及Groups的方法
2015/07/23 Python
Python+树莓派+YOLO打造一款人工智能照相机
2018/01/02 Python
pycharm 将django中多个app放到同个文件夹apps的处理方法
2018/05/30 Python
通过实例了解Python str()和repr()的区别
2020/01/17 Python
django restframework serializer 增加自定义字段操作
2020/07/15 Python
Superdry极度干燥美国官网:英国制造的服装品牌
2018/11/13 全球购物
罗技美国官网:Logitech美国
2020/01/22 全球购物
New Balance比利时官方网站:购买鞋子和服装
2021/01/15 全球购物
4s店机修工岗位职责
2013/12/20 职场文书
竞聘书格式及范文
2014/03/31 职场文书
2014最新开业庆典策划方案(5篇)
2014/09/15 职场文书
卖车协议书范本4篇
2014/10/01 职场文书
2015年上半年信访工作总结
2015/03/30 职场文书
教师节领导致辞
2015/07/29 职场文书
2015国庆节放假通知范文
2015/07/30 职场文书
幼儿园保育员随笔
2015/08/14 职场文书
Mysql中一千万条数据怎么快速查询
2021/12/06 MySQL
Shell脚本一键安装Nginx服务自定义Nginx版本
2022/03/20 Servers
Python内置包对JSON文件数据进行编码和解码
2022/04/12 Python