ES 6エッセンス:関数拡張


ES6は関数の面での拡張が豊富で実用的です.
1矢印関数
矢印関数はES6で定義された関数の新しい形です.新しい形式は、定義された方法を簡略化するだけでなく、関数自体の減量(thisargumnetsなどは以前とは異なる)である.
let fn = () => {
  console.log('fn');
};
fn(); // 'fn'

        ,      。
(n => {
  console.log(n);
})(1); // 1

     {} ,        =>      。
console.log( (n => 2)(1) ); // 2
  ,          ,          ()       。
console.log( (n => (n + 1))(1) ); // 2
1.1 this
矢印関数は、自身のthisを有しない.thisは、外部層を参照するものである.したがって、内部のthisは固定されていて、定義された時点からすでに確定されています.
      。

---             this 。
window.id = 0;

let obj = { id: 1 };
let fn = function () {
  console.log(this.id);
};

fn(); // 0,     window 。
obj.fn = fn;
obj.fn(); // 1,     obj 。


---            this 。
window.id = 0;

let obj = { id: 1 };
let fn = () => {
  console.log(this.id);
};

fn();  // 0,     window 。
obj.fn = fn;
obj.fn(); // 0,     window 。
多層矢印関数を用いて説明する.多重矢印関数、thisの探索方法は、ドメインチェーンルックアップのような役割を果たす階層的なものである.したがって、多層矢印関数は、thisを初めて取得したときに、全関数のthisによって決定される.
foo.call({id: 1})()(); // id: 1

function foo() {
  return () => {
    return () => {
      console.log('id:', this.id);
    };
  };
}

---    

function foo() {
  let _this = this;
  return function() {
    return function() {
      console.log('id:', _this.id);
    }
  }
}
自分のthisがないからです.そのためコンストラクタにはなりません.newオペレータは使用できません.したがって、callapplybindなどの方法でthisの指向を変更することはできない.
let Person = () => {};
let p = new Person(); //   ,Person is not a constructor。

window.id = '000';
let fn = () => { console.log(this.id) };
let fn1 = fn.bind({ id: '111' });
fn1(); // '000'
1.2その他の違い
関数にはargumentsオブジェクトがありません.restパラメータを使用して代替できます.yieldコマンドは使用できませんので、矢印関数はGenerator関数として使用できません.
let fn = (...args) => {
  console.log(args); // [1, 2]
  console.log(arguments); //   ,arguments is not defined。
};
fn(1, 2);
2関数パラメータ
2.1標準値
パラメータのデフォルト値を設定できます.このパラメータまたは値が渡されていない場合には、デフォルト値が使用されます.このようにすれば、関数体を簡略化し、パラメータの性質、タイプなどをより明確にすることができます.
--- ES6   
function fn(id, conf) {
  id || requiredParam();
  conf = conf || {};
  
  conf.name = conf.name || '';
  conf.ago = conf.ago || 0;
  
  console.log(id, conf);
}

--- ES6   
function fn(
  id = requiredParam(),
  conf = {
    name: '',
    ago: 0
  }
) {
  console.log(id, conf);
}

function requiredParam() {
  throw Error('Missing parameter.');
}
2.2分配値
プロファイルを結合すると、標準設定の機能がより強くなります.プロファイルについては、このリンクを参照してください.直感的にその強みを示すために、最終的な結果を3段階に分けます.
1.      ,      ,         。

fn({
  id: '0003'
}); //       :'0003' undefined

--- ES6   
function fn(conf) {
  let id = conf.id;
  let name = conf.name;
  console.log(id, name);
}

--- ES6   
function fn({id, name}) {
  console.log(id, name);
}


2.   ,            。

fn({
  id: '0003'
}); //       :'0003' 'Unnamed'

--- ES6   
function fn(conf) {
  let id = conf.id || '0000';
  let name = conf.name || 'Unnamed';
  console.log(id, name);
}

--- ES6   
function fn({
  id = '0000',
  name = 'Unnamed'
}) {
  console.log(id, name);
}


3.  ,          。

fn(); //       :'0000' 'Unnamed'

--- ES6   
function fn(conf) {
  conf = conf || {
    id: '0000',
    name: 'Unnamed'
  };
  
  let id = conf.id;
  let name = conf.name;
  
  console.log(id, name);
}

--- ES6   
function fn({
  id = '0000',
  name = 'Unnamed'
} = {}) {
  console.log(id, name);
}
もう一つの問題を考えます.解決中ですか?それともパラメータのデフォルトで属性の値を設定しますか?
function fn1(x = {}, {a = 1, b = 2} = x) { console.log(a, b, x) }
function fn2(x = {a: 1, b: 2}, {a, b} = x) { console.log(a, b, x) }

         :  a, b         。
                 ,         。

