前後端技術棧對比
1.簡介
ECMAScript 6.0(以下簡稱 ES6)是 JavaScript 語言的下一代標準,已經在 2015 年 6 月正式發佈了。
目標:是使得 JavaScript 語言可以用來編寫複雜的大型應用程序,成爲企業級開發語言。
2.什麼是ECMAScript
ECMAScript是瀏覽器腳本語言的規範;
ECMAScript是JavaScript的規格,JavaScript是ECMAScript的一種實現;
Node 是 JavaScript 的服務器運行環境(runtime)。
3.ES6新特性與VSCode的使用
shift+!生成html頭
alt+shift+f格式化代碼
3.1let
- let聲明的變量有嚴格局部作用域
// var 聲明的變量往往會越域
// let 聲明的變量有嚴格局部作用域
{
var a = 1;
let b = 2;
}
console.log(a); // 控制檯輸出1
console.log(b); // 會報錯,b未被定義
- let 只能聲明一次
// var 可以聲明多次
// let 只能聲明一次
var m = 1
var m = 2
let n = 3
let n = 4
console.log(m) // 控制檯打印2
console.log(n) // 報錯已經被定義
- let 不存在變量提升
// var 會變量提升
// let 不存在變量提升
console.log(x); // 未定義
var x = 10;
console.log(y); //報錯沒找到y變量
let y = 20;
3.2const聲明常量
- const聲明之後不允許改變,一但聲明必須初始化,否則會報錯
// 1. 聲明之後不允許改變
// 2. 一但聲明必須初始化,否則會報錯
const a = 1;
a = 3; //Uncaught TypeError: Assignment to constant variable.
3.3解構表達式
- 數組解構
let arr = [1,2,3];
//將數組放入abc;
let a = arr[0];
let b = arr[1];
let c = arr[2];
console.log(a,b,c)
//解構寫法將arr賦值給abc
let [a,b,c] = arr;
//打印結果相同
console.log(a,b,c)
- 對象解構
//聲明一個對象
const person = {
name: "jack",
age: 21,
language: ['java', 'js', 'css']
}
//將對象中屬性分別賦值給各個常量
const name = person.name;
const age = person.age;
const language = person.language;
console.log(name, age, language)
//解構寫法
const { name: abc, age, language } = person;
//打印結果相同
console.log(abc, age, language)
- 字符串擴展
1.幾個新的API模板
let str = "hello.vue";
//是否以hello開頭
console.log(str.startsWith("hello"));//true
//是否以.vue開頭
console.log(str.endsWith(".vue"));//true
//是否包含e字符
console.log(str.includes("e"));//true
//是否包含hello
console.log(str.includes("hello"));//true
2.字符串模板
- 多行字符串使用``符號
let ss = `<div>
<span>hello world<span>
</div>`;
console.log(ss);
打印的格式如下:保留了字符串原來的格式
- 字符串插入變量和表達式。變量名寫在{ }中可以放JavaScript表達式
const name = 'jack';
const age = 20;
let info = `我是${name },今年${age + 10}了`;
console.log(info);
//打印:我是jack,今年30歲了
- 字符串中調用函數(接上例)
function fun() {
return "這是一個函數"
}
let info = `我是${abc},今年${age + 10}了, 我想說: ${fun()}`;
console.log(info);//我是jack,今年30歲了,我想說這是一個函數
3.4箭頭函數(函數優化)
- 給函數參數一個默認值
//在ES6以前,我們無法給一個函數參數設置默認值,只能採用變通寫法:
function add(a, b) {
// 判斷b是否爲空,爲空就給默認值1
b = b || 1;
return a + b;
}
// 傳一個參數
console.log(add(10));//輸出11
//現在可以這麼寫:直接給參數寫上默認值,沒傳就會自動使用默認值
function add2(a, b = 1) {
return a + b;
}
console.log(add2(20));//輸出21
- 不定參數:用來表示不確定參數個數,格式爲**…變量名**,由…加上一個具名參數標識符組成。具名參數只能放在參數列表的後面,並且有且只有一個不定參數
function fun(...values) {
console.log(values.length)
}
fun(1, 2) //2
fun(1, 2, 3, 4) //4
- 箭頭函數
1.單個參數
//以前聲明一個方法
var print = function (obj) {
console.log(obj);
}
print("hello");//打印hello
//箭頭函數寫法
var print1 = obj => console.log(obj);
print1("hello");//打印hello
2.多個參數
var sum = function (a, b) {
c = a + b;
return a + c;
}
console.log(sum(10, 20))//30
//箭頭函數寫法
var sum2 = (a, b) => {
c = a + b;
return a + c;
}
console.log(sum2(10, 20))//30
3.5對象優化
- 新增的api
const person = {
name: "jack",
age: 21,
language: ['java', 'js', 'css']
}
//Object.keys()將對象中的屬性封裝成一個數組返回
console.log(Object.keys(person));//["name", "age", "language"]
//Object.values()將對象中屬性對應的值封裝成一個數組返回
console.log(Object.values(person));//["jack", 21, Array(3)]
//Object.entries()將對象中屬性和值的鍵值對封裝成數組返回
console.log(Object.entries(person));//[Array(2), Array(2), Array(2)]
//聲明三個對象
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };
//想要將target對象編程這種格式{a:1,b:2,c:3}
// Object.assign()方法的第一個參數是目標對象,後面的參數都是源對象
Object.assign(target, source1, source2);
console.log(target);//["name", "age", "language"]
- 聲明對象的簡寫方式
const age = 23
const name = "張三"
const person1 = { age: age, name: name }
//當變量或常量名與對象中屬性名相同可以簡寫成以下方式
const person2 = { age, name }
console.log(person2);//{ age: 23, name: 張三 }
- 對象的函數屬性簡寫
let person3 = {
name: "jack",
// 以前:
eat: function (food) {
console.log(this.name + "在喫" + food);
},
//箭頭函數this不能使用,使用對象.屬性
eat2: food => console.log(person3.name + "在喫" + food),
eat3(food) {
console.log(this.name + "在喫" + food);
}
}
person3.eat("香蕉");//jack在喫香蕉
person3.eat2("蘋果");//jack在喫蘋果
person3.eat3("橘子");//jack在喫橘子
- 對象擴展運算符
// 1、拷貝對象(深拷貝)
let p1 = { name: "Amy", age: 15 }
let someone = { ...p1 }
console.log(someone) //{name: "Amy", age: 15}
// 2、合併對象
let age1 = { age: 15 }
let name1 = { name: "Amy" }
let p2 = {name:"zhangsan"}
//會覆蓋之前的屬性值
p2 = { ...age1, ...name1 }
console.log(p2)//{ name: "Amy", age: 15 }
- map和reduce方法
//map():接收一個函數,將原數組中的所有元素用這個函數處理後放入新數組返回。
let arr = ['1', '20', '-5', '3'];
//將數組中每個參數乘以二並返回,item屬性指每個元素
arr = arr.map((item)=> item*2);
console.log(arr);//[2, 40, -10, 6]
//reduce() 爲數組中的每一個元素依次執行回調函數,不包括數組中被刪除或從未被賦值的元素,
//arr.reduce(callback,[initialValue(初始執行的值)])
let result = arr.reduce((a,b)=>{
console.log("上一次處理後:"+a);
console.log("當前正在處理:"+b);
return a + b;
},100);
console.log(result)
輸出如下
3.6Promise異步編排
-
Promise爲什麼出現?
在Promise之前,在js中的異步編程都是採用回調函數和事件的方式,但是這種編程方式在處理複雜業務的情況下,很容易出現callback hell(回調地獄),使得代碼很難被理解和維護。 -
Promise是什麼?
Promise是ES6中的一個內置的對象(實際上是一個構造函數,通過這個構造函數我們可以創建一個Promise對象), Promise就是改善這種回調地獄的異步編程的解決方案。 -
Promise的三種狀態
1.pending[待定]初始狀態
2.fulfilled[實現]操作成功
3.rejected[被否決]操作失敗
注 : 當promise狀態發生改變,就會觸發then()裏的響應函數處理後續步驟; -
Promise對象的狀態改變,只有兩種可能:
從pending變爲fulfilled
從pending變爲rejected。
注 : 這兩種情況只要發生,Promise狀態就凝固了,不會再變了。 -
resolve()與reject()
resolve() 作用: 將Promise對象的狀態從“未完成”變爲“成功”在異步操作成功時調用,並將異步操作的結果,作爲參數傳遞出去;
reject() 作用: 將Promise對象的狀態從“未完成”變爲“失敗”,在異步操作失敗時調用,並將異步操作報出的錯誤,作爲參數傳遞出去。 -
then()
then()的作用:是爲Promise實例添加狀態改變時的回調函數。then方法的第一個參數是Resolved(成功)狀態的回調函數,第二個參數(可選)是Rejected(失敗)狀態的回調函數(不建議使用第二個參數我們可以選擇catch(),catch()方法返回的還是一個Promise對象,我們可以在後面繼續使用then進行鏈式調用。)。
--------->.then()返回一個新的Promise實例,所以它可以鏈式調用
--------->then()會根據Promise的狀態改變結果,選擇特定的狀態響應(成功或失敗回調)函數執行。
--------->狀態響應函數可以返回新的promise,或其他值,不返回值也可以我們可以認爲它返回了一個null;
--------->如果返回新的promise,那麼下一級.then()會在新的promise狀態改變之後執行
--------->如果返回其他任何值,則會立即執行下一級.then() -
Promise.all()
方法用於將多個Promise實例包裝成一個新的Promise實例,如下所示:
var p = Promise.all([p1, p2, p3]);
p的狀態由p1,p2,p3決定, 分成下面的兩種情況:
只有p1、p2、p3的狀態都變成fulfilled,p的狀態纔會變成fulfilled,此時p1、p2、p3的返回值組成一個數組,傳遞給p的回調函數。
只要p1、p2、p3之中有一個被rejected,p的狀態就變成rejected,此時第一個被reject的實例的返回值,會傳遞給p的回調函數。
function promiseClick(){
let p = new Promise(function(resolve, reject){
setTimeout(function(){
var num = Math.ceil(Math.random()*20); //生成1-10的隨機數
console.log('隨機數生成的值:',num)
if(num<=10){
resolve(num);
}
else{
reject('數字太於10了即將執行失敗回調');
}
}, 2000);
})
return p
}
promiseClick().then(
function(data){
console.log('resolved成功回調');
console.log('成功回調接受的值:',data);
}
)
.catch(function(reason, data){
console.log('catch到rejected失敗回調');
console.log('catch失敗執行回調拋出失敗原因:',reason);
});
3.7模塊化
- 什麼是模塊化?
1.模塊可以理解爲函數代碼塊的功能,是封裝對象的屬性和方法的javascript代碼,它可以是某單個文件、變量或者函數。
2.模塊實質上是對業務邏輯分離實現低耦合高內聚,也便於代碼管理而不是所有功能代碼堆疊在一起,模塊真正的魔力所在是僅導出和導入你需要的綁定,而不是將所有的東西都放到一個文件。
3.理想狀態下我們只需要完成自己部分的核心業務邏輯代碼,其他方面的依賴可以通過直接加載被人已經寫好模塊進行使用即可。 - export 導出 與import導入命令
一個模塊就是一個獨立的文件。如果想從外部能夠讀取模塊內部的某個變量,就必須使用export關鍵字輸出該變量。分爲以下幾種情況:
1.在需要導出的hello.js文件中, 使用 export{接口名} 導出變量,常量或函數,接口名就是hello.js的變量名或函數名,對應的導入命令import {接口名} from "導入接口所在文件位置"
導出命令user.js
var name = "jack"
var age = 21
function add(a,b){
return a + b;
}
export {name,age,add}
導入到main.js
import {name,age,add} from "./user.js"
2.在export接口的時候, 也可以使用 export { var1 as num1, var2 as num2};修改導出的接口名字,在導入時直接使用重新定義的接口名
var name = "jack"
var age = 21
function add(a,b){
return a + b;
}
export {name as name1,age as age1,add as add1}
導入到main.js
import {name1,age1,add1} from "./user.js"
3.直接在變量或函數聲明前面加上export命令可以實現直接導出(書寫簡易):導入命令同上1.
export const util = {
sum(a, b) {
return a + b;
}
}
4.不需要知道變量名字(相當於是匿名的)的情況,可以 直接把開發的接口給export。如果一個js模塊文件就只有一個功能, 那麼就可以使用export default導出。導入時可自定義變量或者函數名
user.js
export default {
sum(a, b) {
return a + b;
}
}
導入到main.js
import fun1 from "user.js"