函数:声明和表达式

函数:声明和表达式

函数,像变量一样,可以在代码的任意地方定义它。

JS 提供了几个方法去定义它们。

1.函数声明     (Function Declaration)

2.函数表达式  (Function Expression)

3.通过调用new Function 返回。

语法

创建一个函数的基本方法是通过一个函数声明。语法如下:

function f(arg1, arg2, ...) {
   ... code ...
}

实现起来像这样子:

1 function sayHi(name) {
2   alert("Hi, "+name)
3 }
4  
5 sayHi(‘John‘)

上面的例子声明了一个带有一个参数name,函数名为sayHi的函数,并且调用了它。

返回值

我们用return语句来返回一个值。

1 function sum(a, b) {
2   return a+b
3 }
4  
5 var result = sum(2,5)
6 alert(result)

如果函数不返回任何东西,它的结果 会是一个特殊的值,undefined。你可以从下面的代码看到。

1 function getNothing() {
2   // no return
3 }
4  
5 var result = getNothing()
6  
7 alert(result)

一个空的返回也是一样:

1 function getNothing() {
2   return
3 }
4 alert( getNothing() === undefined ) // true

局部变量

一个函数可以包括变量,通过var来定义。这些变量被称为局部变量,而且只能在函数内部使用。

1 function sum(a, b) {
2   var sum = a + b
3  
4   return sum
5 }

函数声明

 函数的声明的解析是在预执行(pre-execution)阶段,也就是浏览器准备执行代码的时候。

因此,通过函数声明来定义函数,可以在定义前或后被调用。

下面的代码是可以跑的:

1 function sayHi(name) {
2   alert("Hi, "+name)
3 }
4  
5 sayHi("John")

换个顺序也可以:

1 sayHi("John")
2  
3 function sayHi(name) {
4   alert("Hi, "+name)
5 }

     一个函数可以在代码任意位置声明。

比如,我们可能要根据条件来声明不同的函数:

