==========================函數參數默認值=======================
es6使用參數的默認值, 在書寫的時候,直接給形參賦值,賦的值就是默認值
例如:
function add( a = 1, b = 2 , c){
retrun a + b + c;
}
add(undefined,undefined, 2 ) // 5
add(1,2,3) // 6
默認參數不一定只可以是字面量, 可以是對象, 任何有意義的賦值都可以, 函數, 對象, 數組,正則等
參數默認值對arguements的影響?
嚴格模式下 "use strict" , 形參與arguements是脫離的
非嚴格格式下, 形參與arguements是統一的
只要給函數加上參數默認值, 該函數就會自動變成嚴格模式下, 就是形參與arguements脫離
留意暫時性死區?
形參和ES6中的let或者const聲明一樣, 具有作用域,並且根據形參的聲明順序,存在暫時性死區
例如:
function test(a, b= a){
console.log(a, b)
}
第一次調用: test(1, 2) // 1 2
第二次調用: test(1) // 1 1
但是如果test方法是如下的寫法:
function test(a = b, b){
console.log(a, b)
}
第一次調用 test(undefined, 2) // 報錯, 報暫時性死區的錯誤
得出結果: 在函數裏面,定義變量儘量不要和形參同名
=====================es6剩餘參數========================
以前使用的是arguements,
arguements的缺陷:
1. 如果和形參配合使用, 容易導致混亂, 嚴格模式形參與arguements還相脫離
2. 從語義上使用arguements獲取參數,由於參數缺少,無法從函數定義上無法理解函數的意圖
es6的剩餘參數: 專門用於收集末尾的所有參數,將其放置到一個形參數組中
使用方法: 形參前面加上三點
function(...形參名){
}
細節:
1. 一個函數,僅能出現一個剩餘參數
2. 一個函數,如果有剩餘參數, 剩餘參數必須是最後一個參數
=====================展開運算符===============================
如下面的例子:
<script>
/**
* @description:
* @param : arg 剩餘參數
* @return: 函數的和
*/
function sum(...arg) {
let res = 0;
arg.forEach(item => {
res += item;
})
return res;
}
/**
* @description: 獲取指定長度的數組
* @param : length 長度
* @return: 結果
*/
function getRandomNumbers(length) {
let res = [];
for (let i = 0; i < length; i++) {
res.push(Math.random());
}
return res;
}
</script>
let arr = getRandomNumbers(10);
sum(arr) // 此時傳入的是一個數組, 但是剩餘參數哪裏打印 arg會得到一個二維數組
所以數組需要展開
es6 提供對數組展開: ...需要展開的數組
es7 提供對對象展開: ...需要展開的對象
所以上面的例子就可以使用 sum(...arr); 就可以求和了。
使用 ... 還可以實現下面的操作,
1. 一個數組克隆到另一個數組(淺克隆) 如: const arr = [1,2,3,4]; const arr2 = [...arr1];
2. 一個對象克隆到另一個對象(淺克隆), 如 const obj1 = {name: 1, age: 2}; const obj2 = {...obj1, sex: male}
/**
* @description: 柯里化 用戶固定某個函數前面的參數,得到一個新的函數,新函數調用時候,接受剩餘參數
* @param :
* @return:
*/
function curry(fn, ...args) {
return function (...subArgs) {
const allArgs = [...args, ...subArgs];
// 參數夠了
if (allArgs.length >= fn.length) {
return fn(...allArgs);
} else {
// 參數不夠,繼續固定
curry(fn, ...allArgs);
}
}
}
=========================es6函數的雙用途=====================
函數可以當作普通函數, 也可以當作構造函數
例如:
function Person(firstName, lastName){
// 嚴格模式需要判斷是否使用new 來判斷
// 過去的判斷方式
if(!(this instance of Person)){
throw new Errow(" 該函數沒有使用new 來調用")
}
//es6判斷, 完美判斷
if(new.target === undefined){
throw new Errow(" 該函數沒有使用new 來調用")
}
this.firstName = firstName;
this.lastName = lastName;
this.fullName = `${firstName}${lastName}`
}
const p1 = new Person("成", "都");
console.log(p1) // 要給構造函數對象
const p2 = Person("成", "都");
console.log(p2) //undefined
過去的那種方法會存在弊端, 如果有人強制傳遞this是person,但是又不是new如下:
const p3 = Person.call(new Person("成","都"),"成","都");
console.log(p3) // undefined
現在es6提供一個特殊的api, 可以使用該API在函數的內部,判斷函數是否使用了new來調用
語法:
new.target
// 該表達式得到的是:如果沒有使用new來調用函數,返回的是undefined,
如果使用new來調用,則得到的是new關鍵字後面的函數本身
===============es6箭頭函數===================================
解決this的指向問題
this指向:
1. 通過對象調用函數,this指向那個調用者
2. 直接調用函數, this指向的是window
3. 如果通過new調用函數, this指向新創建的對象
4. 如果通過 apply, call, bind調用函數, this指向指定的數據
5. 如果是DOM時間函數, this指向事件源
存在的問題 :
例如:
const obj = {
count: 0,
start: function(){
// 這裏的this指向的是調用者, 就是obj
setInterval(function(){
// 這裏的這個this 指向的是全局的window
this.count++;
},1000)
},
regEvent: function(){
windwo.onclick = function(){
// this 指向的是事件源
}
}
}
obj.start();
obj.regEvent();
箭頭函數解決this的指向問題:
語法:
箭頭函數是一個函數表達式,理論上任何使用函數表達式的場景,都可以使用箭頭函數
(參數1,參數2,...) => {}
如果參數只有一個,可以省略小括號
參數 => {}
如果箭頭函數裏面只有一條語句並且還是返回的,那麼可以省略大括號和return
例如: const isOdd = num => num%2 !== 0;
// 返回值是一個對象,需要用小括號括起來
const sum = (a,b) => ({
a: a,
b: b,
sum: a + b;
})
細節:
1. 箭頭函數的的函數體中的this,取決於箭頭函數定義的位置的this指向,而於調用無關
2. 箭頭函數, 不存在this, arguments, new.target, 如果使用了,那就是使用的是外層函數的
3. 箭頭函數沒有原型, 箭頭函數佔用的內存空間小,因爲沒有原型
4. 箭頭函數不能當作構造函數, 沒有原型
應用場景:
1. 臨時性使用的函數,並不會調用它, 比如:
1. 事件處理函數
2. 異步處理函數, setTimeOut等
3. 其他臨時性函數
2. 爲了綁定外層this的函數
3. 數組方法中的回調函數
4. 在不影響其他代碼的情況下,保持代碼的簡潔
es6 函數 學習總結
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.