ES6函式比對ES5函式

小小坤發表於2019-02-28

簡介

這裡只做簡單的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);
}	
複製程式碼
  1. 先說說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);
}	
複製程式碼
  1. es6寫法如果傳入undefined,將觸發該引數等於預設值,其他值不會觸發預設值。
  2. 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);
}
複製程式碼
  1. 設定引數預設值會產生單獨的作用域。
/**
 * 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); // 答案是?
複製程式碼
  1. 使用引數預設值時,函式不能有同名引數。
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);
}
複製程式碼

需要注意的是:

  1. 函式length 屬性不包含rest 引數
(function(a) {}).length  // 1
(function(...a) {}).length  // 0
(function(a, ...b) {}).length  // 1
複製程式碼
  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的指向。
 * */
複製程式碼
  1. this指向
//this指向lib
var lib={
	option:{
		name:`小小坤`
	},
	init(){
		this.click();
	},
	click(){
		setTimeout(()=>{
			console.log(this.option.name);
		},2000);
	}
}
lib.init();//小小坤
複製程式碼
  1. 不能使用建構函式
var des=(n)=>{this.n=n};
new des(1);//des is not a constructor
//因為沒有this
複製程式碼
  1. 沒有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的同學我們也要抓緊學習啦!

相關文章