本文所有Demo的運行環境為nodeJS, 參考:讓nodeJS支持ES6的詞法----babel的安裝和使用 ;
函數的默認值:
如果有參數 ,那就用參數, 如果沒有參數, 那就用默認的參數;
ajax的請求經常要做這些判斷, ES6規定了新的表達式, 讓判斷參數的邏輯更加簡單;
function fn(a = 1, b = 2, c = 3) { console.log(a,b,c); } fn(); //輸出 1, 2, 3; fn(4,5,6); //輸出 4, 5, 6
如果調用函數的時候不想給函數傳參, 用函數的默認值, 那么要傳一個undefined;
function fn(a = 1, b = 2, c = 3) { console.log(a,b,c); } fn(undefined, 1 ,2); //輸出 1, 1, 2 // 以下這種寫法, 會要報異常的; fn( , 1 ,2);
要注意的一種情況, 如果要給函數傳了默認值, 函數的length為: 該函數預期傳入的參數的長度, 不包含已經定義默認值的參數;
function fn(a = 1, b = 2, c = 3) { }; console.log(fn.length); //輸出: 0
函數默認值也可以是一個函數;
function fn(x,y,f = (x,y) => x*y ) { return f(x,y); }; console.log( fn(4,5) ); //輸出:20 console.log( fn(4,5, (x,y) => x+y) ); //輸出:9
函數默認值得一個實際應用, 設置一個參數為必須傳, 不傳者報錯;
function fn( foo = (()=>{throw new Error("Missing parameter")})()) { console.log(foo) } fn(1); fn(); //如果沒有傳參數 , 那么會拋 異常;
rest參數和擴展運算符
rest參數和擴展運算符這兩個表達式是相反的操作, 用處比較廣, 方便了不少
function (...args) {}這里面的...args就叫做rest參數;
...[1,2,3,4]這種方式叫做擴展運算符;
下面這個Demo可以看出來 arr 和 [...arr]是相等的, 這個等式適用於一般的數組:
let arr = [1,2,3,4]; console.log( arr.toString() ===[...arr].toString() ); //輸出 : true
rest參數, 一般都是作為定義函數時候的參數, 一般是function( (...args) ){}或者function (foo, bar, ...args) {} 這樣用的:
let fn = (...args) => { return args; }; console.log(fn(1,2,3,4)); // 輸出 : [ 1, 2, 3, 4 ]
獲取元素的最小值的demo, 雖然沒有什么卵用
let min = (...args) => { return Math.min.apply(null, typeof args[0] === "object" ? args[0] : args); }; console.log(min([2,1,5,7,-2])); //輸出 -2; console.log(min(2,1,5,7,-2)); //輸出 -2;
...rest 這種獲取參數的方式不能用默認值, 否則要拋異常;
let min = (...args = [2,1]) => { return Math.min.apply(null, args); }; console.log(min());
擴展運算符的使用:
let args = [1,2,3,4]; console.log(...args);
擴展運算符能用作函數的調用, 沒發現其他的好處:
let fn = function (...args) { let insideFn = () => { console.log(arguments); }; insideFn(...args); }; console.log( fn(1,2,3,4) );
實際應用,我們想給一個數組的頭部加一個數據,尾部再加一個數據;
let fn = function(...args ) { console.log(args) }; let arr = [1,2,3,4]; fn(0,...arr,5); //輸出 [ 0, 1, 2, 3, 4, 5 ]
或者用來合並數組:
console.log([...[1,2],...[3,4],...[5,6]]); //輸出[ 1, 2, 3, 4, 5, 6 ] let [arr0, arr1, arr2] = [[0],[1],[2]]; console.log([...arr0,...arr1, ...arr2] ); //輸出 : [ 0, 1, 2 ]
擴展運算符內部調用的是Inerator接口, 只要是具有Iterator接口的對象,都可以用擴展運算符,比如Map和Generator:
let map = new Map([ [1,"one"], [2,"two"], [3,"three"] ]); console.log(...map.keys()); // 1 2 3 console.log(...map.values()); //one two three
let fn = function* () { yield 1; yield 2; yield 3; yield 4; }; console.log( ...fn() ); //輸出 1 2 3 4;
ES6的箭頭函數:
ES5和ES3定義函數基本都這樣:
function Fn() {
}
ES6以后就厲害了, 我們還能用箭頭函數表達一個函數, 如下表示的是返回參數的平方:
let fn = (x) => x*x; console.log(fn(10));
在使用箭頭函數的時候, 要直接返回 一個對象的話,return的對象要用括號()括起來, 因為大括號是底層開始解釋js代碼標志, 所以用括號括起來;
let fn = () => ({a:10,b:20}); console.log(fn())
箭頭函數的this指向一定要注意:
let fn = () => { return this; }; console.log(fn); //此時的this為fn; let fn1 = () => console.log(this); //如果是在瀏覽器環境運行的話, 那么此時this為window,如果在node環境下運行this為undefined; fn1();
箭頭函數里面的this不是調用箭頭函數的this, 箭頭函數雖然也有自己的作用域鏈, 但是箭頭函數沒有this, 箭頭函數的this為:離箭頭函數最近的一個通過function(){}創建的函數的this, 說不清的話, 看下Demo....
(function fn(){ let Fn = () => { this.x = 0; this.y = 1; return this; }; //Fn = Fn.bind(new Object); console.log( Fn.call(new Object) ); //輸出結果: { obj: 1, x: 0, y: 1 } }.bind({obj:1}))();
以上Demo能夠說明, 箭頭函數的作用域內的this和誰調用它沒有關系;
當然, 箭頭函數的this跟方法也沒有關系;
(function() { let obj = { method : () => { console.log(this); } }; obj.method(); }.bind("hehe"))()
也正因為箭頭函數的this和箭頭函數一點關系都沒有, 所以箭頭函數不能作為構造函數;
箭頭函數的內部無法獲取到arguments;
箭頭函數不能作為Generator;
ES7提供了一個很方便去綁定作用域的寫法
ES3和ES5和ES6, 綁定作用域都用bind, 或者call, 或者apply, 好家伙, 現在用 :: 兩個冒號
foo::bar; // 等同於 bar.bind(foo); const hasOwnProperty = Object.prototype.hasOwnProperty; function hasOwn(obj, key) { return obj::hasOwnProperty(key); }; */ let query = document.querySelectorAll.bind(document) 等同於: let query = document::document.querySelectorAll;
參考:
Arrow functions : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
ruanyifeng:http://es6.ruanyifeng.com/#docs/function
作者: NONO
出處:http://www.cnblogs.com/diligenceday/
QQ:287101329
微信:18101055830