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:原始字符串 }); }; }());
内容版权声明:除非注明,否则皆为本站原创文章。