JS--Day23(闭包+柯里化)

一、demo01回顾

①in 运算符:判断一个对象是否有某个属性(或者说:判断一个属性是否在对象中有)

let obj = {
    name:"二哈",
    sex:"男",
    age:12
}
if("name" in obj){
    console.log("obj中有name属性");
}

②Proxy:代理,可以代理一个对象。

     1、使用的时候:当需要操作源对象时,现在操作代理对象。代理对象会操作源对象。

     2、干什么用:能够在源对象和操作之间设立一个屏障(如:可以判断属性值的合法性)

// 1)、修改源对象的age属性
let p1 = new Proxy(obj,{
    set:function(target,key,val){
       if(val<0 || val>150){
        return;
       }
       target[key] = val;
    },
    has:function(target,key){
        console.log('has');
        return key in target;
    }
});
p1.age = 250;
// 2)、 当判断对象中是否有某个属性(用in操作符)
if( "age" in p1){
    console.log("obj有age属性");
}

二.闭包

     1、粗浅理解:嵌套的函数定义。里面的函数是局部函数。

     2、深度理解:一个函数和其周围状态(数据)的引用,绑定在一起,这样的组合才是闭包。
   

 function fn01() {
        var num = 10;
        console.log("num", num);
        // fn02是局部函数
        function fn02() {
            console.log("fn02");
        }
        // fn02();
        return fn02;//如果希望在外面调用fn02。可以返回出去。
    }
    let f = fn01();
    document.getElementById("btn01").onclick = function () {
        f();
    }

三.带有闭包的代码执行过程


    function fn01() {
        var num = 10;
        function fn02() {
            num++;
            console.log("num", num);
        }
        return fn02;
    }
    let f = fn01();//产生一个闭包
    f();//num:11
    f();//num:12
    f();//num:13
    let f2 = fn01();//产生一个闭包
    f2();//11
    f();//14;
    f2();//12
    fn01()(); //11//产生一个闭包
    fn01()(); //11//产生一个闭包

四.闭包的场景:只有一个方法的对象

function person(str){
    var name = str;
    return function(){
        console.log(name+"在吃,天在看……");
    }
}
let eat = person("宋和叶");
eat();

五.闭包的场景:如果某些数据只希望某些函数使用(让数据私有,也可以让方法私有)

// 需求:某些数据只希望某些函数使用
// 如下示例:count只希望fn01和fn02可以使用。
    function person() {
        var count = 10;
        function fn01() {
            count += 2;
            console.log("fn01:count", count);
        }
        function fn02() {
            count++;
            console.log("fn02:count", count);
        }
        return [fn01];
    }
    function fn03() {
    }
    console.log(person());

六.用闭包和类进行对比

//闭包
function person(){
    var count = 10;//count:可以在fn01和fn02函数共享
    function fn01(){
        count+=2;
        console.log("fn01:count",count);
    }
    function fn02(){
        count++;
        console.log("fn02:count",count);
    }
    return [fn01];
}
function fn03(){
}
//类
class dog{
    constructor(){
        this.count = 2;//count:可以在fn01和fn02函数共享
    }
    fn01(){
        this.count+=2;
        console.log("fn01:count",this.count);
    }
    fn02(){
        this.count+=1;
        console.log("fn02:count",this.count);
    }
}

七.循环里使用闭包

/*
function fn1(){
    let arr = [];
    for(var i=0;i<5;i++){
        //循环体中,完成的事情:给数组的元素赋值,不会调用函数
        arr[i] = function(){
            return i;
        }
    }
    console.log(i); //5,循环结束后,i的值是5;
    return arr;
}
var arr2 = fn1();
console.log(arr2[0]());//
console.log(arr2[1]());
*/
function fn1(){
    let arr = [];
    for(var i=0;i<5;i++){
        //循环体中,完成的事情:给数组的元素赋值,不会调用函数
        arr[i] = (function(){
            return i;
        })();
    }
    console.log(i); //5,循环结束后,i的值是5;
    return arr;
}
var arr2 = fn1();
console.log("arr2",arr2);

八.作用域和作用域链

 // 1、ES5及其之前
    var count = 100;
    function fn01() {
        var n = 20;
        count++;
        console.log("fn01:count", count);
        console.log("fn01:n", n);
    }
    function fn02() {
        count--;
        console.log("fn02:count", count);
    }
    function add(){
        fn01();
    }
    function sub(){
        fn02();
    }
// 2、ES6+;
    let count = 100;
    function fn01() {
        let n = 20;
        count++;
        if(true){
            let m = 10;
            console.log("m",m);
            console.log("n",n);
            console.log("count",count);
        }
        {
            let y =30;
            console.log("y",y);
        }
        console.log("fn01:count", count);
        console.log("fn01:n", n);
    }
    function fn02() {
        count--;
        console.log("fn02:count", count);
    }
    function add(){
        fn01();
    }
    function sub(){
        fn02();
    }

九.函数的柯里化

 function sum(a,b,c){
     return a+b+c;
 }
  sum(3,4,5)
// 一、柯里化函数的意思:
 function sum(m){
     return function(n){
         return function(k){
             return m+n+k;
         }
     }
 }
   let s = sum(3)(4)(5);
   console.log("s",s);
// 二、柯里化工具:把一个函数进行柯里化
function sum(a,b,c,d){
     return a+b+c+d;
}
function curry(cb){
    //这个数组是保存原函数的参数的。
    let arrs = [];
    //这个函数(fn),用来收集原函数的参数,如果没有收集够,就返回函数(fn)本身;如果收集够 
    //了,那就调用原函数(cb)
    function fn(...args){   
        arrs = [...arrs,...args];//[1,2,3,4]
        if(arrs.length<cb.length){//判断实参个数是否和原函数的形参个数的关系                    
            return fn;
        }else{
            return cb(...arrs);
        }
    }
    return fn;
}
  let sfn = curry(sum);
  let s = sfn(1)(2)(3)(4);
  let s = sfn(1,2)(3)(4);
  let s = sfn(1,2,3)(4);
  let s = sfn(1,2)(3,4);
  let s = sfn(1,2,3,4);
// 三、柯里化工具函数(进一步)
function sum(a,b,c,d){
     return a+b+c+d;
}
// 把sum(a,b,c,d)转成 sum(a)(b)(c)(d);
function curry(cb,arr=[]){
    return function(...args){
        let arrs = [...arr,...args];//1
        if(arrs.length<cb.length){//判断实参个数是否和原函数的形参个数的关系
            return curry.call(this,cb,arrs)//调用闭包时,传入arrs,把前面调用的状态进行保持。
        }else{
            return cb(...arrs);
        }
    } 
}
let sfn = curry(sum);
let s = sfn(1)(2)(3)(4);

猜你喜欢

转载自blog.csdn.net/weixin_72756818/article/details/129841761