zoukankan      html  css  js  c++  java
  • js声明变量的三种方式及作用域

    一、参考链接

      本篇文章的创作灵感来源于博主-奔跑的铃铛关于js中const,var,let区别的介绍,特此鸣谢!!!

    二、基础知识

    UpdateTime--2017年9月12日15:18:28

    1.使用变量的步骤:a.声明-->b.赋值-->3.调用

     正确用法:

    <script type="text/javascript">
        // 方式一:声明和赋值不分离
        var correctUsage = "正确使用变量的方式一";
        alert(correctUsage);// 能够弹出来该变量所对应的值
        // 方式二:声明和赋值分离
        var correctUsage2;
        correctUsage2 = "正确使用变量的方式二";
        alert(correctUsage2);// 能够弹出来该变量所对应的值
    </script>

    错误用法:

    <script type="text/javascript">
        var correctUsage;
        // 错误一:没有赋值就使用
        alert(correctUsage);// undefined
        // 错误二:没有赋值就拼接字符串
        correctUsage+="没有赋值就改值";
        alert(correctUsage);// undefined没有赋值就改值
    </script> 

    2.变量的产生与死亡                             

      以使用var关键字声明变量为例,
      2.1 声明在函数外部的变量
      产生:js加载到该变量所在行时产生;
      死亡:js代码加载完毕,变量死亡。
      2.2 声明在函数内部的变量
      前提:该变量所在的函数被调用
      产生:js执行到该变量所在行时产生;
      死亡:该变量所在的函数执行结束。
      举例:

      情景一:函数只声明,不调用

    <script type="text/javascript">
        function test() {
            var aa = "test";    
            aa += "只声明,但不调用该函数时,该函数会不会执行?";// 添加内容
            alert(aa); 
            aa = "该函数的变量不会执行!"; // 重新赋值
            alert(aa);
        }
    </script>

      说明:上面2个alert不会执行
      情景二:声明并调用该函数

    <script type="text/javascript">
        // 1.声明该函数
        function test() {
            var aa = "test";    
            aa += "只声明,但不调用该函数时,该函数会不会执行?";// 添加内容
            alert(aa); 
            aa = "该函数的变量不会执行!"; // 重新赋值
            alert(aa);
        }
        // 2.调用该函数
        test();
    </script>

      说明:上面2个alert均会执行

    3.全局变量与局部变量

      3.1 全局变量

      声明在函数体外,任何地方都可访问到该变量。

      3.2 局部变量

      声明在函数体内,只有在函数体内可访问到该变量。

    三、声明变量的3种方式及作用域 

      UpdateTime--2017年9月13日15:06:03

      1 使用var(最常见) 

       var声明的变量可以是全局的(函数外面),也可以是函数级的(函数内部)

    function test() {
        globalVar = "这是一个全局变量";
        var partialVar = "这是一个局部变量";
    }
    test();
    alert(globalVar);// 这是一个全局变量
    alert(partialVar);// 直接报错 

      说明:函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!

       情景一:

    var varLocation = "函数外部声明并赋值";
    function test() {
        varLocation = "函数内部改值";
        alert(varLocation);// 函数内部改值
    }
    test();
    alert(varLocation);// 函数内部改值 

      说明:函数外面声明的变量,在函数内部改变该变量的值后,函数外面的该变量的值也随之改变。    

      情景二:

    var varLocation = "函数外部声明并赋值";
    function test() {
        var varLocation = "函数内部改值";
        alert(varLocation);// 函数内部改值
    }
    test();
    alert(varLocation);// 函数外部声明并赋值  

      说明:在函数外面使用var声明一个变量后,再在函数内部使用var再次声明一次并改变其值,函数外面的该变量的值不会发生改变。 

      2 使用const

      const用于修饰常量,定义的变量不可修改,而且必须初始化,声明位置不限(通常声明在js开头),与java类的final关键字性质一样

      举例:

    <script type="text/javascript">
        function test() {
            const testConstant = "测试常量";
            alert(testConstant);
            testConstant = "改变常量值";// 直接报错
        }
        test();
    </script>   

      3 使用let

      let声明的变量在{}中使用,变量的作用域限制在块级域中

      举例:使用js动态给ul添加li对象并点击第几项,显示当前点击是第几个

    window.onload = function() {
        var ul = document.getElementById("ulList");
        // 
        for (var i = 1; i <= 5; i++) {
            // 创建一个li对象
            var li = document.createElement("li");
            // li标签内内容设置为:Itemi
            li.appendChild(document.createTextNode("Item " + i));
            // 声明一个块级变量j,并将i赋给j
            let j = i;
            // 绑定点击事件
            li.onclick = function() {
                alert("Item " + j + " is clicked.");
            };
            // 将li对象item拼接到ul标签体内
            ul.appendChild(li);
        }
    }

       错误方式:

    window.onload = function() {
        var ul = document.getElementById("ulList");
        // 
        for (var i = 1; i <= 5; i++) {
            // 创建一个li对象
            var li = document.createElement("li");
            // li标签内内容设置为:Itemi
            li.appendChild(document.createTextNode("Item " + i));
            // 绑定点击事件
            li.onclick = function() {
                alert("Item " + i + " is clicked.");
            };
            // 将li对象item拼接到ul标签体内
            ul.appendChild(li);
        }
    }

      结果:点击每个li,提示的都是“Item 6 is clicked.”

      扩展:使用var如何实现这种效果?闭包

    window.onload = function() {
        var ul = document.getElementById("ulList");
        // 
        for (var i = 1; i <= 5; i++) {
            // 创建一个li对象
            var li = document.createElement("li");
            // li标签内内容设置为:Itemi
            li.appendChild(document.createTextNode("Item " + i));
            // 绑定点击事件
            li.onclick = (function(i) {
                return function () {
                    alert("Item " + i + " is clicked.");
                };
            })(i);// 闭包
            // 将li对象item拼接到ul标签体内
            ul.appendChild(li);
        }
    }

      说明:采用的闭包的方式在绑定的时候已经把j的值已经传递给对应的click事件了,所以能够实现相同的结果,但是,从程序的可维护性来说不推荐使用。 

      4 声明变量的要项  

      js声明的变量取值的原则:就近原则;

      js是弱类型语言,不同的数据类型可以用同一个变量名表示;

      函数内部声明的变量,不会影响函数外部同名的变量的值。

    四、如何避免全局污染?  

      方法:闭包

      举例一:

    (function() {
        // 声明一个JSON对象
        var JsonObj = {};
        // 定义该对象的属性及属性值
        JsonObj.name = "对象的属性";
        // 定义该对象的方法
        JsonObj.method = function() {
            alert("测试是否能够调用该方法");
            return JsonObj.name;
        }
        // 通过操作window对象,供外部访问该对象的属性和方法
        window.GlobalObj = JsonObj;
    })();
    // 调取该对象的方法并接受返回值
    var name = GlobalObj.method();//获取的是返回值name
    alert(name);// 对象的属性
    // 只获取该方法但不调用
    var method = GlobalObj.method;//获取的是对象GlobalObj2的method1()方法
    alert(method);
    // function() {
    //     alert("测试是否能够调用该方法");
    //     return JsonObj.name;
    // }
    // 调用接受到的方法,但不接收返回值
    method(); 

      UpdateTime--2017年11月8日08:27:48

      闭包的优缺点说明:

      优点:设计私有的方法和变量,保护函数内的变量安全;

      弊端:闭包有一个非常严重的问题,那就是内存浪费问题,这个内存浪费不仅仅因为它常驻内存,更重要的是,对闭包的使用不当会造成无效内存的产生。

    2020/04/16

      关于let变量的实际运用

      如上图所示,想实现的效果就是:鼠标离开文本框的时候,自动将一级指标所对应的二级指标打分结果进行求和,并将计算结果自动填充到合计栏。

      笨方法实现:

    $(function(){
    // 合计
        $(".index_01").on('blur', function(){
            var sum = 0;
            $(".index_01").each(function(){
    // 				sum += parseInt($(this).val());// 使用parseInt,字符串转数字失败
                sum += new Number($(this).val());
            });
            $("#score_01").text(sum);
        });
        $(".index_02").on('blur', function(){
            var sum = 0;
            $(".index_02").each(function(){
                sum += new Number($(this).val());
            });
            $("#score_02").text(sum);
        });
        $(".index_03").on('blur', function(){
            var sum = 0;
            $(".index_03").each(function(){
                sum += new Number($(this).val());
            });
            $("#score_03").text(sum);
        });
        $(".index_04").on('blur', function(){
            var sum = 0;
            $(".index_04").each(function(){
                sum += new Number($(this).val());
            });
            $("#score_04").text(sum);
        });
        $(".index_05").on('blur', function(){
            var sum = 0;
            $(".index_05").each(function(){
                sum += new Number($(this).val());
            });
            $("#score_05").text(sum);
        });
    });
    

      借助for循环实现

    function indexTotalCalculate(firsIndexCount) {
      if (firsIndexCount >= 10) return;
      // 有多少个一级指标就执行多少次
      for (var i = 1; i <= firsIndexCount; i++) {
        // 必须使用变量let
        let index = '.index_0' + i;
        let score = '#score_0' + i;
    //		var index = '.index_0' + i;
    //		var score = '#score_0' + i;
        $(index).on('blur', function(){
          var sum = 0;
          $(index).each(function(){
            sum += new Number($(this).val());
          });
          $(score).text(sum);
        });
      }
    }
    $(function(){
        // 自动求和
      indexTotalCalculate(5);
    });
    

      这样,避免了冗余的代码,也实现了同样的效果  

      但是,刚开始的时候,需要用let声明变量的地方使用了var,导致的结果就是:  

      只有最后一个一级指标能够进行自动求和运算,而前面的4个都没有实现。

      原因就是由于var的作用域是函数级别,所以同一个函数内不管使用for循环声明并赋值多少次,其值都是最后一次所赋的值,也就造成对最后一个指标重复了5次绑定失去焦点事件的结果。

      也就是实际解析出来的是5个一样的代码

    $(".index_05").on('blur', function(){
        var sum = 0;
        $(".index_05").each(function(){
            sum += new Number($(this).val());
        });
        $("#score_05").text(sum);
    });
    $(".index_05").on('blur', function(){
        var sum = 0;
        $(".index_05").each(function(){
            sum += new Number($(this).val());
        });
        $("#score_05").text(sum);
    });
    $(".index_05").on('blur', function(){
        var sum = 0;
        $(".index_05").each(function(){
            sum += new Number($(this).val());
        });
        $("#score_05").text(sum);
    });
    $(".index_05").on('blur', function(){
        var sum = 0;
        $(".index_05").each(function(){
            sum += new Number($(this).val());
        });
        $("#score_05").text(sum);
    });
    $(".index_05").on('blur', function(){
        var sum = 0;
        $(".index_05").each(function(){
            sum += new Number($(this).val());
        });
        $("#score_05").text(sum);
    });
    

      这样的话,循环多少次也是白瞎!!!     

  • 相关阅读:
    DM7 安装
    LeetCode 第 183 场周赛
    MySQL 源码中的 ut_a 、 ut_ad
    存储领域的会议和研究机构
    LeetCode 第 15 场双周赛
    LeetCode 第 167 场周赛
    值得推荐的C/C++框架和库
    InnoDB 中的锁实现
    LeetCode-第 166 场周赛
    LeetCode 第 165 场周赛
  • 原文地址:https://www.cnblogs.com/Marydon20170307/p/7505964.html
Copyright © 2011-2022 走看看