1 sayHi()
2  
3 if (1) {
4   function sayHi() {  alert(1)  }
5 else {
6   function sayHi() {  alert(2)  } // <--
7 }

在写这篇文章的时候(作者本人没有给出他这这篇文章的时间——译者注),尝试在不同浏览器,火狐会抛出异常,其他两个浏览器都会给出结果 2。

这是因为声明是在代码执行前解析的。根据规范(p.10.5),后面函数会覆盖前面存在的同名函数。

到了执行时期,声明会被忽略。所以if语句没有起作用。

函数表达式

在JS里面,函数function和number、string一样,是一阶值(原文为:first-class value,有人也译作:‘一等公民’)

只要可以放置变量的地方,都可以放置函数。在那个‘地方’用函数表达式的语法来声明:function (arguments) {}

例如,你可以这样使用变量:

var f = 5

也可给f赋值一个函数表达式:

1 var f = function(name) {
2     alert("Hi, " + name + "!");
3 }

‘function‘ 关键字什么时候用作 表达式,什么时候又用作 声明

规则很简单

当js解析器看到function出现在主码流( main code flow 不知如何翻译),function被认为是声明。

当 function 作为语句(statement)的一部分出现的,都会是表达式。

(译者认为,可以看能不能加分号来判断,能加分号的都为语句(statement)。)

函数表达式会在执行流( execution flow)执行到它的时候才会创建函数。所以,函数表达式必须被执行了(此时函数才定义了)才能被调用。

01 var sayHi
02  
03 // sayHi() <-- can‘t call here, there is no sayHi yet
04  
05 if (1) {
06   sayHi = function() {  alert(1)  }
07 else {
08   sayHi = function() {  alert(2)  }
09 }
10  
11 sayHi()

上面的例子,在所有浏览器执行的结果都一样。

请用函数声明

有经验的开发者,会将函数通过表达式来定义。

... code ...
var f = function() { ... }
...

函数声明会更短更有可读性。

... code ...
function f() { ... }
...

此外函数这样定义可以在定义前调用。

在你真正需要用函数表达式的使用它!特别是在有条件判断的时候定义函数。

函数是一个值

函数在JS里面是一个基本类型。我们甚至可以输出它:

1 function f() { alert(1) }
2  
3 alert(f)

上面的例子会输出这个function,通常是输出这个函数的源代码

无论是函数声明还是表达式,对函数来说,只是创建的时间不同而已。

传递一个函数

想所有值一样,不管是以哪种方式定义,函数可以被赋值,作为参数传递到另外的函数等等。

1 function sayHi(name) {
2   alert("Hi, "+name)
3 }
4  
5 var hi = sayHi // assign a function to another variable
6  
7 hi("dude")     // call the function

函数的传递是引用类型。也就是说,函数会存在内存的某个位置,sayhi是它的一个引用(如果你懂指针的话)。当把sayhi赋给hi的时候,两者都会引用到同一个函数。

函数可以接受另一个函数作为参数。

1 function runWithOne(f) {  // runs given function with argument 1
2   f(1)
3 }
4  
5 runWithOne(
6   function(a){ alert(a) }
7 )

逻辑上,函数是一个行为(action)。所以传递一个函数就是传递了一个可以被其他程序启动的行为。这个特性在js中广泛使用。

在上面的例子中,我们创建了一个没有名字的函数,而且没有把它赋给其他变量。这种函数被称为匿名函数。

就地运行

我们可以使用函数表达式创建一个函数并马上执行它。

1 (function() {
2  
3   var a, b    // local variables
4   
5   // ...      // and the code
6  
7 })()

我们涉及到局部变量的时候常用这种技巧。我们不想让局部变量污染到全局变量,所以我们把代码包在一个函数里面。

在代码执行后,全局变量还是干净的。这是一个最佳实践。

为什么函数被包在括号里面?这是因为js只能就地运行函数表达式。

函数声明不能像上面一样执行。

1 function work() {
2   // ...
3 }()  // syntax error

即使我们把名字去掉,JS还是会发现function这个关键字,把它解析成函数声明。

1 function() { // error, function declaration without name.
2   // ...
3 }()

所以,只有把函数包在括号面才可行。然后解析器会认为它是语句中的一部分,把它提升为函数表达式。

如果函数明显就是一个表达式,那么也不用包起来。

1 var result = function(a,b) { return a+b }(2,2)
2 alert(result) // 4

上面的代码,函数会被创建并且马上执行。

下面代码的结果是啥?为啥?

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

P.S. 想清楚哦童鞋,有陷阱哦~Ok, 我已经提醒过你了。 

Solution

答案是 error. Try it:

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

因为var a = 5 后面没有加分号,JS会这样处理的。

1 var a = 5(function() {
2   alert(a)
3 })()

所以,JS尝试把5当做函数来调用,这会导致错误。真正能用的代码如下。

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

这应该是JS没有分号的最危险的陷阱了。

还有一种方法去定义还是就是直接调用Function构造器:

1 var sayHi = new Function(‘name‘‘ alert("Hi, "+name) ‘);
2  
3 sayHi("Benedict");

它很少用,基本不用。

命名函数表达式

一个函数表达式可以有名字:

var f = function sayHi(name) {
  alert("Hi, "+name)
}

这个语法被称作命名函数表达式(named function expression or NFE), 但是在IE<9下表现都不正常。

在支持这个语法的浏览器下,这个函数的名字只可以在函数内部被访问。

1 var f = function sayHi(name) {
2   alert(sayHi) // outputs function
3 }
4  
5 alert(sayHi) // error: undefined variable ‘sayHi‘

IE在这种情况下却创造了两个函数对象:sayHi 和 f

1 var f = function g() {  }
2  
3 // false in IE, error (g is undefined) in other browsers
4 alert(f=== g)

NFE 存在的目的是让匿名函数可以递归。

看下面的包含在setTimeout里面的factorial函数:

setTimeout(function factorial(n) {
  return n == 1 ? n : n*factorial(n-1)
}, 100)

下面代码的结果是什么?为什么?

function g() { return 1 } )
 
alert(g)

Solution

答案是 error:

1 function g() { return 1 } )
2  
3 alert(g)

关键点是要理解(function ... )是一个函数表达式而不是函数定义.

所以这是一个命名函数表达式。

命名表达式的名字只能在函数内部访问。

除了IE<9 ,其他浏览器都支持 NFEs, 所以它们会抛出 ‘undefined variable’ 异常, 因为函数名 g 只能在内部被访问。

IE<9 不支持 NFE, 所以它们会输出整个函数(源代码).

 函数命名

函数是行为(action),所以应该起一个动词做名字,像get,red,calculateSum这些。

下面的情况是允许短函数名的:

1.函数在内嵌函数里面暂时使用的,和变量的逻辑一样。

2.函数会在整个代码里的多次被调用。一方面,你不会忘了它是干嘛用的,另一反面,你可以少些点代码。

现实世界中,像‘$‘,‘$$‘,‘$A‘,这些,会经常在JS函数库里被使用。

其他情况下,还是应该用动词,或者动词做开头的函数名字

总结

函数在JS里面是基本类型。它们可以根据需要被赋值,传递和调用。

一个不返回任何东西的函数其实返回了undefined

用动词做函数名字。

Function Declaration Function Expression
function 在主代码流里面 function 作为函数表达式的一部分
函数在代码执行前创建,可以在定义前被调用。 当代码执行到的是创建,只能在定义后调用。
  可以就地调用

转载:

http://www.cnblogs.com/Xdoable/archive/2011/09/08/2171512.html

