函数式编程

JavaScript采用词法作用域(lexical scoping)。
函数的执行依赖于变量作用域,这个作用域是在函数定义时决定的,而不是函数调用时决定的。
为了实现这种词法作用域,JavaScript函数对象的内部状态不仅包含函数的代码逻辑,还必须引用当前的作用域链。
函数对象可以通过作用域链相互关联起来,函数体内部的变量都可以保存在函数作用域内,这种特性在计算机科学文献中称为“闭包(closure)”。
从技术的角度讲,所有的JavaScript函数都是闭包:它们都是对象,它们都关联到作用域链。

嵌套函数

var scope = "globle scope";
function checkscope() {
  var scope = "local scope";
  function f() {
    return scope;
  }
  return f;
}
var ff = checkscope();
console.log(ff());
var scope = "globle scope";
function checkscope() {
  var scope = "local scope";
  function f() {
    return scope;
  }
  return f();
}
console.log(checkscope());

如果这个函数定义了嵌套的函数,并将它作为返回值返回或者存储在某处的属性里,这时就会有一个外部引用指向这个嵌套的函数。

<script>
  let items = document.querySelectorAll("ul#test li");
  function bindClick(nodes) {
    for (var i = 0; i < nodes.length; i++) {
      nodes[i].onclick = function () {
        console.log(i, nodes[i].innerHTML);
      };
    }
  }
  bindClick(items);
</script>

let声明的变量识别块作用域,块作用域中声明的函数就形成了闭包。
每次循环都会创建一个新的函数,则这些函数每一个都会形成闭包。
因此,每次调用特定函数时所访问的i,就是其闭包中引用了外部函数作用域链上的i。

function bindClick(nodes) {
  for (let i = 0; i < nodes.length; i++) {
    nodes[i].onclick = function () {
      console.log(i, nodes[i].innerHTML);
    };
  }
}

通过创建一个名称易懂的独立函数,调用是无需每次传入第一个参数,因为第一个参数通过bind提供了固定值。
当有一个很通用的函数,为了方便提供一个较常用的变体

let sum = function (x, y) {
  return x + y;
};
let succ = sum.bind(null, 1);
// succ被称为偏函数
console.log(succ(2));

自定义偏函数示例

  let jack = {
    firstName: "Jack",
    say(time, phrase) {
      console.log(`[${time}] ${this.firstName}: ${phrase}`);
    },
  };
  let tom = {
    firstName: "Tom",
  };
  jack.sayNow = partial(
    jack.say,
    new Date().getHours() + ":" + new Date().getMinutes()
  );
  tom.sayNow = jack.sayNow;
  jack.sayNow("Hello");
  tom.sayNow("World");

实现高级柯里化函数,针对n个参数的函数
如果传递args数与原函数已经定义的参数个数一样或更长,那么直接调用func函数。
获得偏函数:否则,不调用func函数,返回另一个包装器pass,提供连接之前的参数一起做为新参数重新应用curried。然后再次执行一个新调用,返回一个新偏函数(如果参数不够)或最终结果。

function curry(func) {
    return function curried(...args) {
      if (args.length >= func.length) {
        return func.apply(this, args);
      } else {
        return function pass(...args2) {
           return curried.apply(this, args.concat(args2));
        };
      }
    };
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值