`
ruilin215
  • 浏览: 1149123 次
  • 性别: Icon_minigender_2
  • 来自: 成都
文章分类
社区版块
存档分类
最新评论

[updated]JavaScript中的私有成员

阅读更多

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 设计模式.docx

    本文简要介绍了JavaScript中几种常见的设计模式,包括闭包和封装的基本概念及其在实际编程中的应用。通过上述示例,我们可以看到设计模式不仅能够帮助我们编写出结构清晰、易于维护的代码,还能提高代码的复用性和...

    vue,以及前端面试题

    JavaScript中的原型链是通过`__proto__`属性或`Object.getPrototypeOf()`方法建立的。每个对象都有一个原型,可以指向另一个对象,形成链式结构,从而实现了继承。 5. **内存泄漏**: 当不再需要的变量、对象占用...

    经典vue面试题及答案

    组件已渲染到DOM中)、`beforeUpdate`(数据更新前,但视图未更新)、`updated`(数据更新后,DOM已更新)、`beforeDestroy`(实例销毁前)和`destroyed`(实例销毁后)。这些生命周期钩子在开发中常用于初始化数据...

    npm组件源码.zip

    6. **生命周期钩子**:Vue组件有自己的生命周期,如`created`、`mounted`、`updated`等,可以在这些钩子函数中执行特定操作。 7. **插槽**:Vue的插槽机制允许父组件向子组件注入内容,实现更灵活的布局和内容组合...

    vue-modal-mixin:用CodeSandbox创建

    6. **版本控制和发布**:虽然不直接涉及压缩包文件,但通常开发者会使用Git进行版本控制,并通过npm或Yarn发布到公共或私有的包仓库,以便在其他项目中安装和使用`vue-modal-mixin`。 7. **ES6语法**:由于涉及到...

    代表

    在IT行业中,JavaScript是一种至关重要的编程语言,尤其在网络开发领域占据着核心地位。"代表"这个标题可能是在指代JavaScript中的“代理”(Proxy)特性,这是一个强大的工具,允许我们创建自定义对象的行为。让...

    vue 基础思维导图pdf

    - 私有过滤器可以在组件的`filters`选项中定义,仅在当前组件内可用。 以上就是Vue.js基础思维导图中涵盖的主要内容,这些知识构成了Vue开发的基础,通过熟练掌握这些概念,可以构建复杂的前端应用。在实际开发中...

    面试.docx

    10. **原型与原型链**:JavaScript中每个对象都有一个proto属性指向其构造函数的原型对象,形成原型链,用于查找对象属性。 11. **this指向**:在JavaScript中,this取决于函数调用的位置,可以是全局对象、对象上...

    vue基础知识及思维导图,安装脚手架详细过程

    - 私有过滤器:仅在当前组件内部有效。 - 全局过滤器:在整个应用范围内可用。 - **侦听器** - `watch`:用于观察数据变化并执行相应操作。 - 配置属性: - `immediate`:组件初次加载完毕后立即调用。 - `...

    更新恢复

    在"Updated-Resume-master"这个压缩包文件名中,"master"通常表示这是项目的主要分支,可能是一个GitHub仓库的主分支,其中包含了简历更新的最新版本。这个文件很可能包含HTML源代码,以及可能的CSS(Cascading ...

    js代码-利用 Proxy 包裹对象

    JavaScript中的`Proxy`是一个强大的工具,它允许我们创建代理对象,这个代理对象可以拦截并定制对原对象的各种操作。在JavaScript的世界里,`Proxy`为我们提供了面向对象编程中的一些高级特性,比如数据验证、动态...

    最新的Vue全套面试题

    **解答:** MVVM(Model-View-ViewModel)是一种软件架构设计模式,广泛应用于前端开发中,特别是像Vue.js这样的现代JavaScript框架。在这种模式下,视图(View)和模型(Model)之间不能直接通信,而是通过ViewModel进行...

    vue-boolzapp

    8. **ES6语法**:Vue.js推荐使用ES6(ECMAScript 6)语法,Vue-Boolzapp中可能会看到箭头函数、解构赋值、模板字符串、类等现代JavaScript特性。 9. **插槽和道具**:Vue.js中的插槽用于组件间的内容分发,而道具...

    详解AngularJS的通信机制

    这里使用了RevealingModule模式,这是一种设计模式,用来在模块或服务中返回私有函数的公共接口,从而隐藏内部实现细节。因此,最终对外暴露的方法只包含我们希望其他开发者使用的方法。 ### 结论 通过使用发布/...

    mayasrikanth.github.io

    【描述】提到的"my personal website (updated in March 2021)"表明这是一个个人展示的平台,用户可能在这里分享他们的简历、作品集、博客文章或其他与他们技能和兴趣相关的内容。Materialize是基于Google的Material...

Global site tag (gtag.js) - Google Analytics