函数作用域以及立即执行函数表达式

函数作用域

JavaScript函数是指一个特定代码块,可能包含多条语句,可以通过名字来供其它语句调用以执行函数包含的代码语句。

作用域指的是变量存在的范围。JavaScript只有两种作用域:

  • 全局作用域:变量在整个程序中一直存在,所有地方都可以读取。
  • 函数作用域:变量只在函数内部存在。

在函数外部声明的就是全局变量,可以在函数内部读取。

var a = 1;
function fn() {
    console.log(a);
}
fn(); // 1

在函数内部定义的变量,外部无法读取,这就是局部变量。

function fn() {
    var b = 1;
}
b; // Uncaught ReferenceError: b is not defined

函数本身也是一个值,也有自己的作用域。它的作用域与变量一样,就是其声明时所在的作用域,与其运行时所在的作用域无关。

var a = 1;
function fn1(){
  function fn2(){
    console.log(a)
  }
  function fn3(){
    var a = 4
    fn2()
  }
  var a = 2
  return fn3
}
var fn = fn1();
fn() // 2

上面的代码中,我们需要的结果是fn()的最终输出。我们先一层一层的往上找,fn()等于fn1(),所以我们看一下fn1()的结果。fn1()里面定义了a等于2,这就覆盖了全局变量的a等于1。这时告诉我们返回值是fn3(),我们在去看fn3()fn3()里面的返回值是fn2()fn2()直接打印了a的值,并没有设定a的值。这时,我们就需要去fn2()的父层去找a。此时,发现var a = 2,所以结果为2。

这里我们是通过作用域链来寻找结果的,作用域链是在一个大的作用域下形成的一个关系层。子对象会一级一级的向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的;但是子对象的变量,对父对象是不可见的。

我们在解析函数时应遵守以下规则:

  1. 函数在执行的过程中,先从自己的内部找变量。
  2. 如果找不到,再从创建当前函数所在的作用域去找,以此往上。
  3. 注意找的是变量当前的状态。

立即执行函数表达式

在JavaScript中,一对圆括号()是一种运算符,跟在函数明之后,表示调用该函数。比如,fn()就表示调用fn函数。

立即执行函数表达式是一种利用JS函数生成新作用域的编程方法。

有时我们需要在定义函数之后,立即调用该函数。这时,你不能在函数的定义之后加上圆括号,这会产生语法错误。

funtion() {/*内容*/}();
// Uncaught SyntaxError: Unexpected token {

这是因为,function可以被当作表达式,也可以当作语句来执行。

为了避免解析上的歧义,JavaScript引擎规定 ,如果function关键字出现在行首,一律解释成语句。

解决方法就是不要让function出现在行首,让引擎将其理解成一个表达式。

( function () {} () );
( function () {} ) ();
! function () {} ();
~ function () {} ();
- function () {} ();
+ function () {} ();

这些写法是都是可以的。通常情况下,只对匿名函数使用这种“立即执行函数表达式”。它有三个作用:

  • 令函数中声明的变量绕过变量声明前置规则
  • 避免新变量被解释成全局变量或函数名占用全局变量名的情况
  • 在禁止访问函数内变量声明的情况下,允许外部对函数的调用
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容