JavaScript中的私有成员[翻译]
原作者:Douglas Crockford,原文地址:http://www.crockford.com/javascript/private.html
JavaScript 是世界上被误解最深的编程语言. 有人认为它缺少信息隐藏的能力,因为它的对象不能拥有私有的实例变量和方法。事实上这是一种误解。JavaScript 对象可以拥有私有成员。下边就讲讲怎么做。
对象(Objects)
JavaScript 从根本上来说就是关于对象的语言。数组(Arrays)是对象。函数(Functions)是对象。 对象(Objects)是对象。那么对象是什么呢?对象就是键值对的集合(name-value pairs)。键(name)是字符串(strings) ,值(value)可以是字符串(strings)、数值(numbers)、布尔值(booleans)和对象(objects(包括数组(arrays)和函数(functions)))。对象通常是以hashtable的形式实现的,以便于值的快速检索。
如果对象的某个值是一个函数,我们可以认为它是这个对象的方法。当一个对象的方法被调用时,方法中的this变量代表调用它的对象。这样方法就可以通过this变量访问实例中的变量了。
对象可以由构造器(constructors)产生,构造器就是专门用来初始化对象的函数。在其他语言中由“类”(class)提供的功能,在JavaScript中由构造器提供,包括静态变量和方法。
公有的(Public)
在JavaScript中对象的成员都是公有(public)成员。任何函数都能访问、修改、删除这些成员,或者添加新成员。给一个新对象设置成员主要有两种方式:
在构造器中(In the constructor)
这种技术通常用来初始化公有的实例变量。构造器的this变量被用来给对象添加成员。
function Container(param) {
this.member = param;
}
这样,当我们构造一个新对象时
var myContainer = new Container('abc');
那么 myContainer.member 就是 'abc'.
在原型中(In the prototype)
这种技术通常用来添加公有的方法。当一个成员在对象本身中找不到时,那么它是来自对象的构造器的原型(prototype)成员。原型机制用来实现继承。也能节约内存。想要给一个构造器产生出来的所有对象都添加一个方法,只要给这个构造器的原型(prototype)添加一个函数即可:
Container.prototype.stamp = function (string) {
return this.member + string;
}
那么,我们可以调用这个方法
myContainer.stamp('def')
产生了 'abcdef'。
私有的(Private)
私有的(private)成员由构造器产生。构造器的普通vars和parameters变成了私有成员。
function Container(param) {
this.member = param;
var secret = 3;
var that = this;
}
这个构造器创造了三个私有的实例成员:param,secret和that。它们被附加到(构造器构造出来的)对象上,但是它们既不能被从外部访问,也不能被这个对象自己的公有方法访问。它们能够被私有方法访问。私有方法即构造器的内部函数。
function Container(param) {
function dec() {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}
this.member = param;
var secret = 3;
var that = this;
}
私有方法dec检查实例变量secret。如果secret大于0,将secret递减并返回true。否则返回false。这个方法可以用来将这个对象限制为仅能使用三次。
按照惯例,我们创建了一个私有变量that。这是为了让对象对私有方法可见。这样的j解决方案是因为ECMAScript语言规范中有一个错误,会导致this不能正确地设置给内部函数。
私有方法不能被公有方法调用。想要让私有方法发生作用,我们需要引入一个特权方法。
特权的(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 () {
return dec() ? that.member : null;
};
}
service是一个特权方法。前三次调用myContainer.service()时将返回'abc'。之后,将会返回null。service调用私有方法dec,而dec访问私有的secret变量。service对其他对象和方法可见,但是它不允许对私有成员的直接访问。
闭包(Closures)
这种公有、私有和特权成员的模式之所以可行,是因为JavaScript有闭包(closures)。这意味着内部函数总是能访问到外部函数的vars和parameters,甚至当外部函数已经返回后依然能访问。这是这个语言极其强大的一个特性。目前还没有JavaScript编程方面的书籍讲述如何利用这一特性。大多数甚至都没有提到它。
私有的和特权的成员只能在对象构造时创建。公有的成员在任何时候都能添加。
模式(Patterns)
Public
function Constructor(...) {
this.membername = value;
}
Constructor.prototype.membername = value;
Private
function Constructor(...) {
var that = this;
var membername = value;function membername(...) {...}
}
注意: 函数语句
function membername(...) {...}
是对如下语句的简写
var membername = function membername(...) {...};
Privileged
function Constructor(...) {
this.membername = function (...) {...};
}
JavaScript中的私有成员[翻译]的更多相关文章
- javascript模式(1)--私有成员
javascript是基于对象的一门语言,没有想java等语言那样子拥有封装的特性.但是javascript可以通过闭包来进行模拟. 1.构造函数与私有成员 可以用构造函数形成一个闭包,实现内部成员的 ...
- C#中访问私有成员
首先访问一个类的私有成员不是什么好做法.大家都知道私有成员在外部是不能被访问的.一个类中会存在很多私有成员:如私有字段.私有属性.私有方法.对于私有成员造访,可以套用下面这种非常好的方式去解决. pr ...
- C#中访问私有成员技巧
源代码是别人的,你就不能修改源代码,只提供给你dll.或者你去维护别人的代码,源代码却有丢失.这样的情况如果你想知道私有成员的值,甚至去想直接调用类里面的私有方法.那怎么办呢?其实在.net中访问私有 ...
- C#中访问私有成员--反射
首先我必须承认访问一个类的私有成员不是什么好做法.大家也都知道私有成员在外部是不能被访问的.而一个类中会存在很多私有成员:如私有字段.私有属性.私有方法.对于私有成员访问,可以套用下面这种非常好的方式 ...
- 『无为则无心』Python面向对象 — 55、多层继承和继承中的私有成员
目录 1.Python支持多层继承 (1)多层继承实现 (2)多层继承和多重继承区别 2.继承中的私有成员 (1)继承中父类私有属性和私有方法 (2)获取和修改私有属性值 1.Python支持多层继承 ...
- JavaScript中函数式编程中文翻译
JavaScript 中的函数式编程 原著由 Dan Mantyla 编写 近几年来,随着 Haskell.Scala.Clojure 等学院派原生支持函数式编程的偏门语言越来越受到关注,同时主流的 ...
- C中的私有成员
skynet_context声明在.h里 但定义在.c里面 外部使用的时候无法用ctx->handle获取私有成员,会提示解引用类型错误 必须用.h里函数获取ctx里属性.
- JavaScript中的私有属性
一.使用构造函数获得私有属性: function Gadget(){ var name = 'iPod'; this.getName = function(){ return name; }; }; ...
- javascript中的私有作用域
我们知道js中所有的块级作用域都是无效的,块级作用域内的变量,在外部仍然可以被读取,其实是申明在外部的.如何实现变量的私有化,只在块级作用域起效,避免污染全局的变量呢.而且,挂载在全局的变量很难被回收 ...
随机推荐
- 使用腾讯云“自定义监控”监控GPU使用率
欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 作者:李想 随着人工智能以及比特币的火热,GPU云服务的使用场景是越来越广,在很多场景下我们也需要获取GPU服务器的性能参数来优化程序的执行.目 ...
- MySQL数据库基础(二)(约束以及修改数据表)
一,约束以及修改数据表 约束的作用?1.约束保证数据的完整性.一致性:2.约束分为表级约束.列级约束:3.约束类型包括:NOT NULL(非空约束).PRIMARY KEY(主键约束).UNIQUE ...
- js的call和apply拾遗
一.产生背景 1. JavaScript 的函数存在「定义时上下文」和「运行时上下文」以及「上下文是可以改变的」这样的概念 2.正因为上下文的不同所以call 和 apply 都是为了改变某个函数运行 ...
- Visual Studio 2017 Enterprise 发布 15.3.2 版,附离线安装包下载。
Visual Studio 2017 Enterprise 更新至 15.3.2 ,本安装包使用微软原版安装文件,配合layout指令全量下载后制作,内置中文语言包,包含 Visual Studio ...
- nginx虚拟域名的配置以及测试验证
1.保证该机器上安装了nginx 未安装请看:centos/linux下的安装Nginx 2.使用root用户编辑配置文件 vim /usr/local/nginx/conf/nginx.conf 3 ...
- Linux Centos下编译安装Redis
需要安装 tcl 8.5 wget http://downloads.sourceforge.net/tcl/tcl8.6.1-src.tar.gz //直接下载 sudo tar xzvf tcl8 ...
- Eventlog控件的使用
CreateEventSource 已重载. 建立一个能够将事件信息写入到系统的特定日志中的应用程序. Delete 已重载. 移除日志资源. DeleteEventSource 已重载. 从事件日志 ...
- ActiveMq笔记1-消息可靠性理论
原博客:http://shift-alt-ctrl.iteye.com/blog/2020182 https://mp.weixin.qq.com/s/h74d6LtGB5M8VF0oLrXdCA 我 ...
- C#访问修饰符(public,private,protected,internal,sealed,abstract)
为了控件C#中的对象的访问权限,定义对象时可以在前面添加修饰符. 修饰符有五种:private(私有的),protected(受保护的),internal(程序集内部的),public(公开的),以及 ...
- Srtuts2实现登录界面(不连接数据库)报错(四)
1.利用Struts2写一个登录界面,出现以下问题 三月 01, 2014 12:26:18 下午 org.apache.struts2.dispatcher.Dispatcher warn 警告: ...