【前端面試】(四)JavaScript var let const的區別

帕圖納克斯 發表於 2022-06-28
前端 面試 JavaScript

視訊連結:
JavaScript var let const的區別 - Web前端工程師面試題講解

參考連結:
JavaScript 變數
JavaScript Let
JavaScript Const

練習網站:
codepen.io
【前端面試】(四)JavaScript var let const的區別

初步認識:

功能實現

HTML的部分:

<input type="text" placeholder="帕圖納克斯">
<button>發表評論</button>
<div></div>

JS的部分:

//首先要要我想弄一個評論功能,
//通過document.querySelector獲取到HTML中input標籤的type屬性為"text"的輸入框的部分
//於是賦值給這個var變數text,該變數就成類似容器一樣的存在
var text = document.querySelector("input[type='text']");
var button = document.querySelector("button");
var div = document.querySelector("div");

button.onclick = function(){
//用var建立變數content,把輸入的內容賦值給content
  var content = text.value;
//接著就把內容賦值給下面的評論顯示區域
  div.innerText = content;
};

現在我輸入內容就顯示出評論的結果了:
【前端面試】(四)JavaScript var let const的區別

重複宣告

在不新增變數以及不該寫整體結構的前提下,我們可以利用var變數可以重複宣告的性質,改寫原來評論輸入的內容:

JS部分改寫:

var text = document.querySelector("input[type='text']");
var button = document.querySelector("button");
var div = document.querySelector("div");

button.onclick = function(){
  var content = text.value;
  var content = "下次一定";
  div.innerText = content;
};

【前端面試】(四)JavaScript var let const的區別

值的修改

而 如果我們不宣告 var 這個變數,直接賦值就叫值的修改:

button.onclick = function(){
  var content = text.value;
  content = "下次一定";
  div.innerText = content;
};

當我們使用let變數時,想重複定義是不可以的,但是可以進行值的修改或者建立一個新的let變數
【前端面試】(四)JavaScript var let const的區別

const變數則更加嚴格,即不能重複定義,也不存在值修改,但是可以建立一個陣列,利用陣列通過指標指向和被引用的特點,來存新的變數達到我們修改評論的目的,例子如下。

JS的部分:

button.onclick = function(){
  const content = [];
  content[0] = text.value;
  content[1] = "下次一定";
  div.innerText = content[1];
};

宣告提升

接下來弄一個新的例子來說明
HTML部分:

<p class="p1">聽君一席話</p>
<p class="p2"></p>

JS部分:

var p1 = document.querySelector("p.p1");
var p2 = document.querySelector("p.p2");

p2.innerText=content;

var content = "如聽一席話"

【前端面試】(四)JavaScript var let const的區別

之所以p2的類沒有顯示內容,則是因為var變數可以宣告提示,類似如下的效果:

var content

p2.innerText=content;

content = "如聽一席話"

此外let、const宣告的變數是沒有宣告提升,但是可以利用值的修改可令let宣告的變數不報錯。

建立塊級作用域

就是弄個函式,一個函式儘管使用了函式外的同名變數,但是可以選擇是否呼叫,來達到改變該案例p2段落的情況。
【前端面試】(四)JavaScript var let const的區別

不過這樣太麻煩了,其實用let/const+花括號內容括起來就可以形成塊級作用域的效果:
【前端面試】(四)JavaScript var let const的區別

迴圈

注意:ES6之前的迴圈不算是塊級作用域的一種
以下就弄也給迴圈案例
HTML部分:

<ul>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>

JS部分:

var li = document.querySelectorAll("li");
//這裡進行5次迴圈
for(var i=0;i<5;i++){
  //每次迴圈都為li元素新增滑鼠事件
  li[i].onmouseover = function(){
    //在這個監聽事件,就新增文字節點用迴圈裡的i賦值
    var text = document.createTextNode(i);
    this.appendChild(text);
    //並且修改li元素的高度
    this.style.height = i * 10 + "px";
  }
}

滑鼠逐個移動每個li,可以看到它們的間距確實變大了,但是變大的間距都是一致的,並不是逐個上升的,這裡是回撥函式的問題。
【前端面試】(四)JavaScript var let const的區別

該函式的具體實現流程如下:

首先滑鼠事件裡的內容是回撥函式
【前端面試】(四)JavaScript var let const的區別

需要等執行棧裡面的正常任務執行以後才會執行任務佇列裡面的回撥函式的結果,var關鍵字沒有形成塊級作用域,回撥函式只儲存了引數i,等正常任務執行後,i就為5了。

可以在迴圈宣告一個新的let變數j,把i的數值賦給j,並且令滑鼠事件只認j,這樣因為塊級作用域的關係,每次迭代可以進行重新繫結,這樣就可以使任務佇列裡面的回撥函式都有不一樣的i

var li = document.querySelectorAll("li");

for(var i=0;i<5;i++){
  let j=i;
  li[j].onmouseover = function(){
    var text = document.createTextNode(j);
    this.appendChild(text);
    this.style.height = i * 10 + "px";
  }
}

【前端面試】(四)JavaScript var let const的區別
可以看到現在就達到我們希望可以逐個增大的效果了

當然也可以把塊級作用域鎖定在迴圈裡面達到同樣的效果(我測試不成功,不知道為什麼i引數的0與1總是重合
JS修改:

var li = document.querySelectorAll("li");

for(let i=0;i<5;i++){
  li[i].onmouseover = function(){
    var text = document.createTextNode(i);
    this.appendChild(text);
    this.style.height = i * 10 + "px";
  }
}

總結:

【前端面試】(四)JavaScript var let const的區別