一、參考鏈接
本篇文章的創作靈感來源於博主-奔跑的鈴鐺關於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);
});
這樣的話,循環多少次也是白瞎!!!
