Javascript语言精粹(二)
2015-07-15 16:45
537 查看
闭包
// 创建一个构造函数quo // 它带有get_status方法和status私有属性 var quo = function(status){ return { get_status: function(){ return status; } }; }; var myQuo = quo('amazing'); alert(myQuo.get_status());
当我们调用quo时,它返回一个对象:
①该对象包含一个get_status方法,②该对象的一个引用保存在myQuo中。
即使quo已经返回了(return status;),但get_status方法仍然有访问status属性的特权。
get_status方法访问的并不是status参数的副本,而是status参数本身!
因为该函数可以访问它被创建时所处的上下文环境。也因此该函数被称为闭包。
再看一个更有用的栗子:
// 定义一个函数,它使一个DOM节点的背景色由黄变白 var fade = function(node){ var level = 1; var step = function(){ var hex = level.toString(16); node.style.backgroundColor = '#FFFF' + hex + hex; if(hex < 15){ level += 1; setTimeout(step, 100); } }; setTimeout(step, 100); }; fade(document.body);
只要fade的内部函数step需要level,level变量就会持续保留。
糟糕的栗子:
// 弹出节点的序号 var add_the_handlers = function(nodes){ var i; for(i=0; i<nodes.length; i++){ nodes[i].onclick = function(){ alert(i); //总是弹出节点的数目 }; } };
未能达到目的的原因,是因为onclick时间处理器函数绑定了变量 i 本身,而不是函数在构造时的变量 i 的值。
(个人理解:js解析的时候,把for循环解析了一遍, 运行的时候 i 已经等于节点数目了。绑定了 i 本身,故弹出的 i 等于节点数目。我们需要弹出的 i 是在它被构造时的值。)
解决糟糕的栗子:
var add_the_handlers = function(nodes){ var helper = function(i){ return function(){ alert(i); }; }; var i; for(i=0; i<nodes.length; i++){ nodes[i].onclick = helper(i); } };
避免在循环中创建函数,这会带来无谓的计算,还会引起混淆。
可以在循环之外先创建一个辅助函数helper,让辅助函数返回一个绑定了当前 i 值的函数,这样就不会混淆了。
模块
我们可以使用函数和闭包来构建模块,这几乎可以完全摒弃全局变量的使用。模块是一个提供接口却隐藏状态和实现的函数或对象。
模块模式也可以用来产生安全的对象。
我们来构造一个产生序列号的对象:
var serial_maker = function(){ // 该对象包含一个设置前缀的方法 // 该对象包含一个设置序列号的方法 // 和一个生成字符串的方法 var prefix = ''; //前缀 var seq = 0; //序列号 return { set_prefix: function(p){ prefix = String(p); }, set_seq: function(s){ seq = s; }, generate: function(){ var result = prefix + seq; seq += 1; return result; } }; }; // 调用 var seqer = serial_maker(); seqer.set_prefix('Q'); seqer.set_seq(1000); var unique = seqer.generate(); // "Q1000"
如果我们把seqer.generate作为一个值传递给第三方函数,这个函数能产生唯一的字符串,但却不能通过它来改变prefix和seq的值。
级联
有一些方法没有返回值。例如一些设置或修改对象状态的方法。如果我们让这些方法返回 this 而不是 undefined,就可以启用级联。
getElement('mydiv') .move(350, 150) .width(100) .height(100) .on('mouseenter', 'drag');
这些方法每一个都返回该对象,所以每次调用返回的结果可以被下一次调用所用。
级联能给“全能”接口的热潮降降温,一个接口没必要一次做太多事情。
相关文章推荐
- JS中document对象和window对象的区别
- JS中Null与Undefined的区别
- js 弹出对话框3种方式
- JS滚轮事件(mousewheel/DOMMouseScroll)了解
- json详解
- js对象冒充实现的继承
- extjs2.2 panel加背景色
- 图片滚动js代码
- 读书时间《JavaScript高级程序设计》四:BOM,客户端检测
- Javascript打印金字塔,倒立金字塔,空心金字塔,菱形,空心菱形等
- Ajax实现异步操作实例_针对JSON格式的请求数据
- js异步收集
- js异步收集
- JSONP VS CORS
- 什么是JSON格式
- Js New一个函数和直接调用的区别
- H5+JS实现《Just Do 8》游戏源码分享
- js刷新页面方法大全
- javascript 类型检测
- JSTL常用函数总结