猫叔:Fighting!!!

[JavaScript] 模拟块级作用域、私有变量/函数

JavaScript没有块级作用域的概念。

function outputNumbers(count){
    for (var i=0; i < count; i++){
        alert(i);
    }
    alert(i);   //计数
}

  ①块语句中定义的变量,实际是在包含函数中而非语句中创建的。即变量i的作用域是它的包含函数outputNumber(),而不是for语句。
    在java、C++等语言中,变量i只会在for语句块中定义,循环结束后就被销毁。
  ②甚至在outputNumber()函数中可以重新声明同一个变量,JavaScript会忽略后续的声明但会执行声明中的初始化

在一个函数内重复声明一个变量
function outputNumbers(count){
    for (var i=0; i < count; i++){
        alert(i);
    }
    var i;     //JavaScript不会提示重复声明了一个变量
    alert(i);   //count
}

1、私有作用域
  使用匿名函数 模拟块级作用域(私有作用域) 语法:

(function(){
    //这里就是块级作用域
})();

  ①调用并立即调用一个匿名函数。由于函数声明后面是不能加圆括号,故需要用圆括号将函数声明包围起来,使其转换为函数表达式
  ②临时需要一些变量时,可以使用私有作用域。

私有作用域 例子
function outputNumbers(count){

    (function () {
        for (var i=0; i < count; i++){
            alert(i);
        }
    })();
    
    alert(i);   //导致一个错误
}

  ③在匿名函数中的任何变量在执行结束后会被销毁,故变量i只能在for循环语句中被使用,使用后即被销毁。匿名函数是闭包,可访问count参数。
  ④优点:可避免过多的全局变量而导致的命名冲突。
    同时,也有利于减少闭包占用内存问题,因为没有指向匿名函数的引用,匿名函数的作用域链在代码执行后销毁。

2、私有变量
  严格来讲,JavaScript没有私有成员的概念,所有对象属性都是公有的。但有一个私有变量的概念。
  任何在函数中定义的变量,都可以认为是私有变量。私有变量包括函数的参数、局部变量和在函数内部定义的其他函数。

  2-1.特权方法(privileged method)
    指有权访问私有变量和私有函数的公有方法。有2种创建方法:在构造函数中定义特权方法、在私有作用域中定义私有变量或函数。

    2-1-1.实例变量(在构造函数中定义特权方法)

方法1
function MyObj(){

    //私有变量
    var privateVar = 10;
    //私有函数
    function privateFunc(){
        return false;
    };

    //特权方法
    this.publicMethod = function(){
        privateVar++;
        return privateFunc();
    };
}

    ①外界无法访问MyObj()函数内的私有变量和私有函数,但由于特权方法是闭包 而可以通过它访问包含函数中的私有变量和私有函数。
    ②在创建MyObj实例后,除了通过publicMethod()这一个途径,没有其他方法能直接访问privateVar和privateFunc()。
    ③利用私有和特权成员,可以隐藏那些不应该被直接修改的数据。
    缺点:使用构造函数模式后,每个实例都会创建同样一组新方法。
      即每次都要重新创建特权方法,故之前的数据无法重用。使用第二种创建方法可解决。

    2-1-2.静态私有变量(在私有作用域中定义私有变量或函数+原型模式)

方法2
(function(){

    //私有变量
    var privateVar = 10;
    //私有函数
    function privateFunc(){
        return false;
    };

    //构造函数
    MyObj = function(){
    };

    //公有/特权方法
    MyObj.prototype.publicMethod = function(){
        privateVar++;
        return privateFunc();
    };

})();

     ①此模式,将所有私有变量、私有函数和特权方法等 都定义在一个私有作用域中。

    ②构建函数中,没使用函数声明,因为函数声明只能创建局部函数
      变量MyObj没有用var关键字声明,因为初始化为经声明的变量,都会创建一个全局变量。(在严格模式给为声明的变量赋值会出错)
    ③特权方法是在原型(prototype)上定义的,原型模式定义函数时不用函数声明,而是使用函数表达式,才能创建全局函数。
    区别:使用此模式,私有变量和函数都是由实例共享的,由于特权方法是在原型创建的,所以实例都用同一个特权方法。
      因此,当在一个实例中调用该特权方法修改私有变量时,所有实例都会被影响,所有实例中引用的私有变量对应着改变。
    优点:创建静态私有变量因为使用了原型而增进代码复用。
    缺点:所有实例都没有自己的私有变量和函数(都引用同一个)

静态私有变量
(function(){

    var name = "";
    
    Person = function(value){                
        name = value;                
    };
    
    Person.prototype.getName = function(){
        return name;
    };
    
    Person.prototype.setName = function (value){
        name = value;
    };
})();

var person1 = new Person("Nicholas");
alert(person1.getName());   //"Nicholas"
person1.setName("Greg");
alert(person1.getName());   //"Greg"
                   
var person2 = new Person("Michael");
alert(person1.getName());   //"Michael"
alert(person2.getName());   //"Michael"

 

posted @ 2013-05-10 11:54  庄丶大虾  阅读(1426)  评论(1编辑  收藏  举报