JavaScript函数的特性与应用实践深入详解(7)

注意:最后一行是 (),所以我们是立即调用刚刚创建的函数!

模块模式利用函数的作用域和闭包来创建被绑定对象和私有成员的关联。这个例子中只有 deentityify 方法才有权访问 entity (字符实体表)。

模块模式是一个定义了私有变量和函数的函数。先利用闭包创建一个可以访问私有变量和函数的特权函数,最后返回这个函数,或者把它保存到一个可以被访问到的地方。

模块模式做到了信息隐藏,是一种优秀的设计实践,特别适合于封装应用程序或者构造单例哦O(∩_∩)O~

模块模式还可以产生安全对象。比如我们想构造一个能够产生序列号的对象:

/**
 * 产生唯一字符串的对象(安全的对象)
 * 唯一字符串由 (前缀 + 序列号) 组成
 * @returns {{set_prefix: Function, set_seq: Function, gensym: Function}}
 */
var serial_number = function () {
  var prefix = '';
  var seq = 0;
  return {
    /**
     * 设置前缀
     * @param p
     */
    set_prefix: function (p) {
      prefix = String(p);
    },
    /**
     * 设置序列号
     * @param s
     */
    set_seq: function (s) {
      seq = s;
    },
    /**
     * 产生唯一的字符串
     * @returns {string}
     */
    gensym: function () {
      var result = prefix + seq;
      seq += 1;
      return result;
    }
  };
};
var seqer = serial_number();
seqer.set_prefix('Q');
seqer.set_seq(1000);
var unique = seqer.gensym();
console.log(unique);//Q1000

sequer 包含的方法没有用到 this 或 that,所以很安全。sequer 是一组函数的集合,只有那些特权函数才能够获取或修改私有属性哦O(∩_∩)O~

如果把 sequer.gensym 作为值传递给第三方函数,那么那个函数可以使用它产生唯一的字符串,但却不能通过这个函数改变 prefix 或 seq 的值。因为这个函数的功能只是“产生唯一的字符串”呀!

13 级联

如果我们让某些方法返回 this,那么就会启动级联。在级联中,我们可以在单条语句中依次调用同一个对象的多个方法,最著名的例子就是 jQuery 哦O(∩_∩)O~

形如:

getElement('myDiv')
 .move(350,150)
 .width(100);

级联可以产生出极富表现力的接口。

14 柯里化

柯里化指的是:把函数与传递给它的参数结合,产生出新的函数:

Function.method('curry', function () {
  var slice = Array.prototype.slice,
    args = slice.apply(arguments),//创建一个真正的数组
    that = this;
  return function () {
    return that.apply(null, args.concat(slice.apply(arguments)));
  };
});
var add1 = add.curry(1);
console.log(add1(6));//7

因为 arguments 不是真正的数组,所以没有 concat 方法,因此我们使用 slice 创建出了真正的数组。