s 6ノート--関数


es 6参照:リンクを開くにはクリックしてください.
パラメータ
        restパラメータの組み合わせの変数は、行列に余分なパラメータを入れた配列です.
function sorNumber(){
    return [].slice.call(arguments,0).sort()
}
function sorNumberRest(x,y,...values){
    return values.sort()
}
sorNumber(1,8,9,6,7,8,4,3,2);       //[2, 3, 4, 6, 7, 8, 9]
sorNumberRest(1,8,9,6,7,8,4,3,2);   //1, 2, 3, 4, 6, 7, 8, 8, 9
関数の厳密なモード:    
        関数パラメータが標準値、アンチエイジング、または拡張演算子を使用している限り、関数内部では明示的に厳格なモードに設定できません.そうでないとエラーが発生します.関数内部の厳密なモードは関数体と関数パラメータに適用されるからです.ただし、関数が実行される場合は、まず関数パラメータを実行してから関数体を実行します.このように不合理なところがあります.パラメータは厳密なモードで実行すべきかどうかは関数体の中からしか分かりませんが、パラメータは関数体より先に実行すべきです.
function a(value = 070){"use strict"}
name属性
        関数名を返します
 矢印関数 
let foo = () => 5;//    5
let foo = (x,y,...values) => { return {x+y,values} };//         , return   
        注意: 
            (1)関数体内のthisオブジェクトは、使用時の対象ではなく定義時の対象です.
            (2)コンストラクタとしてはいけません.つまり、使用してはいけません.newコマンドでないと、エラーが発生します.
            (3)使用できないargumentsオブジェクトは、関数内に存在しません.使うなら、restパラメータで代替できます.
            (4)使用できないyieldコマンドですので、矢印関数はGenerator関数として使用できません.
 function Timer() {
  this.s1 = 0;
  this.s2 = 0;
  //     
  setInterval(() => this.s1++, 1000);
  //     
  setInterval(function () {
    this.s2++;
  }, 1000);
}

var timer = new Timer();

setTimeout(() => console.log('s1: ', timer.s1), 3100);
setTimeout(() => console.log('s2: ', timer.s2), 3100);
// s1: 3
// s2: 0
        矢印関数のこの特性をどのように実現しましたか?
function foo() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}

// ES5
function foo() {
  var _this = this;

  setTimeout(function () {
    console.log('id:', _this.id);
  }, 100);
}
        ここでは、矢印関数は直接呼び出された外層のthisであり、同じことからわかるthisarguments・、supernew.target矢印関数の中にも存在せず、外層関数に対する対応変数を指す.
二重コロン演算
     矢印関数は、バインディングthisオブジェクトとして、明示的バインディングthisオブジェクトの書き方を大幅に低減しています(callapplybind).しかし、矢印関数はすべての場合には適用されないので、現在は「関数バインディング」演算子を提案しています.
foo::bar;
//    
bar.bind(foo);

foo::bar(...arguments);
//    
bar.apply(foo, arguments);

const hasOwnProperty = Object.prototype.hasOwnProperty;
function hasOwn(obj, key) {
  return obj::hasOwnProperty(key);
}
//         ,          ,               
var method = obj::obj.foo;
//    
var method = ::obj.foo;

let log = ::console.log;
//    
var log = console.log.bind(console);
//             ,      ,         。
import { map, takeWhile, forEach } from "iterlib";

getPlayers()
::map(x => x.character())
::takeWhile(x => x.strength > 100)
::forEach(x => console.log(x));
テールコール最適化
    1、テールコール
        関数プログラミングの重要な概念は、関数の最後のステップを指します.関数の呼び出しです.
function f(x){
  return g(x);
}
/***************************    *****************************/
//    
function f(x){
  let y = g(x);
  return y;
}

//    
function f(x){
  return g(x) + 1;
}

//    
function f(x){
  g(x);
}
       2、テールコールの最適化:
       関数aで関数bを呼び出すと、aの呼出フレーム上でbの呼出フレームが開かれ、メモリを占めます(bでcが呼び出されたら、呼び出されたスタックが階層的に形成されます).テイルコールの関数が外層関数に依存しない場合は、aの呼び出しフレームを削除し、bの呼び出しフレームを保持することで、メモリを大幅に節約することができます.
function a(param){
  var v1 = 1,
      v2 = 2;
  return b(param);
}

function a(param){
  var v1 = 1;
  function inner(b){
    return b + v1;
  }
  return inner(param);
}
        注意:1、ここのパラムはその値をパラメータとしてbに渡すだけです.パラムの値は変数パラムではなく、パラム変数に依存していません.
                2、ES 6の終端呼び出し最適化は厳格なモードでのみ開かれ、正常モードは無効です.これは、通常モードでは関数内部に2つの変数があります.                      トレース関数でコールスタックを呼び出します.call:呼び出し時関数のパラメータを返します.applybind:現在の関数を呼び出した関数を返します.
               最後の呼び出し最適化が発生すると、関数の呼び出しスタックが書き換えられますので、上の二つの変数が歪みます.厳密モードではこの2つの変数を無効にしますので、最後の呼び出しモードは                 厳格なモードで有効です.
最後に再帰する
        名前の通り、関数の最後に呼び出されました.呼出されたのは自分で再帰的に形成されたものです.今回は絶えずコールフレームが生まれ、コールスタックが形成されています.最大コールスタックを超える可能性があります.だから、最適化を考えています.再帰的を循環に変えます.
       次は再帰的なものです.私達は酔っ払いコールスタックを超えて運行します.
function sum(x, y) {
  if (y > 0) {
    return sum(x + 1, y - 1);
  } else {
    return x;
  }
}

sum(1, 100000)
        トランポリン関数(trmpoline)は再帰的な実行を循環的に実行することができます.
function trampoline(f) {
  while (f && f instanceof Function) {
    f = f();  //            ,        ,            
  }
  return f;
}
function sum(x, y) {
  if (y > 0) {
    return sum.bind(null, x + 1, y - 1);
  } else {
    return x;
  }
}
trampoline(sum(1, 100000))
// 100001
        トランポリンの機能は本当の最後の再帰的最適化ではなく、次の実現こそです.
function tco(f) {
  var value;
  var active = false;
  var accumulated = [];

  return function accumulator() {
    accumulated.push(arguments);
    if (!active) {
      active = true;
      while (accumulated.length) {
        value = f.apply(this, accumulated.shift());
      }
      active = false;
      return value;
    }
  };
}

var sum = tco(function(x, y) {
  if (y > 0) {
    return sum(x + 1, y - 1)
  }
  else {
    return x
  }
});

sum(1, 100000)
// 100001
        
上のコードで、            func.arguments関数は最後の再帰的最適化の実現であり、その奥妙は状態変数にあります.            .デフォルトでは、この変数は非アクティブです.最後の再帰的最適化のプロセスに入ると、この変数はアクティブになります.そして、その都度再帰する.            func.caller帰るのは全部tcoしたがって、再帰的な実行は避けられます.に対するactive配列保存sum実行するパラメータは、常に値があることを保証します.undefined関数内部のaccumulatedループは常に実行されます.このように「再帰」を巧みに「循環」に変え、その後、一輪のパラメータが前回のパラメータに取って代わります.