JavaScript的作用域介绍

JavaScript的作用域介绍

作用域(scope)是编程语言中的一个基本概念,它定义了程序中变量、函数、对象等标识符(identifier)的可见性和生命周期。简单说,就是决定了在程序的哪些部分可以访问或使用这些标识符。

JavaScript的作用域规定了变量和函数的可访问性和可见性。作用域定义了变量和函数的有效范围和生命周期。

JavaScript中有以下几种作用域:

全局作用域(Global Scope):

全局作用域是定义在代码的最外层,不在任何函数内部的作用域。在全局作用域中定义的变量和函数可以在代码的任何地方访问。

var globalVar = 'I am global';function globalFunction() {console.log(globalVar); // 输出 "I am global"
}console.log(globalVar); // 输出 "I am global"
globalFunction();

在全局作用域中使用var声明变量时,在整个脚本范围内都可以访问,且这些变量会成为全局对象(在浏览器中是window对象)的属性。这意味着可以通过全局对象来访问这些变量,例如window.x。
在全局作用域中使用let声明变量时,在整个脚本范围内都可以访问,但这些变量不会成为全局对象(在浏览器中是window对象)的属性。这意味着不能通过全局对象来访问这些变量,例如window.y。
例如
var x = 10;
let y = 20;
console.log(window.x); // 10
console.log(window.y); // undefined

在现代JavaScript开发中,推荐使用let(或const,如果变量不需要重新赋值)来替代var。let提供了更好的作用域控制,减少了因变量提升或作用域混淆造成的错误,提高代码的可维护性和可读性。

 

函数作用域(Function Scope):

函数作用域是指在函数内部定义的变量和函数只在函数内部可见。函数作用域可以避免变量命名冲突,并且提供了封装和信息隐藏的特性。

function myFunction() {var x = 10;console.log(x); // 输出 10
}myFunction();
console.log(x); // 报错:x is not defined

块级作用域(Block Scope):

块级作用域是指在一对花括号{}内部定义的变量和函数,只在该块级作用域内可见。在ES6之前,JavaScript中没有块级作用域,只有函数作用域和全局作用域。

