聊一聊JavaScript作用域和作用域链

yizhihongxing

下面是详细讲解“聊一聊JavaScript作用域和作用域链”的完整攻略。

JavaScript中的作用域

JavaScript中的作用域是指变量的适用范围,也就是变量能够被访问的区域。在JavaScript中,变量的作用域有全局作用域和局部作用域两种。

全局作用域

全局作用域是指在所有函数外部定义的变量,它的作用域范围是整个JavaScript程序。在全局作用域中定义的变量可以被任何函数和代码块访问。

下面是一个在全局作用域中定义变量的例子:

var globalVar = "I am a global variable!";

function printGlobalVar() {
  console.log(globalVar);
}

printGlobalVar(); // 输出 "I am a global variable!"

上面的代码中,globalVar是在全局作用域中定义的变量,并且可以被printGlobalVar函数访问和使用。

局部作用域

局部作用域是指在函数内部定义的变量,它的作用域范围只限于该函数内部。在局部作用域中定义的变量不能被函数外部的代码访问。

下面是一个在局部作用域中定义变量的例子:

function printLocalVar() {
  var localVar = "I am a local variable!";
  console.log(localVar);
}

printLocalVar(); // 输出 "I am a local variable!"
console.log(localVar); // 报错,无法访问局部变量 localVar

上面的代码中,localVar是在printLocalVar函数内部定义的局部变量,只能在该函数内部访问和使用,无法在函数外部的代码块中访问。

JavaScript中的作用域链

作用域链是指JavaScript中变量的查找顺序,也就是在访问一个变量时,JavaScript引擎会从当前作用域开始查找,直到找到该变量为止。如果在当前作用域中没有找到该变量,JavaScript引擎会沿着作用域链向上查找,直到找到全局作用域为止。

下面是一个示例,演示了作用域链的查找顺序:

var globalVar = "I am a global variable!";

function foo() {
  var localVar = "I am a local variable!";

  function bar() {
    console.log(localVar); // 输出 "I am a local variable!"
    console.log(globalVar); // 输出 "I am a global variable!"
  }

  bar();
}

foo();

上面的代码中,bar函数被定义在foo函数内部,因此它的作用域链中包含foo函数的作用域和全局作用域。在调用bar函数时,当访问localVar变量时,JavaScript引擎会首先查找当前作用域(也就是bar函数的作用域)是否有该变量,由于该变量是在foo函数内部定义的,所以bar函数的作用域中并没有该变量,因此JavaScript引擎会沿着作用域链向上查找,直到在foo函数的作用域中找到该变量为止。

作用域的注意事项

在实际开发中,应当注意以下几点:

  • 变量的作用域范围应当尽量小,以避免变量污染和冲突。
  • 如果在函数内部使用var关键字定义变量,该变量会被提升到函数作用域的顶部,因此在函数内部可以在定义变量前使用该变量。
  • 如果在函数内部没有使用var关键字定义变量,JavaScript引擎会将该变量视为全局变量,会在全局作用域中定义该变量。
  • 在使用闭包时,要注意变量的作用域和生命周期,以避免出现不必要的错误和问题。

示例1

下面是一个使用闭包和作用域链的示例,演示了如何将一个计数器封装到一个函数中:

function createCounter() {
  var count = 0;

  return function() {
    count++;
    console.log(count);
  }
}

var counter = createCounter();
counter(); // 输出1
counter(); // 输出2
counter(); // 输出3

上面的代码中,createCounter函数返回了一个函数,该函数可以用来实现一个计数器。在createCounter函数内部,定义了一个变量count,该变量只能在返回的函数中被访问,因此实现了计数器的封装。

示例2

下面是一个在for循环中使用闭包的示例,演示了如何避免由于变量作用域问题导致的意外结果:

for (var i = 0; i < 5; i++) {
  setTimeout(function() {
    console.log(i);
  }, 1000);
}

上面的代码中,希望通过setTimeout函数来延迟输出变量i的值。然而实际上由于变量作用域的问题,输出的结果是5个5。这是因为setTimeout函数的回调函数是在循环结束后才被调用的,此时变量i已经被累加到了5。

为了避免这种情况,可以在循环中使用一个立即执行函数来创建一个新的作用域,以确保每个回调函数都能够访问到正确的变量值:

for (var i = 0; i < 5; i++) {
  (function(j) {
    setTimeout(function() {
      console.log(j);
    }, 1000);
  })(i);
}

