[20141030]编写高质量JS代码的68个有效方法(三)
Tips:
//第一个事实:JavaScript允许你引用在当前函数以外定义的变量。 function testClosures(){ var all = 'Test'; function test(m){ return all + ' and ' + m; } return test('closures'); } testClosures(); //'Test and closures' //第二个事实:即使外部函数已返回,当前函数仍然可以引用在外部函数所定义的变量。 function testClosures(){ var all = 'Test'; function test(m){ return all + ' and ' + m; } return test; } var t = testClosures(); t('closures'); //'Test and closures' //第三个事实:闭包可以更新外部变量的值 function TestClass(){ var all; return { set: function(value){ all = value; }, get: function(){ return all; } }; } var t = new TestClass(); t.set('555'); t.get();
闭包的优缺点: 优点: 变量保护、封装性,能够实现字段的可访问性(示例如下)
function ModelClass(){ //Property var name,age=23; return { setName: function(value){ //设置名称 name = value; }, getName: function(){ //获取名称 return name; }, getAge: function(){ //只读 return age; } }; }
缺点: 常驻内存,会增加内存使用量,使用不当和容易造成内存泄露。
JavaScript支持词法作用域,而不支持块级作用域
function test(){ alert(a); //undefined var a = 1; alert(a); //1 } test(); 以上代码等价于: function test(){ var a; alert(a); //undefined a = 1; alert(a); //1 } test();
一个例外是 try...catch :catch块中的变量作用域只在catch中。
function test(){ var x = '1'; try{ throw '' }catch(x){ alert('error'); x = '2'; } alert(x); // 1 } test();
看看以下代码段输出什么?
function test(){ var arr = [1,2,3,4,5]; var result = []; for(var i = 0, len = arr.length; i < len; i++){ result[i] = function(){ return arr[i]; } } return result; } var result = test(); result[0]();
可以通过立即调用表达式来解决JavaScript缺少块级作用域。如上代码可修改为:
function test(){ var arr = [1,2,3,4,5]; var result = []; for(var i = 0, len = arr.length; i < len; i++){ (function(){ var j = i; result[i] = function(){ return arr[j]; } })(i); } return result } var result = test(); result[0]();
匿名和命名函数表达式的官方区别在于后者会绑定到与其函数名相同的变量上,该变量将作为该函数内部的一个局部变量。这可以用来写递归函数表达式。
var f = function find(tree, key){ if(!tree){ return null; } if(tree.key === key){ return tree.value; } //函数内部可以访问find return find(tree.left, key) || find(tree.right, key); }
结论:尽量避免使用命名函数表达式
function f(){ return 'global'; } function test(x){ var result = []; if(x){ function f(){ return 'local'; } result.push(f()); } result.push(f()); return result; } test(true); test(false);
结论:尽量将函数块定义为变量,防止函数提前