函数表达式

定义函数的两种方式

函数声明

  1. function funcName (arg0, arg1, arg2) {
  2. }

特点

  • 函数声明提升

执行代码之前,会先读取函数声明,可以把函数声明放在调用它的语句的后面;

函数表达式

  1. const funcName = function (arg0, arg1, arg2) {
  2. // 函数体
  3. }

这种形式看起来像是常规的变量赋值语句。即创建一个函数,并将它赋值给变量 funcName

特点

函数既然可以赋值给一个变量,那么其也可以作为一个参数进行传递,也可以作为其他函数的返回值进行返回。

  1. // 作为返回值
  2. const getFunctionA = function () {
  3. return function () {
  4. console.log('functionA')
  5. }
  6. }
  7. // 作为参数
  8. const sayFunctonA = function (sayFunctionA) {
  9. sayFunctionA()
  10. }

注意

函数表达式与其他表达式一样,在使用前,必须赋值;

  1. sayHello();
  2. const sayHello = function () {
  3. alert('hello')
  4. }// 执行结果: 出错

从一个例子看两种方法的区别

需求:根据一个条件判断,来对同一个同名方法进行不同的定义

函数声明这样做

  1. if (condition) {
  2. function sayHello () {
  3. console.log('吃了吗?')
  4. }
  5. } else {
  6. function sayHello () {
  7. alert('吃了再吃点!')
  8. }
  9. }
  • 执行结果:出现某种意想不到的结果,不应如此使用

    以上做法,在ECMAScript中属于无效语法

    • 大部分浏览器默认返回第第二个函数定义,忽略 condition的值
    • Firefox在condition为true时返回第一个函数定义

函数表示式这样做

  1. const sayHello;
  2. if (condition) {
  3. sayHello = function () {
  4. console.log('吃了吗?')
  5. }
  6. } else {
  7. sayHello = function () {
  8. alert('吃了再吃点!')
  9. }
  10. }
  • 执行结果:不会出任何意外;

闭包

定义

指有权访问另一个函数作用域中的变量的函数

创建闭包的常见方式

创建闭包的常见方式,就是在一个函数内部创建另一个函数

  1. function createFunction (propertyName) {
  2. return function(object1, object2){
  3. let value1 = object1[propertyName] // 内部函数,访问了外部函数的变量
  4. let value2 = object2[propertyName] // 内部函数,访问了外部函数的变量
  5. if (value1 < value2) {
  6. return -1
  7. } else if (value1 > value2) {
  8. return 0
  9. }
  10. }
  11. }

代码中,注释处,内部函数的代码,访问了外部函数中的变量。即使这个内部函数被返回了,而且在其他的地方调用了,但他仍然可以访问外部函数中的propertyName。之所以还能够访问这个变量,是因为内部函数的作用域链中包含了外部函数的作用域

为了彻底搞清楚其中的细节,必须从理解函数第一次被调用的时候都会发生什么入手。

某个函数第一次被调用时

  • 1.创建执行环境
  • 2.创建对应的作用域链
  • 3.把作用域链赋值给一个特殊的内部属性([Scope])
  • 4.使用 this、arguments 和 其他命名参数的值来初始化函数的活动对象

函数执行过程中,为读取和写入变量的值,需要在作用域链中查找变量

例子:

  1. function compare (value1, value2) {
  2. if (value1 < value2) {
  3. return -1
  4. } else if (value1 > value2) {
  5. return 1
  6. } else {
  7. return 0
  8. }
  9. }
  10. let result = compare(5, 10)

未完待续……