ES6中函數新增的方式方法
緒 言
ES6
大家對JavaScript中的函數都不陌生。今天我就為大家帶來ES6中關於函數的一些擴展方式和方法。
1.1函數形參的默認值
1.1.1基本用法ES6 之前,不能直接為函數的參數指定默認值,只能采用變通的方法。如下代碼:
function func(x,y){ y = y || "tom"; console.log(x,y); } func("hello"); //hello tom func("hello","woeld"); //hello woeld func("hello",""); //hello tom
function func(x,y){ if(typeof y === "undefined"){ y = y || "tom"; } console.log(x,y); } func("hello"); //hello tom func("hello","woeld"); //hello woeldfunc("hello",""); //hello
ES6 允許為函數的參數設置默認值,即直接寫在參數定義的後面。如下代碼:
function func(x,y="tom"){ console.log(x,y); } func("hello"); //hello tom func("hello","woeld"); //hello woeld func("hello",""); //hello
ES6 的寫法還有兩個好處:首先,閱讀代碼的人,可以立刻意識到哪些參數是可以省略的,不用查看函數體或文檔;其次,有利於將來的代碼優化,即使未來的版本在對外接口中,徹底拿掉這個參數,也不會導致以前的代碼無法運行。
1.1.2默認值與解構賦值結合
function func({x,y=3}){ console.log(x,y); } func({}); //undefined 3 func({x:1}); //1 3 func({x:1,y:2}); //1 2 func(); //Uncaught TypeError: Cannot destructure property `x` of ‘undefined‘ or ‘null‘.
上面代碼只使用了對象的解構賦值默認值,沒有使用函數參數的默認值。只有當函數func的參數是一個對象時,變量x
和y
才會通過解構賦值生成。如果函數func
調用時沒提供參數,變量x
和y
就不會生成,從而報錯。通過提供函數參數的默認值,就可以避免這種情況。
如果沒有提供參數,函數func
的參數默認為一個空對象。
1.1.3參數默認值的位置
function func(x,y=2,z){ console.log(x,y,z); } func(); //undefined 2 undefined func(1); //1 2 undefined func(1, ,3); //Uncaught SyntaxError: Unexpected token func(1,undefined,3);//1 2 3
func(1,null,3); //1 null 3
上面代碼中,有默認值的參數都不是尾參數。這時,無法只省略該參數,而不省略它後面的參數,除非顯式輸入undefined
。
如果傳入undefined
,將觸發該參數等於默認值,null
則沒有這個效果。
1.1.4函數的length屬性和作用域
length
指定了默認值以後,函數的length
屬性,將返回沒有指定默認值的參數個數。也就是說,指定了默認值後,length
屬性將失真。
作用域
一旦設置了參數的默認值,函數進行聲明初始化時,參數會形成一個單獨的作用域(context)。等到初始化結束,這個作用域就會消失。這種語法行為,在不設置參數默認值時,是不會出現的。
1.2rest參數
ES6 引入 rest 參數(形式為...變量名
),用於獲取函數的多余參數,這樣就不需要使用arguments
對象了。rest 參數搭配的變量是一個數組,該變量將多余的參數放入數組中。如下代碼:
function add(...values) { var sum = 0; for (var val of values) { sum += val; } console.log(sum); } add(2, 5, 3) // 10
上面代碼的add
函數是一個求和函數,利用 rest 參數,可以向該函數傳入任意數目的參數。
rest 就是一個真正的數組,數組特有的方法都可以使用
註意,rest 參數之後不能再有其他參數(即只能是最後一個參數),否則會報錯。
1.3name屬性
函數的name
屬性,返回該函數的函數名。如下代碼:
var a = function func(){}; console.log(a.name); //func var b = function(){}; console.log(b.name); //b
1.4箭頭函數
基本用法與註意事項
ES6 允許使用“箭頭”(=>
)定義函數。如下代碼:
var f = v => v; //上面的箭頭函數等同於 var f = function(v) { return v; };
如果箭頭函數不需要參數或需要多個參數,就使用一個圓括號代表參數部分。如下代碼:
var f = () => 5; // 等同於 var f = function () { return 5 }; var sum = (num1, num2) => num1 + num2; // 等同於 var sum = function(num1, num2) { return num1 + num2; };
如果箭頭函數的代碼塊部分多於一條語句,就要使用大括號將它們括起來,並且使用return
語句返回。如下代碼:
var sum = (num1, num2) => { return num1 + num2; }
箭頭函數可以與變量解構結合使用。如下代碼:
var full = ({ first, last }) => first + ‘ ‘ + last; // 等同於 function full(person) { return person.first + ‘ ‘ + person.last; }
箭頭函數使得表達更加簡潔。如下代碼:
var isEven = n => n % 2 == 0;
var square = n => n * n;
註意事項:
(1)函數體內的this
對象,就是定義時所在的對象,而不是使用時所在的對象。
(2)不可以當作構造函數,也就是說,不可以使用new
命令,否則會拋出一個錯誤。
(3)不可以使用arguments
對象,該對象在函數體內不存在。如果要用,可以用 rest 參數代替。
(4)不可以使用yield
命令,因此箭頭函數不能用作 Generator 函數。
this
對象的指向是可變的,但是在箭頭函數中,它是固定的。
1.5綁定this
箭頭函數可以綁定this
對象,大大減少了顯式綁定this
對象的寫法(call
、apply
、bind
)。但是,箭頭函數並不適用於所有場合,所以現在有一個提案,提出了“函數綁定”(function bind)運算符,用來取代call
、apply
、bind
調用。
函數綁定運算符是並排的兩個冒號(::
),雙冒號左邊是一個對象,右邊是一個函數。該運算符會自動將左邊的對象,作為上下文環境(即this
對象),綁定到右邊的函數上面。如下代碼:
foo::bar; // 等同於 bar.bind(foo); foo::bar(...arguments); // 等同於 bar.apply(foo, arguments);
1.7尾調用
尾調用(Tail Call)是函數式編程的一個重要概念,是指某個函數的最後一步是調用另一個函數。如下代碼:
function f(x){ return g(x); }
尾調用不一定出現在函數尾部,只要是最後一步操作即可。下面代碼中,函數m
和n
都屬於尾調用,因為它們都是函數f
的最後一步操作。
function f(x) { if (x > 0) { return m(x) } return n(x); }
ES6中函數新增的方式方法