zoukankan      html  css  js  c++  java
  • [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"
  • 相关阅读:
    html之marquee详解
    CSS盒模型
    基于windows API的手柄/键盘映射编程(一)
    阿超的烦恼来临的始端
    阿超的小目标
    程序员的800字作文
    Link to Coding
    项目经理都干些什么啊
    停不下来的英语课联想
    Markdown
  • 原文地址:https://www.cnblogs.com/slowsoul/p/3070674.html
Copyright © 2011-2022 走看看