參數默認值
function sum(a, b, c) {
// b = b || 1;
// c = c || 1;
b = b === undefined && 1;
c = c === undefined && 1;
return a + b + c;
}
console.log(sum(10, 11, 12)); // 33
使用
在書寫形參時宴杀,直接給形參賦值茅郎,賦的值即為默認值蜗元。
這樣一來,當調用函數時系冗,如果沒有給對應的參數賦值(給它的值是undefined)奕扣,則會自動使用默認值。
function sum(a, b = 1, c = 1) {
return a + b + c;
}
console.log(sum(10)); // 12
<div id="container"></div>
<script>
const parent = document.getElementById("container");
function craeteElement(name = "div", container = parent, content = "") {
const ele = document.createElement(name);
if(content) {
ele.innerHTML = content;
}
container.appendChild(ele);
}
// craeteElement("div", parent, "123");
craeteElement(undefined, undefined, "123");
</script>
對 arguments 的影響
function test(a, b) {
console.log("a:", a, "b:", b); // a: 1 b: 2
console.log(arguments); // [1, 2]
a = 3;
console.log("a:", a, "b:", b); // a: 3 b: 2
console.log(arguments); // [3, 2]
}
test(1, 2);
嚴格模式下:
"use strict"
function test(a, b) {
console.log("a:", a, "b:", b); // a: 1 b: 2
console.log(arguments); // [1, 2]
a = 3;
console.log("a:", a, "b:", b); // a: 3 b: 2
console.log(arguments); // [1, 2]
}
test(1, 2);
只要給函數加上參數默認值掌敬,該函數會自動變成嚴格模式下的規(guī)則:argument 和 形參脫離惯豆。
function test(a = 1, b = 3) {
console.log("a:", a, "b:", b); // a: 2 b: 3
console.log(arguments); // [2]
a = 3;
console.log("a:", a, "b:", b); // a: 3 b: 3
console.log(arguments); // [2]
}
test(2);
留意暫時性死區(qū)
形參和ES6中的let和const聲明一樣池磁,具有作用域,并且根據參數的聲明順序楷兽,存在暫時性死區(qū)框仔。
function test(a = b, b) {
console.log(a, b); // Cannot access 'b' before initialization
}
test(undefined, 1);
剩余參數
function sum(arg) {
let sum = 0;
for(let i = 0; i < arg.length; i ++) {
sum += arg[i];
}
return sum;
}
console.log(sum([1])); // 1
console.log(sum([1, 2, 3, 4])); // 10
arguments的缺陷:
- 如果和形參配合使用,容易導致混亂拄养。
- 從語義上离斩,使用arguments獲取參數,由于形參缺失瘪匿,無法從語義上理解函數的真實意圖跛梗。
function sum() {
let sum = 0;
for(let i = 0; i < arguments.length; i ++) {
sum += arguments[i];
}
return sum;
}
console.log(sum(1)); // 1
console.log(sum(1, 2, 3, 4)); // 10
ES6的剩余參數專門用于收集末尾的所有參數,將其放置到形參數組中棋弥。
語法:
function (...形參名) {
}
function sum(...args) {
// args 收集了所有的參數核偿,形成一個數組
// console.log(args);
let sum = 0;
for(let i = 0; i < args.length; i ++) {
sum += args[i];
}
return sum;
}
console.log(sum(1)); // 1
console.log(sum(1, 2, 3, 4)); // 10
細節(jié):
1. 一個函數,只能出現(xiàn)一個剩余參數顽染。
2. 一個函數漾岳,如果有剩余參數,剩余參數必須是最后一個參數粉寞。
展開運算符
使用方式: ...要展開的東西
尼荆。
對 數組展開 ES6
// 對所有數組求和
function sum(...args) {
let sum = 0;
for(let i = 0; i < args.length; i ++) {
sum += args[i];
}
return sum;
}
// 獲取一個指定長度的隨機數組成的數組
function getRandomNumbers(length) {
const arr = [];
for(let i = 0; i < length; i ++) {
arr.push(Math.random());
}
return arr;
}
const numbers = getRandomNumbers(10);
console.log(numbers);
// 將數組的每一項展開,依次作為參數傳遞唧垦,而不是把整個數組作為一個參數傳遞
console.log(sum(...numbers)); // 相當于傳遞了10個參數
深度克峦比濉:
const arr1 = [1, 2, 3];
const arr2 = [...arr1];
console.log(arr2, arr2 === arr1); // [1, 2, 3] false
對 對象展開 ES7
const obj1 = {
name: "劉",
age: 20
}
const obj2 = {
...obj1
}
console.log(obj2, obj2 === obj1); // {name: "劉", age: 20} false
明確函數的雙重用途
使用構造函數,或使用普通函數振亮。
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.fullName = `${firstName} ${lastName}`;
}
const p1 = new Person("p1", "p");
console.log(p1); // {firstName: "p1", lastName: "p", fullName: "p1 p"}
const p2 = Person("p2", "p");
console.log(p2); // undefined
function Person(firstName, lastName) {
// 判斷是否是使用new的方式來調用函數
// 過去的判斷方式
if(!(this instanceof Person)) {
throw new Error("該函數沒有使用new來調用");
}
this.firstName = firstName;
this.lastName = lastName;
this.fullName = `${firstName} ${lastName}`;
}
const p1 = new Person("p1", "p");
console.log(p1); // {firstName: "p1", lastName: "p", fullName: "p1 p"}
// 可避開判斷
const p3 = Person.call(p1, "p3", "p");
console.log(p3); // undefined
const p2 = Person("p2", "p");
console.log(p2); // Uncaught Error: 該函數沒有使用new來調用
ES6提供了一個特殊的API巧还,可以使用該API在函數內部,判斷該函數是否使用了new來調用坊秸。
new.target
// 該表達式麸祷,得到的是:如果沒有使用new來調用函數,則返回undefined褒搔;如果使用new調用函數阶牍,則得到的是new關鍵字后面的函數本身
function Person(firstName, lastName) {
// 判斷是否是使用new的方式來調用函數
// ES6 判斷方法
// console.log(new.target);
if(new.target === undefined) {
throw new Error("該函數沒有使用new來調用");
}
this.firstName = firstName;
this.lastName = lastName;
this.fullName = `${firstName} ${lastName}`;
}
const p1 = new Person("p1", "p");
console.log(p1); // Person {firstName: "p1", lastName: "p", fullName: "p1 p"}
const p3 = Person.call(p1, "p3", "p");
console.log(p3); // Uncaught Error: 該函數沒有使用new來調用
const p2 = Person("p2", "p");
console.log(p2);
箭頭函數
回顧:this指向
- 1.通過對象調用函數,this指向對象
- 2.直接調用函數站超,this指向全局對象
- 3.如果通過new調用函數荸恕,this指向新創(chuàng)建的對象
- 4.如果通過apply、call死相、bind調用函數融求,this指向指定的數據
- 5.如果是DOM事件函數,this指向事件源
const obj = {
count: 0,
start: function() {
console.log(this); // this --> obj
setInterval(function() {
console.log(this); // this --> window
this.count ++;
console.log(this.count); // NaN
},1000)
}
}
obj.start();
const obj = {
count: 0,
start: function() {
// console.log(this); // this --> obj
var self = this;
setInterval(function() {
console.log(self); // this --> obj
self.count ++;
console.log(self.count);
},1000)
}
}
obj.start();
使用語法
箭頭函數是一個函數表達式算撮,理論上生宛,任何使用函數表達式的場景都可以使用箭頭函數县昂。
完整寫法:
(參數1, 參數2) => {
// 函數體
}
const obj = {
count: 0,
start: function() {
console.log(this); // this --> obj
setInterval(() => {
console.log(this); // this --> obj
this.count ++;
console.log(this.count);
},1000)
}
}
obj.start();
如果參數只有一個,可以省略小括號:
參數 => {
// 函數體
}
如果箭頭函數只有一條返回語句陷舅,可以省略大括號倒彰,和return關鍵字:
參數 => 返回值
注意細節(jié)
- 箭頭函數的函數體中的this,取決于箭頭函數定義的位置的this指向莱睁,而與如何調用無關待讳。
1. 箭頭函數中,不存在 this仰剿、arguments创淡、new.target ,如果使用了南吮,則使用的是函數外層的對應的 this琳彩、arguments、new.target 部凑。
2. 箭頭函數沒有原型露乏。
3. 箭頭函數不能作為構造函數使用。
應用場景
1. 臨時性使用的函數涂邀,并不會刻意調用它瘟仿。比如:事件處理函數、異步處理函數必孤、其他臨時性的函數猾骡。
2. 為了綁定外層this的函數。
3. 在不影響其他代碼的情況下敷搪,保持代碼的簡潔。最常見的是數組方法中的回調函數幢哨。
const num = [3, 5, 5, 3, 2];
const result = num.filter(num => num % 2 === 0).map(num => num * 2);
console.log(result); // [4]