function blockScopeExample() {if (true) {var x = 10; // 在块级作用域之外仍可访问let y = 20; // 只在块级作用域内可访问const z = 30; // 只在块级作用域内可访问}console.log(x); // 输出 10console.log(y); // 报错:y is not definedconsole.log(z); // 报错:z is not defined
}blockScopeExample();

在上述示例中,变量x在块级作用域之外仍可访问,而使用let和const声明的变量y和z则只在块级作用域内可访问。

词法作用域(Lexical Scope)

词法作用域(Lexical Scope)和闭包相关。

闭包(Closure)是指一个函数能够访问和操作其词法作用域之外的变量的能力。简而言之,闭包是由函数以及其相关的引用环境组合而成的包裹(或封闭)体。

在JavaScript中,当一个函数被定义时,它会创建一个词法作用域,并捕获(或保存)它所在的作用域链。作用域链是一个包含所有父级作用域的链式结构,它决定了函数在执行时可以访问的变量。当函数形成闭包时,它会保留对其词法作用域中变量的引用,即使该词法作用域的上下文已经销毁。

闭包的特性使得函数可以在其定义的作用域之外被调用,但仍然可以访问其词法作用域中的变量。这使得闭包非常有用,可以用于创建私有变量和实现模块化的代码结构。

JavaScript采用词法作用域,也称为静态作用域。词法作用域意味着变量的作用域是在函数定义时确定的,而不是在函数调用时确定的。

function outer() {var x = 10;function inner() {console.log(x); // 闭包:可以访问外部函数outer的变量x}return inner;
}var closureFunc = outer(); // 返回inner函数形成的闭包
closureFunc(); // 输出 10

在上述示例中,函数inner形成了一个闭包,可以访问外部函数outer中的变量x。即使outer函数执行完毕,变量x的相关信息仍然保留在闭包中,使得closureFunc可以继续访问并输出x的值。

Javascript中,在“严格模式”中不会自动创建全局变量

"自动创建全局变量"是指在非严格模式下,当在全局作用域或函数内部使用一个未声明的变量时,JavaScript会自动将该变量创建为一个全局变量。这意味着该变量可以在程序的任何地方被访问和修改,而不仅仅在当前作用域内。

在 JavaScript 的严格模式(strict mode)下,如果在全局作用域或函数内部使用未声明的变量,会抛出一个错误,而不是自动创建一个全局变量。可以在脚本或函数的顶部添加 "use strict"; 来启用严格模式。

在非严格模式下,如果你在全局作用域或函数内部使用一个未声明的变量,JavaScript 会自动创建一个全局变量。例如:

function foo() {x = 10; // 在非严格模式下,会自动创建一个全局变量 x
}
foo();
console.log(x); // 输出 10
但是,在严格模式下,这种行为是不允许的。你必须显式地声明变量,否则会抛出一个错误。例如:
"use strict";function foo() {x = 10; // 在严格模式下,会抛出一个 ReferenceError,因为 x 没有被声明
}foo(); // 抛出 ReferenceError: x is not defined

使用严格模式可以帮助你避免一些常见的编程错误,例如使用未声明的变量,并促使你编写更加规范和可维护的代码。建议在 JavaScript 文件的开头或函数的开头启用严格模式,以确保整个脚本或函数都运行在严格模式下。

Javascript的作用域链

JavaScript的作用域链(scope chain)是指在程序执行过程中,变量和函数的查找顺序。当在一个作用域中引用一个变量或函数时,JavaScript会按照作用域链的顺序从内层作用域向外层作用域逐级查找,直到找到该变量或函数为止。

作用域链的构建是基于函数的嵌套关系。每当定义一个函数时,JavaScript会创建一个包含该函数的作用域,并将其嵌套在当前作用域中。这样形成了一个作用域的层级结构,每个作用域都有一个指向外层作用域的引用。

当在一个作用域中引用一个变量时,JavaScript首先在当前作用域中查找该变量,如果找到了,则使用该变量;如果未找到,则会沿着作用域链向上查找,直到全局作用域。如果在全局作用域中仍未找到该变量,则会抛出一个错误。

以下是一个简单的示例来说明作用域链的概念:

let x = 10;function outer() {let y = 20;function inner() {let z = 30;console.log(x + y + z); // 在此处的作用域链为 inner -> outer -> global}inner();
}outer();

在上面的示例中,当在inner函数中引用变量x、y和z时,JavaScript会按照作用域链的顺序查找这些变量。首先在inner的作用域中查找变量z,然后在外层作用域outer中查找变量y,最后在全局作用域中查找变量x。因此,最终输出的结果为60。

附录

作用域https://developer.mozilla.org/zh-CN/docs/Glossary/Scope

闭包https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures

实用的闭包https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures

理解Javascript的作用域和作用域链https://juejin.cn/post/6844904069413224462

一文彻底搞懂JS作用域https://segmentfault.com/a/1190000044251549

深入理解JavaScript作用域和作用域链https://segmentfault.com/a/1190000018513150

说说你对作用域链的理解https://vue3js.cn/interview/JavaScript/scope.html#%E4%B8%80%E3%80%81%E4%BD%9C%E7%94%A8%E5%9F%9F

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/31854.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ioquake笔记

ioquake代码分析一 目录结构主流程框架main函数流程Com_Init 初始化过程OpenGL初始化流程InitOpenGL 其他信息NET_InitNET_Config 流程 wiki :http://wiki.ioquake3.org 目录结构 misc:各个工程和配置文件 msvc/msvc10nsisosxfe/setupico图标和照片文件…

print(“{}{}“.format())

print("{}{}".format()) 是 Python 中用于格式化字符串并将其输出到控制台的一种方法。format 方法允许你在字符串中插入变量或表达式的值,并以指定的格式显示它们。 基本语法 print("format_string".format(value1, value2, ...))format_str…

JAVA学习笔记DAY7——Spring_Ioc

文章目录 Bean配置注解方式配置注解配置文件调用组件 注解方法作用域 DI注入注解引用类型自动装配文件结构自动装配实现 基本数据类型DI装配 Bean配置 注解方式配置 类上添加Ioc注解配置文件中告诉SpringIoc容器要检查哪些包 注解仅是一个标记 注解 不同注解仅是为了方便开…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 反射计数(200分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 📎在线评测链接 https://app5938.acapp.acwing.com.cn/contest/2/problem/OD…

单例模式---线程安全实现

文章目录 1.单例模式的特点😊2.单例模式两种实现🤣🤗😊2.1 饿汉式2.2 懒汉式 3.传统单例模式的线程安全问题4.解决方法4.1静态局部变量4.2加锁4.3双重检查锁(DCL)4.4pthread_once 1.单例模式的特点&#x1…

刷代码随想录有感(111):动态规划——零钱兑换II

干,被上了一课。注意题干,到底是求能装最大价值的方案还是装满这个容量共有多少种方法。他们的公式都不同,最大价值的方案是: dp[j] max(dp[j], dp[j - weight[i]] value[i]); 而装满有多少种方法是: dp[j] dp[j…

FISSURE:一款功能强大的RF和逆向工程框架

关于FISSURE FISSURE是一款功能强大的RF和逆向工程框架,该工具适用于不同技能水平的安全研究人员,并提供了信号检测、信号分类、协议发现、渗透测试、IQ操作、漏洞分析、自动化和AI/机器学习等功能。该框架旨在促进软件模块、无线电、协议、信号数据、脚…

Spring相关注解详细版

1、RestController RequestMapping("/api")这两个的作用分别是什么?如何相互区分? RestController 注解用于标识一个类是RESTful风格的Controller,它会将方法的返回值直接转换为HTTP响应体,通常用于返回JSON或XML格式的…

[力扣二叉树]本地调试环境指导手册

以236. 二叉树的最近公共祖先为例子 本地编译软件为Viusal Studio 2022 写代码 项目里文件位置 CreateTree.h #pragma once #ifndef CLIONPROJECT_LEETCODECREATETREE_H #define CLIONPROJECT_LEETCODECREATETREE_H #include<vector> #include<queue> using na…

qt 简单实验 画一个等边三角形

1.概要 2.代码 2.1 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPainter>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr)…

Linux (centos7.9)上部署 NFS(Network File System)服务

NFS&#xff08;Network File System&#xff09;是一种网络文件系统协议&#xff0c;允许不同计算机之间通过网络共享文件和目录。NFS 最初由 Sun Microsystems 在 1984 年开发&#xff0c;现已成为许多 Unix 和类 Unix 系统&#xff08;包括 Linux&#xff09;上的标准文件系…

Chromium 调试指南2024 Mac篇 - 编译 Chromium(二)

1.引言 在完成了环境准备和源码获取之后&#xff0c;下一步就是编译Chromium源码。编译是将源码转换为可执行程序的关键步骤&#xff0c;对于验证代码更改和调试至关重要。由于Chromium项目的庞大规模和复杂性&#xff0c;编译过程可能会遇到各种问题和挑战&#xff0c;因此了…

RSA —非对称加密算法

常见的数字加密方式分为两类&#xff1a;对称加密 和 非对称加密。 对称加密&#xff0c;又称为私钥加密&#xff0c;指的是加密和解密使用同一个密钥的方式。其特点是加密和解密过程简单、快速&#xff0c;并且只需要一个密钥。常见的对称加密算法包括DES、AES等。然而&#x…

LabVIEW常用的加密硬件

LabVIEW在工程和科学领域中广泛应用&#xff0c;其中数据保护和程序安全尤为重要。为了确保数据的安全性和完整性&#xff0c;常用的加密硬件设备包括TPM&#xff08;可信平台模块&#xff09;、HSM&#xff08;硬件安全模块&#xff09;和专用加密芯片。本文将推荐几款常用的加…

【嵌入式开发】UART

目录 一、概述 1.1 常见的通信类别/特点 1.2 常见几种通信 二、UART通信协议 2.1 UART通信介绍 2.2 UART通信协议 物理连接示意图&#xff1a; 三、STM32的UART接口 3.1 STM32的UART特点 3.2 STM32的UART框图分析 3.3 UART初始化步骤 3.4 STM32中UART使用 一、概述…

物联网技术-第4章物联网通信技术-4.1无线网络

目录 1. 无线通信概念 &#xff08;1&#xff09;有线与无线 &#xff08;2&#xff09;电磁波的频谱 &#xff08;3&#xff09;频段的划分 &#xff08;4&#xff09;调制与解调 &#xff08;5&#xff09;调制技术 &#xff08;6&#xff09;信道的复用 &#xff08;…

【ARMv8/v9 GIC 系列 4.3 -- GIC 中断控制系统寄存器 ICC_SRE_ELn 使用介绍】

文章目录 GIC 中断控制系统寄存器 ICC_SRE_ELn寄存器位域介绍Interrupt BypassBypass IRQBypass FIQBypass 配置GIC 中断控制系统寄存器 ICC_SRE_ELn ICC_SRE_EL3是中断控制器系统寄存器(Interrupt Controller System Register),用于控制在异常级别3(EL3)下,对GIC CPU接口…

恒昌公益第五所“云杉校园”于湖南怀化正式揭牌

在中国近代史上湖南无疑是不可忽视的存在&#xff0c;在“敢为天下先”的湖湘文化熏陶下更是涌现了无数改变国家命运的人物。而作为推动民族复兴与社会进步的关键支柱&#xff0c;重视教育的传统起到的作用功不可没。在迈向中国式现代化的当下&#xff0c;积极推动优质教育资源…

无版权图片素材搜索网站,解决无版权图片查找问题

在数字内容创作领域&#xff0c;图片素材的选择至关重要。一张高质量、合适的图片不仅能够吸引读者的眼球&#xff0c;还能有效传达信息。然而&#xff0c;找到既免费又无版权限制的图片素材并非易事。小编将为大家介绍几个解决这一问题的无版权图片素材搜索网站&#xff0c;这…

简易版的进程池

1.使用匿名管道实现 进程池 #pragma oncetypedef void(*task_t)();void task1() {cout << "游戏 刷新日志" << endl; }void task2() {cout << "游戏 刷新野区" << endl; } void task3() {cout << "游戏 检测软件是否更…