ES6函數比對ES5函數
阿新 • • 發佈:2017-12-17
cto 箭頭函數 pan ply 單獨 {} pos efi 直接
簡介
這裏只做簡單的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的同學我們也要抓緊學習啦!
ES6函數比對ES5函數