ECMAScript常用新特性
首先,什麼是ES6呢,這裏不再去複製粘貼概念,說白了ES6不是一門語言,而是腳本語言規範,而JavaScript是ES6規範的一種實現.我們可以簡單想像成JDK和Java之間的關係.
1. 變量的聲明 let
1)var聲明的變量會越域,而let聲明的變量有嚴格的局部作用域
{
var a = 1;
let b = 2;
}
console.log(a);
console.log(b);
2)var可以對同一個變量聲明多次,而let對同給一個變量只可以聲明一次
var a = 1;
var a = 2;
var a = 3;
let b = 1;
let b = 2;
console.log(a);
console.log(b);
3)var會變量提升,在var a 之前使用a,會得到undefined但是,在let b之前使用b會直接報錯
2. const 聲明常量(只讀變量)
const a = 1;
a = 3;
console.log(a);
3. 解構表達式
個人而言,第一次接觸解構表達式是在python,話說python對編程語言的影響真的好大,無論是java還是ES6標準這次的ES6很多新特性感覺都是借鑑了python,這將使得我們以後用js開發越發的便捷.
1)數組解構
普通方式:
let arr = [1,2,3];
let a = arr[0];
let b = arr[1];
let c = arr[2];
解構表達式:
let arr = [1,2,3];
let [a, b, b] = arr;
2)對象解構
普通方式:
const person = {
name: "jack",
age: 21,
language: ['java','js','css']
}
const name = person.name;
const age = person.age;
const language = person.language;
解構表達式:
let {person.field:foo);
這裏":"左邊是對象中的屬性,而右邊是要接收屬性值的變量名稱.
let {name:nm, age:a, language:lan} = person;
console.log(nm);
console.log(a);
console.log(lan);
如果要用來接收屬性值的變量名稱和屬性名稱相同,name可以簡寫爲:
let {name, age, language} = person;
console.log(name);
console.log(age);
console.log(language);
4. 字符串擴展
類似java語言,ES6新特性中,對字符串添加了如下的支持.
let str = "hello.vue";
console.log(str.startsWith("hello")); //true
console.log(str.endsWith(".vue")); //true
console.log(str.includes("e")); //true
console.log(str.includes("hello")); //true
5. 字符串模板
這個寫法我也在python中見過,只不過python中好像是三單引號
ES6中用的是反向的點(tab鍵上面的那個)
let str = `
<div>
<span>hello world</span>
</div>
`
console.log(str);
真的是很方便啊,想想以前苦逼的拼接字符串是多麼痛苦
6.字符串插入變量和表達式
這個最早在shell中見到過,python中也有,強!拼接字符串越來越方便了.
let name = "jack";
let age = 23;
let info = `名字:${name}, 年齡:${age + 1}`;
console.log(info);
還可以調用方法哦!這個就越來越像shell了
function hi() {
return "Hello World";
}
let info = `你好:${hi}`;
let info2 = `你好:${hi()}`;
console.log(info);
console.log(info2);
7. 函數優化
1) 函數參數的默認值
這樣,我們在調用add2的時候,即使只傳一個a的值進去,也可以正常執行.
function add(a, b) {
b = b || 11
return a + b;
}
function add2(a, b = 11) {
return a+b;
}
2) 不定參數
這樣我們可以根據不同個數的參數,動態的處理不同的業務
function fun(...values) {
console.log(values.length);
}
fun(1, 2);
fun(1, 2, 3, 4);
3) 箭頭函數
這不是JavaScript版lambda表達式嗎…太強了!
3-1)單參數
普通方式:
var prt = function(obj) {
console.log(obj);
}
箭頭函數:
var prt = obj => console.log(obj);
prt("Hello world");
3-1)多參數
普通方式:
var sum = function(a, b) {
return a + b;
}
箭頭函數:
var sum2 = (a, b) => a + b;
console.log(sum2(1, 2));
多行寫法
var sum2 = (a, b) => {
let c = a + b;
return c;
}
8. 對象優化
1) 獲取對象中信息的方法
const person = {
name: "jack",
age: 21
language: ['java','js','css']
}
console.log(Object.keys(person));
console.log(Object.values(person));
console.log(Object.entries(person));['java','js','css']]]
2)assign
將後面的內容依次分配給target.
const target = {a:1};
const source1 = {b:2};
const source2 = {c:3};
Object.assign(target, source1, source2);
console.log(Object.entries(target));
3) 聲明對象的簡寫方式
普通方式:
const age = 23;
const name = "jack"
const person1 = {age: age, name: name};
新方式:
但是要求,對象屬性和變量同名
const person2 = {age, name};
4) 對象的函數屬性簡寫
普通方式:
let person = {
name: "jack",
eat: function(food) {
console.log(this.name + " is eating " + food);
}
}
新方式:
let person = {
name: "jack",
eat2: food => {
// 箭頭函數this不能使用
console.log(person.name + " is eating " + food);
},
eat3(food) {
console.log(this.name + " is eating " + food);
}
}
person.eat2("apple");
person.eat3("banana");
5)對象的擴展運算符
感覺類似python的封裝
1- 拷貝對象
let person = {name:"Amy", age:15};
let p1 = {...person};
console.log(p1);
2- 合併對象
將多個對象合併爲一個對象
let age1 = {age: 15};
let name1 = {name: "Amy"};
let p2 = {...age1, ...name1};
console.log(p2);
9.map和reduce函數
1)map解構一個函數,將原數組中的元素,用這個函數處理後,放入新數組返回
這個在python中也見過,java8中的map也是如此,這裏map不是集合而是映射的含義
將數組中的元素都擴大爲原來的2倍
let arr = ['1', '20', '3', '-6'];
arr = arr.map((item) => {
return item * 2;
});
也可以寫成
arr = arr.map(item => item * 2);
2) reduce
爲數組中的每一個元素依次執行回調函數,不包括數組中被刪除或從未被賦值的元素
語法:
/*
initialValue:是初始值
callback可以有4個參數:
callback
(
previousValue,
currentValue,
index,
array);
previousValue:
上一次處理後的返回值,或者是initialValue,如果沒有initialValue則是第一個元素
currentValue:
數組中當前被處理的元素
index:當前元素索引
array:調用reduce函數的數組.
*/
arr.reduce(callback, [initialValue]);
舉例:
let arr = [1, 20, -5, 3];
let result = arr.reduce(
(prev, curr) => {
console.log(`previousValue: ${prev}`);
console.log(`currentValue: ${curr}`);
return prev + curr;
},100);
console.log(result);
10. (※)Promise
在JavaScript世界中,所有的代碼都是單線程執行的.
由於這個"缺陷",導致JavaScript的所有網絡操作,都必須是異步執行回調函數實現。
一旦有一連串的ajax請求a,b,c,d…後面的請求依賴前面的請求結果,就需要層層嵌套。
這種縮進和層層嵌套的方式,非常容易造成上下文代碼混亂,我們不得不非常小心翼翼處理內層函數與外層函數的數據,一旦內層函數使用了上層函數的變量,這種混亂程度就會加劇…總之,這種"層疊上下文"的層層嵌套方式,着實增加了神經的緊張程度.
傳統寫法:
一層套一層,閱讀起來很繁瑣,也很容易出錯.
const url_stu = "./data/stu";
const url_course = "./data/course";
const url_score = "./data/scores";
$.ajax({
url: `${url_stu}.json`,
success(stu) {
console.log("getting students's info ~~~~~~");
console.log(stu.students[0]);
$.ajax({
url: `${url_course}_${stu.students[0].id}.json`,
success(course) {
console.log("getting courses's info ~~~~~~");
console.log(course.courses[0]);
$.ajax({
url: `${url_score}_${course.courses[0].id}.json`,
success(score) {
console.log("getting scores's info ~~~~~~");
console.log(score.scores[0]);
},
error(error) {
// ....
}
})
},
error(error) {
// ....
}
})
},
error(error) {
// ....
}
});
Promise寫法:
const url_stu = "./data/stu";
const url_course = "./data/course";
const url_score = "./data/scores";
let p = new Promise((resolve, reject) => {
$.ajax({
url: `${url_stu}.json`,
success(stu) {
console.log("getting stu's info ~~~~~");
console.log(stu.students[0]);
resolve(stu);
},
error(error) {
reject(error);
}
});
});
let p2 = p.then(obj => {
return new Promise((resolve, reject) => {
$.ajax({
url: `${url_course}_${obj.students[0].id}.json`,
success(course) {
console.log("getting course's info ~~~~~");
console.log(course.courses[0]);
resolve(course);
},
error(error) {
reject(error);
}
});
});
}).catch(error = {
// ....
}).then(obj => {
new Promise((resolve, reject) => {
$.ajax({
url: `${url_score}_${obj.courses[0].id}.json`,
success(score) {
console.log("getting scores's info ~~~~~~");
console.log(score.scores[0]);
resolve(score);
},
error(error) {
reject(error);
}
});
});
}).catch(error = {
// ....
});
很有邏輯感是不是,每一次ajax請求都是單獨的書寫,不用嵌套.
但是看起來還是很多,很麻煩,接下來簡化一下.
const url_stu = "./data/stu";
const url_course = "./data/course";
const url_score = "./data/scores";
function get(url) {
return new Promise((resolve, reject) => {
$.ajax({
url: url,
success(data) {
resolve(data);
},
error(error) {
reject(error);
}
})
})
}
get(`${url_stu}.json`)
.then(obj => {
console.log("getting stu's info success");
console.log(obj.students[0]);
return get(`${url_course}_${obj.students[0].id}.json`);
})
.then(obj => {
console.log("getting course's info success");
console.log(obj.courses[0]);
return get(`${url_score}_${obj.courses[0].id}.json`);
}).then(obj => {
console.log("getting score's info success");
console.log(obj.scores[0]);
});
11. 模塊化
1)什麼是模塊化
模塊化就是把代碼進行拆分,方便重複利用。
類似java中的導包:要使用一個包,必須先導包。
而js中沒有包的概念,js中是模塊的概念(越來越像python了)
模塊功能主要由2個命令構成:export和import
2)實例演示
export命令用於規定模塊的對外接口,它不僅可以導出對象,一切JS變量都可以導出,比如:基本類型變量,函數,數組,對象.
util.js
const util = {
sum(a, b) {
return a + b;
}
}
let a = 1;
let person = {
name: "jack",
age: 18
}
let arr = [1, 2, 3]
export { util, a, person, arr }
hello.js
import {util,a,person,arr} from "/js/util.js";
console.log(util.sum(1, 2));
console.log(a);
console.log(person);
console.log(arr);
這裏的調用方式,如果是在html引入的話,需要加上type="module"
,這是由於<script>
標籤默認的type是application/javascript
,所以默認的只是當成普通的js文件引入,而模塊化的概念是ES6的標準,在ES6中,import和export語法只能在模塊中使用,如下圖所示,因此,要告訴瀏覽器,我們要以模塊的形式引入這個js文件.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script type="module" src="./js/hello.js">
</script>
</body>
</html>
當然還有很多其他的特性,但是目前只接觸到了這些,算是比較常用的吧,以後碰到了還會陸續更新。