时间: 2024-08-13 08:59:26

函数:声明和表达式的相关文章

JavaScript学习总结(三、函数声明和表达式、this、闭包和引用、arguments对象、函数间传递参数)

一.函数声明和表达式 函数声明: function test() {}; test();    //运行正常 function test() {}; 函数表达式: var test = function() {}; test;    //undefined test();   //TypeError var test = function() {}; 命名函数的赋值表达式: var test = function bar() { test();    //正常运行 }; test();    /

函数声明与表达式

将脚本编写为函数可避免页面载入时直接执行该脚本 函数中有代码,这些代码只能被事件激活或在函数运行时才会执行 变量声明 函数中声明的变量,叫做局部变量,该变量只能在函数中访问,退出函数后该变量就会被撤销:这意味着我们可以在不同的函数中声明名称相同的变量 函数声明 这种方法会在执行前被解析,它可以存在于该函数运行代码的前后任意位置.代码如下所示 function fun () { ... }; fun(); 或 fun(); function fun () { ... }; 运行结果都为正常 函数赋

js中函数声明与表达式

//函数声明:function 函数名(){} //函数表达式: function 函数名(可写可不写的)(){}  : 命名函数表达式 匿名函数表达式 //function aaa(){} : 函数声明 //var a = function aaa(){} : 命名函数表达式 //var a = function(){}  : 匿名函数表达式 (function aaa(){}) : 表达式 ~function aaa(){} -function aaa(){} +function aaa()

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

记得在面试腾讯实习生的时候,面试官问了我这样一道问题. //下述两种声明方式有什么不同 function foo(){}; var bar = function foo(){}; 当初只知道两种声明方式一个是函数声明一个是函数表达式,具体有什么不同没能说得很好.最近正好看到这方面的书籍,就想好好总结一番. 在ECMAScript中,有两个最常用的创建函数对象的方法,即使用函数表达式或者使用函数声明.对此,ECMAScript规范明确了一点,即是,即函数声明 必须始终带有一个标识符(Identif

js函数表达式和函数声明的区别

我们已经知道,在任意代码片段外部添加包装函数,可以将内部的变量和函数定义"隐 藏"起来,外部作用域无法访问包装函数内部的任何内容. 例如: var a = 2; function foo() { // <-- 添加这一行 var a = 3; console.log( a ); // 3 } // <-- 以及这一行 foo(); // <-- 以及这一行 console.log( a ); // 2 虽然这种技术可以解决一些问题,但是它并不理想,因为会导致一些额外的

JS中函数表达式与函数声明的区别

hello,沐晴又来更新啦,今天呢,跟大家讲讲让人头疼的函数表达式和函数声明,反正我当初看那本高级程序的时候,是没怎么看太透,哈哈.我是个比较重基础的人,跟我一起探讨函数表达式和函数声明的世界吧. 首先呢,先看看他们的颜值:   函数声明:function 函数名(){}   函数表达式:function 函数名(可写可不写)(){}; (不写名叫做匿名函数表达式.写名叫做命名函数表达式.推荐用匿名的.) 这么一看长的好像没啥区别,反正颜值也都不高.那么我们如何区别是函数表达式还是函数声明呢?答

声明和表达式区别

函数:声明和表达式 函数,像变量一样,可以在代码的任意地方定义它. JS 提供了几个方法去定义它们. 1.函数声明     (Function Declaration) 2.函数表达式  (Function Expression) 3.通过调用new Function 返回. 语法 创建一个函数的基本方法是通过一个函数声明.语法如下: function f(arg1, arg2, ...) {    ... code ... } 实现起来像这样子: 1 function sayHi(name)

javascript 函数声明和函数表达式的区别(学习笔记)

javascript中声明函数的方法有两种:函数声明式和函数表达式. 区别如下: 1).以函数声明的方法定义的函数,函数名是必须的,而函数表达式的函数名是可选的. 2).以函数声明的方法定义的函数,函数可以在函数声明之前调用,而函数表达式的函数只能在声明之后调用. 3).以函数声明的方法定义的函数并不是真正的声明,它们仅仅可以出现在全局中,或者嵌套在其他的函数中,但是它们不能出现在循环,条件或者try/catch/finally中,而 函数表达式可以在任何地方声明. 下面分别用两种方法定义函数:

函数声明与函数表达式的区别

1.函数声明 函数声明以function关键字开头,接着是必须的函数(变量)名和以逗号分隔的可选的参数列表,再接着就是以大括号封装的函数体.函数声明必须是一个单独的JavaScript语句. 2.函数表达式 在任何情况下都是其它JavaScript语句的一部分(比如复制表达式等号的右侧.函数的参数)的函数被称为函数表达式. 3.比较 //函数声明function myFunctionDeclaration(){ function innerFunction() {} } //以下为函数表达式 v