標準開頭
今天我們來看一下ES6的函式部分知識
函式
函式初始值
有時候,函式的非必填引數,我們可以給予其預設值。保證程式完整不會出錯
在早期,我們賦初始值可能是這樣做的:
// 早期ES5方法
function ajax(url, method, param) {
method = method ? method : 'GET';
param = param ? param : {};
console.log(url, method, param);
}複製程式碼
但是這種方法不夠整潔和美觀。且維護較為麻煩
在ES6中,我們可以直接在引數欄上指定預設值
function ajax(url, method = 'GET', param = {}) {
console.log(url, method, param)
}複製程式碼
這樣讓方法看起來更加整潔。且保證了程式的正常執行
我們可以用babel編譯為ES5程式碼review一下:
'use strict';
function ajax(url) {
var method = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'GET';
var param = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
console.log(url, method, param);
}
ajax('http://www.baidu.com');複製程式碼
轉換為ES5程式碼後,我們可以看出:其轉換方法就是判斷引數列表內是否有值且長度是否足夠。然後再進行判斷
函式剩餘操作符
在對於很多重複引數的函式,我們可以用“...”剩餘操作符進行省略
例如,我們現在有個方法,要把每個引數進行相加,引數可以隨便定義長度。但是長度必須>2
在ES5中,我們可能要重複寫好多的引數名。不僅造成浪費,也讓程式易讀性變差
function sum(param1, param2, param3, param4, param5) {
console.log(param1 + param2 + param3 + param4 + param5);
}複製程式碼
其實我們從param2 - param5可以藉助ES6合併為同一個引數。且無需手動擴充套件
function sum(param1, ...paramN) {
let result = param1;
paramN.forEach((param) => {
result += param
});
console.log(result);
}複製程式碼
合併後的引數會輸出為一個陣列,大家可以按照陣列的操作來操作它
函式引數解構
如果我們按照一個物件的方式當作引數傳入一個函式,且函式引數也是物件的方式接受。那我們可以完成一次解構
還記得之前解構要怎麼做嗎?要保證解構雙方的型別,資料格式要類似
function f({name, age}) {
console.log(name, age);
}
f({name: 'janlay', age: 8});複製程式碼
不難理解
箭頭函式
箭頭函式應該是ES6函式中最Nice的一個知識了。中文名叫“箭頭函式”,英文名叫“Lambda表示式”。
箭頭函式是為了在你宣告方法時,更加簡單便捷。其語法如下:
let sum = (a, b) => {
return a + b;
};複製程式碼
箭頭左邊的是引數列表,右邊的就是函式方法體
當你的函式只有一個引數時,你可以更加簡化函式方法
let result = num => num * 2;複製程式碼
但是當你使用箭頭函式時,你可就小心咯。我們用箭頭函式會涉及到一個叫“作用域”的問題。這個問題通常影響我們的關鍵字this的值
因為箭頭函式內呼叫this,作用域並不是指向箭頭函式本身,而是指向比箭頭函式還要大一層的函式。舉個栗子
let myInfo = {
name: 'janlay',
sayHello: () => {
console.log(`Hi,My name is ${this.name}`)
}
};
myInfo.sayHello();複製程式碼
這時候控制檯輸出undefined
正如我們所說的,箭頭函式內的this會指向它上一層函式中的作用域。但是他並沒有上一層函式體。所以我們列印this,也是顯示undefined
簡述深淺拷貝
先上這樣一段程式碼
let myInfo = {
name: 'janlay',
age: 17
};
let heInfo = {};
heInfo = myInfo;
heInfo.name = 'Mike';
console.log(myInfo);複製程式碼
按照一般邏輯,我們複製一份myInfo到heInfo。然後我們修改heInfo內的屬性,輸出myInfo應該不會變才對
但是我們錯了
{ name: 'Mike', age: 17 }複製程式碼
像這種物件拷貝叫做 “淺拷貝”。意味著只是拷貝了記憶體地址,但是並沒有再記憶體中複製一份給新變數
像這樣的淺拷貝,還有ES6的“Object.assign()”方法。他的作用是傳入2個物件進行合併,然後賦值給第三個物件。
有時候我們會用到淺拷貝,但是一般情況下我們要用到深拷貝。也就是我們常說的值傳遞
深拷貝的方式很多。由於本人學識有限,給大家帶來一個容易理解的深拷貝方法
1. JSON.parse()和JSON.stringify方法
這應該算是最簡單的深拷貝方法了。其原理就是將源物件轉化為一個JSON物件,然後用parse方法再釋放為一個物件。經過這麼一折騰,記憶體地址就發生了改變。也就達到了深拷貝的效果
let myInfo = {
name: 'janlay',
age: 17
};
let heInfo = {};
heInfo = JSON.parse(JSON.stringify(myInfo));
heInfo.name = 'Mike';
console.log(myInfo);複製程式碼
結果輸出為: { name: 'janlay', age: 17 }
2. 使用外接clone方法
其原理也很簡單,通過遍歷物件,讓物件的每個值都挨個複製給新物件,不再進行整體複製。細分到物件的最小單位
function clone(origin) {
let newObj = {}; //新物件
for (let key in origin) { //迴圈原始物件
if (typeof origin[key] === 'object') { //如果物件內的屬性是一個物件
newObj[key] = clone(origin[key]) // 用遞迴方式對物件內的物件進行拆分
} else { //否則
newObj[key] = origin[key]; //如果是簡單的屬性,直接複製
}
}
return newObj; //返回拷貝後的新物件
}複製程式碼
呼叫 heInfo = clone(myInfo);
結果輸出為 { name: 'janlay', age: 17 }
以上兩種深拷貝方法都非常簡單。像瞭解更深度的深拷貝,這裡推薦一個掘金的另一篇文章