JavaScript的public、private和privileged模式


Posted in Javascript onDecember 28, 2009

Summary
私有变量 在对象内部使用'var'关键字来声明,而且它只能被私有函数和特权方法访问。
私有函数 在对象的构造函数里声明(或者是通过var functionName=function(){...}来定义),它能被特权函数调用(包括对象的构造函数)和私有函数调用。
特权方法 通过this.methodName=function(){...}来声明而且可能被对象外部的代码调用。它可以使用:this.特权函数() 方式来调用特权函数,使用 :私有函数()方式来调用私有函数。
公共属性 通过this.variableName来定义而且在对象外部是可以读写的。不能被私有函数所调用。
公共方法 通过ClassName.prototype.methodName=function(){...}来定义而且可以从对象外部来调用。
原型属性 通过ClassName.prototype.propertyName=someValue来定义。
静态属性 通过ClassName.propertyName=someValue来定义。
另外注意下这种写法: var 函数名=function 函数名(){...} 这个函数被调用时具有特权函数和私有函数的特性。
例:

<html> 
<head> 
<title></title> 
<script type="text/javascript"> 
function Container( param ) { 
function dec(){ 
if ( secret > 0 ) { 
secret -= 1; 
setSecret( 7) 
alert( secret ); 
return true; 
} 
else { 
// alert( "over"+this.member); 
return false; 
} 
} 
// this.dec = dec; 
//this.dec = function dec (){...} different from above code. 
function setSecret( num ){ 
secret = num; 
} 
this.member = param; 
var secret = 3; 
var self = this; 
this.service = function () { 
if (dec()) { 
alert(); 
} 
else { 
return null; 
} 
} 
} 
// --------------------------------------- 
function start(){ 
alert( "Start" ) 
var test = new Container( 'liuqi' ); 
// test.setSecret( 2 ); 
test.service(); 
test.service(); 
test.service(); 
test.service(); 
var test2 = new Container( 'liuqi' ); 
//test2.service(); 
// Container.dec(); 
} 
</script> 
</head> 
<body> 
<div onclick="start()" style="color:blue">click me</div> 
</body> 
</html>

JavaScript是世界上最被误解的编程语言。有人认为它缺少信息隐藏的特性,因为JavaScript对象不能拥有私有变量的方法。
但是这是个误解。JavaScript对象可以拥有私有成员。
对象
JavaScript从根本上就是关于对象的。数组是对象,方法是对象,Object也是对象。什么是对象?对象就是键值对的集合。键是字符串,
值可以是字符串,数字,布尔和对象(包括数组和方法)。对象通常被实现为Hashtable,这样值就可以被快速获取。
如果值是一个函数,我可以称其为方法。当对象的方法被调用时,“this”变量则被赋予该对象。方法可以通过“this”变量访问实例
变量。
对象可以由初始化对象的方法 -- 构造函数产生。构造函数提供在其他编程语言中类提供的特性,包括静态变量和方法。
Public
对象的成员都是public成员。任何对象都可以访问,修改,删除这些成员或添加新成员。主要有两种方式来在一个新对象里放置成员:
在构造函数里
这种技术通常用来初始化public实例变量。构造函数的“this”变量用来给对象添加成员。
Java代码
functin Container(param) { 
this.member = param; 
} 
functin Container(param) { 
this.member = param; 
}

这样,如果我们构造一个新对象var myContainer = new Container('abc'),则myContainer.member为'abc'。
在prototype里
这种技术通常用来添加public方法。当寻找一个成员并且它不在对象本身里时,则从对象的构造函数的prototype成员里找。
prototype机制用来做继承。为了添加一个方法到构造函数创建的所有对象里,只需添加到构造函数的prototype:
Java代码
Container.prototype.stamp = function (string) { 
return this.member + string; 
} 
Container.prototype.stamp = function (string) { 
return this.member + string; 
}

这样,我们可以调用该方法myContainer.stamp('def'),结果为'abcdef'。
Private
private成员由构造函数产生。普通的var变量和构造函数的参数都称为private成员。
Java代码
function Container(param) { 
this.member = param; 
var secret = 3; 
var that = this; 
} 
function Container(param) { 
this.member = param; 
var secret = 3; 
var that = this; 
}

