你的位置:首页 > 软件开发 > Java > 深入理解JavaScript系列(2):揭秘命名函数表达式

深入理解JavaScript系列(2):揭秘命名函数表达式

发布时间:2011-12-30 11:00:48
前言网上还没用发现有人对命名函数表达式进去重复深入的讨论,正因为如此,网上出现了各种各样的误解,本文将从原理和实践两个方面来探讨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 (#换成@)。