let命令的介紹javascript
let是ECMAScript6中新增的關鍵字,用於聲明變量。它的用法相似於varcss
var a = 3 let b = 4
let變量的聲明html
let 命令的特色不容許在同一做用域下聲明已經存在的變量,也就是不能重複聲明(不容許多個變量的變量名相同)java
// var a = 1; // var a = 3;//重複聲明變量不會報錯,a變成了3 // let b = 4; // let b = 6;//會報錯:Identifier 'b' has already been declared (變量名已經存在) var a = 2; let a = 3; //這樣也會報錯:SyntaxError: Identifier 'a' has already been declared
let 命令的特色—沒有預解析閉包
var
命令會發生「變量提高」現象,即變量能夠在聲明以前使用,值爲undefined
。這種現象多多少少是有些奇怪的,按照通常的邏輯,變量應該在聲明語句以後纔可使用。函數
爲了糾正這種現象,let
命令改變了語法行爲,它所聲明的變量必定要在聲明後使用,不然報錯。this
console.log(a)//不會報錯,會顯示a這個變量的值爲undefined var a = 1; console.log(b)//會報錯:b is not defined(…),該變量未定義 let b = 4;
變量a
用var
命令聲明,會發生變量提高,即腳本開始運行時,變量a
已經存在了,可是沒有值,因此會輸出undefined
。spa
變量b
用let
命令聲明,不會發生變量提高。這表示在聲明它以前,變量b
是不存在的,這時若是用到它,就會拋出一個錯誤。code
let 命令的特色—塊級做用域htm
一對{}包括的區域成爲代碼塊,塊級做用域指一個變量或者函數只有在該區域才起做用
{ let a = 10; var b = 1; } console.log(a) // ReferenceError: a is not defined. console.log(b) // 1
let命令的特色—暫時性死區
let f = 10; function fn() { f = 7; //暫時性死區 let f = 2; } fn(); //執行結果依然報錯,緣由是在fn函數內又聲明瞭一遍變量f
let f = 10; function fn() { f = 7; //暫時性死區 // let f = 2; // 這裏重複聲明f變量會報錯 console.log(f) // 打印結果是7 } console.log(f) // 打印結果是10 fn();
let在for循環中的應用
在實驗以前先來看一下var在for循環中的應用中會產生什麼樣的問題和解決問題的方法以及案例
for(var i = 0;i<10;i++){ setTimeout(function(){ console.log(i)//打印結果是10個10,由於for執行了10次 ,i的值已經到了10,setTimeout纔開始第一次執行 }) } for(var i = 0;i<10;i++){ (function(i){ //這裏使用閉包的方式 setTimeout(function(){ console.log(i); //打印結果依次是:1,2,3,4,5,6,7,8,9,10 }) })(i) }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <button>1</button> <button>2</button> <button>3</button> <button>4</button> <button>5</button> </body> </html> <script> var btns = document.querySelectorAll('button'); // for(var i = 0;i<btns.length;i++){ // btns[i].onclick = function () { // console.log(i) // } // } // for(var i = 0;i<btns.length;i++){ // btns[i].index = i; //自定義屬性 // btns[i].onclick = function () { // console.log(this.index) // } // } for (var i = 0;i<btns.length;i++){ (function (i) { btns[i].onclick = function () { console.log(i) } })(i) } </script>
上面代碼中咱們可使用使用自定義屬性的方式解決這個問題也可使用閉包的方式解決這個問題
再來看一下使用let在for循環中的應用會不會出現上述的問題,在循環語句以內是一個父做用域,在循環體之中是一個子做用域
for(let i = 0;i<10;i++){ setTimeout(function(){ console.log(i); //打印結果依次是:1,2,3,4,5,6,7,8,9,10 }) }
for(let i = 0;i<10;i++){ let i = 10; console.log("for:"+i); //結果都是10 } console.log(i); //報錯:ReferenceError: i is not defined
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <button>1</button> <button>2</button> <button>3</button> <button>4</button> <button>5</button> </body> </html> <script> var btns = document.querySelectorAll('button'); for(let i = 0;i<btns.length;i++){ btns[i].onclick = function () { console.log(i) } } </script>
下面來一個平常工做中很是常見的需求——就是選項卡功能
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> div{ display: none; } .show{ display: block; } .active{ background-color: yellow; } </style> <script type="text/javascript"> "use strict" window.onload = function(){ var tabs = document.getElementsByTagName('input'); var divs = document.getElementsByTagName('div'); for(var i=0;i<tabs.length;i++){ tabs[i].index = i; tabs[i].onclick = function(){ for(var j=0;j<tabs.length;j++){ divs[j].className = ''; tabs[j].className = ''; } this.className = 'active'; divs[this.index].className = 'show'; } } // var tabs = document.getElementsByTagName('input'); // var divs = document.getElementsByTagName('div'); // // for(let i=0;i<tabs.length;i++){ // // tabs[i].onclick = function(){ // for(let j=0;j<tabs.length;j++){ // divs[j].className = ''; // tabs[j].className = ''; // } // this.className = 'active'; // divs[i].className = 'show'; // } // } } </script> </head> <body> <input type="button" value="tab1" class="active"> <input type="button" value="tab2"> <input type="button" value="tab3"> <div class="show">div1</div> <div>div2</div> <div>div3</div> </body> </html>