`

[翻译]JS中的私有成员

 
阅读更多

翻译自:Private Members in JavaScript http://www.crockford.com/javascript/private.html

作者虽然写于早年,但还是挺有参考价值和值得学习的。

JavaScript中的私有成员

      JavaScript是世界上被误解最深的程序设计语言。一些人认为它缺乏信息隐藏(information hiding)的特性,理由是对象不能有私有实例变量和方法。但其实这是误解,JavaScript对象可以有私有成员。以下就是解释。

     对象Objects

     JavaScript的本质就是对象。数组是对象,函数是对象,对象是对象。那么什么事对象呢?对象就是名值对(name-value pairs)的集合。名是字符串(string),值是字符串、数值、布尔值或对象(包括数组和函数)。对象通常被实现为哈希表的方式以便其值能快速被获取到。

 

     如果值是一个函数(function),我们可以称之为一个方法(method)。当一个对象的某个方法被调用时,变量this就会被配置到该对象上,方法就能通过this变量来方法实例变量。

 

     对象可用通过构造器(constructor)创建,构造器就是能初始化对象的函数。构造器表现出了一些其他语言中类的特征,包括静态变量和方法。

      公开Public

     一个对象的成员全部都是公开成员(public member)。任何函数都可以访问、修改或删除这些成员。有两种主要方式把成员放到一个新对象中。

      方法1:在构造器中(In the constructor

      这个技术通常用来初始化公开的实例变量。构造器的this变量要用于指明把成员添加给对象。

 

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

     那么,如果我们这样构造一个新对象:

     var myContainer = new Container('abc');

     然后,myContianer.member的值就是'abc'。

     方法2:在原型中(In the prototype

      这个技术通常用来初始化公开的方法。当查找一个成员且在对象本身中找不到时,就从对象的构造器的原型prototype成员中去找。原型机制被用于继承,也可以存储。为了通过一个构造器给所有对象添加一个方法,我们可以给构造器的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 that = this;
}

    这个构造器创建出了3个私有的实例变量: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实例变量,如果大于0,就减少1然后返回true。否则返回false。它能用来限制对象只使用3次。

     

     通常,我们创建一个私有的that变量,使得私有方法也能引用对象,这是为了避免在ECMAScript规范中提到的一个错误:this在函数的内部函数被不正确地指向window。    如以下代码:

    //本文译者引入的一个例子

function a(){   
	console.log(this);  //a {}
	function b(){     
		console.log(this);  //window   
	}   
	b(); 
} 

new a();

     但是,此问题在严格模式已被修改。使用暂存方式,仅在非严格模式中运用。     

 

     私有方法不能被公开方法调用。为了使得私有方法有用,我们需要引入一个授权方法(privileged method)。

   

    授权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)。这意味着一个内部函数总是能访问var和外部函数的参数,甚至在外部函数返回之后。这是语言一种十分有力的特性。(注:这里有一句省略,大意是说作者写作时很少有书提到闭包概念,更不用说进一步探讨)

 

    模式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(...) {...};

    也就是说membername其实也是var声明的私有成员(方法) 

 

     Privileged

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

 

 

分享到:
评论

相关推荐

    JavaScript_Garden_CN

    ### JavaScript的秘密花园:深入探索JS的核心概念 #### 引言 `JavaScript_Garden_CN`,中文译为“JavaScript的秘密花园”,是一份详尽且不断更新的文档,专注于揭示JavaScript中的那些微妙而奇特的用法。这份文档...

    JS 函数式编程指南

    我们不得不到处使用 bind 以免 this 不知不觉地变了,语言里没有类可以用(目前还没有),我们还发明了各种变通方法来应对忘记调用 new 关键字后的怪异行为,私有成员只能通过闭包(closure)才能实现,等等。...

    语义分析的编译的分析的原理

    9. **对象和类的成员访问**:验证类成员的访问权限,如私有成员、保护成员和公有成员的使用。 10. **表达式求值顺序**:在某些语言中,语义分析会考虑操作符的优先级和结合性来决定表达式的求值顺序。 在编译过程...

    jQuery编写程序解释模拟prototype原理机制

    内容索引:脚本资源,jQuery,Prototype 使用jQuery统写一小程序说明prototype的原理,见源文件中注释,闭包生成私有成员P实际为静态私有变量,注释中以**开头的,表示prototype机制中内核自动生成或处理的。参考资料,...

    java关于字符串拼接的笔试题-test:Git测试(私有)

    编译应用程序时尝试访问未在对象中定义的方法将立即获得错误反馈 java:编译成字节码,然后由Java虚拟机解释成机器码 c#:编译为中间语言 (IL),然后由公共语言运行时 (CLR) 翻译成机器代码从 .NET 4 开始,添加了...

    教育软件基础之三:高级程序设计语言2

    类定义包括数据成员(属性)和方法成员,其中数据成员通常为私有,方法成员则多为公共。类继承允许创建新的类(子类),这些子类继承父类的属性和方法,同时可以添加自己的特性和功能。类继承提高了代码的复用性和...

    hyperledger-fabric-linux-amd64-2.0.0.tar.gz

    Hyperledger Fabric是Linux基金会主导的开源项目,是区块链技术中的一个重要框架,专为构建私有、许可型区块链网络而设计。这个名为"hyperledger-fabric-linux-amd64-2.0.0.tar.gz"的压缩包文件,包含了Hyperledger ...

    2021-2022计算机二级等级考试试题及答案No.15422.docx

    - **类成员的访问与调用**:在一个类中定义的方法可以调用该类的其他方法。例如,在类C中,方法b可以调用方法a,只要方法a不是私有的(private)。因此,正确的说法是在b的代码中执行a()。 #### 知识点二十:网页样式...

    Filosaurios:Grupo7

    3. **编程语言**:虽然没有明确指出,但项目可能使用了常见的编程语言,如Python、Java、JavaScript或C++,具体取决于项目的性质和目标。 4. **软件开发流程**:团队可能遵循敏捷开发方法,如Scrum或Kanban,强调...

    humeval.github.io:网站humeval.github.io的存储库

    评估NLP系统的关键在于测量其在各种任务上的性能,如文本分类、情感分析、机器翻译和问答系统等。研讨会可能涵盖了最新的评估方法、指标和挑战。 2. **EACL(欧洲计算语言学协会)**:EACL是欧洲计算语言学领域的...

Global site tag (gtag.js) - Google Analytics