闭包和高阶函数

小知识:

var test3={
a:'asd'
}
console.log(test3['a']);

Array.prototype.slice.call(arguments)能将具有length属性的对象转成数组

相当于给数组的原型添加全局方法

 var toArray = function(s){
 2     try{
 3         return Array.prototype.slice.call(s);
 4     } catch(e){
 5             var arr = [];
 6             for(var i = 0,len = s.length; i < len; i++){
 7                 //arr.push(s[i]);
                   arr[i] = s[i];  //据说这样比push快
 8             }
 9              return arr;
10     }
11 }

一个闭包例子

function test(){
    var a=12;
    function innertest(){
        console.log(a);
    }
    return innertest;
}
var t = test();
t();//12

这是因为test函数返回一个innertest函数 并且将其赋值给 t变量 即使该函数位于外部但innertest函数 依然保留着在test中的内部作用域依然能够访问内部的属性值

因此innertest拥有该函数内部的闭包

一般来说函数执行完函数后 js的 GC垃圾自动回收机制会回收不再使用的函数作用域单在这里由于闭包而阻止销毁 

注意:不建议使用闭包占内存

    //备忘函数
function cache(fn){
    const ca = {};
    return function(...args){
        const key = JSON.stringify(args);
       return ca[key]||(ca[key] = fn.apply(fn,args))
    }
}

//进行运算
function add(a){
  return a;
}
var adder = cache(add);
adder(1);

解释:

add赋值算出值

JSON.stringify将传递的参数转换为字符串作为建
fn.apply(fn,args)) 调用闭包作用域中的参数执行该函数

需要改进:
如果无限存储元素则相当耗内存 建议使用持久化存储 比如浏览器的 cookie 或者LocalStorage

高阶函数:
传入的参数有函数或者返回中的有函数


函数作为返回值主要是利用闭包保持作用域


函数科里化:
function test(fn,...test1){
    return function(...test2){
        return fn.apply(null,test1.concat(test2));
    }
}
function sayHello(age,username,s){
    console.log(11);
   console.log(age+""+username+""+s);
}
//运算前提前传递参数
var s = test(sayHello,12); s('webcyh','he');
 
柯里化是固定部分参数,返回一个接受剩余参数的函数,也称为部分计算函数,目的是为了减少适用范围
,创建一个正对性更强的函数,核心思想是把多参数传入的函数拆成单参数或者部分参数函数,
内部在调用下一个单参数或者部分函数,依次处理剩下的参数

反柯里化
function test(fn){
    return function(args,...a){
        return fn.apply(args,a);
    }
}

var push =test(Array.prototype.push);
//提前传递的参数 或者上下文到最后是用
function check(){ push(arguments,5); console.log(arguments); } check(1,2,1);
ES5 和ES6作用域差别
ES6 出现了块级作用域
例子:
var arr=[];
    for(var i=0;i<4;i++){
       arr[i]=function(){
           console.log(i);
       }
    }
    arr[2]();//返回4
    /*这里var 声明的为函数作用域在这里也就是全局变量 后面调用的函数 打印的也是全局变量最后的结果4*/
    var arr=[];
    for(let i=0;i<4;i++){
       arr[i]=function(){
           console.log(i);
       }
    }
    arr[2]();//返回2
    /*这里let  为ES6语法 这里的i作用域为块级 也就是该变量知识在该次循环中有效每次循环都是一个新的变量*/

ES6 不存在变量提升

// let、const 命令不存在变量提升
console.log(boo) // 报错 ReferenceError
let boo = 2

ES6 暂时性死区

在块作用域中 用let 或者const 声明一个变量之前 该变量不可用

ES6不允许重复声明

ES6箭头函数

总结:

当函数有只有一个参数时 可以忽略 括号 

如果 没有参数时 括号不可忽略

如果函数体只有返回值 可以忽略花括号和return关键字 

如果 返回值是一个对象字面型 返回值要添加括号

箭头函数不会自己创建自己的this 只有在定义函数时继承自上一级的this

例子:

function test(){
        var age=12;
        setInterval(()=>{
            this.age++;
            console.log(age);
        },1000);
    }
    var t = new test();
箭头函数中的this就是定义时所在的对象,而不是使用时所在的对象
无法作为构造函数,不可以使用new
不存在arguments对象,但可以使用Rest参数代替
箭头函数无法使用yield命令不能作为Generator函数
不可以通过bind call apply绑定this 可以通过call apply传递参数


class语法



ES5:
function Foo(){this.kind='foo'}
Fool.staticMethod = function(){console.log('静态方法')}
Fool.prototype.doThis = function(){console.log('实例方法')}


ES6:
class Foo{
constructor(){

}

static staticMethod(){


}
doThis(){


}
}

继承 静态方法无法被实例继承只能通过类名调用
class Bar extends Foo{
constructor(){
super();
this.tpe='bar'
}

解构赋值 只要等号模式相等即可赋值
let [a,b,c] = [1,2,3] a:1 b:2 c:3
let [a,b,...c] = [1,2,3,41,1,1,1]a:1 b:2 c[3,41,1,1,1]



原文地址:https://www.cnblogs.com/webcyh/p/11291747.html