欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

函数是“一等公民”

程序员文章站 2022-05-04 15:01:50
在JS中,函数被称为“一等公民”,英文原文first-class object(第一类对象)。 既然是对象,那么它就可以: 除了上述对象的功能,函数区别其它对象之处是能被调用。 在JS中,存在变量提升。当一个变量通过var声明之后,会立即被提升至当前作用域顶部(let 和 const 声明的变量则不 ......

在JS中,函数被称为“一等公民”,英文原文first-class object(第一类对象)。

既然是对象,那么它就可以:

  1. 通过字面量创建
  2. 赋值给变量,数组元素和其他对象的属性(property)
  3. 作为参数传递给函数
  4. 作为函数的返回值
  5. 含有能被动态创建和赋值的属性

除了上述对象的功能,函数区别其它对象之处是能被调用。

 

在JS中,存在变量提升。当一个变量通过var声明之后,会立即被提升至当前作用域顶部(let 和 const 声明的变量则不会)。例如:

1 function a() {
2     console.log(b);
3     var b = 10;
4 }
5 a();  //undefined

上面这段代码的运行结果为undefined。原因是,当b变量通过var声明后,发生了变量提升,立即被提升至当前作用域顶部(注意,提升是在声明之后立即发生,此时b还未被定义!),此时的“当前作用域”就是函数a的作用域。因此,上面的代码其实是这样的:

1 function a() {
2     var b;  //变量的声明被提升至当前作用域顶部
3     console.log(b);
4     b = 10;
5 }
6 a();

变量b的声明被提升至第二行(提升的只是声明),且此时b没有被赋值,因此代码继续执行至第三行console.log(b)时,就输出了undefined。

 

而JS除了变量提升外,还存在“函数提升”。同理,函数也会被提升,只不过,函数不仅仅是声明的提升,而是“整体提升”。请看下面的代码:

1 function a() {
2     b();
3     function b() {
4         console.log("yes!");
5     }
6 }
7 a();  //yes!

此时可以正常执行函数b。这正是因为函数被提升,而且是“整体提升”,所以b()才能正常执行。这段代码其实等价于:

1 function a() {
2     function b() {
3         console.log("yes!");
4     }
5     b();
6 }
7 a();  //yes!

需要注意的是,只有普通形式声明的函数才能被提升!例如:

1 function a() {
2     b();
3     var b = function() {        //字面量声明的函数
4         console.log("yes!");
5     }
6 }
7 a();  //报错

这里的匿名函数是通过字面量声明的,所以不存在函数提升,结果就会报错。

 

但是,当变量和函数同时被声明时,谁提升得更优先呢?

在JS中,函数之所以被称为“一等公民”,其中一个原因就是它比变量更有优先级,在发生提升时,函数会提升至作用域的最顶部!例如:

1 function a() {
2     var b = 10;
3     function b () {
4         console.log("yes!");
5     }
6     console.log(b);
7     console.log(typeof b);
8 }
9 a();    //10  number

在这段代码中,变量b的声明被提升,但作为“一等公民”的函数却被提升到变量b的声明之上。在执行代码阶段,10赋值给b,因此输出结果,b是10,类型变成了number。