Es 6-関数

26244 ワード

前言
杭州の今週の温度は-5度に達して、温度の下がるのはとても速くて、年会のダンスはとても懸かっている感じがして、どんな道を撮ることができることを知らないで、今唯一の願いは、早く家に帰って、寒くても私の家に帰る足どりを止めることができなくて、うんうん.
私のブログアドレス:http://www.aymfx.cn/
リード
ES 6関数の変更はそれほど大きくなく、他の言語ではとっくに存在する機能であるが、Javascriptは関数パラメータのデフォルト値、任意のパラメータの表現法など、関数パラメータのデフォルト値、最大の変化は矢印関数(他の言語ではLAMBDA式と呼ばれている)をサポートすることであり、匿名関数に対する簡単な書き方である.
関数パラメータのデフォルト値
Es 5シミュレーションデフォルトパラメータ
function sendAjax(url,timeout,callback){
    timeout = timeout || 2000;
    callback = callback || $.noop(); //    

    $.ajax(url).done(function(){
        setTimeout(callback,timeout)
    })

}

上の付与操作に問題があるので、es 6のデフォルトパラメータを導入しました.

function add(a=200,b=2){
    return a+b;
}

console.log(add()); //202
console.log(add(2)); //4


console.log(add(null,2)); //2  null        0
console.log(add(undefined,2)); //202


デフォルトパラメータがargumentsオブジェクトに与える影響
非厳格モード
function temp(first,second){
    console.log(first=== arguments[0]);
    console.log(second=== arguments[1]);
    first = 'c';
    second = 'd'
    console.log(first=== arguments[0]);
    console.log(second=== arguments[1]);
}

temp('a','b')


//true
//VM264:3 true
//VM264:6 true
//VM264:7 true


厳格モード
function temp(first,second){
    'use strict'
    console.log(first=== arguments[0]);
    console.log(second=== arguments[1]);
    first = 'c';
    second = 'd'
    console.log(first=== arguments[0]);
    console.log(second=== arguments[1]);
}

temp('a','b')


//true
//VM264:3 true
//VM264:6 false
//VM264:7 false

非厳格モードでは、パラメータはargumentの値と一致し、厳格モードではargumentsは転送された初期パラメータと一致し、es 6のデフォルト値が存在する場合を参照してください.
非厳格モード
function temp(first,second='b'){
    console.log(arguments.length)
    console.log(first=== arguments[0]);
    console.log(second=== arguments[1]);
    first = 'c';
    second = 'b'
    console.log(first=== arguments[0]);
    console.log(second=== arguments[1]);
}

temp('a')

//1
//true
//VM264:3 false
//VM264:6 false
//VM264:7 false


厳格モード
function temp(first,second='b'){
    'use strict'
    console.log(arguments.length)
    console.log(first=== arguments[0]);
    console.log(second=== arguments[1]);
    first = 'c';
    second = 'd'
    console.log(first=== arguments[0]);
    console.log(second=== arguments[1]);
}

temp('a')

// Illegal 'use strict' directive in function with non-simple parameter list

//hhhhhhhhhhhh,   ,  

デフォルトのパラメータ式、関数を渡すことができます
function getValue(){
    return 5;
}

function add(first,second=getValue()){
    return first+second;
}


console.log(add(1,2)); //3
console.log(add(10));  //15

以前に定義したシェイプをデフォルト値として使用できます.

function add(first,second=first){
    return first+second;
}

console.log(add(1,2)); //3
console.log(add(10));  //20

     

function add(first=second,second){
    return first+second;
}

console.log(add(1,2)); //3
console.log(add(undefined,10));  //second is not defined

//          TDZ,           

不定パラメータ(...keys)
//  Underscore.js pick()  

