1

我正在读一本略高于我水平的书。这本书的作者正在展示如何使用匿名函数创建私有作用域。我理解私有范围的概念,但是,我不明白它是如何实现的。我确实知道这些局部变量只能在当前范围内访问(这是作者的话),但我不确定如何调用/实现它。你能给我一个例子,说明如何使用var Tim = new Person();下面的代码在实际代码中使用它

使用匿名函数创建私有范围:

var Person = function(){};

(function(){
  var findById = function(){ /* ... */ };
  Person.find = function(id){
    if (typeof id == "integer")
      return findById(id);
   };
})();

我的理解

var Tim = new Person(); 

我会怎么称呼?我会尝试找到蒂姆的身份吗?

4

2 回答 2

3

首先:您提供的代码段不会返回 id,但会在传递 id 时返回一些东西。我必须承认,当涉及到私有作用域时,这个例子并不是最好的例子。我会给你一个更详细的,但我希望更清楚的例子:

(function ()
{
    var personObjects = [];
    var findById = function(id)
    {
        return personObjects[id];
    }
    var Person = function (name)
    {
        this.id = personObjects.length;//first available index ~= auto increment
        this.name = name;
        personObjects.push(this);
    };
    Person.find = function(id)
    {
        //I woudl do: id = +id;, but sticking to your example
        if (typeof id === 'number')
        {
            return findById(id);
        }
        return undefined;
    }
    window.Person = Person;//expose to global object
})();

那么,我们这里有什么。您说您了解范围,所以我假设您知道此处声明的所有变量在包装函数返回后都将继续存在,但它们仅对在同一范围中声明的函数可见。如果不是:personObjects数组和findById函数对象仍然存在,但只能由Person构造函数访问,构造函数暴露(因为也分配了)全局对象。

每当实例化一个人对象时,我都会使用数组的长度来确定下一个可用的 ID,从而为每个对象创建一个唯一的 ID。当您将有效的 id(数组键)传递给它时,函数 findById 只会返回对其中一个对象的引用。该Person.find方法调用这个封闭的函数,但在这样做之前会对参数进行一些检查。在某些非常特殊的情况下,这对于调试或在长原型链中使用通用 setter 和 getter 可能很有用。这就是为什么,至少对我来说,这个例子作为一个起点有点牵强。

无论如何,您可以findById像这样调用这个私有方法 ( ):

var tim = new Person('tim');
Person.find(0);// returns a reference to tim
//or even
var tom = new Person('Tom');
tim.find(1);//returns tom
tom.find(0);//returns tim
tim.find(tom.id);//...

同样,这种方法在 AFAIK 中不太常见,要练习/习惯范围和闭包,我建议使用一些魔术和事件委托(例如:尝试为移动设备上setInterval的事件创建自己的委托者)。tab只需谷歌它们,您很快就会明白为什么这是一个很好的练习,但一开始有点令人生畏。

于 2012-09-11T20:27:44.093 回答
0

findById只能通过调用间接调用Person.find

// Assuming code similar to your code above
// Assume that Tim.id === 1
var someone = Person.find(1); // Call findById to get a reference to Tim
console.log(someone.name); // Tim
findById(1) // Error, findById is not available in the global scope
于 2012-09-11T20:11:58.950 回答