该构造函数创建了3个private实例变量: param,secret和that。它们被添加到对象中,但是不能被外部访问,也不能被该对象自己的
public方法访问。它们只能由private方法访问。private方法是构造函数的内部方法。
Java代码
function Container(param) { 
function dec() { 
if (secret > 0) { 
secret -= 1; 
return true; 
} else { 
return false; 
} 
} 
this.member = param; 
var secret = 3; 
var that = this; 
} 
function Container(param) { 
function dec() { 
if (secret > 0) { 
secret -= 1; 
return true; 
} else { 
return false; 
} 
} 
this.member = param; 
var secret = 3; 
var that = this; 
}

private方法dec检查secret实例变量。如果它大于0,则减少secret并返回true,否则返回false。它可以用来让这个对象限制用3次。
按照惯例,我们定义一个private的that变量。这用来让private方法可以使用本对象。这样做是因为ECMAScript语言规范有一个错误,
该错误导致不能正确的设置this给内部方法。
private方法不能被public方法调用。为了让private方法有用,我们需要引入privileged方法。
Privileged
privileged方法可以访问private变量和方法,并且它本身可以被public方法和外界访问。可以删除或替代privileged方法,但是不能
更改它或强制它泄露自己的秘密。
privileged方法在构造函数里用this分配。
Java代码
function Container(param) { 
function dec() { 
if (secret > 0) { 
secret -= 1; 
return true; 
} else { 
return false; 
} 
} 
this.member = param; 
var secret = 3; 
var that = this; 
this.service = function() { 
if (dec()) { 
return that.member; 
} else { 
return null; 
} 
}; 
} 
function Container(param) { 
function dec() { 
if (secret > 0) { 
secret -= 1; 
return true; 
} else { 
return false; 
} 
} 
this.member = param; 
var secret = 3; 
var that = this; 
this.service = function() { 
if (dec()) { 
return that.member; 
} else { 
return null; 
} 
}; 
}

service是privileged方法。前三次调用myContainer.service()将返回'abc'。之后,它将返回null。service调用private的dec方法,
dec方法访问private的secret变量。service对其他对象和方法可见,但是它不允许直接访问private变量。
闭包
由于JavaScript有闭包,public,private和privileged成员的模式是可行的。这意味着一个内部方法始终可以访问它的外部方法的
var变量和参数,甚至在外部方法返回之后。这是JavaScript语言的一个非常强大的特性。当前没有展示如何发掘这种特性的JavaScript
编程书籍,大多数甚至都没提到。
private和privileged成员只能在对象被构造时产生。public成员则可以在任何时候添加。
模式
public
Java代码
function Constructor(...) { 
this.membername = value; 
} 
Constructor.prototype.membername = value; 
function Constructor(...) { 
this.membername = value; 
} 
Constructor.prototype.membername = value;

Private
Java代码
function Constructor(...) { 
var that = this; 
var membername = value; 
function membername(...) {...} 
} 
// 注意: function语句 
// function membername(...) {...} 
// 是如下代码的简写 
// var membername = function membername(...) {...}; 
function Constructor(...) { 
var that = this; 
var membername = value; 
function membername(...) {...} 
} 
// 注意: function语句 
// function membername(...) {...} 
// 是如下代码的简写 
// var membername = function membername(...) {...};

Privileged
Java代码
function Constructor(...) { 
this.membername = function (...) {...}; 
} 
function Constructor(...) { 
this.membername = function (...) {...}; 
}

