zoukankan      html  css  js  c++  java
  • 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 (...) {...};

    }

  • 相关阅读:
    CSS 选择器及各样式引用方式
    The usage of docker image wurstmeister/kafka
    kafka connect rest api
    Kafka connect in practice(3): distributed mode mysql binlog ->kafka->hive
    jail-break-rule
    Ubuntu下把缺省的dash shell修改为bash shell
    mysql 5.7 enable binlog
    Docker CMD in detail
    记一次深度系统安装至windows系统盘提示挂载为只读模式问题
    android 监听声音变化
  • 原文地址:https://www.cnblogs.com/xxnn/p/8437193.html
Copyright © 2011-2022 走看看