锁定老帖子 主题:JavaScript匿名函数
该帖已经被评为隐藏帖
|
|
---|---|
作者 | 正文 |
发表时间:2011-02-09
最后修改:2011-02-12
在JavaScript中,匿名函数是一种非常强大的工具,其特点与用途之多,难于在一篇文章中概括其全部,不过掌握其基本运用并不算太难,本文将尝试从如下方面进行归纳:
其中有2个知识点是笔者认为需要涉及的,不过好在只有你在担忧代码的性能和优雅问题之时,你才需要额外关注,不妨继续往下概览全文@_^
匿名函数基本特点这个特点应该是自解释的,即它是一个没有名字的函数,或说,没有指针指向该函数
function() { alert("hello world"); }
这段代码是完全合法的,但问题是定义之后无法调用,不过本文后面有一个小案例来教你如何使用。
匿名函数基本用法从其特点决定,匿名函数基本会有如下4大类用途 :
1、用来声明一个函数表达式,赋值给某一个变量保存起来,留待调用
var demo = function() { alert("hello world"); }; //some script demo(); //一段设置XMLHttpRequest回调属性的代码 xhr.onreadystatechange = function() { //some script }; 2、将匿名函数当作参数传递
//一段调用dwr发布的远程对象逻辑的代码 dwrobj.findById(uid, function(data) { //some script }); 3、当作返回值动态获取函数实现
function createFn(flag) { if (flag) return function() { alert("dude"); }; else return function() { alert("buddy"); }; } var demo = createFn(1); demo(); demo = createFn(0); demo(); demo = createFn(""); demo(); demo = createFn(NaN); demo(); demo = createFn(undefined); demo(); demo = createFn(null); demo(); 4、利用其变量作用域的特点创建“块级作用域” 之所以打上引号是因为,在ECMA-262中,没block-level scope这个概念,但是通过匿名函数,我们可以模拟出来 首先来看这段代码:
function demo() { for ( var i = 0; i < 3; i++) { var j = "inner variable"; } alert(i); alert(j); } demo(); //alert(j);//勿取消,留待在JavaScript变量及其作用域中进行分析 结论为:先后弹出3,“inner variable” 看来在for语句块中定义的i和j在语句块结束时并没销毁,但在函数运行结束后销毁了,虽然有些出乎意料之外,但是请先记住这个效果,留待以后分析。
为了满足某种需求,并且利用上刚才的效果,你可能需要在某一个块中定义某些变量,然后做到用后即弃的效果,但是需要对上述代码进行修改:
function() { var j = "inner variable"; alert("do sth. with variable j"); }(); try { alert(j); } catch (e) { alert(e); } 首先定义一个匿名函数,然后加了一对小括号让它立马运行,如果能弹出一个警示框,而不是j在块中定义的值(“inner variable”),应该就是ok的,但是最后在浏览器中会报错:
因为JavaScript将function关键字视作一个函数声明的开始,其后不能跟随小括号,要这样做的话,得将它外面再套一层小括号,从而转换成一个函数表达式。
(function() { var j = "inner variable"; alert("do sth. with variable j"); })(); try { alert(j); } catch (e) { alert(e); } 这样做的目的无非就是避免向全局作用域中添加过多的咚咚,因为他们所占用的资源要等到浏览器关闭的时候才会释放,同时也是为了避免命名冲突。
没错,这其实也就是jQuery中一段比较经典的语法。你再想想看为什么上面的try语句块不能替换成if?
if (j) alert(j); else alert("variable j has been released");
在JavaScript中,匿名函数的用法非常之灵活,非master不能阐述详尽且得当,因此本文纯属抛砖引玉,职业习惯告诉我,一个好的问题胜似一个好的答案。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-02-11
为什么上面的try语句块不能替换成if?
想不明白,无从下手 |
|
返回顶楼 | |
发表时间:2011-02-11
受益良多,谢了
|
|
返回顶楼 | |
发表时间:2011-02-11
最后修改:2011-02-11
yolio2003 写道
为什么上面的try语句块不能替换成if?
想不明白,无从下手
yolio2003,你好。 在你关注的这段代码中,使用if的前提有可能是你预期j的值为undefined(1),而对undefined的逻辑判断为false,从而执行else这一部分(2) 假设2正确,而1过于乐观。 我们来看看undefined值的解释
ECMA-262 写道
The undefined value is a primitive value used when a variable has not been assigned a value.
文档指出,undefined是一个原始类型,当一个变量没给其赋值时,它的值就(被初始化)为undefined
var num; alert(num); 去掉第一行的定义就会出“大粽子”了。。。 它其实有一个隐藏的前提:你得先有一个合法的变量(预先定义好,或者从函数参数中接收),如果没有的话,那它就不认你的帐,直接抛出错误了,所以得try-catch搞定它。 抛出的这种错误为ReferenceError:对某一个标识符求值而解析不出值的情况导致
造成这种误解多半是因为对undefined的翻译导致的,笔者认为ECMAScript的这种设计(既然有了null为啥还要有undefined)还是有待商榷,或许改天再X贴讨论下,你或许可以在这个链接中继续寻求帮助:ECMA-262,在百度文库里面也有这篇文档1-10章节的中文翻译,good luck。
|
|
返回顶楼 | |
发表时间:2011-02-11
大概懂了,谢谢详细的解答。
但这个代码: if (f) alert(j); else alert("variable j has been released"); 里面是 if (f) 貌似应该是 if (j) 的笔误。 |
|
返回顶楼 | |
发表时间:2011-02-11
yolio2003 写道 大概懂了,谢谢详细的解答。
但这个代码: if (f) alert(j); else alert("variable j has been released"); 里面是 if (f) 貌似应该是 if (j) 的笔误。 已校正,thx:) |
|
返回顶楼 | |
发表时间:2011-02-12
最后修改:2011-02-12
if (j) alert(j); else alert("variable j has been released"); 不行。 可以用下面这样就没问题了 if (typeof(j)!='undefined') alert(j); else alert("variable j has been released"); |
|
返回顶楼 | |
发表时间:2011-02-12
最后修改:2011-02-12
本来以为你有个地方写错了 原来是我看错了
|
|
返回顶楼 | |
发表时间:2011-02-12
mfkvfn 写道
if (j) alert(j); else alert("variable j has been released"); 不行。 可以用下面这样就没问题了 if (typeof(j)!='undefined') alert(j); else alert("variable j has been released");
nice! mark一下
特意查看了一下参考资料,typeof操作符大致这样来运行: 1、对该一元表达式求值 2、对1取得的结果进行类型判断,如果判断结果非引用,goto步骤4 3、对1取得的结果进一步获取其基类对象,如果为null,则return "undefined" 4、对1取得的结果进行求值 5、根据对4取得的结果进行类型判断,据此返回各种不同的字符串值
针对上面这个案例,因为j为闭包产生的局部变量,退出闭包时己经释放,本身为null,其基类对象理应为null
if (typeof j!="undefined") //我把j外面的括号去掉了,考虑到typeof是操作符,而非function alert(j); else alert("variable j has been released");应尽可能减少使用try-catch来进行流程控制,mfkvfn这段代码是值得推荐的。 |
|
返回顶楼 | |
浏览 5722 次