1

请考虑以下代码:

function Outer(){
  function Inner(){
    var private="something";
    this.method = function(){    
     //some code here    
   };
  }

 var inner = new Inner(); //Why does this line not throw an error?
 alert(inner.private); // not accessible here
 inner.method();//no errors here
}

我无法理解为什么 method() 调用不会引发错误并且变量引用会引发错误?我知道变量的范围仅在声明它们的函数内?但是函数的范围呢?

4

2 回答 2

3

它没有什么复杂的,它与数据类型无关。

new Inner()创建一个新对象。您正在构造函数中为该对象分配一个属性

this.method = function(){...};

另一边,没有这样的财产private。你永远不会this.private = ...;private只是Inner函数的局部变量。

这是另一个等效于您的代码的示例,但希望使其更清晰:

function createObject() {
    var someVariable = '42';
    var obj  = {};
    obj.foo = 'bar';
    return obj;
}

var myObject = createObject();
// works, since we assigned the property to the object
console.log(myObject.foo); 
// does not work, we never assigned such a property to the object
console.log(myObject.someVariable); 

里面createObject声明了两个变量,someVariableobjobj是一个对象,我们为它分配一个属性并从函数中返回它。someVariable与对象无关,但可以在函数内用于其他目的。

于 2013-06-02T12:53:53.327 回答
1

var inner = new Inner() 行确实会引发错误,因为未定义内部,它只能在外部函数的主体内访问。

inner.private 不能作为 inner 的属性访问,因为它是一个闭包变量。所以 (new Inner()).private 不存在。(private 似乎是 JS 中的关键字,所以我在示例代码中将其更改为 priv)

它可以在内部函数体内访问,因为函数体内的代码保留了对闭包变量的引用。

  function Inner(){
    var priv="something";
    this.method = function(){//wrong, should declare as prototype
     console.log("private from within Inner function body:"
       ,priv)
    };
  }

var inner = new Inner();
console.log(inner.priv); //=undefined
inner.method();//=something

将有许多实例的对象的函数属性;像 Inner 可以有许多实例,例如: var a=new Inner(); var b = new Inner()... 不应该用 this 定义。您应该改用原型。

当您使用原型时,您不能在原型函数中使用私有变量,因为私有(闭包)变量只能在主函数体内访问。这就是为什么许多开发人员使用_privateprivate_表明它是私有的,因为 JavaScript 没有一种很好的方法可以在不破坏原型的情况下使成员私有。

function Inner(){
  var priv="private";//wrong
  this._priv="private"
}
Inner.prototype.method=function(){
  //cannot access priv
  console.log(this._priv);//no problem
}

可能在一种情况下,您可以通过这种方式使用私有数据,那就是当您的对象只有一个实例时。

var Mediator=(function(){
  var events={};//private, other code can't mess this up
  return{
    addEvent:function(eventName){
      events[eventName]=(events[eventName])?
        events[eventName]:[];
    },
    addLisener:function(eventName,func){
      events[eventName].push(func);
      return events[eventName].length-1;
    }
    //more stuff like removeListener, trigger ...
  }
})()

您可以在这个基本示例中了解原型。您可以使用 firebug 控制台在 Chrome 或 Firefox 中运行代码。按 F12 将其打开并将该链接中的代码粘贴到控制台中。然后随心所欲地摆弄它,看看你是否得到了预期的输出并理解了 JS 中的原型设计。

于 2013-06-02T12:54:01.643 回答