整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

JavaScript全局变量、局部变量与作用域链揭秘

JavaScript全局变量、局部变量与作用域链揭秘

JavaScript(简称JS)作为现代Web开发的基石,其灵活性和强大功能为前端开发人员提供了无限可能。理解和掌握JS的作用域机制,包括全局变量、局部变量以及作用域链的概念,对于编写高效、可维护的代码至关重要。本文旨在深入剖析这些概念,通过实例讲解它们的工作原理,帮助初学者和有经验的开发者巩固知识,提升编程技能。

技术概述

全局变量与局部变量

  • 全局变量:在任何函数外部声明的变量,可以在整个程序范围内被访问。
  • 局部变量:在函数内部声明的变量,仅在该函数或其闭包中可见。

核心特性与优势

  • 隔离性:局部变量有助于代码模块化,避免命名冲突。
  • 封装性:作用域规则保护了变量,防止外部意外修改。

代码示例

var globalVar='I am global';

function localScope() {
    var localVar='I am local';
    console.log(localVar); // 输出: I am local
}

localScope();
console.log(globalVar); // 输出: I am global
console.log(localVar); // 报错: localVar is not defined

技术细节

作用域链

作用域链是JS引擎在函数执行时创建的一个链表,用于确定变量的可访问性。每个函数都有自己的作用域链,链的最前端是当前函数的局部变量,随后是包含它的函数的作用域,直到全局作用域。

原理分析

当JS引擎查找一个变量时,它会从当前作用域开始搜索,如果没有找到,则沿着作用域链向上查找,直到找到变量或者到达全局作用域。

难点解析

  • 闭包:闭包允许函数访问并修改其外部作用域中的变量,即使该函数在外部作用域之外被调用。

代码示例

function outerFunction() {
    var outerVar='Outer Variable';

    function innerFunction() {
        console.log(outerVar); // 输出: Outer Variable
    }

    return innerFunction;
}

var innerFunc=outerFunction();
innerFunc();

实战应用

应用场景

在构建模块化和可复用的代码时,理解作用域机制是至关重要的。例如,在异步回调或事件处理程序中正确使用闭包,可以避免“变量泄漏”。

代码示例

function setupEvent() {
    var counter=0;

    document.getElementById('myButton').addEventListener('click', function() {
        counter++;
        console.log('Clicks:', counter);
    });
}

setupEvent();

优化与改进

性能考量

过度依赖全局变量可能导致内存泄漏和命名空间污染。使用模块模式或ES6的letconst关键字可以有效避免这些问题。

代码示例

(function(module) {
    module.init=function() {
        // 初始化代码
    };
})(window.MyModule={});

// 或者使用ES6
const myModule=(()=> {
    let privateVar='Private';

    return {
        getPrivate: ()=> privateVar
    };
})();

常见问题

  • Q: 什么是变量提升(hoisting)?
  • A: JS会自动将所有变量和函数声明提升到当前作用域的顶部,但只有声明会被提升,初始化不会。

总结与展望

全局变量、局部变量以及作用域链是JS编程的基础概念,深刻理解它们有助于编写健壮、高效的代码。随着ES6及后续版本的推出,诸如块级作用域、箭头函数等新特性进一步增强了作用域管理的能力,为开发者提供了更多的工具和可能性。未来,随着前端工程化的发展,作用域管理和模块化的最佳实践将变得更加重要,助力开发者构建更加复杂和高性能的应用。

希望本文能帮助你建立对JS作用域机制的深入理解,并在实际项目中加以运用,不断精进你的编程技艺。

带领学生学习JavaScript,都讲到计时事件了。发现如果不讲清楚全局变量,便没办法把停止计时事件讲清楚。

clearInterval() 方法用于停止 setInterval() 方法执行的函数代码。

要使用 clearInterval() 方法, 在创建计时方法时你必须使用全局变量-----------菜鸟教程 JavaScript计时事件

便补充一下:

原本全局变量这个东西,在讲了函数后就应该介绍一下的,只是一直没有较好的应用场景,一直拖着。正好,借着这个机会,现讲现用。

举例1:

<script>function aa(){ var a=10; alert(a);}function bb(){ alert(a);}</script>

在函数bb中就无法访问到a这个变量。

每一个花括号({})好比我们的一间教室,而这个a好比是老师我,现在老师在这间教室上课,隔壁班的学生能听到吗?

不能!

类比一下,所以这种情况为什么是错误的,就能够理解了。

现在,如果老师我跑出去,跑到广播室,大声地宣布:都去到操场,课不上了,请问隔壁班的能听到吗?

<script>

var a=10;

functionaa(){

alert(a);

}

functionbb(){

alert(a);

}

</script>

能听到!

这种情况下,a就是一个全局变量!

这样比方之后,感觉学生大部分能理解了。但是出现了恶意抬杠的(感觉还是没理解透),问我这种情况a的值为什么变了:

<script>

ar a=10;

function aa(){

var a=100;

alert(a);

}

function bb(){

alert(a);

}

</script>

首先,函数aa里面的var 是多余的,有或者没有,一个意思。其次,这种情况好比:老师在广播里通知大家去操场, 回头又跑到你们班来说,不用去了。你们听哪一个?是去还是不去?

不去。

同样的道理,虽然全局变量的初始值是10,但是在函数里重新赋值为100,这个时候已经改变了变量的值。

学生进一步胡搅蛮缠:

<script>

var a=10;

function aa(){

var b=100;

alert(a);

}

function bb(){

alert(a);

}

</script>

那这种情况呢?

好比老师在广播通知你们班接下来两节课到机房上,然后你们班主任跑到教室通知你们下午的卫生要好好打扫,你们听谁的?

班主任的!这一次异口同声。

我倒忘了这茬,反问,接下来两节课都不是她的,你们也听她的啊?

两个变量毫不相干,没有任何影响嘛。

全局变量就讲了这么多,觉得这个比方还算贴切,所以贴了出来……

随后在计时事件中完善代码,终于完成了停止功能,按下不表……

我自己是一名从事了多年开发的web前端老程序员,目前辞职在做自己的web前端私人定制课程,今年年初我花了一个月整理了一份最适合2019年学习的web前端学习干货,各种框架都有整理,送给每一位前端小伙伴,想要获取的可以关注我的头条号并在后台私信我:前端,即可免费获取



作者:yulele
链接:https://www.jianshu.com/p/06e8f6a2fb65

avascript有两种变量:局部变量和全局变量。局部变量是指只能在变量声明的函数内部调用。全局变量时整个代码中都可以调用的变量(window对象的变量)。

局部变量包括函数内声明的变量和函数的形式参数。

全局变量num预处理时,只声明未定义,所以第一次输出undefined;函数fn内部num被声明,所以其为局部变量,预处理时函数fn既声明又定义了,并且函数fn有俩个形式参数n1和n2;函数fn执行时会开辟新的作用域,在新的作用域下,此时的局部变量num预处理时只声明,所以输出undefined;n1被赋值100,n2被赋值200,局部变量num为300,所以第三次输出为300;第四次输出为全局变量num,无法访问函数内的局部变量num,所以结果为10。

函数形成了一个私有的作用域,保护了内部的局部变量不被外界干扰。局部变量和全局变量相互独立、互不影响。

此时函数fn内的num未被声明,按照javascript作用域链的原理,当一个变量在当前作用域下找不到该变量的定义,那么javascript引擎就会沿着作用域链往上找直到在全局作用域里查找,所以函数fn内的num属于全局变量。

关键词:作用域 变量 作用域链 闭包