在 ES6 之前,JavaScript 的函式語法幾乎沒有發生太大的變化,而遺留的一些問題導致實現一些基本的功能經常要編寫很多程式碼。而 ES6 對函式的大力度改進,讓我們編寫函式時更加方便且更少出錯。
而關於引數的處理以及箭頭函式是我非常喜歡的功能。
一、函式形參的預設值
JavaScript 中的函式有一個比較特別的地方是形參和實參的數量可以不相同。當定義的形參沒有預設值傳入的時候,JavaScript 會為我們自動傳入一個預設值。
在 ES5 的階段,我們通常會自己設定一個預設值,就像下面這樣:
function getAge(age) {
age = age || 10;
console.log(age);
}
getAge(12); // 12
getAge(0); // 10
複製程式碼
這段程式碼想告訴我們,當傳入引數時,我們就取傳入的值,如果沒有傳入,我們就取預設的 10。但是這通常會有一個問題,當我們傳入一個 0 的時候,它也會被預設為一個假值,並最終將 age 賦值為 10。
在這種情況下,我們往往通過 typeof
檢查引數型別,來實現相關功能:
function getAge(age) {
age = (typeof age !== "undefined") ? age : 10;
console.log(age);
}
getAge(12); // 12
getAge(0); // 10
複製程式碼
這種寫法可以幫助我們更好地處理引數,但仔細想想,若是有多個引數時,這會讓我們寫許多額外的程式碼。幸好 ES6 引數預設值設定的出現,讓我們可以很好的解決這個問題。
function getAge(age=10) {
console.log(age);
}
getAge(); // 10,使用預設值
getAge(12); // 12,不使用預設值
getAge(0); // 0,不適用預設值,且傳入引數為假值的情況
複製程式碼
值得注意的一點是:
function getAge(age=10, newAge=age) {
console.log(newAge);
}
getAge(); // 10
複製程式碼
你可以把第二個引數的預設值設定為第一個引數,但是不能把第一個引數的預設值設定為第二個引數。
另一方面,函式的預設值還可以是一個表示式:
function getValue() {
return 3;
}
function add(first, second=getValue()) {
return first + second;
}
add(1, 3); // 4
add(2); // 5
複製程式碼
二、箭頭函式
箭頭函式是一個比較有趣的特性。因為簡單的語法,大家工作中也經常用到,所以大家也比較熟悉,下面就簡單說說箭頭函式的語法。
箭頭函式有1個引數,且函式體只有一條語句:
let f = value => value;
// 相當於
let f = function(value) {
return value;
};
複製程式碼
箭頭函式沒有引數或者有多個引數,引數部分需要使用小括號:
let f = () => 20;
// 相當於
let f = function() {
return 20
};
let f = (a, b) => a + b;
// 相當於
let f = function(a, b) {
return a + b;
}
複製程式碼
箭頭函式的函式體內有多條語句:
let f = (a, b) => {
return a * b;
};
複製程式碼
想讓箭頭函式返回一個物件字面量,需要將該字面量包裹在小括號裡:
let f = () => ({ id: 1, name: 'zhangsan', age: 18 });
// 相當於
let f = function() {
return {
id: 1,
name: 'zhangsan',
age: 18
};
}
複製程式碼
簡單的介紹完箭頭函式的基本語法,我們來看看箭頭函式的一些主要特性:
1、箭頭函式沒有 this 繫結
箭頭函式中沒有 this
繫結,必須通過查詢作用域鏈來決定其值。如果箭頭函式被非箭頭函式包含,則 this
繫結的是最近一層非箭頭函式的 this
;否則,this
的值會被設定為全域性物件。
或者再簡單一點來說:箭頭函式的 this
指向離它最近的父級作用域 。
舉個例子:
// 普通函式
let person = {
name: 'zhangsan',
age: 18,
say: function() {
console.log(this); // person 物件
console.log(this.name); // 'zhangsan'
console.log(this.age); // 18
}
};
person.say(); // 普通函式,誰呼叫,this 指向誰
複製程式碼
// 箭頭函式
let person = {
name: 'zhangsan',
age: 18,
say: () => {
console.log(this); // window 物件
console.log(this.name); // undefined
console.log(this.age); // undefined
}
};
person.say(); // 箭頭函式,沒有 this,函式內部的 this,指向父級作用域,即全域性
複製程式碼
最後,因為箭頭函式中沒有 this
,所以也不能用 call()、apply()、bind()
等方法改變 this
的指向。
2、箭頭函式沒有原型,不能通過 new
來呼叫
箭頭函式的設計初衷是”即用即棄“,所以不能用它來定義新型別。所以,箭頭函式中沒有 prototype
屬性,自然不能例項化,也就是不能用 new
關鍵字來呼叫。
let Person = () => {};
let p1 = new Person(); // Uncaught TypeError: Person is not a constructor
let Person = () => {};
console.log(Person.prototype); // undefined
複製程式碼
3、沒有 argments 繫結
// 普通函式
let person = function() {
console.log(arguments);
}
person(1); // 列印 arguments 物件
複製程式碼
// 箭頭函式
let person = () => {
console.log(arguments);
}
person(1); // Uncaught ReferenceError: arguments is not defined
複製程式碼
總的來說,箭頭函式和一些小特性的加入,可以使我們的編碼更加方便。
友情連結
如果文章中錯誤或表述不嚴謹的地方,歡迎指正
也歡迎大家關注我的同名微信公眾號:李等等扣丁