现在的位置: 首页 > 综合 > 正文

[updated]JavaScript中的私有成员

2018年07月05日 ⁄ 综合 ⁄ 共 7494字 ⁄ 字号 评论关闭
文章目录

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


抱歉!评论已关闭.