JavaScript中的私有成员

JavaScript是世界上是被误解得最厉害的编程语言。有些人认为它不具备“信息隐藏”的能力,因为JavaScript的对象没有私有变量和方法。这是误解。JavaScript对象可以拥有私有成员,下面我们来看看怎么做。(SharkUI.com注:JavaScript并不是真正拥有私有、公有等等OOP的特性,这篇译文中提到的这些私有、公有、特权等特性,是利用JavaScript的其他特性(参看本文的“闭包”一节)“模拟”出来的。感兴趣的话可以搜索相关的文章来看,当然也可以不管这些,就当它是真正的OOP来用。Have fun!)

对象

JavaScript是建立在对象之上的。数组(Array)是对象,函数(Function)是对象,对象(Objects)当然也是对象。那什么是对象呢?对象是一组“名称:值”对(name-value pair)的集合。名称是字符串,值却可以是字符串、数值、布尔或对象(包括数组和函数)。对象通常是用哈希表来实现的,以便可以快速地取值。

如果值是一个函数,我们就可以把它当作一个“方法”。当对象的一个方法被执行,变量this就被设为对象本身。如此,方法就可以通过this变量来访问对象的实例。

对象可以通过“构造器(constructor)”来创建。构造器是一个拥有初始化对象的函数。构造器提供了类似其他语言中的“类(class)”所提供的特性和功能,包括静态变量和方法。

公有

对象的所有成员都是公有成员。任何函数都可以访问、修改或者删除这些成员,当然也可以添加新的成员。给对象添加成员的两种主要方法:

通过构造器

这种方法一般用来初始化对象实例的公有变量。构造器的this变量被用来给对象添加成员:

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

构造一个新的对象:

var myContainer = new Container('abc');

然后,公有变量 myContainer.member 就拥有了值 'abc'。

通过原型(prototype)

这种方法通常用来添加公有方法。在对象本身搜寻一个成员但没有找到时,就使用构造器的原型(prototype)成员。这种原型机制实现了面向对象所谓的 “继承(inheritance)”,同时也节省了内存。给创建自同一个构造器的所有的对象加上一个方法,只需要给构造器的prototype增加一个函数:

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

然后我们就可以调用这个方法:

myContainer.stamp('def')

返回'abcdef'。

私有

私有(Private)成员是由构造器创建的。通常构造器中用var声明的变量和函数参数成为私有成员。

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

这个构造器创建了三个私有的实例变量:param,secret和self。

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

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


私有方法dec会检查实例变量secret,如果它大于0,自减1并返回true;如果它小于0,返回false。这样就实现了由这个架造器所创建对象的dec函数只能用三次的功能。

按惯例,我们创建了一个私有变量self。私有方法可以通过它来访问到对象本身。但这只是一种权宜之计,因为《ECMAScript Language Specification》中有一个错误,使得内部函数的this变量被设置成一个错误值。

公有方法(SharkUI.com注:即上文说的通过prototype创建的方法)是无法调用私有方法的,所以为了能使用私有方法,我们需要引入特权方法(privileged method)。

特权

一个特权方法可以访问私有变量和方法,而它本身可以被公有方法和外界访问。你可以删除或替换一个特权方法,但不能修改它,也不能强制它放弃自己的密秘(SharkUI.com注:原文如此,可能是指它的特权,关于这点请高手指教)。

特权方法是在构造器内部通过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是一个特权方法。前三次调用myContainer.service()将返回'abc',之后将返回null。service通过调用私有方法dec来访问私有变量secret。对于其他对象和方法来说,可以访问到service,但不能直接访问到私有的成员。

闭包

这种公有、私有和特权成员模式的存在是由于JavaScript的内在机制:闭包。这意味着一个内部函数永远可以访问它外部函数的变量和参数,即使外部函数已经返回。这是JavaScript语言非常强大的一个特性。目前还没有关于JavaScript编程的书籍展示了如何来利用它,它们甚至都没有提到这一点。

私有和特权成员只能在对象初始化的时候创建,而公有成员可以被随时添加进来。

模式


公有
function Constructor(...) {
this.membername = value;
}
Constructor.prototype.membername = value;

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

注:这句代码:

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

事实上是以下代码的简略写法

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

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

后记

Douglas Crockford的这篇文章为我们写出更优美的JavaSciprt程序奠定了基础,为我们创建出更合理的面向对象应用和框架带来了可能。在这篇译文快要完成的时候,惊诧的发现作者网站上出现了一个本文中文版的链接。好事!有越来越多的中国人开始关注这些“边边角角”的技术。虽然做了重复工作,但一样希望各位能从这篇文章中有所收益。也希望有更多的人能投入到原创和翻译前端技术文章中来,在多数人浮躁的时候,我们需要更多基础性的工作。一周一篇不多,一年一篇不少,只要开始了就行!

(0)