function pick(object,...keys){
    console.log(arguments.length); //3
    let result = Object.create(null);
    for(let i=0,len=keys.length;ireturn result;

}


let person = pick({name:'ly',age:'18',sex:'mael'},'age','sex'); 

console.log(person.name); //undefind
console.log(person.age); //18
console.log(person.sex); //mael

不定パラメータの要件
function pick(obj,...keys,last){} //  ,            

//             setter  

let object = {
    set name(...values){
        //    
    }
}

Functionコンストラクション関数の機能強化では、デフォルトパラメータと不定パラメータを使用できます.
const add = new Function('first','second = first','return first+second')

console.log(add(1,2),add(1))  //3 2


var pick = new Function("...args","return args[0]")

console.log(pick(1,2));  //1


展開演算子
//         

let values = [25,100,75,56];

console.log(Math.max.apply(this,values));  //100

//    ,          

console.log(Math.max(...values)); //100

//    ,              

console.log(Math.max(...values,200)); //200

関数で関数名を取得できる属性name
var func1 = function () {};
// ES5
func1.name // ""
// ES6
func1.name // "func1"
//     ,  func1        , ES5   ES6  name         。
//                ,  ES5   ES6  name                。
const bar = function baz() {};
// ES5
bar.name // "baz"
// ES6
bar.name // "baz"
//Function           ,name      “anonymous” 。
(new Function).name // "anonymous"
//bind     ,name       “bound ”   。
function foo() {};
foo.bind({}).name // "bound foo"
(function(){}).bind({}).name // "bound "



//    es6   

var dosomething = function(){}

console.log(dosomething.bind().name);  //bound dosomething
console.log((new Function()).name);    //anonymous

関数の多重用途を明確にする
js関数には2つの内部方式[[Call]]と[[Construct]]があり、newキーワードで関数を呼び出すと[[Construct]]関数が実行され、通常インスタンスと呼ばれる新しいオブジェクトを作成し、関数体を実行してthisをインスタンスにバインドします.newが異なる場合は[[Call]]関数を実行し、コード内の関数体を直接実行します.
Es 5判定関数が呼び出される方法
function Person(name){
    if(this instanceof Person){
        this.name = name;
    } else{
        throw new Error('  new  ,  ')
    }
}

var person = new Person("ly"); //
var notperson =Person("ll"); //   new  ,  

//        

var notperson =Person.call(peson,"ll"); //


新.target精確判断
function Person(name){
    if(typeof new.target !== 'undefined'){
        this.name = name;
    } else{
        throw new Error('  new  ,  ')
    }
}

var person = new Person("ly"); //
var notperson =Person.call(person,"ll"); //

ブロックレベルのスコープ
es 5の時代、厳格モードが有効になった場合、以下のコードはエラーを報告し、es 6はブロックレベルの役割ドメインが発生したため、このif条件文の内部で使用することができ、外部はundefinedのままである.
 "use strict"
 if(true){
    console.log(typeof add); //function
    function add(a,b){
        return a+b;
    }
 }

 console.log(typeof add);  //undefined

しかし、非厳密モードでは、この関数はグローバル役割ドメインの上部に昇格します.
 if(true){
    console.log(typeof add); //function
    function add(a,b){
        return a+b;
    }
 }

 console.log(typeof add);  //function


重要な変更矢印関数
いくつかの面白い変化(興奮状)
  • this,spuer,argumentsおよびnew.targetバインド
  • なし
  • newキーワード呼び出し
  • は使用できません.
  • プロトタイプなし
  • thisのバインドを変更することはできません
  • argumentsオブジェクト
  • はサポートされていません.
  • 重複ネーミングパラメータ
  • はサポートされていません.
    矢印関数の構文
    let add = (a,b) => a+b;
    
    //     
    
    let add = function(a,b){return a+b}
    
    
    //            ,     
    
    let reflrct = value => value
    
    //   
    
    let reflrct = function(value){return value}
    
    //         
    
    let name = () => 'ly';
    
    
    //   
    
    let name = function(){return 'ly'}
    
    
    //           ,      
    
    let getName = (fisrtName,secondName) => {
        return firstName+' '+ secondName;
    }
    
    //   
    
    let getName = function(fisrtName,secondName){
        return firstName+' '+ secondName;
    }
    
    //                  
    
    let person = () => ({
        name:'ly',
        age:18
    })
    
    //   
    
    let person = function(){
        return {
        name:'ly',
        age:18
    }
    }
    
    //          
    
    let person = ((name) => ({getName:() => name}))('ly')
    
    //       ,  
    
    

    矢印関数はthisバインドされていません
    let PageHandler = {
         id:'13579',
         init:function(){
             document.addEventListener('click',function(event){
                 this.doSomething(event.type)  //   
             })
         },
         doSomething:function(type){
             console.log(type);
         }
    }
    

    Es 5のやり方は、そうします.
    let PageHandler = {
         id:'13579',
         init:function(){
             document.addEventListener('click',(function(event){
                 this.doSomething(event.type)  
             }).bind(this))
         },
         doSomething:function(type){
             console.log(type);
         }
    }
    
    
    

    でも矢印関数があれば、ずっとかっこいいです
    let PageHandler = {
         id:'13579',
         init:function(){
             document.addEventListener('click',event => this.doSomething(event.type) 
             )
         },
         doSomething:function(type){
             console.log(type);
         }
    }

    矢印関数にはthisはありませんので、処理中にthisが関数外部の非矢印関数のthis値に依存します.
    矢印関数にargumentsバインドは存在しないので、このように操作できます.
     function outer(){
         return () => arguments[0];
     }
    
     let inner = outer(18)
    
      console.log(inner()); //18        ,             arguments
    

    call()、bind()、apply()は使えますが、thisの値は変えられません.
    テールコールの最適化(Tail Call)
    最後の呼び出しとは、関数が別の関数として最後の文として呼び出されることを意味し、呼び出しスタックに新しいスタックフレームを追加するのではなく、呼び出しスタックを直接更新し、呼び出しスタックの占有空間は常に定数であり、メモリを節約し、スタックを爆発させる可能性を回避するが、es 5は呼び出しスタックが大きすぎるとプログラムの問題を引き起こす
    エンドコールインスタンス
    
     function add(a,b){
    
     }
    
     function max(a,b,c,d){
    
        //......
         return add(a,c);
    
     }
    

    最適化には、新しいスタックフレームを作成するのではなく、現在のスタックフレームを消去して再利用するには、次の条件を満たす必要があります.
  • 末尾呼び出し現在のスタックにアクセスしない変数(閉パケットを形成しない)
  • 末尾呼び出しは関数内部の最後の文
  • である.
  • の最後の呼び出しの結果は、関数値として返されます(returnfn()が必要です)
  • .
    シーンの最後の再帰を使用する
    エラーモード
    console.time('testForEach');
    function factorial(n) {
        if(n<=1){
            return 1
        } else {
            return n*factorial(n-1)  //  n  ,         ,    ,       
        }
    }
    var a =factorial(5000);
    console.log(a); 
    console.timeEnd('testForEach'); // 1.55322265625ms
    
    

    正しい書き方
    console.time('testForEach');
    function factorial(n,p=1) {
        if(n<=1){
            return 1*p;
        } else {
            let result = p*n;
            return factorial(n-1,result)  
    }
    }
    factorial(5000);
    console.timeEnd('testForEach'); //0.492919921875ms       10000