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

fade 函数在最后一行被调用后已经返回,但只要 fade 的内部函数又需要,它的变量就会持续保留。

注意:内部函数能够访问外部函数的实际变量:

var add_the_handlers_error = function (nodes) {
  var i;
  for (i = 0; i < nodes.length; i += 1) {
    nodes[i].onclick = function (e) {
      alert(i);//绑定的是变量 i 本身,而不是函数在构造时的变量 i 的值!!!
    }
  }
};

add_the_handlers_error 函数的本意是:想传递给每个事件处理器一个唯一的 i 值,但因为事件处理器函数绑定了变量 i 本身,而不是它的值!

/**
 * 给数组中的节点设置事件处理程序(点击节点,会弹出一个显示节点序号的对话框)
 * @param nodes
 */
var add_the_handlers = function (nodes) {
  var helper = function (i) {//辅助函数,绑定了当前的 i 值
    return function (e) {
      alert(i);
    };
  };
  var i;
  for (i = 0; i < nodes.length; i += 1) {
    nodes[i].onclick = helper(i);
  }
};

我们在循环之外向构造一个辅助函数,让这个函数返回一个绑定了当前 i 值的函数,这样就可以解决问题啦O(∩_∩)O~

11 回调

假设用户触发了一个请求,浏览器向服务器发送这个请求,然后最终显示服务器的响应结果:

request = prepare_the_request();
response = send_request_synchronously(request);
display(response);

这种方式的问题在于,网络上的同步请求可能会导致客户端进入假死状态。

所以建议使用异步请求,并为服务端的响应创建一个回调函数。这个异步请求函数会立即返回,这样我们的客户端就不会被阻塞啦:

request = prepare_the_request();
send_request_asynchronously(request, function(response){
 display(response);
)};

一旦接收到服务端的响应,传给 send_request_asynchronously 的匿名函数就会被调用啦O(∩_∩)O~

12 模块模式

模块是一个提供接口但却隐藏状态与实现的函数。可以使用函数和闭包来构建模块。通过函数来生成模块,就可以不用全局变量啦。

假设我们想给 String 增加一个 deentityify 方法。它会寻找字符串中的 HTML 字符,并把它们替换为对应的字符。这就需要在对象中保存字符实体的名字和它对应的字符。不能用全局变量,因为它是魔鬼!如果定义在函数内部,那么就会带来运行时的损耗,因为每次执行函数时,这个字面量就会被求值一次。所以理想的方式是把它放入闭包:

String.method('deentityify', function () {
  //字符实体表:映射字符实体的名字到对应的字符
  var entity = {
    quot: '"',
    lt: '<',
    gt: '>'
  };
  //返回 deentityify 方法
  return function () {
    /**
     * 返回以'&'开头 和 以';'结尾的子字符串
     */
    return this.replace(/&([^$;]+);/g, function (a, b) {
      var r = entity[b];//b:映射字符实体名字
      return typeof r === 'string' ? r : a;//a:原始字符串
    });
  };
}());


      

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/447.html