前言网上还没用发现有人对命名函数表达式进去重复深入的讨论,正因为如此,网上出现了各种各样的误解,本文将从原理和实践两个方面来探讨JavaScript关于命名函数表达式的优缺点。简单的说,命名函数表达式只有一个用户,那就是在Debug或者Profiler分析的时候来描述函数的名称,也可以使用函数名实现递归,但很快你就会发现其实是不切实际的。当然,如果你不关注调试,那就没什么可担心的了,否则,如果你想 ...
前言
网上还没用发现有人对命名函数表达式进去重复深入的讨论,正因为如此,网上出现了各种各样的误解,本文将从原理和实践两个方面来探讨JavaScript关于命名函数表达式的优缺点。
简单的说,命名函数表达式只有一个用户,那就是在Debug或者Profiler分析的时候来描述函数的名称,也可以使用函数名实现递归,但很快你就会发现其实是不切实际的。当然,如果你不关注调试,那就没什么可担心的了,否则,如果你想了解兼容性方面的东西的话,你还是应该继续往下看看。
我们先开始看看,什么叫函数表达式,然后再说一下现代调试器如何处理这些表达式,如果你已经对这方面很熟悉的话,请直接跳过此小节。
函数表达式和函数声明
在ECMAScript中,创建函数的最常用的两个方法是函数表达式和函数声明,两者期间的区别是有点晕,因为ECMA规范只明确了一点:函数表达式必须带有标示符(Identifier)(就是大家常说的函数名称),而函数表达式则可以省略这个标示符:
函数声明:
function 函数名称 (参数:可选){ 函数体 }
函数表达式:
function 函数名称(可选)(参数:可选){ 函数体 }
所以,可以看出,如果不声明函数名称,它肯定是表达式,可如果声明了函数名称的话,如何判断是函数声明还是函数表达式呢?ECMAScript是通过上下文来区分的,如果function foo(){}是作为赋值表达式的一部分的话,那它就是一个函数表达式,如果function foo(){}被包含在一个函数体内,或者位于程序的最顶部的话,那它就是一个函数声明。
function foo(){} // 声明,因为它是程序的一部分 new function bar(){}; // 表达式,因为它是new表达式 (function(){ function fn() { if (true) { // 相反,这样情况,我们要用函数表达式函数语句
在ECMAScript的语法扩展中,有一个是函数语句,目前只有基于Gecko的浏览器实现了该扩展,所以对于下面的例子,我们仅是抱着学习的目的来看,一般来说不推荐使用(除非你针对Gecko浏览器进行开发)。
1.一般语句能用的地方,函数语句也能用,当然也包括Block块中:
if (true) { if (typeof docEl.compareDocumentPosition != 'undefined') { // 这里我们使用了3个带名字的函数声明 // Call stack // Call stack // Call stack: // 又再次看到了清晰的调用栈信息了耶!下面我们就来看看IE在实现中究竟犯了那些错误,俗话说知已知彼,才能百战不殆。我们来看看如下几个例子:例1:函数表达式的标示符泄露到外部作用域 var f = function g(){};例2:将命名函数表达式同时当作函数声明和函数表达式 typeof g; // "function"这个例子引出了下一个例子。 f.expando = 'foo';再来看一个稍微复杂的例子:例4:仅仅顺序解析函数声明而忽略条件语句块
var f = function g() { var arr = [ ]; without `null`: 7.6K -> 20.3K IE7: without `null`: 14K -> 29.7K另一个把内部对象实现为全局Object对象的是黑莓(Blackberry)浏览器。目前,它的活动对象(Activation Object)仍然继承Object.prototype。可是,ECMA-262并没有说活动对象也要“像调用new Object()表达式那样”来创建(或者说像创建保存NFE标识符的对象一样创建)。 人家规范只说了活动对象是规范中的一种机制。 那我们就来看看黑莓里都发生了什么: Object.prototype.x = 'outer'; // 声明要引用函数的变量 // 有条件地创建命名函数 // 声明一个与函数名(标识符)对应的变量,并赋值为null // 返回根据条件定义的函数 var docEl = document.documentElement; // 2) 声明要引用函数的变量 if (docEl.addEventListener) { // 3) 有意给函数一个描述性的标识符 // 4) 清除由JScript创建的addEvent函数 // 5) 最后返回由fn引用的函数 // 定义私有变量 // 使用函数声明 // 返回函数 var docEl = document.documentElement; function addEventListener(){ if (typeof docEl.addEventListener != 'undefined') { // 此前,你可能会使用arguments.callee
海外公司注册、海外银行开户、跨境平台代入驻、VAT、EPR等知识和在线办理:https://www.xlkjsw.com
原标题:深入理解JavaScript系列(2):揭秘命名函数表达式
关键词:JavaScript,匿名函数,函数表达式
*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们:
admin#shaoqun.com
(#换成@)。