摘要:考慮到環境導致的行為差異太大,應該避免在塊級作用域內聲明函數。函數聲明語句函數表達式循環循環還有一個特別之處,就是循環語句部分是一個父作用域,而循環體內部是一個多帶帶的子作用域。聲明一個只讀的常量。
es6學習筆記-let,const和塊級作用域_v1.0 塊級作用域
javascript 原來是沒有塊級作用域的,只有全局作用域和函數作用域
例子1因為沒有塊級作用域,所以每次的i都是一樣
var a = []; for (var i = 0; i < 10; i++) {//變量i是var聲明的,在全局范圍內都有效 a[i] = function () { console.log(i); //每次的i變化都是全局的,所以每一個i的值都會變成最終的10 }; } a[1](); //返回10 a[6](); //返回10例子2
這里可以跟以前在
function createFunctions() { var result = new Array(); for (var i = 0; i < 10; i++) { result[i] = function () { //這是一個閉包 //因為閉包保存的是整個createFunctions變量對象,所以當他執行完成的時候(for循環結束), //i是等于10的,所以就會是10,由始至終,閉包里面引用的都是一整個變量對象,而不是一個變量 return i; }; } return result; //返回的是一個數組,數組里面每一個項目都是一個function } var test = createFunctions(); for (var i = 0; i < 10; i++) { //需要執行這個 function 才能夠獲取里面的值 console.log(test[i]());//都是10 }
//看看區別,這里會傳入一個參數來避免使用變量對象的參數 function createFunctions() { var result = new Array(); for (var i = 0; i < 10; i++) { result[i] = function (num) {//這是一個匿名函數,參數是 num return function () {// 這是一個閉包,不過這個閉包訪問的num是我們傳入的num,即使閉包保存一整個變量對象,但是我們將變量對象改成了外面這個匿名函數 return num; //相當于在閉包外面包了一層活動對象,將活動對象改變成能夠改變值 num的活動對象 }; }(i);//這個匿名函數會立即執行,并且傳入了 i 作為 num } return result; //返回的是一個數組,數組里面每一個項目都是一個function } var test = createFunctions(); for (var i = 0; i < 10; i++) { //需要執行這個 function 才能夠獲取里面的值 console.log(test[i]());//返回0-9 }
例子3雖然這里是說閉包保存的是整個變量對象,導致了i的值跟著變量對象一起變化,不過也是殊途同歸,這里只是替換為做全局對象來做例子
這里還原到真實的應用
//這里運行報錯:Uncaught TypeError: Cannot read property "innerText" of undefined at HTMLButtonElement.( var buttons = document.querySelectorAll(".button"); var output = document.querySelector("#output"); for(var i =0;i 總的來說,那么在以前的js里面要實現塊級作用域的話:
要么使用函數作用域,例如在函數里面重新定義變量
要么就使用類似閉包的方式,使用獨立的變量
letlet的作用就是將變量保持在塊級作用域里面,那就沒有了跟其他作用域互搶的情況了.
var會出現變量提升的情況(變量可以在聲明前使用),但是let沒有
不允許重復聲明(var可以,let不可以)
改成用let之后
var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[1](); // 返回1 a[6](); // 返回6其他例子也是可以簡單的改成let代替var就可以生效了.
塊級作用域與函數聲明es5規定函數只能在頂層作用域和函數作用域之中聲明,不能再塊級作用域聲明(一般模式可以使用,但是嚴格模式不可以使用)
es6規定,明確允許在塊級作用域之中聲明函數
但是考慮到舊代碼的問題,為了減輕因此產生的不兼容問題,ES6在附錄B里面規定,瀏覽器的實現可以不遵守上面的規定,有自己的行為方式。
考慮到環境導致的行為差異太大,應該避免在塊級作用域內聲明函數。如果確實需要,也應該寫成函數表達式,而不是函數聲明語句。
// 函數聲明語句 { let a = "secret"; function f() { return a; } } // 函數表達式 { let a = "secret"; let f = function () { return a; }; }for循環for循環還有一個特別之處,就是循環語句部分是一個父作用域,而循環體內部是一個多帶帶的子作用域。
for (let i = 0; i < 3; i++) { //i在for循環變化 let i = "abc"; //然后for循環內部的i也設置了一個 console.log(i); } // abc // abc // abc上面代碼輸出了3次abc,這表明函數內部的變量i和外部的變量i是分離的。
constconst聲明一個只讀的常量。一旦聲明,常量的值就不能改變。
const實際上保證的,并不是變量的值不得改動,而是變量指向的那個內存地址不得改動。
對于簡單類型的數據(數值、字符串、布爾值),值就保存在變量指向的那個內存地址,因此等同于常量。
于復合類型的數據(主要是對象和數組),變量指向的內存地址,保存的只是一個指針,const只能保證這個指針是固定的,至于它指向的數據結構是不是可變的,就完全不能控制了
const foo = {}; // 為 foo 添加一個屬性,可以成功,雖然設置了常量,但是里面的屬性還是能夠改變 foo.prop = 123; foo.prop // 123 // 將 foo 指向另一個對象,就會報錯,這里看到常量還是設置成功的 foo = {}; // TypeError: "foo" is read-only如果需要將對象凍結,保證為一個真正的"常量",需要用Object.freeze,而且為了保證排除對象里面包含對象的情況,需要遞歸凍結
//普通凍結 const foo = Object.freeze({}); // 常規模式時,下面一行不起作用; // 嚴格模式時,該行會報錯 foo.prop = 123; //遞歸凍結 var constantize = (obj) => { Object.freeze(obj); Object.keys(obj).forEach( (key, value) => { if ( typeof obj[key] === "object" ) { constantize( obj[key] ); } }); };總而言之:一般情況下,使用const來定義值的存儲容器(變量)
只有在值容器明確地被確定將會被改變時才使用let來定義變量
不在使用var
參考引用:
es6-函數的擴展
es實戰2015
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/81940.html
摘要:學習筆記函數擴展函數參數的默認值如果參數默認值是變量,那么參數就不是傳值的,而是每次都重新計算默認值表達式的值。屬性函數的屬性,返回該函數的函數名。箭頭函數詳細鏈接參考引用函數擴展 es6學習筆記-函數擴展_v1.0 函數參數的默認值 function Point(x = 0, y = 0) { this.x = x; this.y = y; } var p = ne...
摘要:因為箭頭函數本身沒有所以不可以當作構造函數,也就是說,不可以使用命令,否則會拋出一個錯誤。箭頭函數不可以使用對象,該對象在函數體內不存在。 es6學習筆記-箭頭函數_v1.0 箭頭函數使用方法 var f = v => v; //普通函數配合箭頭函數寫法,這里并且是傳參的 //相當于 var f = function(v) { return v; }; /*-----------...
摘要:學習筆記頂層對象雖然是筆記但是基本是抄了一次大師的文章了頂層對象頂層對象,在瀏覽器環境指的是對象,在指的是對象。之中,頂層對象的屬性與全局變量是等價的。的寫法模塊的寫法上面代碼將頂層對象放入變量。參考引用頂層對象實戰 es6學習筆記-頂層對象_v1.0 (雖然是筆記,但是基本是抄了一次ruan大師的文章了) 頂層對象 頂層對象,在瀏覽器環境指的是window對象,在Node指的是gl...
摘要:學習筆記字符串的擴展字符的表示法允許使用的形式表示一個字符,但在之前,單個碼點僅支持到,超出該范圍的必須用雙字節形式表示,否則會解析錯誤。返回布爾值,表示參數字符串是否在源字符串的頭部。,是引入了字符串補全長度的功能。 es6學習筆記-字符串的擴展_v1.0 字符的Unicode表示法 JavaScript 允許使用uxxxx的形式表示一個字符,但在 ES6 之前,單個碼點僅支持u00...
摘要:學習模塊不是對象,而是通過命令顯式指定輸出的代碼,輸入時也采用靜態命令的形式。的模塊自動采用嚴格模式命令用于規定模塊的對外接口,命令用于輸入其他模塊提供的功能。該文件內部的所有變量,外部無法獲取。 es6 學習-module_v1.0 ES6模塊不是對象,而是通過export命令顯式指定輸出的代碼,輸入時也采用靜態命令的形式。 ES6的模塊自動采用嚴格模式 export命令用于規定模...
閱讀 1733·2021-11-24 10:18
閱讀 2207·2021-11-18 13:20
閱讀 2332·2021-08-23 09:46
閱讀 992·2019-08-30 15:56
閱讀 2840·2019-08-30 15:53
閱讀 738·2019-08-30 14:22
閱讀 470·2019-08-29 15:34
閱讀 2532·2019-08-29 12:14