簡介
這裡只做簡單的ES6函式與ES5函式對比,把ES6函式中新增的方法或者用法介紹一下。方便大家學習、記憶。隨著社會發展,瀏覽器肯定會在不久全部支援ES6語法,因為現在的IE8使用者都很少了,做web前端將不再受此束縛!
函式引數的預設值
其他語言已經支援函式引數預設值,我們們Js也不會落後的。例:
//es6寫法
/**
* @a {number} 預設值10
* @b {number} 預設值20
* */
function fn(a=10,b=20){
console.log(a,b);
}
fn();//沒有傳遞引數
fn(1,3);//傳遞了引數
//es5寫法
/**
* @a {number} 預設值10
* @b {number} 預設值20
* */
function fn(a, b) {
a = a || 10;//設定預設值
b = b || 20;//設定預設值
console.log(a, b);
}
複製程式碼
- 先說說es5寫法這種寫法,如果a傳遞的是false或者(求值為false的值) 則a會使用預設值10,這樣程式碼就沒有按照我們期望的那樣去執行。
//修改es5寫法讓它實現類似於es6:
//es5寫法
/**
* @a {number} 預設值10
* @b {number} 預設值20
* */
function fn(a, b) {
a = a!==undefined?a:10;//設定預設值
b = b!==undefined?b:20;//設定預設值
console.log(a, b);
}
複製程式碼
- es6寫法如果傳入undefined,將觸發該引數等於預設值,其他值不會觸發預設值。
- es6設定預設引數值,在函式體內不允許再次使用let或者const宣告。例:
/**
* es6寫法
* @a {number} 預設值10
* @b {number} 預設值20
* */
function fn(a=10,b=20){
let a=100;//會報錯哦!
const b=20;//會報錯哦!
console.log(a,b);
}
複製程式碼
- 設定引數預設值會產生單獨的作用域。
/**
* es6寫法
* 預設值會產生單獨的作用域,作用域的程式碼也是按照先左後右順序執行。
* @a {number} 預設值10
* @b {number} 預設值10+20
* */
function fn(a=10,b=a+20){//如果這裡是(a=b+20,b=10)呼叫時a沒有傳遞引數此時會報錯!
console.log(a,b);
}
//複雜的例子
/*-----------一條華麗的分割線-------------*/
/**
* ----------預設值會產生單獨的作用域-----------
* 呼叫函式fn 時,未傳遞引數,【預設引數單獨作用域】a值為undefined,b值為undefined。
* 當執行b()函式時,則查詢到a值為undefined,不在查詢全域性a。
* 因此為結果為:a的值為: undefined
* */
var a=`全域性變數`;
function fn(a,b=function(){ console.log(`a的值為:`,a);}){
b();
}
fn();//a的值為: undefined
/**
* ----------預設值會產生單獨的作用域-----------
* 呼叫函式fn 時,未傳遞引數,b值為undefined。
* 當執行b()函式時,則尋找a值發現全域性a。
* 因此為結果為:a的值為: 全域性變數
* */
var a=`全域性變數`;
function fn(b=function(){ console.log(`a的值為:`,a);}){
b();
}
fn();//a的值為: 全域性變數
**
* 現在再來理解一下這個。看看你能答對嗎?
* */
var a = `小小坤`;
function fn(a, y = function() {a = `小小坤1`;}) {
var a = `小小坤2`;
y();
console.log(a);
}
fn() // 答案是?
console.log(a); // 答案是?
複製程式碼
- 使用引數預設值時,函式不能有同名引數。
function fn(a,a,b){
console.log(a,b);//不報錯
}
function fn(a,a,b=1){
console.log(a,b);//報錯
}
複製程式碼
rest 引數
ES6 引入 rest 引數(形式為…變數名),用於獲取函式的多餘引數,這樣就不需要使用arguments物件了。rest 引數搭配的變數是一個陣列,該變數將多餘的引數放入陣列中。例:
//es6寫法
/**
* @b {arry} 引數列表
*
* */
function fn(...b){
b.push(`小小坤`);
console.log(b);
}
fn(1,`20`);//[1, "20", "小小坤"]
//es5寫法
/**
* @a {number} 引數a
* @b {number} 引數b
* */
function fn(a, b) {
var arg=[].slice.call(arguments);
arg.push(`小小坤`);
console.log(arg);
}
複製程式碼
需要注意的是:
- 函式length 屬性不包含rest 引數
(function(a) {}).length // 1
(function(...a) {}).length // 0
(function(a, ...b) {}).length // 1
複製程式碼
- rest 引數不可以這樣使用,只能是最後一個引數
function fn (a,...b,d){
//會報錯!
}
複製程式碼
箭頭函式
使用時注意事項:
1)函式體內的this物件,就是定義時所在的物件,而不是使用時所在的物件。
2)不可以當作建構函式,也就是說,不可以使用new命令,否則會丟擲一個錯誤。
3)不可以使用arguments物件,該物件在函式體內不存在。如果要用,可以用 rest 引數代替。
4)不可以使用yield命令,因此箭頭函式不能用作 Generator 函式。
複製程式碼
簡單例子
/*-----------例子--1------*/
//es6寫法
var fn = n => n;
//等同於es5 寫法
var fn = function(n) {
return n;
};
複製程式碼
/*-----------例子--2------*/
//es6寫法
var fn = () => 5;
// 等同於 es5 寫法
var fn = function () { return 5 };
複製程式碼
/*-----------例子--3------*/
//es6寫法
var sum = (n1, n2) => n1 + n2;
// 等同於es5 寫法
var sum = function(n1, n2) {
return n1 + n2;
};
複製程式碼
如果箭頭函式的程式碼塊部分多於一條語句,就要使用大括號將它們括起來,並且使用return語句返回。
/*-----------例子--4------*/
//es6寫法
var sum = (n1, n2) => { return n1+n2; }
//由於大括號被解釋為程式碼塊,所以如果箭頭函式直接返回一個物件,必須在物件外面加上括號,否則會報錯。
// 報錯
let fn = id => { id: id, age: 18 };
// 不報錯
let fn = id => ({ id: id, age: 18 });
複製程式碼
/*-----------例子--5------*/
function fn() {
setTimeout(() => {
console.log(`id:`, this.id);
}, 100);
}
var id = 21;
fn.call({ id: 42 });
// id: 42
//ES5程式碼需要這樣寫
function fn() {
var _this=this;//儲存this
setTimeout(function() {
console.log(`id:`, _this.id);
}, 100);
}
var id = 21;
fn.call({ id: 42 });
/**
* 上面程式碼中,setTimeout的引數是一個箭頭函式,這個箭頭函式的定義生效是在fn函式生成時,
* 而它的真正執行要等到 100 毫秒後。如果是普通函式,執行時this應該指向全域性物件window,
* 這時應該輸出21。但是,箭頭函式導致this總是指向函式定義生效時所在的物件(本例是{id: 42}),
* 所以輸出的是42。
* 箭頭函式可以讓setTimeout裡面的this,繫結定義時所在的作用域,而不是指向執行時所在的作用域。
*
* 另外,由於箭頭函式沒有自己的this,所以當然也就不能用call()、apply()、bind()這些方法去改變this的指向。
* */
複製程式碼
- this指向
//this指向lib
var lib={
option:{
name:`小小坤`
},
init(){
this.click();
},
click(){
setTimeout(()=>{
console.log(this.option.name);
},2000);
}
}
lib.init();//小小坤
複製程式碼
- 不能使用建構函式
var des=(n)=>{this.n=n};
new des(1);//des is not a constructor
//因為沒有this
複製程式碼
- 沒有arguments屬性
var des=(n)=>{console.log(arguments)};
des();//arguments is not defined
//可以這樣使用
var des=(...n)=>{console.log(n)};
des(1,2,3,4,5);//[1,2,3,4,5]
複製程式碼
總結
經過以上對比可以看出ES6寫的程式碼會越來越少,程式碼質量也逐漸提升。比如預設引數,箭頭函式,還有rest 引數,使用起來爽爆棚!沒有在開發環境使用的ES6的同學我們也要抓緊學習啦!