JavaScript
是一個持續演進的程式語言,並由瀏覽器廠商、開發者和社群成員組成的委員會制定標準。委員會引入了JavaScript
歷史上的最大更新 ES6
(ES2016),而 ES7
是年度更新的第一版(ES2017)。
2、ES6
和ES7
優點
-
-
簡化常見程式設計模式
-
使程式碼更容易編寫以及定製底層的
JavaScript
行為。
-
3、新特性
-
-
類
Class
可以讓開發者更容易地編寫物件導向程式,並安全地擴充套件extend
JavaScript內建物件。 -
箭頭函式
Arrow functions
、預設引數default parameters
和陣列的遍歷方法array convenience methods
使得常用功能更容易編寫,而不需要在專案之間複製黏貼程式碼。 -
JavaScript
的非同步處理流和巢狀回撥讓人難以理解,所以 ES6 中引入了promises
、迭代器和生成器iterators, and generators
以簡化非同步程式碼,讓控制流更直觀而不易出錯。
-
4、ES6
基礎---let
命令
-
- 用於宣告(區域性)變數,類似於var(全域性),但是宣告的變數只在let命令所在的程式碼塊有效。
-
-
建立塊級作用域(下面詳細介紹)
1 if(true){ 2 let a=10; 3 var b=1; 4 } 5 console.log(a); //Uncaught ReferenceError: a is not defined 6 console.log(b); //1
-
沒有變數提升
1 console.log(typeof str); //undefined 2 var str = 10; 3 4 console.log(typeof abc); //Uncaught ReferenceError: abc is not defined 5 let abc = 10;
-
不允許重複宣告
1 let a=10; 2 let a=20; 3 console.log(a); //Uncaught SyntaxError: Identifier 'b' has already been declared 4 5 var a=10; 6 var a=20; 7 console.log(a); //20
-
暫時性死區
在塊級作用域中使用
let
宣告變數時,塊級作用域會形成一個封閉的環境,不能訪問外部宣告的變數1 var c = 19; 2 if(true) { 3 console.log(c); 4 let c; //Uncaught ReferenceError: c is not defined 5 }
-
5、為什麼需要塊級作用域?
ES5 只有全域性作用域和函式作用域,沒有塊級作用域,這帶來很多不合理的場景。
-
- 第一種場景----內層變數可能會覆蓋外層變數。
1 var tmp = 'hi'; 2 function f() { 3 console.log(tmp); //這裡想使用外層的tmp='hi' 4 if (false) { //if程式碼塊之內使用內層的tmp='hello' 5 var tmp = 'hello'; 6 } 7 } 8 f(); //但是輸出結果是undefined,因為這裡存在變數提升,導致內部tmp覆蓋了外層的tmp
- 第一種場景----內層變數可能會覆蓋外層變數。
-
- 第二種場景----用來計數的迴圈變數洩露為全域性變數。
1 var s = 'hello'; 2 for (let i = 0; i < s.length; i++) { 3 console.log(s[i]); 4 } 5 console.log(i); // 5 6 //上面程式碼中,變數i只用來控制迴圈,但是迴圈結束後,它並沒有消失,洩露成了全域性變數
- 第二種場景----用來計數的迴圈變數洩露為全域性變數。
6、ES6
基礎---const
命令
const
宣告一個只讀的常量。
-
-
一旦宣告,常量的值就不能改變
1 const PI = 3.1415; // 3.1415 2 PI = 3; // TypeError: Assignment to constant variable.
-
只宣告,不賦值,也會報錯
1 const a; // SyntaxError: Missing initializer in const declaration
-
-
-
與
1 if (true) { 2 const a = 5; 3 } 4 console.log(a); // Uncaught ReferenceError: a is not defined
-
-
-
1 var message = "Hello!"; 2 let age = 25; 3 4 // 以下兩行都會報錯 5 const message = "Goodbye!"; 6 const age = 30;
- 也沒有變數提升,存在暫時性死區
1 if (true) { 2 console.log(a); //Uncaught ReferenceError: a is not defined 3 const a = 5; 4 }
-
7、ES6
宣告變數的六種方法
-
ES5
只有兩種宣告變數的方法:var
命令和function
命令。ES6
除了新增let
和const
命令,另外兩種宣告變數的方法:import
命令和class
命令。所以,ES6
一共有6種宣告變數的方法。
8、箭頭函式
-
- ES6 允許使用“箭頭”(
=>
)定義函式。1 var f = v => v;
- ES6 允許使用“箭頭”(
-
- 上面箭頭函式等同於
1 var f = function(v) { return v;};
- 上面箭頭函式等同於
-
- 引入箭頭函式的兩個作用
- 更簡短的函式書寫,簡化回撥函式
1 // 正常函式寫法 2 [1,2,3].map(function (x) { 3 return x * x; 4 }); 5 // 箭頭函式寫法 6 [1,2,3].map(x => x * x);
- 更簡短的函式書寫,簡化回撥函式
- 引入箭頭函式的兩個作用
-
- 使用時需注意
- 函式體內的
this
物件,就是定義時所在的物件,而不是使用時所在的物件。 - 不可以當作建構函式,也就是說,不可以使用
new
命令,否則會丟擲一個錯誤。 - 不可以使用
arguments
物件,該物件在函式體內不存在。如果要用,可以用 rest 引數代替。 - 不可以使用
yield
命令,因此箭頭函式不能用作 Generator 函式1 //this物件的指向是可變的,但是在箭頭函式中,它是固定的。 2 function foo() { 3 setTimeout(() => { 4 console.log('id:', this.id); 5 }, 100); 6 } 7 var id = 21; 8 foo.call({ id: 42 }); // id: 42 9 //箭頭函式可以讓setTimeout裡面的this,繫結定義時所在的作用域,而不是指向執行時所在的作用域
- 函式體內的
- 使用時需注意
-
- 小測試:請問下面的程式碼中有幾個this?
1 function foo() { 2 return () => { 3 return () => { 4 return () => { 5 console.log('id:', this.id); 6 }; 7 }; 8 }; 9 } 10 11 var f = foo.call({id: 1}); 12 13 var t1 = f.call({id: 2})()(); // id: 1 14 var t2 = f().call({id: 3})(); // id: 1 15 var t3 = f()().call({id: 4}); // id: 1
- 小測試:請問下面的程式碼中有幾個this?
上面程式碼之中,只有一個this
,就是函式foo
的this
,所以t1
、t2
、t3
都輸出同樣的結果。因為所有的內層函式都是箭頭函式,都沒有自己的this
,它們的this
其實都是最外層foo
函式的this
。
除了this
,以下三個變數在箭頭函式之中也是不存在的,指向外層函式的對應變數:arguments
、super
、new.target
。
9、promise物件
-
- 非同步程式設計的一種解決方案
- 避免了層層巢狀的回撥函式,使用鏈式呼叫方式來組織程式碼,更加直觀
- 提供統一的介面,使得控制非同步操作更加容易。
- 三種狀態
- Pending進行中
- Resolved已完成(又稱Fulfilled)
- Rejected已失敗
- 基本用法
1 //創造一個promise例項 2 var promise = new Promise(function(resolve, reject) { 3 // ... some code 4 5 if (/* 非同步操作成功 */){ 6 resolve(value); 7 } else { 8 reject(error); 9 } 10 }); 11 //例項生成後,可以用then方法分別指定Resolved狀態和Reject狀態的回撥函式。 12 promise.then(function(value) { 13 // success 14 }, function(error) { 15 // failure 16 });
- promise.all()
- 非同步程式設計的一種解決方案
-
-
-
var p = Promise.all([p1, p2, p3]);
-
p
的狀態由p1
、p2
、p3
決定,分成兩種情況。(1)只有
p1
、p2
、p3
的狀態都變成fulfilled
,p
的狀態才會變成fulfilled
,此時p1
、p2
、p3
的返回值組成一個陣列,傳遞給p
的回撥函式。(2)只要
p1
、p2
、p3
之中有一個被1 // 生成一個Promise物件的陣列 2 var promises = [2, 3, 5, 7, 11, 13].map(function (id) { 3 return getJSON('/post/' + id + ".json"); 4 }); 5 6 Promise.all(promises).then(function (posts) { 7 // ... 8 }).catch(function(reason){ 9 // ... 10 }); //上面程式碼中,promises是包含6個 Promise 例項的陣列,只有這6個例項的狀態都變成fulfilled,或者其中有一個變為rejected,才會呼叫Promise.all方法後面的回撥函式
-
-
先到這裡吧!有什麼不對的地方望大家多多指點!