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);
});

  這樣的話,循環多少次也是白瞎!!!     


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM