`
yunfuby126
  • 浏览: 6691 次
  • 性别: Icon_minigender_2
  • 来自: 广州
最近访客 更多访客>>
社区版块
存档分类
最新评论

javascript的函数声明与函数表达式

    博客分类:
  • js
阅读更多

函数定义方式

在javascript中,定义一个函数大体上有3种方式:
1.函数申明  2.函数表达式 3.通过 Function 函数构造函数定义。
一般来说 方法3 不太常出现,仅仅只会在一些JS类库中实现比如解析json,解析函数的字符串格式等作用。
今天主要来讲解下我所理解的前2种方式 函数声明 和 函数表达式。

函数声明

ECMA对于函数声明的定义为:
function Identifier ( FormalParameterListopt ) { FunctionBody }


使用函数申明的函数其名称会被提升,严格意义上讲就是在进入上下文阶段便已经处在的该上下文中的变量对象中(VO),位于代码执行之前。

  1. alert(func);
  2. function func(){
  3.   return "a function";
  4. }

很显然,alert 为 func函数。
在line-1中便可以访问func,就是所谓的函数使用函数声明产生的函数提升。函数作为ECMAScript三种代码类型中的一种(还有global和eval),代码的执行都会依赖自身的一个上下文,执行上下文分为2个阶段 进入执行上下文 和 代码执行。 该处的函数声明名称被放入变量对象中,是在进入执行上下文阶段,是在代码执行阶段之前,所以可以在代码执行阶段被访问到,而无关于在代码中声明位子进行的函数声明。关于执行上下文可以参考TOM大叔的 javascript核心 和执行上下文 ,讲的很有深度的。

对于函数声明也是有规范的:要么处于程序级别,要么处于其他函数中。除了这2处,其他位置都是违反规范的,也会导致一些浏览器的解析不正确。

比如

  1. function foo(){
  2.   if(window===parent){
  3.     function bar(){alert(1);}
  4.   }
  5.   else{
  6.     function bar(){alert(2);}
  7.   }
  8.   bar();
  9. }
  10. foo();


显然讲函数声明置于if的块中是不符合ECMA规范的,一般浏览器会将



ECMA中作用域只有函数级的作用域,而没有块级作用域,所以if的块级作用域是无效的。
而在与火狐下



该问题就是由于火狐浏览器下对块内函数声明与一般的浏览器有差异导致的,所以需要注意对于一般函数声明需要有规范。

函数表达式

函数表达式的声明为

function Identifier

opt

 ( FormalParameterList

opt

 ) { FunctionBody }

与函数声明的区别在于,标示符名称可以省略,并且处于表达式中,为表达式的一部分。

  1. var func1 = function f(){};
  2.  
  3. var func2 = function(){};
  4.  
  5. (function func3(){});
  6.  
  7. ~function func4(){};
  8.  
  9. !function func5(){};
  10.  
  11. true,function func6(){};
  12. ...


以上等等,函数部分均为自身表达式的一部分,所以都为函数表达式。
函数表达式与函数声明的一个重要的区别在于,对于 var func1 = function f(){}; 来说,规范定义其中的 f 标示符不会暴露出来,仅仅可以供 f 函数内部进行访问。

当然在此对于IE8-版本的浏览器来说又有一个重大的BUG。
对于表达式  var func1 = function f(){};   来说,其解析就会出现较为严重的错误,它会现将表达式中的函数部分单独提取出来先进行函数声明,在进行函数表达式解析。更为严重的是,其中的 func1 != f,相当于独自创建了 函数f ,再对表达式中的函数在创建一份,并且将地址赋予 func1。解决的办法就是尽量避免IE的这些特性保证兼容所有浏览器。

实例

e.g.1

  1. alert(a);
  2. var a = 2;
  3. function a(){}
  4. alert(a)

结果为  function a(){} 和 2。
首先在进入上下文阶段时 函数声明将变量声明覆盖掉(变量的赋值是处于代码执行阶段),所以第一个 alert 弹出的为函数,当代码执行过程中,a又被重新赋值为2,故第二个 alert 显示的为2。整个流程可以与 e.g.2 进行比较就不难理解了。

e.g.2

  1. alert(a);
  2. var a;
  3. function a(){}
  4. alert(a)

其结果均为  function a(){}。
就可以看出,将a赋值
为2,是在代码执行阶段进行的。那么对于

e.g.3

  1. alert(a);
  2. var a = 2;
  3. alert(a);

可以很清楚的知道 答案为 undefined 与 2
但是对于

e.g.4

  1. alert(a);
  2. function a(){}
  3. var a = 2;
  4. alert(a)

为什么又是  function a(){} 和 2  为什么之后的变量声明中 a为undefined没有覆盖函数声明的a呢?
一般的看法为权重说法,就是函数声明一个标示符之后,如果再对该标示符进行变量声明,那么该变量声明将视为无效。而另一种看法是对于函数声明其实其流程与变量声明是一直的,在进入上下文阶段 均赋值为undefined,但是函数声明将函数引用赋给标示符这一过程,是在代码执行之前触发那一刻。 就好第一个 alert 之前那一刻,a从undefined变为了function。个人偏向于后一种看法。当然如果要知道真正的流程那么还是需要去看 ECMA3或者ECMA5详细规范吧(http://ecmascript.cn/)。
当然说到了函数,那么势必需要知道一下关于 this 的一些资料,可以参考下上篇文章  JS的this简单理解~ 文章下面有好几篇经典的 this 介绍。

e.g.5

  1. var f = function(){ return true; };
  2. var g = function(){ return false; };
  3. (function(){
  4.   alert(f());
  5.   if(g() && [] !== []){
  6.     f = function f(){ return false; }
  7.     function g(){ return true; }
  8.   }
  9. })();
  10. alert(f());

这是一个比较绕的题目,考察的就是上面说的2点。
先来看下答案 chrome opera IE9+等普通浏览器 会弹出  true false ,火狐这个文艺浏览器 会弹出 true true  而IE8-这2B浏览器就会弹出false true。 呵呵开玩笑。

首先说下普通浏览器 true false 吧,JS中只有函数作用域,而没有块级作用域,所以匿名自执行函数中判断的中的  g() 就为块中定义的函数g(所谓的函数提升),然后 f 被重新指向返回 false 的函数了。 所以结果为 true false。

那么第二种 true true的话,由于规范中的函数声明只可以在 程序级 或者 其它函数中,位于 if 块语句中显然会有悖于这个规范,而火狐是无法忍受该错误的,会将块中的函数声明作为 函数表达式的形式来处理。那么在 if 判断的时候就直接米有通过 那么就为 2个true了。

  1. var g = function(){ return false; };
  2. (function(){
  3.   alert(g());
  4.   {
  5.     function g(){ return true; }
  6.   }
  7.   alert(g());
  8. })();

从这段代码在火狐下执行可以看出来, false 和 true 相当于 火狐下,块中的函数声明被当做了函数表达式来处理(效果上可以这么说)。

最后对于IE8-下的浏览器来说对于有名称的函数表达式,该标示符会被暴露出来。确切的来讲 IE8-下 会将 f = function f(){} 先进行函数声明一次,然后再进行一次函数声明,也导致了该处的 f 并不是会到全局变量下的 f ,而是因为已经在该函数作用域下有了f的函数声明,而覆盖该函数作用域下的 f。则有了 true false 的结果。

呵呵 能力有限,菜鸟观点,还有很多地方没有弄清楚,望大家多多指教。

分享到:
评论

相关推荐

    javascript 函数声明与函数表达式的区别介绍

    在JavaScript编程中,函数声明与函数表达式是两种不同定义函数的方式,它们在使用场景和作用机制上存在明显的区别。为了更好地理解这两种定义方式,让我们深入探讨它们的定义、区别以及各自的特点。 首先,函数声明...

    函数声明与函数表达式1

    总结来说,函数声明和函数表达式在JavaScript中有着不同的行为和用法。理解这两者的区别对于编写可预测且无bug的代码至关重要。在实际开发中,应根据需求选择合适的函数定义方式,例如,如果你需要在函数声明之前...

    浅析函数声明和函数表达式-函数声明的声明提前_.docx

    【函数声明与函数表达式】在JavaScript中,函数是第一类对象,这意味着它们可以作为值进行传递和存储。本文将重点讨论两种常见的函数定义方式:函数声明和函数表达式,特别是函数声明的声明提前(Hoisting)现象。 ...

    浅谈javascript 函数表达式和函数声明的区别

    javascript中声明函数的方法有两种:函数声明式和函数表达式. 区别如下: 1).以函数声明的方法定义的函数,函数名是必须的,而函数表达式的函数名是可选的. 2).以函数声明的方法定义的函数,函数可以在函数声明之前调用,...

    JavaScript基础篇(6)之函数表达式闭包

    #### 一、函数表达式与函数声明 JavaScript中定义函数主要分为函数声明和函数表达式两种形式。函数声明一般会使用`function`关键字直接声明一个函数,如`function fn() {}`,而函数表达式则通常将函数作为赋值...

    揭秘命名函数表达式

    在JavaScript的世界里,创建函数的两大方式——**函数表达式**与**函数声明**——构成了语言的核心部分,两者之间微妙的差异往往决定了代码的行为模式与性能表现。 ##### 函数声明: 函数声明是一种明确定义函数的...

    浅析javascript中函数声明和函数表达式的区别

    JavaScript是Web开发中不可或缺的一部分,它提供了两种声明函数的方式:函数声明式和函数表达式。这两者虽然看似相似,但存在显著的区别。 1. **函数声明式**:这是JavaScript中最直接的函数定义方式,通常以`...

    JavaScript中函数表达式和函数声明及函数声明与函数表达式的不同

    JavaScript中函数表达式和函数声明是创建函数的两种基本方式,它们在语法和行为上有所区别。函数声明(Function Declaration)和函数表达式(Function Expression)的不同之处在于它们在代码中的处理方式和使用时机...

    javascript函数声明和函数表达式区别分析

    在JavaScript中,函数的声明方式主要有两种:函数声明(Function Declaration)和函数表达式(Function Expression)。尽管它们在表面上看起来相似,但它们之间存在着本质的区别。下面将详细地对这两者的概念和区别...

    JavaScript的函数声明与应用

    本文将深入探讨JavaScript的函数声明与应用。 首先,我们需要理解函数声明的两种基本形式:函数声明(Function Declaration)和函数表达式(Function Expression)。函数声明是最常见的形式,它允许我们在任何地方...

    javascript强制函数自动执行.pdf

    ### JavaScript中的函数声明与函数表达式 在JavaScript中,函数是一种非常重要的编程构造,它可以被定义为函数声明或函数表达式。这两种定义方式各有特点,并且在不同的上下文中有着不同的行为。 #### 函数声明...

    全面了解函数声明与函数表达式、变量提升

    了解函数声明与函数表达式以及变量提升对于编写清晰、无误的JavaScript代码至关重要。 首先,我们来探讨函数声明与函数表达式的差异。函数声明,如`function foo(){};`,是一种直接定义函数的方式,这种声明在代码...

    JS 有名函数表达式全面解析

    此例展示了 JScript 如何将有名函数表达式同时视为函数声明和函数表达式。按照 JavaScript 规范,函数声明会在执行上下文中优先于其他表达式进行解析,而 JScript 的实现则让 `g` 作为一个函数声明提前被解析了。 *...

    JavaScript中的函数声明和函数表达式区别浅析

    当初只知道两种声明方式一个是函数声明一个是函数表达式,具体有什么不同没能说得很好。最近正好看到这方面的书籍,就想好好总结一番。  在ECMAScript中,有两个最常用的创建函数对象的方法,即使用函数表达式或者...

    Javascript中的函数声明与函数表达式(奇技淫巧)

    在阐述为什么之前,让我们先来明确Javascript中的两个概念:函数声明和函数表达式: 先来看看什么样的是函数声明: [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行] 再来看看什么样的是函数表达式: [Ctrl+A ...

Global site tag (gtag.js) - Google Analytics