前端入门17-JavaScript进阶之作用域

声明

本系列文章内容全部梳理自以下几个来源:

  • 《JavaScript权威指南》
  • MDN web docs
  • Github:smyhvae/web
  • Github:goddyZhao/Translation/JavaScript

作为一个前端小白,入门跟着这几个来源学习,感谢作者的分享,在其基础上,通过自己的理解,梳理出的知识点,或许有遗漏,或许有些理解是错误的,如有发现,欢迎指点下。

PS:梳理的内容以《JavaScript权威指南》这本书中的内容为主,因此接下去跟 JavaScript 语法相关的系列文章基本只介绍 ES5 标准规范的内容、ES6 等这系列梳理完再单独来讲讲。

正文-作用域

在 ES5 中,变量的作用域只有两类:

  • 全局作用域

  •     函数作用域
    

只要不是在函数内部定义的变量,作用域都是全局的,全局的变量在哪里都可以被访问到,即使跨 js 文件。

函数作用域是指在函数体定义的变量,不管有没有在函数体的开头定义,在函数体的任何地方都可以被使用,因为 JavaScript 中的变量有声明提前的行为。

函数作用域需要区别于 Java 语言中的块级作用域:

var i = 0;
function A() {
    console.log(i); //输出undefined
    for (var i = 0; i < 1; i++) {}
    console.log(i); //输出1
}

在 Java 中,类似的代码,在 for 循环前后输出的 i 都会是 0,因为都会使用成员变量 i,for循环内定义的 i 由于块级作用域限制,只在for 循环的 {} 大括号中的代码有效。

但在 JavaScript 中,变量作用域只分函数作用域,而且变量有声明提前的特性,所以在函数体内部第一次输出 i 时,此时变量已经提前声明,但还没初始化,所以会是 undefined。而函数内定义的变量的作用域或者说生命周期是整个函数内,所以即使 for 循环体语句结束,仍旧可以访问到 i 变量。

由于允许变量的重复定义,所以全局变量很容易起冲突,因为无法确保多份 js 文件中是否已经在全局中定义了该变量,一旦起冲突,浏览器行为仅仅是将后定义的覆盖掉前定义的而已,这对于浏览器角度没什么大问题,但对于程序而已,很容易出现不可控的问题。而且,极难排查。

所以,实际编程中,建议不要过多的使用全局变量,有多种方法可以避免:

  • 使用一个全局对象来作为命名空间,将其余不在函数体内部定义的变量,作为该全局对象的属性来定义使用。
  • 使用一个立即执行的函数来作为临时命名空间,函数执行结束释放临时命名空间。
  • 如果临时命名空间内的部分变量需要供外部使用,一可以将这部分变量添加到作为命名空间的全局对象上的属性,二可以利用闭包的特性,返回一个新建的对象,为该对象添加一些接口可访问这部分变量。

全局对象作为命名空间

var DASU = {};
DASU.num = 1;
function a() {
    console.log(DASU.num);
}

这里的全局对象意思是说,数据类型为对象的全局变量,简称全局对象,与前端里说的全局对象window是两个不同概念,区分一下。

其实也就是一种思想,将所有函数外需要定义的变量,都替换成对指定对象的属性来操作。

立即执行的函数作为临时命名空间

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

当引入 js 文件到 HTML 时,js 文件中的代码就会被执行,或者声明了

你可能感兴趣的:(前端入门17-JavaScript进阶之作用域)