上面的代码中,使用一个立即执行函数来创建了一个新的作用域,将变量i的值传递给了这个函数中的参数j,从而确保每个回调函数都能够访问到正确的变量值。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:聊一聊JavaScript作用域和作用域链 - Python技术站

(0)
上一篇 2023年5月28日
下一篇 2023年5月28日

相关文章

  • 详细谈谈JS中的内存与变量存储

    JS中的内存与变量存储 内存的概念 在JS中,变量都是存储在内存中的。内存是计算机硬件中的一种可读写数据存储器,它用来存储计算机正在运行的程序、运行时所需要的数据以及运行之后产生的结果。在JS中,内存分为堆内存和栈内存两种。 栈内存 栈内存是一种连续的内存空间,可以自动分配和释放,其中存储函数的局部变量、函数参数、函数的返回值、对象的引用等。当函数运行结束或…

    JavaScript 2023年6月11日
    00
  • 详解ES6 CLASS在微信小程序中的应用实例

    详解ES6 Class在微信小程序中的应用实例 介绍 ES6 Class 是用来创建对象的模板,它具有面向对象编程的特性,使代码更加清晰、易于维护和扩展。在微信小程序开发中,使用 ES6 Class 可以大大提升代码的可读性和可维护性。 ES6 Class 的基本用法 ES6 Class 的基本语法如下: class MyClass { constructo…

    JavaScript 2023年6月11日
    00
  • JavaScript函数、闭包、原型、面向对象学习笔记

    JavaScript函数学习笔记 什么是函数 函数是 JavaScript 中的一个代码块,它可以重复执行,并且可通过传入参数和返回值来实现对信息的处理和存储。 函数的定义方式 JavaScript 中有多种定义函数的方式,以下是其中常用的三种方式: 1. 函数声明 使用 function 关键字定义的函数,代码如下: function functionNa…

    JavaScript 2023年5月27日
    00
  • JavaScript常用对象的方法和属性小结

    JavaScript常用对象的方法和属性是 JavaScript 开发中经常用到的,包括字符串对象、数组对象、数值对象、日期对象、正则表达式对象等等。下面我将为你详细讲解这些常用对象的方法和属性。 字符串对象 字符串对象是 JavaScript 中最常用的对象之一,有很多对字符串进行操作的方法和属性。 常用方法 charAt(index):返回字符串中指定下…

    JavaScript 2023年5月19日
    00
  • 深入理解JavaScript 箭头函数

    深入理解JavaScript 箭头函数 箭头函数是 ES6 中的一个新语法,它可以更简洁地定义一个匿名函数,并且具有一些特殊的语法规则和行为。在本篇文章中,我们将深入理解 JavaScript 箭头函数,包括其语法、使用方法、特殊行为以及一些示例说明。 箭头函数语法 箭头函数的语法是这样的: (parameters) => { statements }…

    JavaScript 2023年5月27日
    00
  • JavaScript之promise_动力节点Java学院整理

    关于JavaScript中的Promise,我们可以从以下几个方面来介绍: 一、Promise概述 Promise是一种异步编程的解决方案,简单来说就是用更优雅的方式解决回调地狱的问题。根据MDN的定义,Promise是一个代表了一个异步操作最终完成或者失败的对象。 二、Promise三种状态 Promise有三种状态:pending(进行中)、fulfil…

    JavaScript 2023年5月28日
    00
  • js open() 与showModalDialog()方法使用介绍

    JS open() 与 showModalDialog() 方法使用介绍 在JavaScript中,通过 open() 与 showModalDialog() 方法可以打开新的浏览器窗口或对话框,提供更好的交互体验。 open() 方法介绍 open() 方法可以在新的浏览器窗口或选项卡中打开一个URL地址。具体语法如下: window.open(url, …

    JavaScript 2023年6月11日
    00
  • 和我一起学 Three.js【初级篇】:1. 搭建 3D 场景

    ? 本篇文章共 5572 字,最近更新于 2023 年 04 月 19 日。 0. 系列文章合集 本系列第 6,7,8 章节支持在我的个人公众号「前端乱步」内付费观看,将在全平台文章「点赞数」+「评论数」 >= 500(第 6 章), 1000(第 7,8 章) 时分别解锁发布。 《和我一起学 Three.js【初级篇】:0. 总论》 ? 您当前在这里…

    JavaScript 2023年4月20日
    00
合作推广
合作推广
分享本页
返回顶部