抹桥的博客
Language
Home
Archive
About
GitHub
Language
主题色
250
2107 文字
11 分
ECMAScript6 学習メモ(3) - 関数拡張

1.関数引数のデフォルト値#

以前は、以下のようなコードをよく書いていました。

function doS(e) {
  e = e | window.e;
  //doSomeThing with e
}

このような方法で関数にデフォルト値を設定すると、渡された引数の真偽値がfalse(例えば空文字列や0)の場合に問題が発生するという欠点がありました。

そのため、上記のコードで正しい結果を得たい場合は、eが代入されているかどうかをさらに判断する必要がありました。

これは非常に面倒だったので、ES6では以下のような新しい方法が導入されました。

function doS(e = window.e) {
  //doSomeThing with e
}

これにより、コードが大幅に短縮されるだけでなく、可読性も大幅に向上し、コードを読む人がどの引数にデフォルト値があるのかを一目で確認できるようになりました。

また、デフォルト値の設定は非常に柔軟です。

function get(url,{body='',method='GET'){
    console.log(method);
}

上記のコードでは、2番目の引数としてオブジェクトが渡されており、そのオブジェクトのプロパティにデフォルト値を設定できます。

さらに、二重のデフォルト値を設定することも可能です。

fetch(url, { method = 'GET' } = {}){
  console.log(method);
}

上記のコードでは、関数fetchを呼び出す際に、2番目の引数が含まれていない場合、デフォルト値は空のオブジェクトになります。2番目の引数が含まれている場合、そのmethodプロパティのデフォルト値はGETになります。

引数のデフォルト値設定は、分割代入もサポートしています。

function ha({ x, y = 5 }) {
  console.log(x, y);
}
ha(); //TypeError: Cannot read property 'x' of undefined
ha({}); //undefined 5
ha({ x: 1 }); //1 5
ha({ x: 1, y: 2 }); //1 2

デフォルト値を定義する引数は、引数リストの末尾に配置する必要があります。デフォルト値が設定されると引数を省略できるようになるため、末尾に配置されている場合にのみ、どの引数が省略されたかを関数が判断できるからです。

デフォルト値が設定された引数にundefinednullを渡した場合、前者はデフォルト値が適用されますが、後者は適用されません。

function a(b = 1, c = 2) {
  console.log(b, c);
}
a(undefined, null);
//1 null

注意すべき点として、デフォルト値を設定すると、関数のlengthプロパティが実際の引数の数と一致しなくなります。

> (function a(a,b){}).length
2
> (function b(a,b,c){}).length
3
> (function c(a,b,c=1){}).length
2
> (function e(a,b=1,c=1){}).length
1

デフォルト値が設定されていない場合、関数のlengthは引数の数に等しいことがわかります。一方、デフォルト値が設定された後では、そのlength値はデフォルト値が設定されていない引数の数に等しくなります。

2.rest引数#

rest引数は、関数の余分な変数を取得するために使用され、argumentsオブジェクトの使用を避けることができます。

function add(...values) {
  let sum = 0;
  values.forEach(function(value){
    sum += value;
    });
  return sum;
}
> add(1,2,3,4,5)
15

この関数が渡された引数の合計を返すことがわかります。同時に、rest引数が実際には配列であることに注意してください。そのため、配列のすべてのメソッドを使用でき、上記のコードのforEachも使用可能です。

注意すべき点として、rest引数は引数のデフォルト値と同様に、引数リストの最後に配置する必要があります。また、関数のlengthプロパティにはrest引数は含まれません。

(function (a) {})
  .length(
    // 1
    function (...a) {},
  )
  .length(
    // 0
    function (a, ...b) {},
  ).length; // 1

3.スプレッド演算子#

スプレッド演算子(記号は3つの点...)は、rest引数の逆の操作と見なすことができ、配列をカンマ区切りの引数シーケンスに変換します。

> let array = [1,2,34];
> console.log(...array)
1 2 34
> console.log(11,22,...array,4)
11 22 1 2 34 4

この演算子は主に、関数の呼び出しで使用されます。

function push(array, ...items) {
  array.push(...items);
}
function add(x, y) {
  return x + y;
}
var numbers = [4, 38];
add(...numbers); // 42

上記のコードのarray.push(...items)add(...numbers)の2行は、いずれも関数の呼び出しであり、両方ともスプレッド演算子を使用しています。この演算子は配列を引数シーケンスに変換します。

スプレッド演算子で配列を展開できるため、配列を関数の引数に変換するためにapplyメソッドを使用する必要がなくなりました。

// ES5的写法
function f(x, y, z) {}
var args = [0, 1, 2];
f.apply(null, args);
// ES6的写法
function f(x, y, z) {}
var args = [0, 1, 2];
f(...args);

実際の例:

> let a=[1,23,12,31,23,12,31,23,123,12,31,24,]
'use strict'
> Math.max(...a)
123
//ES5要实现同样的功能则需要
Math.max.apply(null,a);

スプレッド演算子は、多くのES5の記述を簡素化できます。

```javascript
// ES5
[1, 2].concat(more)
// ES6
[1, 2, ...more]

// ES5
list.push.apply(list, [3, 4])
// ES6
list.push(...[3, 4])

// ES5
list = [1,2,3,4]
var a = list[0], rest = list.slice(1)
a = 1,rest = [2,3,4]
// ES6  这里是用到了解构赋值
var [a, ...rest] = list
a = 1,rest = [2,3,4]
// ES5
new (Date.bind.apply(Date, [null, 2015, 1, 1]))
// ES6
new Date(...[2015, 1, 1]);
```

注意すべき点として、スプレッド演算子を配列の代入に使用する場合、引数リストの最後にのみ配置できます。そうしないとエラーが発生します(これは当然です。そうでないと、プログラムはスプレッド演算子の長さがどれくらいになるかを知ることができません)。

スプレッド演算子は文字列を配列に変換できます(Array.from()も同様です)。

> [...'hello']
[ 'h', 'e', 'l', 'l', 'o' ]

4.アロー関数#

基本的な使い方#

「アロー」を使って関数を素早く定義します。

let fn = (f) => f;

これは以下と同等です。

let fn = function (f) {
  return f;
};

引数が必要ない場合、または引数が複数ある場合は、括弧で引数部分を表します。

```javascript
var f = () => 5;
//等于
var f = function(){return 5};

var sum =(sum1,sum2) => num1 + num2;
//等于
var sum = function(sum1,sum2){
    return sum1+sum2;
}
```

要するに、アローの後ろが関数がreturnする内容になります。 アロー関数のコードブロック部分が複数のステートメントで構成される場合、波括弧で囲み、returnを使用して値を返します。波括弧はコードブロックとして解釈されるため、アロー関数がオブジェクトを返す必要がある場合は、オブジェクトの外側に括弧を追加する必要があります。そうしないと、コードブロックとして解釈されてしまいます。

var sum = (num1, num2) => {
  return num1 + num2;
};
var sum1 = (sumI) => ({ su1: "1", su2: "2" });

同様に、アロー関数は変数の分割代入と組み合わせることができます。

let person = ({you,i}) => you + 'love' + i;
> person({you:'y',i:'i'})
'ylovei'
//等于
var person = function(obj){
    return obj.you +'love'+obj.i;
}

使用上の注意点 アロー関数にはいくつかの使用上の注意点があります。

(1)関数本体内のthisオブジェクトは、定義された時点のオブジェクトにバインドされ、使用された時点のオブジェクトにはバインドされません。

(2)コンストラクタとして使用することはできません。つまり、newコマンドを使用することはできません。使用するとエラーがスローされます。

(3)argumentsオブジェクトを使用することはできません。このオブジェクトは関数本体内に存在しません。使用したい場合は、Rest引数で代替できます。

(4)yieldコマンドを使用することはできません。したがって、アロー関数はジェネレータ関数として使用できません。

上記4点の中で、特に1点目は注目に値します。thisオブジェクトの指し示す先は可変ですが、アロー関数では固定されています。以下のコードは、thisオブジェクトが定義された時点のオブジェクトにバインドされる例です。

版権#

記事内のすべてのコードは以下から引用または派生しています。

阮一峰-ECMAScript 6 入门、本記事も表示-非営利ライセンスに従います。

ECMAScript6 学習メモ(3) - 関数拡張
https://blog.kisnows.com/ja-JP/2015/09/09/learning-ecmascript6-three/
作者
Kisnows
公開日
2015-09-09
ライセンス
CC BY-NC-ND 4.0