【问题标题】:scoping of private variables in object prototype methods对象原型方法中私有变量的作用域
【发布时间】:2009-02-24 10:28:00
【问题描述】:

这个问题是关于在其原型链中添加方法和一些私有变量的对象的行为。只是出于好奇,想弄清楚这个谜。

function SomeObject() {
    if (this instanceof SomeObject) {
      var args  = arguments[0],
          proto = SomeObject.prototype,
          privatevalue = 0,
      /** assign first element of args[0] 
        * (=instance name) to private variable [id],
        * to be able to keep track of the instance
        */
          id = args[0] ||'no id';


      /** public 'set' adds a value to
        * the private variable [privatevalue]
        */
      this.set =
         function(){
           privatevalue += arguments[0] || 1;
           return privatevalue;
          };
       /** toString functions as a kind of getter */
       this.toString = function(){
            return id+' privatevalue: '+privatevalue;
       }

       /** add two methods to the prototype chain 
         * this happens only once
         */
       if (!proto._initialized_) {
         /** SomeObject.prototype.add 
           * uses 'this.set' to add a value
           * to [privatevalue] and returns
           * the object value (from tostring)
           */
         proto.add =
           function(){
             this.set(arguments[0]);
             return this;
         };
         /** SomeObject.prototype.add2 
           * uses 'this.set' to add a value
           * to [privatevalue] but returns
           * a string using private variables
           * [id] and [privatevalue] 
           */
         proto.add2 =
            function(){
              this.set(arguments[0]);
              return id+' privatevalue: '+privatevalue;
         };
         proto._initialized_ = true;
        }

        } else {
           return new SomeObject(Array.prototype.slice.call(arguments));
        }
  }

  /** create 2 instances of SomeObject */
  var objA = SomeObject('objA'),
      objB = SomeObject('objB');

  /** show the values and use the prototype [add] method
    * to change [privatevalue]
    */
  alert ([objA, objB].join(' | ')); 
        //=> objA privatevalue: 0 | objB privatevalue: 0
  alert ([objA.add(4), objB.add(2)].join(' | ')); 
         //=> objA privatevalue: 4 | objB privatevalue: 2

  /** use prototype method 'add2' to change and view the
    * private variables [id] and [privatevalue] for objA
    */
  alert (objA.add2()); 
         //=> objB privatevalue: 2!

现在的问题是:为什么来自 ojbA 的原型方法 add2(因此:objA.add2())返回来自 objB 的私有变量的值?我会说这些私人不应该被 objA 访问。换句话说:这里发生了什么样的范围界定? 还是陌生的。如果你这样做:

  alert (objA.add2()); 
  alert (objB.add2());

你得到 objA.add2():objA privatevalue: 5 和 objB.add():objA privatevalue: 5

【问题讨论】:

    标签: javascript prototype scoping


    【解决方案1】:

    问题在于您创建添加函数的范围。

    它们是在您实例化 'objA' 时在 SomeObject 执行范围内创建的。

    因此,Add2 访问的 id 和 privatevalue 变量是属于 'objA' 的变量,无论您将 .Add2 称为 'objA' 还是 'objB'。

    基本上基于原型的方法不能访问类的私有成员。为了访问私有成员,需要在这些成员的相同范围(或子范围)中创建一个函数。这就是 set 起作用的原因,因为它是在 SomeObject 的每个实例上创建的。

    【讨论】:

    • 'add' 和 'add2' 不是在原型链中创建的,所以假设在原型作用域中,而在函数作用域中创建 'set' 和 'toString'?
    • 不,没有“原型范围”。 add 和 add2 是在创建 'objA' 时在函数范围内创建的。它们被添加到原型链中,以便“objB”的实例可以看到它们,但它们将从创建它们的函数范围访问变量。
    • 好吧,我想我明白了。 “add2”只能访问在第一次实例化时分配的私有变量。顺便说一句,这个问题与问题无关,只是对我使用这种构造函数创建模式注意到的东西感到好奇,并没有完全理解。
    • 这可能会有所帮助:- stackoverflow.com/questions/99927/… 对你来说重要的是要记住作用域链和原型链是两个不同的东西。
    猜你喜欢
    • 2011-04-06
    • 2010-11-10
    • 2013-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多