5.函数式编程

219 阅读3分钟

理解JavaScript纯函数

满足以下条件属于纯函数:

  • 函数在相同的输入值时,永远产生相同的输出
  • 函数的输出和输入值意外的其他隐藏信息或状态无关
  • 函数不能有语义上的可以观察的函数副作用(函数执行的过程中不能有副作用) 实例:
var names = ['123', '234', '345'];
var newNames = names.splice(0,3);
console.log(newNames, names);

var newNames2 = names.splice(0,3); //原数组被修改

slice函数本身就是纯函数,方法不会对原数组进行修改。splice就不属于纯函数,数组截取以后会对原数组进行相关的修改.

//没有副作用的纯函数
function foo(num1, num2){
    return num1*2+num2*2;
}
//有副作用不属于纯函数,修改了外界的变量
var name = 1;
function bar(){
    console.log('2');
    name = 2;
}
bar();

纯函数的好处:

  • 使用时候输入内容不会被任意篡改,只要自己确定的输入,一定有确定的输出
  • 写的时候保证函数的纯度,只要保证自己的业务逻辑即可,不需要关心传入内容如何或者依赖

柯里化

接收多个参数的函数,编程接收一个单一参数的函数,并且返回接收剩余的参数,返回结果的新函数 过程:传递给函数一部分参数来调用它,让它返回一个函数去处理剩余的参数

function foo(m,n,x,y){
    return m+n+x+y;
}
//实现柯里化的过程
function foo(m){
    return function(n){
        return function(x){
            return function(y){
                return m+n+x+y;
            }
        }
    }
}

var foo2 = m => n => x => y => return x+y+m+n; 
foo(10)(20)(30)(40);

好处:

  • 单一职责原则,一个函数只处理一个问题
function sum(m,n,x,y){
    return m*m+n*2+x*3+y*4;
}
function sum(m){
    m*=m;
    return function(n){
        n=n*2;
        return function(x){
            x*=3;
            return function(y){
                y*=4;
                return m+n+x+y;
            }
        }
    }
}

相比较传统函数而言单独的逻辑处理可以放置在函数内部,不会冗余,处理起来相对比较明确。

  • 逻辑复用原则
function sum(m,n){
    return m+n;
}
//调用
sum(5,10);
sum(5,12);
sum(5,18);
sum(5,19);

var sun = (m)=>{
    return function(n){
        return m+n
    }
}
var result = sum(5)
result(10);
result(12);
result(18);
  • 柯里化函数的实现
function curring(fn){
    function curried(...args){
        if(args.length >= fn.lengt){
            return fn.apply(this,args);
        }else{
            function curried2(...args2){
                return curried2.apply(this,[...args, ...args2]);
            }
            return curried2;
        }
    }
}

组合函数

使用场景:

  • 某一个数据进行函数的调用,执行两个函数fn1和fn2,这两个函数是依次执行的
  • 是否可以将两个函数组合起来使用?
function composeFn(m,n){
    return function(count){
        return n(m(count));
    }
}

with/eval/strict

var obj = {
    name: 'feelone',
    age: 18,
    message: "Hello"
};
function foo(){
    with(obj){
        console.log(message); //Hello
    }
}

with语句会形成一个作用域,常见可以用于优先判断对象的作用域的子元素属性。一般开发中不建议使用,容易混淆错误。 在"use strict"模式下不支持使用该语句。

//eval
var jsString = "var message='hello world'; console.log(message)";
eval(jsString); //可以编译JavaScript字符串代码
  • eval代码可读性非常差
  • eval是一个字符串很容易被修改
  • eval的执行必须经过JavaScript解释器,不能被JavaScript引擎优化

严格模式

是一种具有限制性的JavaScript的模式,支持严格模式的浏览器在检测代码中有严格模式时,会以更加严格的方式对代码进行检测和执行;

//默认不开启严格模式,以下代码不报错
name = "123";
123.name = "345";

//开启严格模式会报错 
"use strict";
name = "123"; //error:没有指定类型

严格模式不支持在ECMAScript未来版本中可能会定义的一些语法.

  1. 禁止意外创建全局变量
  2. 不允许函数有相同的名称
  3. 不允许使用八进制格式
  4. with语句不能使用
  5. eval函数不能向上引用变量
  6. 严格模式下的全局thisundefined