[updated]JavaScript中的私有成员

翻译 2006年05月19日 15:08:00

Private Members in JavaScript



JavaScript中的私有成员


Douglas Crockford
www.crockford.com

 翻译:袁晓辉(blog.csdn.net/uoyevoli/


JavaScript is the world's most misunderstood programming language. Some believe that it lacks the property of information hiding because objects cannot have private instance variables and methods. But this is a misunderstanding. JavaScript objects can have private members. Here's how.

JavaScript世界上误解最深的语言。有人认为它缺少信息隐藏的能力,理由是它的对象不能拥有私有(private)的变量和方法。但是这是一种误解。JavaScript对象也有私有成员。方法就在这里。




Objects

对象

JavaScript is fundamentally about objects. Arrays are objects. Functions are objects. Objects are objects. So what are objects? Objects are collections of name-value pairs. The names are strings, and the values are strings, numbers, booleans, and objects (including arrays and functions). Objects are usually implemented as hashtables so values can be retrieved quickly.

JavaScript是植根于对象的。数组是对象,函数是对象,对象是对象。那么究竟什么是对象呢?对象就是一个集合,其中包含“名称-值”的映射。名称是字符串,值可以是字符串,数字,逻辑值或对象(包括数组和函数)。对象通常用哈希表来实现,以便能快速获得值。


If a value is a function, we can consider it a method. When a method of an object is invoked, the this variable is set to the object. The method can then access the instance variables through the this variable.

如果一个“值‘是函数,我们叫它方法,当一个对象的方法被调用时, 这个对象就被赋值给this 变量。这样方法就可以通过this来访问对象实例的变量了。


Objects can be produced by constructors, which are functions which initialize objects. Constructors provide the features that classes provide in other languages, including static variables and methods.

对象可以由构造函数产生,构造函数是用来初始化对象的函数。构造函数在这里扮演了其他语言中“类”扮演的角色,也提供了定义static变量和方法的手段。




Public

公开

The members of an object are all public members. Any function can access, modify, or delete those members, or add new members. There are two main ways of putting members in a new object:

对象的所有成员都是公开(public)成员。任何函数都可以访问、修改和删除这些成员或添加新成员。向一个新的对象中添加成员主要有两种方式:


In the constructor

在构造函数中

This technique is usually used to initialize public instance variables. The constructor's this variable is used to add members to the object.

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

So, if we construct a new object

var myContainer = new Container('abc');

then myContainer.member contains 'abc'.

这种技术通常用来初始化公开(public)的实例变量。构造函数使用this变量来向对象中添加成员。

function Container(param) {
this.member = param;
}
如果我们构造了一个新的对象
var myContainer = new Container('abc');
那么myContainer.member 将包含 'abc'


In the prototype

在原型(prototype)中

This technique is usually used to add public methods. When a member is sought and it isn't found in the object itself, then it is taken from the object's constructor's prototype member. The prototype mechanism is used for inheritance. It also conserves memory. To add a method to all objects made by a constructor, add a function to the constructor's prototype:

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

So, we can invoke the method

myContainer.stamp('def')

which produces 'abcdef'.

这种技术通常用来添加公开(public)方法。当(JavaScript解释器)遇到一个对象的成员,发现它在对象自身中并不存在时,就会到对象构造函数的prototype中去找。这种prototype机制可以用来实现继承。它同样占用内存。如果想要给某个构造函数生成的所有对象都添加一个方 法,只要给构造函数的prototype添加这个方法就可以了。

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

我们调用这个方法
myContainer.stamp('def')
将返回'abcdef'。



Private

私有

Private members are made by the constructor. Ordinary vars and parameters of the constructor becomes the private members.

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

私有(Private)成员是由构造函数生成的。普通的(var定义的)变量和参构造函数的参数会成为私有(private)成员。

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


This constructor makes three private instance variables: param, secret, and self. They are attached to the object, but they are not accessible to the outside, nor are they accessible to the object's own public methods. They are accessible to private methods. Private methods are inner functions of the constructor.

function Container(param) {

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

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

这个构造函数产生了三个私有(private)实例变量:param,secret和self。它们是属于对象的,但是它们对外部是不可见的,对这个对象自身的公开(public)方法也是不可见的。它们对私有(private)方法可见。私有法是构造函数的内部函数。

function Container(param) {

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

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


The private method dec examines the secret instance variable. If it is greater than zero, it decrements secret and returns true. Otherwise it returns false. It can be used to make this object limited to three uses.

私有(private)方法 dec 检查实例变量 secret 的值,如果它大于0就减少它的值然后返回true;否则它返回false。它可以用于限制这个对象只能被使用3次。


By convention, we make a private self parameter. This is used to make the object available to the private methods. This is a workaround for an error in the ECMAScript Language Specification which causes this to be set incorrectly for inner functions.

根据惯例,我们生成了一个私有(private)的 self 变量,用于让私有(private)方法可以访问对象本身。这是一个变通的解决方案,需要它的根本原因在于ECMAScript语言规范的一个错误,而这个错误导致内部函数的this变量有错误。(译者注:真的是这样吗?根据我的试验好像不需要这个self变量)


Private methods cannot be called by public methods. To make private methods useful, we need to introduce a privileged method.

私有(private)方法不能被公开(public)方法调用。为了让私有函数有作用,我们需要引入特权(privileged)方法的概念。




Privileged

特权

A privileged method is able to access the private variables and methods, and is itself accessible to the public methods and the outside. It is possible to delete or replace a privileged method, but it is not possible to alter it, or to force it to give up its secrets.

一个特权(privileged)方法可以访问私有(private)变量和方法,并且它本身可以被公开(public)方法和外部访问。可以删除或替换一个特权方法但是不能改变它或强迫它放弃自己的秘密。


Privileged methods are assigned with this within the constructor.

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()) {
    //译者注:根据我的试验
    //这里使用 this.member 也是可以的
return self.member;
} else {
return null;
}
};
}