译者注:我认为可以简单的把privileged方法简单的看成是构造函数里的public方法,因为privileged方法可以被外界和public方法访问,
而它自身又可以访问private变量。
Javascript 相关文章推荐
js 加载时自动调整图片大小
May 28 Javascript
javascript游戏开发之《三国志曹操传》零部件开发(一)让静态人物动起来
Jan 23 Javascript
jQuery点击tr实现checkbox选中的方法
Mar 19 Javascript
javascript校验价格合法性实例(必须输入2位小数)
May 05 Javascript
Node.js 制作实时多人游戏框架
Jan 08 Javascript
js+html5通过canvas指定开始和结束点绘制线条的方法
Jun 05 Javascript
JavaScript基本语法学习教程
Jan 14 Javascript
关于function类中定义变量this的简单说明
May 28 Javascript
Javascript基础_简单比较undefined和null 值
Jun 14 Javascript
有趣的bootstrap走动进度条
Dec 01 Javascript
Layui 导航默认展开和菜单栏选中高亮设置的方法
Sep 04 Javascript
JQuery绑定事件四种实现方法解析
Dec 02 jQuery
Javascript 面向对象特性
Dec 28 #Javascript
extJs 常用到的增,删,改,查操作代码
Dec 28 #Javascript
firefox和IE系列的相关区别整理 以备后用
Dec 28 #Javascript
javascript 显示当前系统时间代码
Dec 28 #Javascript
javascript 鼠标悬浮图片显示原图 移出鼠标后原图消失(多图)
Dec 28 #Javascript
javascript options属性集合操作代码
Dec 28 #Javascript
javascript 动态调整图片尺寸实现代码
Dec 28 #Javascript
You might like
PHP中extract()函数的妙用分析
2012/07/11 PHP
PHP文件读写操作相关函数总结
2014/11/18 PHP
Yii2 rbac权限控制之rule教程详解
2016/06/23 PHP
用Jquery.load载入页面后样式没了页面混乱的解决方法
2014/10/20 Javascript
javascript使用正则表达式检测IP地址
2014/12/03 Javascript
js实现鼠标经过时图片滚动停止的方法
2015/02/16 Javascript
浅析javascript中的DOM
2015/03/01 Javascript
JS模拟酷狗音乐播放器收缩折叠关闭效果代码
2015/10/29 Javascript
Javascript中arguments对象的详解与使用方法
2016/10/04 Javascript
原生js获取浏览器窗口及元素宽高常用方法集合
2017/01/18 Javascript
微信小程序中的onLoad详解及简单实例
2017/04/05 Javascript
Vue2.0 事件的广播与接收(观察者模式)
2018/03/14 Javascript
ES6 如何改变JS内置行为的代理与反射
2019/02/11 Javascript
原生JS与JQ获取元素的区别详解
2020/02/13 Javascript
Vue常用API、高级API的相关总结
2021/02/02 Vue.js
k8s node节点重新加入master集群的实现
2021/02/22 Javascript
[54:09]RNG vs Liquid 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.23
2019/09/05 DOTA
python 字典(dict)遍历的四种方法性能测试报告
2014/06/25 Python
Python处理文本文件中控制字符的方法
2017/02/07 Python
对numpy的array和python中自带的list之间相互转化详解
2018/04/13 Python
python实现俄罗斯方块游戏
2020/03/25 Python
详解Django的CSRF认证实现
2018/10/09 Python
python3正则提取字符串里的中文实例
2019/01/31 Python
Python3调用百度AI识别图片中的文字功能示例【测试可用】
2019/03/13 Python
区分python中的进程与线程
2020/08/13 Python
Windows环境下Python3.6.8 importError: DLLload failed:找不到指定的模块
2020/11/01 Python
HTML5本地存储localStorage、sessionStorage基本用法、遍历操作、异常处理等
2014/05/08 HTML / CSS
美国家居装饰店:Z Gallerie
2020/12/28 全球购物
大学新生军训自我鉴定
2014/03/18 职场文书
2014年教育教学工作总结
2014/11/13 职场文书
婚庆开业庆典主持词
2015/06/30 职场文书
客户答谢会致辞
2015/07/30 职场文书
年会邀请函的格式及范文五篇
2019/11/02 职场文书
PHP实现rar解压读取扩展包小结
2021/06/03 PHP
Python实现Matplotlib,Seaborn动态数据图
2022/05/06 Python
win10电脑老是死机怎么办?win10系统老是死机的解决方法
2022/08/05 数码科技