相关推荐

  • 9个javascript语法高亮插件 推荐

    下面介绍的是一些纯javascript实现的语法高亮插件. 英文原文:http://www.webdesignbooth.com/9-useful-javascript-syntax-highlighting-scripts/ 1. SyntaxHighlighter我相信这个插件是我们使用多的,它支持超多的语言,如果遇到不支持的语法还支持自定义. 2. SHJSSHJS 是js语法高亮插件的代表,它支持很多编程语言,兼容Firefox 2 &3, IE 6 & 7, Opera 9.6,

  • javascript中的void运算符语法及使用介绍

    void是javascript中的一个操作符,语法如下: javascript:void(表达式) javascript:void 表达式 void会计算表达式的值,但是会丢弃表达式的返回值. 这个表达式常常用来使链接变成一个死链接: 复制代码 代码如下: <a href = "javascript:void(0)" onclick = "func()">点我</a> 当点击这个链接的时候,不会发生地址跳转,而执行onclick函数. 下面的

  • javascript新手语法小结

    新手入学时常学到的东西~ <script language="javascript">alert('badwolf测试!');</script> //弹提示 <script language="javascript">alert('呵呵!');</script> //弹提示 <script language="javascript">alert(new Date());</scri

  • JavaScript学习笔记(一) js基本语法

    1.标识符与关键字 标识符以字母开头,可以包含字母.数字.下划线.标识符不能使用以下保留字符: 复制代码 代码如下: abstract, boolean, break,byte,case,catch,char,class,const,debugger,default,delete,do,double,else,enum,export,extends,false,final,finally,float,for,function,goto,if,implements,import,in,instan

  • 正则表达式语法规则及在Javascript和C#中的使用方法

    一.正则表达式概念: 在计算机科学中,是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串.在很多文本编辑器或其他工具里,正则表达式通常被用来检索和/或替换那些符合某个模式的文本内容.许多程序设计语言都支持利用正则表达式进行字符串操作. 二.正则表达式的使用: 正则表达式在ASP.NET中主要是用来对输入的内容进行验证,验证一般分为两种一种是客户端JS验证,另一种是服务器端验证 1.JS对输入内容验证 复制代码 代码如下: function check() {           

  • JavaScript 面向对象的 私有成员和公开成员

    其实很简单,废话少说,看了下面的代码及注释相信你就会一目了然! 复制代码 代码如下: //声明类,就是一个方法,其实在JavaScript中,命名空间.类.成员.... 一切皆对象 MyClass =function(){ var _this=this; //私有变量 var aa="11"; //公开变量 this.bb="22"; //私有方法 function fun1(){ alert(aa); alert(_this.bb); } //私有方法 var f

  • JavaScript语法着色引擎(demo及打包文件下载)

    应 得意小蛇 的建议,我整理了一下去年写的JavaScript语法着色引擎,并提供下载,喜欢的尽管拿去,嘿嘿 总的来说是很简单的东西,只是提供了关键字的着色以及一些基本的语法(例如注释,字符串,正则等等),从demo中应该很容易看到其用法,这里简单介绍下: 类名:Lighter 通过new Lighter()可以得到一个着色引擎实例,假设为lighter,有以下属性和方法: 语言属性:lighter.language 这个属性的范围是可以根据语法文件的数量自己添加的,提供的demo中有'cpp'

  • JavaScript 面向对象的之私有成员和公开成员

    上两节讲了 JavaScript 面向对象之命名空间 与 javascript 面向对象的JavaScript类,大家可以先看上面的再继续往下看. 其实很简单,废话少说,看了下面的代码及注释相信你就会一目了然! 复制代码 代码如下: //声明类,就是一个方法,其实在JavaScript中,命名空间.类.成员.... 一切皆对象 MyClass =function(){ var _this=this; //私有变量 var aa="11"; //公开变量 this.bb="22

  • JavaScript建立一个语法高亮输入框实现思路

    textarea元素已被广泛用于网页Web的IDE.通常网站自带的textarea编辑器不能满足我们的需求,作为一名开发者我们经常需要进行代码的在线编辑,高亮显示代码等,因此,通过其他的开源项目,我们可以添加一些实用的功能, 在这篇文章中,我将使用JavaScript库ACE来创建一个输入框效果.这是一个完全开源的脚本.该脚本允许开发人员创建支持语法高亮的输入框.然后你可以代码嵌入到网站中的任何地方 下载库 首先我们需要Github上下载ACE代码. 下载完成后解压缩,在你的header部分引入

  • JavaScript 高级语法介绍

    (function($){})(jQuery); 其实比较简单,要理解几个概念: 1.(),在JavaScript里()表示执行一个方法,如: function x(){ alert("xxx"); } var a = x;   // 没有调用,a 是一个function var a = x(); //调用了函数,a 的值是调用的结果:undefined 2.jQuery是一个jQuery对象,表示调用函数时,传入一个参数是jQuery对象. 这个没什么好说的 3.(function(

  • javascript编程必备_JS语法字典第1/2页

    1.document.write(""); 输出语句 2.JS中的注释为// 3.传统的HTML文档顺序是:document->html->(head,body) 4.一个浏览器窗口中的DOM顺序是:window->(navigator,screen,history,location,document) 5.得到表单中元素的名称和值:document.getElementById("表单中元素的ID号").name(或value) 6.一个小写转大

  • 教你如何在 Javascript 文件里使用 .Net MVC Razor 语法

    相信大家都试过在一个 View 里嵌套使用 javascript,这时就可以直接使用 Razor 语法以调用 .NET 的一些方法.如以下代码嵌套在一个 Razor 的 View 里: <script> var currDate = '@DateTime.Now'; //直接调用.NET的方法 console.log(currDate) </script> 但另一种情况是,如果我想在一个独立的 JS 文件里使用 Razor,那以上的方法可行不通,因为MVC不会直接解释JS文件,只有

  • 12种不宜使用的Javascript语法整理

    1.== Javascript有两组相等运算符,一组是==和!=,另一组是===和!==.前者只比较值的相等,后者除了值以外,还比较类型是否相同. 请尽量不要使用前一组,永远只使用===和!==.因为==默认会进行类型转换,规则十分难记.如果你不相信的话,请回答下面五个判断式的值是true还是false: false == 'false' false == undefined false == null null == undefined 0 == '' 前三个是false,后两个是true.

  • javascript基本语法分析说明

    在phpchina学PCTI前几天教了css与javascript先给大家看看 javascript的标识符 标识符是指javascript中定义的符号 比如变量名,函数名,数组名等等. 标识符可以由任意顺序的大小写字母,数字,下划线和美元符号组成,标识符不能以数字开头,也是不能使用javascript中的保留关键字. javasceipt严格区分大小写,每条功能执行后以分号结束,每个词之间用空格.制表符.换行符或大括号.小括号这样的分隔符隔开. ~~~~~~~~以上部分虽然有些唠叨,但是是需要

  • javascript中基于replace函数的正则表达式语法

    示例代码如下: var strM = "javascript is a good script language"; //在此我想将字母a替换成字母A alert(strM.replace("a","A")); [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行] 它只替换了首字母.但如果加上正则表达式结果就不一样了!replace()支持正则表达式,它可以按照正则表达式的规则匹配字符或字符串,然后给予替换! 注意:被替换的部分不用加双引号

  • 基于JavaScript如何实现私有成员的语法特征及私有成员的实现方式

    前言 在面向对象的编程范式中,封装都是必不可少的一个概念,而在诸如 Java,C++等传统的面向对象的语言中, 私有成员是实现封装的一个重要途径.但在 JavaScript 中,确没有在语法特性上对私有成员提供支持, 这也使得开发人员使出了各种奇技淫巧去实现 JS 中的私有成员,以下将介绍下目前实现 JS 私有成员特性的几个方案以及它们之间的优缺点对比. 现有的一些实现方案 约定命名方案 约定以下划线'_'开头的成员名作为私有成员,仅允许类成员方法访问调用,外部不得访问私有成员.简单的代码如下:

  • Javascript类定义语法,私有成员、受保护成员、静态成员等介绍

    其实通俗的讲类就是对象的模板,为了增强JS的OO特性,受mootoos框架启发我们可以使用一个JSON对象来描述这个对象的模板.在这个模板中我们可以模拟实现私有成员,受保护成员,静态成员. 这是一个在JS中模拟的类定义语法,代码中Class是一个自定义函数,它接受两个参数,第一个参数是类名.第二个参数是一个JSON用来一个对象的模板.在这个JSON对象中其中字段 "extend",,"initialize","static" 为一些预定义关键字,

  • javascript 语法基础 想学习js的朋友可以看看

    1:javascript区分大小写 2:javascript每一条语句必须以";"结束,与C语言一样 3:输出:document.write("字符串")--->还可以输出对应的html标记 4:改变窗体的颜色document.bgColor="red"; 4:类型转换:parseInt,parseFloat 5:随机函数:parseInt(Math.random()*90+10) 产生10--100的随机数 5:弹出对话框:alert(&

  • JavaScript 私有成员分析

    对象 JavaScript操作都是关于对象的.数组(Array)是对象,函数(Function)是对象.Object(类型)是对象.那么什么是对象呢?对象就是"名称-值"对(name-value).名称是字符串,值可以是字符串.数值.布尔值或对象(包括数组和函数).对象经常用哈希表实现,所以取值速度很快. 如果对象的一个值是函数(function),我们可以认为它是成员函数,当成员函数被调用时,this变量就会指向该对象.成员函数可以通过this变量访问对象的成员. 对象可以通过构造器

随机推荐