在近期的Vue開發中,使用了大量的ES6語法,因此覺得有必要找個時間來整理下近期的學習筆記。ES6相對ES5增加了許多新的特性,給我們的開發提供了方便。並且ES6也是未來開發的潮流,所以我覺得大家很有必要去掌握這一技能。
在我們正式學習ES6前,我們需要先去學習下轉碼器。常用的轉碼器有Babel和Traceur。這裡推薦一篇常見的ES6轉碼工具有興趣的可以去看看。
接下來我們就一起去見證ES6的神奇之處吧!
1.let和const
let與var類似是用來宣告變數的,const用來宣告常量。在實際用途中它們存在著許多區別,廢話不多說,直接看程式碼。
{
var a = 100;
let b = 200;
}
console.log(a); //100
console.log(b); //b is not defined -- Error
複製程式碼
是不是感覺很奇怪,為什麼a有值而b卻not defined呢?因為ES5只有全域性作用域和函式作用域,沒有塊級作用域。而let則實際上為JavaScript新增了塊級作用域。用它所宣告的變數,只在let命令所在的程式碼塊內有效。
let不存在變數提升。那麼什麼是變數提升呢?簡單來說就是無論宣告在什麼地方,都會被視為宣告在頂部。下面來看個例子。
//ES5
console.log("ES5:");
var a = [];
for (var i = 0; i < 10; i++) {
var c = i;
a[i] = function () {
console.log(c);
};
};
a[5](); //結果:9
複製程式碼
是不是有許多小夥伴在疑惑為什麼輸出的不是5呢?變數i是var宣告的,在全域性範圍內都有效。所以每一次迴圈,新的i值都會覆蓋舊值,導致最後輸出的是最後一輪的i的值。而使用let則不會出現這個問題。
//ES6
console.log("ES6:");
var b = [];
for (var j = 0; j < 10; j++) {
let d = j;
b[j] = function () {
console.log(d);
};
};
b[5](); 結果://5
複製程式碼
同時let也是不允許重複宣告的。
{
var a = 100;
var a = 200;
console.log(a); //200
}
// 模組內部不允許用let命令重複宣告
{
var a = 1;
let a = 2;
console.log(a); // 報錯
}
複製程式碼
下面再來說說 const。const也用來宣告變數,但是宣告的是常量,一旦宣告,常量的值就不能改變。它和let一樣只在宣告的區域內有用。
{
var a = 100;
const a = 200;
console.log(a); // 報錯
}
複製程式碼
const宣告物件
const person = {};
person.name = "Zhangsan";
person.age = 30;
console.log(person.name); //Zhangsan
console.log(person.age); //30
console.log(person); //Object {name: "Zhangsan", age: 30}
複製程式碼
const物件凍結
const person = Object.freeze({});
person.name = "Zhangsan";
person.age = 30;
console.log(person.name); //undefined
console.log(person.age); //undefined
console.log(person); //Object
複製程式碼
2.模板字串
相對於es5的' '+變數這種字串拼接方法,es6的模板字串要方便許多。
var a = '張三';
var age = 18;
var b = '我的名字是'+a+'我今年'+age+'歲了'; // es5
var c = `我的名字是${a}我今年${age}歲了`; // es6
複製程式碼
當然簡單的兩行程式碼可能它的優勢沒有那麼的明顯,一旦程式碼量變多,你就能體會到它的便利了。
3.函式
函式預設引數
function num(n) {
n = n || 200; //當傳入n時,n為傳入的值,沒有則預設200
return n;
}
複製程式碼
es6為引數提供了預設值。在定義函式時便初始化了這個引數,直接看程式碼。
function num(n = 200) {
return n;
}
console.log(n()); // 200
console.log(n(100)); // 100
複製程式碼
箭頭函式
箭頭函式的基本用法。
// es5
function breakfast(dessert,drink){
return dessert+drink;
}
// es6
let breakfast = (dessert,drink) => dessert + ' ' + drink;
console.log(breakfast('麵包','牛奶'));
複製程式碼
箭頭函式的this指向繫結定義是所在的作用域,而普通函式this指向執行時所在的作用域(全域性物件),箭頭函式沒有自己的this而是引用外層的this。
// es5
cartView: function() {
var _this = this;
this.$http.get("data/cartData.json", {"id": 123}).then(function(res) {
_this.productList = res.data.result.list;
console.log(_this.productList);
});
}
// es6
cartView(){
this.$http.get("data/cartData.json", {"id": 123}).then((res) => {
this.productList = res.data.result.list;
console.log(this.productList);
});
}
複製程式碼
4.解構
陣列和物件是JS中最常用也是最重要表示形式。為了簡化提取資訊,ES6新增瞭解構,這是將一個資料結構分解為更小的部分的過程。
// es5提取物件
let people = {
name : 'json',
age : 18,
sex : 'male'
};
let name = people.name;
let age = people.age;
...
// es6
let people = {
name : 'json',
age : 18,
sex : 'male'
};
let {name, age, sex} = people;
複製程式碼
相比於es5是不是簡便了許多,當然陣列的方法與物件的類似。下面我們再來舉個栗子,函式引數解構賦值的預設值。
fun ({x, y} = { x: 0, y: 0 }) {
return [x, y];
};
console.log(fun({x: 100, y: 200})); //[100, 200]
console.log(fun({x: 100})); //[100, undefined]
console.log(fun({})); //[undefined, undefined]
console.log(fun()); //[0, 0]
複製程式碼
講了這麼多,可能有人就會問了這個解構到底有什麼用呢?其實它適合於各種與陣列,物件,函式打交道的場景。下面我們來舉個運用最廣的例子—變數交換。直接上程式碼。
//ES5
console.log("ES5:");
var a = 100;
var b = 200;
console.log("交換前:");
console.log("a = " + a); //a = 100
console.log("b = " + b); //b = 200
var temp;
temp = a;
a = b;
b = temp;
console.log("交換後:");
console.log("a = " + a); //a = 200
console.log("b = " + b); //b = 100
//ES6
console.log("ES6:");
var x = 100;
var y = 200;
console.log("交換前:");
console.log("x = " + x); //x = 100
console.log("y = " + y); //y = 200
[x, y] = [y, x];
console.log("交換後:");
console.log("x = " + x); //x = 200
console.log("y = " + y); //y = 100
複製程式碼
5. ...操作符
- 展開操作符
let str2 = ['蘋果','梨子'];
console.log(str2);//["蘋果", "梨子"]
console.log(...str2);//蘋果 梨子
複製程式碼
- 剩餘操作符
fun(a,b,...c){
console.log(a,b,...c);//...c指展開陣列
}
fun('蘋果','香蕉','橘子','梨子','李子');//蘋果 香蕉 橘子 梨子 李子
複製程式碼
6.class、 extends、 super
這三個特性涉及了ES5中最令人頭疼的的幾個部分:原型、建構函式,繼承...看到它們是不是開始懷疑人生了。
別怕有來了ES6我們以後再懷疑吧!
ES6提供了更接近傳統語言的寫法,引入了Class(類)這個概念。新的class寫法讓物件原型的寫法更加清晰、更像物件導向程式設計的語法,也更加通俗易懂。
class MyClass {
constructor() { // 建構函式
// ...
}
get prop() { // 取值
return 'getter';
}
set prop(value) { // 存值
console.log('setter: '+value);
}
}
let inst = new MyClass();
inst.prop = 123;
// setter: 123
console.log(inst.prop);
// 'getter'
複製程式碼
extends用法
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
class ColorPoint extends Point {
constructor(x, y, color) {
this.color = color; // ReferenceError
super(x, y);
this.color = color; // 正確
}
}
複製程式碼
在子類的建構函式中,只有呼叫super之後,才可以使用this關鍵字,否則會報錯。這是因為子類例項的構建,是基於對父類例項加工,只有super方法才能返回父類例項。父類的靜態方法,也會被子類繼承。
注意,super雖然代表了父類Point的建構函式,但是返回的是子類ColorPoint的例項,即super內部的this指的是ColorPoint,因此super()在這裡相當於Point.prototype.constructor.call(this)。
super這個關鍵字,既可以當作函式使用,也可以當作物件使用。在這兩種情況下,它的用法完全不同。 作為函式時,super()只能用在子類的建構函式之中,用在其他地方就會報錯。
class A {}
class B extends A {
m() {
super(); // 報錯
}
}
複製程式碼
第二種情況,super作為物件時,在普通方法中,指向父類的原型物件;在靜態方法中,指向父類。
class A {
p() {
return 2;
}
}
class B extends A {
constructor() {
super();
console.log(super.p()); // 2
}
}
let b = new B();
複製程式碼
上面程式碼中,子類B當中的super.p()就是將super當作一個物件使用。這時,super在普通方法之中,指向A.prototype,所以super.p()就相當於A.prototype.p()。這裡需要注意,由於super指向父類的原型物件,所以定義在父類例項上的方法或屬性,是無法通過super呼叫的。
7.Promise
在promise之前程式碼過多的回撥或者巢狀,可讀性差、耦合度高、擴充套件性低。通過Promise機制,大大提高了程式碼可讀性;用同步程式設計的方式來編寫非同步程式碼,儲存線性的程式碼邏輯,極大的降低了程式碼耦合性而提高了程式的可擴充套件性。
this.$http('/api/getData').then((res) => {
res = res.data;
this.dataList = res.result;
}).catch((err) => {
...
});
複製程式碼
這是一個vue的非同步請求,用的就是promise機制,這樣的好處是不會因為多層的回撥而降低程式碼的可讀性。
當然這只是promise的冰山一角,想要更好的掌握它還是需要更加深入的去學習它。
8.Set
例項的方法分為兩大類:操作方法(用於運算元據)和遍歷方法(用於遍歷成員)。下面先介紹四個操作方法。
- 操作方法: add(value):新增某個值,返回Set結構本身。 delete(value):刪除某個值,返回一個布林值,表示刪除是否成功。 has(value):返回一個布林值,表示該值是否為Set的成員。 clear():清除所有成員,沒有返回值。
- 遍歷方法: keys():返回鍵名的遍歷器 values():返回鍵值的遍歷器 entries():返回鍵值對的遍歷器 forEach():使用回撥函式遍歷每個成員 由於 Set 結構沒有鍵名,只有鍵值(或者說鍵名和鍵值是同一個值)
let str = [1,2,3,2,4,3,5,6,4,1,7];
console.log('str的長度為:'+str.length); // 長度為11
let s = new Set(str);
console.log(s);
console.log('去重後的長度為:'+s.size);//長度為7
console.log( Array.from(s));//Array.from 將Set轉換為陣列形式
let set = new Set(['red', 'green', 'blue']);
var arr = new Set();
for (let item of set.keys()) {
console.log(item);// red green blue
arr.add(item);//將item新增到arr set結構中
}
console.log(arr);
arr.forEach((value, key) => console.log(key + ' : ' + value));
複製程式碼
9.import 和 export
//全部匯入
import mallHeader from '../components/header.vue'
//匯入部分
import {name, age} from './example'
// 匯出預設, 有且只有一個預設
export default App
// 部分匯出
export class App extend Component {};
複製程式碼
小結
這些僅僅是es6家族中的冰山一角,想要更加全面的去掌握這一技能,就需要我們更加系統的去學習它。感謝花了這麼長時間,閱讀文章的小夥伴們,希望能對你們帶來幫助。有錯誤的地方希望大佬們多多包涵,給我反饋!