fn1(); // 1 2 {}
fn2(); // 1 2 {a:1, b:2}

fn1({}); // 1 2 {}
fn2({}); // undefined undefined {}

fn1({ a: 0 }); // 0 2 {a:0}
fn2({ a: 0 }); // 0 undefined {a:0}
2.3レスポンスパラメータ
拡張演算子は、パラメータ、すなわちasyncパラメータとして作用する.これは、対応するすべての着信パラメータを一つの配列に結合し、undefinedパラメータに値を与えます.restパラメータは最後のパラメータしかできません.正則における強欲性がないと、エラーが発生します.
   :'0001' ['m1','m2']。

fn('0001', 'm1', 'm2');

function fn(groupId, ...members) {
  console.log(groupId, members);
}
2.4スコープ
関数パラメータがデフォルト、デフォーカシング、または拡張演算子を使用すると、パラメータスコープが生成されます.
関数を実行すると、パラメータ変数をデフォルトで宣言します.パラメータの作用領域があるなら、先にそれを実行して、関数の作用領域に入ります.初期化が完了すると、パラメータのスコープが消失し、関数がデフォルト宣言の同名変数が対応するパラメータ変数を指します.
作用域が存在するため、パラメータは不活性(呼び出し時)です.
let n = 0;

fn(); // 1

n = 1;
fn(); // 2

function fn(num = (n + 1)) {
  console.log(num);  
}
デフォルトの宣言原則のため、同じ名前のパラメータを関数で宣言するのは二次宣言に相当します.restを使用して、restはかなり重複した声明で、エラーを報告します.letを使用すると、関数体とパラメータの作用領域との関連が解け、変数は純粋な関数体変数となる.
---   
let x = 0;
fn(1); // 2
function fn(x, y = () => { console.log(x) }) {
  x = 2;
  y();
}

---   
let x = 0;
fn(1); // 1
function fn(x, y = () => { console.log(x) }) {
  var x = 2;
  y();
}
パラメータの作用領域があると、関数体に明示的に厳格なモードを設定できません.そうでないとエラーが発生します.関数内部の厳密なモードは関数体とパラメータの作用領域に同時に作用するべきである.しかし関数体に入るだけで,明示的に宣言されているかどうかが分かりますが,パラメータ体は関数体より先に実行されます.しかし、この関数は、厳密なモードの環境に置かれています.
  :Illegal 'use strict' directive ...
function fn(n = 0) {
  "use strict";
}
3関数の属性
3.1 name
異なる形式の関数は、const属性値を構築する方法も異なり、以下は個人がまとめた8つの方法である.
1.   ,      。
console.log(fn.name); // 'fn'
function fn() {}

2.       ,      。
let fn1 = function fn() {};
console.log(fn1.name); // 'fn'

3.   ,         /  。
let fn = function() {};
console.log(fn.name); // 'fn'
let fn1 = fn();
console.log(fn.name); // 'fn'
let obj = { fn: function() {} };
console.log(fn.name); // 'fn'

4.          ,  。
console.log( (function() {}).name ); // ''

5.         ,  anonymous 。
console.log( (new Function()).name ); // 'anonymous'

6.   bind()    ,name        bound   。
console.log( (function() {}).bind({}).name ); // 'bound '
console.log( (function fn() {}).bind({}).name ); // 'bound fn'

7.          Symbol  ,name         Symbol    。
let s1 = Symbol();
let s2 = Symbol('s2');
console.log( ({ [s1]() {} })[s1].name ); // ''
console.log( ({ [s2]() {} })[s2].name ); // [s2]

8.getter/setter     name   ,        get/set    ,  get/set    。
let obj = {
   get name() {}
};
Object.getOwnPropertyDescriptor(obj, 'name').get.name; // 'get name'
3.2レングス
その本質的な意味は、関数が着信を期待するパラメータの個数である.パラメータがデフォルトまたはvarパラメータである場合、それ以降のパラメータは計算されません.この点に基づいて、パラメータ設計においては、基本的には省略可能またはデフォルトのあるパラメータをテールパラメータとして設定します.
console.log( (function(...args) {}).length ); // 0
console.log( (function(a, {b}, c = 5, d) {}).length ); // 2
3.3アーグメンント
クラス配列オブジェクトnameが保存しているのは呼び出し方法のみを格納している時に入ってくるパラメータです.これは、デフォルト値を使用するパラメータ、構成パラメータ、またはrestパラメータなどが存在しないことを意味する.
(function (name = 'Wmaker') {
  console.log(name, arguments.length);
})(); // 'Wmaker' 0

(function ({a, b}) {
  console.log(a, b, arguments.length);
})({ a: 1, b: 2 }); // 1 2 1

(function (...arr) {
  console.log(arr, arguments.length);
})(1, 2, 3); // [1, 2, 3] 3