2007-07-21
JavaScript的public、private和privileged模式
关键字: JavaScript public private privileged
JavaScript的public、private和privileged模式
原文:Private Members in JavaScript
JavaScript是世界上最被误解的编程语言。有人认为它缺少信息隐藏的特性,因为JavaScript对象不能拥有私有变量的方法。
但是这是个误解。JavaScript对象可以拥有私有成员。
对象
JavaScript从根本上就是关于对象的。数组是对象,方法是对象,Object也是对象。什么是对象?对象就是键值对的集合。键是字符串,
值可以是字符串,数字,布尔和对象(包括数组和方法)。对象通常被实现为Hashtable,这样值就可以被快速获取。
如果值是一个函数,我可以称其为方法。当对象的方法被调用时,“this”变量则被赋予该对象。方法可以通过“this”变量访问实例
变量。
对象可以由初始化对象的方法 -- 构造函数产生。构造函数提供在其他编程语言中类提供的特性,包括静态变量和方法。
Public
对象的成员都是public成员。任何对象都可以访问,修改,删除这些成员或添加新成员。主要有两种方式来在一个新对象里放置成员:
在构造函数里
这种技术通常用来初始化public实例变量。构造函数的“this”变量用来给对象添加成员。
这样,如果我们构造一个新对象var myContainer = new Container('abc'),则myContainer.member为'abc'。
在prototype里
这种技术通常用来添加public方法。当寻找一个成员并且它不在对象本身里时,则从对象的构造函数的prototype成员里找。
prototype机制用来做继承。为了添加一个方法到构造函数创建的所有对象里,只需添加到构造函数的prototype:
这样,我们可以调用该方法myContainer.stamp('def'),结果为'abcdef'。
Private
private成员由构造函数产生。普通的var变量和构造函数的参数都称为private成员。
该构造函数创建了3个private实例变量: param,secret和that。它们被添加到对象中,但是不能被外部访问,也不能被该对象自己的
public方法访问。它们只能由private方法访问。private方法是构造函数的内部方法。
private方法dec检查secret实例变量。如果它大于0,则减少secret并返回true,否则返回false。它可以用来让这个对象限制用3次。
按照惯例,我们定义一个private的that变量。这用来让private方法可以使用本对象。这样做是因为ECMAScript语言规范有一个错误,
该错误导致不能正确的设置this给内部方法。
private方法不能被public方法调用。为了让private方法有用,我们需要引入privileged方法。
Privileged
privileged方法可以访问private变量和方法,并且它本身可以被public方法和外界访问。可以删除或替代privileged方法,但是不能
更改它或强制它泄露自己的秘密。
privileged方法在构造函数里用this分配。
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
Private
Privileged
译者注:我认为可以简单的把privileged方法简单的看成是构造函数里的public方法,因为privileged方法可以被外界和public方法访问,
而它自身又可以访问private变量。
原文:Private Members in JavaScript
JavaScript是世界上最被误解的编程语言。有人认为它缺少信息隐藏的特性,因为JavaScript对象不能拥有私有变量的方法。
但是这是个误解。JavaScript对象可以拥有私有成员。
对象
JavaScript从根本上就是关于对象的。数组是对象,方法是对象,Object也是对象。什么是对象?对象就是键值对的集合。键是字符串,
值可以是字符串,数字,布尔和对象(包括数组和方法)。对象通常被实现为Hashtable,这样值就可以被快速获取。
如果值是一个函数,我可以称其为方法。当对象的方法被调用时,“this”变量则被赋予该对象。方法可以通过“this”变量访问实例
变量。
对象可以由初始化对象的方法 -- 构造函数产生。构造函数提供在其他编程语言中类提供的特性,包括静态变量和方法。
Public
对象的成员都是public成员。任何对象都可以访问,修改,删除这些成员或添加新成员。主要有两种方式来在一个新对象里放置成员:
在构造函数里
这种技术通常用来初始化public实例变量。构造函数的“this”变量用来给对象添加成员。
functin Container(param) {
this.member = param;
}
这样,如果我们构造一个新对象var myContainer = new Container('abc'),则myContainer.member为'abc'。
在prototype里
这种技术通常用来添加public方法。当寻找一个成员并且它不在对象本身里时,则从对象的构造函数的prototype成员里找。
prototype机制用来做继承。为了添加一个方法到构造函数创建的所有对象里,只需添加到构造函数的prototype:
Container.prototype.stamp = function (string) {
return this.member + string;
}
这样,我们可以调用该方法myContainer.stamp('def'),结果为'abcdef'。
Private
private成员由构造函数产生。普通的var变量和构造函数的参数都称为private成员。
function Container(param) {
this.member = param;
var secret = 3;
var that = this;
}
该构造函数创建了3个private实例变量: param,secret和that。它们被添加到对象中,但是不能被外部访问,也不能被该对象自己的
public方法访问。它们只能由private方法访问。private方法是构造函数的内部方法。
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分配。
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
function Constructor(...) {
this.membername = value;
}
Constructor.prototype.membername = value;
Private
function Constructor(...) {
var that = this;
var membername = value;
function membername(...) {...}
}
// 注意: function语句
// function membername(...) {...}
// 是如下代码的简写
// var membername = function membername(...) {...};
Privileged
function Constructor(...) {
this.membername = function (...) {...};
}
译者注:我认为可以简单的把privileged方法简单的看成是构造函数里的public方法,因为privileged方法可以被外界和public方法访问,
而它自身又可以访问private变量。
- 03:05
- 浏览 (1537)
- 论坛浏览 (1519)
- 评论 (3)
- 分类: Ajax/RIA
- 相关推荐
评论
andot 写道
closure 有一点好处比用 _ 开头的 this.xxx 强,就是你用 JSA 压缩时,它的名字可以被混淆,哈哈。
_开始的也可以压缩,例如dean的压缩器,当然前提是约定_开始的是内部变量,外部是不会访问之的。
老文一篇。不过我一向不太赞同DC直接用public/private的说法。因为实际上与oo的public/private不同,只是效果接近。
但是有好些微妙的区别。
例如正如你所说的,privileged方法才能访问所谓private变量。没有明确指出的事实就是,通过prototype附加的public方法却不能访问private变量。
所以比较严谨的说法,还是:通过closure可以进行信息隐藏。
实际上,多数时候,我们没有必要用构造函数来强制进行隐藏,而可以基于命名约定,所有_开头的,作为private成员,而不允许在外部访问。这就已经足够了。
这有两方面的考虑,第一,如果有人不想遵守约定,或者想搞点破坏,它总能得手的,因为通常的js,没有提供seal的功能,所以任何部分都可以修改。第二,就算其他oo语言,private不可访问通常是编译器保证的,但是有自省机制的,许多情况下仍然可以绕过。
最后,this.xxx比closure包起来的xxx,其访问效率要高一点点。
所以,没有特殊考量的情况下,我建议不要仅仅为了隐藏信息而过分使用closure。
但是有好些微妙的区别。
例如正如你所说的,privileged方法才能访问所谓private变量。没有明确指出的事实就是,通过prototype附加的public方法却不能访问private变量。
所以比较严谨的说法,还是:通过closure可以进行信息隐藏。
实际上,多数时候,我们没有必要用构造函数来强制进行隐藏,而可以基于命名约定,所有_开头的,作为private成员,而不允许在外部访问。这就已经足够了。
这有两方面的考虑,第一,如果有人不想遵守约定,或者想搞点破坏,它总能得手的,因为通常的js,没有提供seal的功能,所以任何部分都可以修改。第二,就算其他oo语言,private不可访问通常是编译器保证的,但是有自省机制的,许多情况下仍然可以绕过。
最后,this.xxx比closure包起来的xxx,其访问效率要高一点点。
所以,没有特殊考量的情况下,我建议不要仅仅为了隐藏信息而过分使用closure。
发表评论
该博客是同时发布到论坛的,无法评论在论坛已被锁定的帖子
- 浏览: 723187 次
- 性别:

- 来自: BJ

- 详细资料
搜索本博客
我的相册
screenshot
共 1 张
共 1 张
最近加入圈子
最新评论
-
Why OO sucks
看成去QQ SUCK 了
-- by xhanxhanxhan -
Rails的富文本编辑器插件 ...
有没有那个像textmate那种语法高亮的富文本编辑器?
-- by zllicho -
翻译www.djangobook.com之 ...
weiertzw 写道 1. >>> from django. ...
-- by chenjihua75 -
PHP、CakePHP哪凉快哪呆 ...
这孩子被java毒害太深。。。跳出java,你会发现外面的世界真的很大。
-- by woodless -
学习svn命令
只会用 apt-get 不是好孩子。
-- by smartly






评论排行榜