/** * 求阶乘(带尾递归的函数) * * JavaScript 当前没有对尾递归进行优化,所以如果递归过深会导致堆栈溢出 * @param i * @param a * @returns {*} 返回自身调用的结果 */ var factorial = function factorial(i, a) { a = a || 1; if (i < 2) { return a; } return factorial(i - 1, a * i); }; console.log(factorial(4));
9 作用域
作用域控制着变量和参数的可见性以及生命周期,它减少了名称冲突,而且提供自动内存管理机制。
var foo = function () { var a = 3, b = 5; var bar = function () { var b = 7, c = 11; console.log("a:" + a + ";b:" + b + ";c:" + c);//a:3;b:7;c:11 a += b + c; console.log("a:" + a + ";b:" + b + ";c:" + c);//a:21;b:7;c:11 }; console.log("a:" + a + ";b:" + b);//a:3;b:5 bar(); console.log("a:" + a + ";b:" + b);//a:21;b:5 }; foo();
JavaScript 支持函数作用域,但要注意一点,就是在一个函数内部的任何位置定义的变量,都这个函数的任何地方都是可见的!
**注意:**JavaScript 不支持块级作用域。所以最好的做法是在函数体的顶部,声明函数中可能会用到的所有变量。
10 闭包
作用域的好处是:内部函数可以访问定义它们外部函数的参数和变量(除了 this 和 arguments)。
注意:内部函数拥有比它的外部函数更长的生命周期。
var myObject = (function () { var value = 0;//只对 increment 与 getValue 可见 return { increment: function (inc) { value += typeof inc === 'number' ? inc : 1; }, getValue: function () { return value; } } }());
通过一个函数的形式来初始化 myObject 对象,它会返回一个对象字面量。函数定义了一个 value 变量,这个变量对 increment 和 getValue 方法总是可见的,但它的函数作用域却使得这个变量对其他的代码来说是不可见的!
/** * quo 构造函数 * @param status 私有属性 * @returns {{get_status: Function}} */ var quo = function (status) { return { get_status: function () {//方法 return status; } }; }; var myQuo = quo("amazed"); console.log(myQuo.get_status());//amazed
当我们调用 quo 时,它会返回一个包含 get_status 方法的新对象,它的引用保存在 myQuo 中。所以即使 quo 函数已经返回了,但 get_status 方法仍然享有访问 quo 对象的 status 属性的特权。get_status 方法访问的可是 status 属性本身,这就是闭包哦O(∩_∩)O~
再看一个例子:
/** * 设置一个 DOM 节点为黄色,然后渐变为白色 * @param node */ var fade = function (node) { var level = 1; var step = function () { var hex = level.toString(16);//转换为 16 位字符 node.style.backgroundColor = '#FFFF' + hex + hex; if (level < 15) { level += 1; setTimeout(step, 100); } }; setTimeout(step, 100); }; fade(document.body);
内容版权声明:除非注明,否则皆为本站原创文章。