特权方法是在构造函数通过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 is a privileged method. Calling myContainer.service() will return 'abc' the first three times it is called. After that, it will return null. service calls the private dec method which accesses the private secret variable. service is available to other objects and methods, but it does not allow direct access to the private members.

service是一个特权方法。前三次调用myContainer.service()将返回'abc',之后它将返回null。service调用private的dec方法,dec方法访问private的secret变量。service对其他对象和函数都是可见的,但是它不允许直接访问private成员。



译者注:

这个有必要吗?根据我的试验(IE6和FF1.5.0.3)都可以正常以下代码:

    function Container(param) {

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

        this.service = function () {
            if (secret > 0) {
                secret -= 1;
                return this.member;
            } else {
                return null;
            }
        };
    }



Closures

闭包

This pattern of public, private, and privileged members is possible because JavaScript has closures. What this means is that an inner function always has access to the vars and parameters of its outer function, even after the outer function has returned. This is an extremely powerful property of the language. There is no book currently available on JavaScript programming that shows how to exploit it. Most don't even mention it.

这种模式的公开(public),私有(private)和特权(privileged)之所以成为可能是因为JavaScript有闭包closures)。闭包的意思是:一个内部函数总是可以访问它外层函数的变量和参数,即使外层函数已经返回。这是JavaScript的一个极其强大的特性。目前还没有如何一本JavaScript编程的书讲到如何利用它,其实大多没用提到它。


Private and privileged members can only be made when an object is constructed. Public members can be added at any time.

私有(private)和特权(privileged)成员只能在对象被构造时生成。公开(public)成员可以在任何时间添加。




Patterns

模式

Public

function Constructor(...) {
this.membername = value;

}
Constructor.prototype.membername = value;

Private

function Constructor(...) {
var self = this;
var
membername = value;

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

}

Note: The function statement

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

is shorthand for

var membername = function membername(...) {...};


注意:

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

是下列语句的简略形式:

var membername = function membername(...) {...};



Privileged

function Constructor(...) {
this.membername = function (...) {...};

}

Copyright 2001 Douglas Crockford. All Rights Reserved Wrrrldwide.


版权所有


<完>

原文链接:http://www.crockford.com/javascript/private.html
袁晓辉 翻译 @ 2006-5-19


相关文章推荐

《JavaScript高级程序设计 第三版》学习笔记 (八)块作用域及私有成员

一、模仿块级作用域 1.js不像C和java一样有块级作用域。在C和java中,一对大括号{}决定一个作用域,比如for循环。在js中,变量可以在函数任何一处定义,并且忽略重复定义。变量初始化之前使...

JavaScript中的私有成员

JavaScript 是世界上最被误解的语言。很多人认为它缺乏信息隐藏的特性所以对象不能有私有实例变量和方法。但这是一个误解。JavaScript对象同样可以拥有私有变量。下面就讲解一下

Private Members In JavaScript(javascript的私有成员)——翻译

翻译大半,发现有人翻译过了,而且翻译地还比较好。但是还是硬着头皮翻下去了,并参考他的做了修改,就作为我翻译e文的第一次吧。 原文:http://javascript.crockford.co...

javascript 创建私有成员和静态私有成员

私有方法和属性在javascript中,因为没有类的概念,所以只能通过构造函数来模拟类,假设现在需要写一个手机类,这个手机需要传入一张电话号码,然后能打电话。最简单的方式是var Phone= fun...

【C++】Accessor and Mutator Functions & 函数形参与类私有成员重名的解决方法

Accessor and Mutator functions. 函数形参与类私有成员重名时的解决方法
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)