Java函数式编程-手写柯里化函数-组合函数-严格模式

1、柯里化函数的实现(自己实现)(面试题)

// 柯里化函数的实现hhCurrying
function hhCurrying(fn) {
    
    
  function curried(...args) {
    
    
    /*判断当前已经接收的参数的个数, 和参数本身需要接受的参数
    是否已经一致了*/
    // 1.当已经传入的参数 大于等于 需要的参数时, 就执行函数
	//args.length:当前已经接收的参数个数,
 	//fn.length函数本身需要接收的参数的个数
    if (args.length >= fn.length) {
    
    
      // fn.call(this, ...args)
      return fn.apply(this, args)
    } else {
    
    
      // 没有达到个数时, 需要返回一个新的函数, 继续来接收的参数
      function curried2(...args2) {
    
    
        /* 接收到参数后, 需要递归调用curried来检查函数的参数
        是否达到一致*/
        //concat函数:连接两个数组
        return curried.apply(this, args.concat(args2))
      }
      return curried2
    }
  }
  return curried
}
//测试1
function add1(x, y, z) {
    
    
  return x + y + z
}

//转为柯里化函数
var curryAdd = hhCurrying(add1)

console.log(curryAdd(10, 20, 30))   //60
console.log(curryAdd(10, 20)(30))  //60
console.log(curryAdd(10)(20)(30))   //60

//测试2
function foo(x, y, z) {
    
    
  return x + y + z;
}

var result1 = foo.call({
    
    }, 1, 2, 3);
console.log(result1); //6

var curryFoo = hhCurrying(foo);
var result2 = curryFoo.call({
    
    }, 1)(2)(4);
console.log(result2); //7

2、组合函数的理解

  • (1)现在需要对某一个数据进行函数的调用,执行两个函数fn1和fn2,这两个函数是依次执行的,那么如果每次我们都需要进行两个函数的调用,操作上就会显得重复。
  • 解决方案:将这两个函数组合起来,自动依次调用,
  • 这个过程就是对函数的组合,我们称之为 组合函数(Compose Function)
//未组合:
function double(num) {
    
    
  return num * 2;
}

function square(num) {
    
    
  return num ** 2;
}

var count = 10;
var result = square(double(count));
console.log(result); //400

// 实现最简单的组合函数
function composeFn(m, n) {
    
    
  return function (count) {
    
    
    return n(m(count));
  };
}

var newFn = composeFn(double, square);
console.log(newFn(10));  //400

3、 通用组合函数的实现(自己实现)

function hhCompose(...fns) {
    
    
  var length = fns.length
  //传入的参数必须是一个函数,否则抛出错误
  for (var i = 0; i < length; i++) {
    
    
    if (typeof fns[i] !== 'function') {
    
    
      throw new TypeError("Expected arguments are functions")
    }
  }

  function compose(...args) {
    
    
    var index = 0
    // 判读一下是否有有值(有无长度),有值的情况执行一下第一个函数
    var result = length ? fns[index].apply(this, args): args
    while(++index < length) {
    
    
      result = fns[index].call(this, result)
    }
    return result
  }
  return compose
}
//测试
function double(m) {
    
    
  return m * 2;
}

function square(n) {
    
    
  return n ** 2;
}

var newFn = hhCompose(double, square);
console.log(newFn(10));  //400

4、JS额外知识补充-with语句-eval函数-严格模式

4.1、with语句(已经不建议使用)(严格模式下不允许包含with语句)

作用:with语句 扩展一个语句的作用域链(可以形成自己的作用域链)

var message = "Hello World";
var obj = {
    
     name: "why", age: 18, message: "obj message" };
// with语句: 可以形成自己的作用域
function foo() {
    
    
  function bar() {
    
    
    with (obj) {
    
    
      console.log(message); //obj message
      console.log("------");
    }
  }
  bar();
}
foo();

var info = {
    
     name: "kobe" };
with (info) {
    
    
  console.log(name); //kobe
}

4.2、eval函数(全局函数)

  • (1)作用:eval是一个特殊的函数,它可以将传入的字符串当做JavaScript代码来运行。
  • (2)不建议在开发中使用eval:
    ①eval代码的可读性非常的差(代码的可读性是高质量代码的重要原则)
    ②eval是一个字符串,那么有可能在执行的过程中被刻意篡改,那么可能会造成被攻击的风险;
    ③eval的执行必须经过JS解释器,不能被JS引擎优化;
var jsString = 'var message = "Hello World"; console.log(message);';
eval(jsString); //Hello World

4.3、 严格模式(‘‘use strict’’;)

  • 严格模式限制
  • (1)无法意外的创建全局变量
  • (2)使引起静默失败(silently fail,注:不报错也没有任何效果)的赋值操作抛出异常
  • (3)严格模式下试图删除不可删除的属性
  • (4)不允许函数参数有相同的名称
  • (5)不允许0的八进制语法
  • (6)不允许使用with
  • (7)eval不再为上层引用变量
  • (8)this绑定不会默认转成对象
 "use strict";

// 1. 禁止意外创建全局变量
 message = "Hello World"  
//会报message is not defined的错误,message未声明  
 console.log(message)

 function foo() {
    
    
   age = 20   //会报age is not defined的错误,age未声明
 }

 foo()
 console.log(age) 
 "use strict";
// 2.不允许函数有相同的参数名称
function foo(x, y, x) {
    
    
  console.log(x, y, x)     
  //会报Duplicate parameter name not allowed in this context的错误,
  //在此上下文中不允许重复的参数名称
 }
foo(10, 20, 30)
// 3.静默错误/试图删除不可删除的属性
 "use strict";
true.name = "abc"; 
//Cannot create property 'name' on boolean 'true'
NaN = 123;  
// Cannot assign to read only property 'NaN' of object '#<Object>'
var obj = {
    
    };
Object.defineProperty(obj, "name", {
    
    
  configurable: false,
  writable: false,
  value: "fifih",
});
console.log(obj.name);  //fifih
// obj.name = "kobe"; 
//Cannot assign to read only property 'name' of object '#<Object>'
delete obj.name;
// Cannot delete property 'name' of #<Object>
 "use strict";
// 4.不允许使用原先的八进制格式 0123 改成0O123就可以
 var num = 0o123 // 八进制
 var num2 = 0x123 // 十六进制
 var num3 = 0b100 // 二进制
 console.log(num, num2, num3)  //83 294 4
 "use strict";
 // 5.with语句不允许使用
// 6.eval函数不会向上引用变量了
message = "Hello eval"  
var jsString = 
  '"use strict"; var message = "Hello World"; console.log(message);'
eval(jsString)   //Hello World
console.log(message)  //报错 message is not defined

猜你喜欢

转载自blog.csdn.net/weixin_53737663/article/details/127486766