【前端】JavaScript中的隐式声明及其不良影响分析


在这里插入图片描述

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳]
本文专栏: 前端

文章目录

  • 💯前言
  • 💯什么是隐式声明?
  • 💯隐式声明的常见情景
    • 1. 赋值给未声明的变量
    • 2. 非严格模式下的隐式声明
    • 3. 函数中的变量漏掉声明
    • 4. for 循环中的隐式声明
    • 5. 使用 `this` 关键字隐式声明
  • 💯隐式声明的危害
  • 💯如何避免隐式声明?
  • 💯JavaScript 中变量作用域的深入理解
    • 1. 全局作用域
    • 2. 函数作用域
    • 3. 块作用域
  • 💯严格模式与隐式声明的关系
  • 💯模块化与命名空间的优势
  • 💯小结


在这里插入图片描述


💯前言

  • JavaScript 是一种普及程度极高的编程语言,广泛用于前端和后端开发。然而,尽管 JavaScript 具备高度灵活性,这种灵活性也带来了许多潜在的不安全隐患,尤其是在 变量声明 方面。
    当开发者不小心进行了 隐式声明 时,变量会被自动地提升为全局变量,从而引发一系列的潜在问题。这些 隐式声明 往往是 JavaScript 中最常见的陷阱之一,不仅困扰新手开发者,也常常让资深程序员陷入困境。
    因此,本文将系统性地讨论 JavaScript隐式声明 的机制、隐式声明 可能带来的问题、常见场景及应对策略。通过深入分析这些内容,我们希望读者能够更好地理解 JavaScript 的行为模式,避免由隐式声明导致的问题。
    JavaScript在这里插入图片描述


💯什么是隐式声明?

在这里插入图片描述

JavaScript 中,隐式声明 指的是在没有使用 varletconst 等关键字的情况下对变量进行赋值的情况。这种赋值方式会使得 JavaScript 引擎 将变量默认为全局变量,从而对整个程序的 可预测性 造成影响。

隐式声明的行为往往是 不经意的,尤其在编写复杂逻辑或大型程序时,由于代码的可读性不强或变量命名不一致,容易因一个简单的错误而污染全局命名空间。

例如,考虑以下代码:

function example() {x = 10;  // 变量 x 被隐式声明为全局变量
}
example();
console.log(x);  // 输出 10(x 现在是全局变量)

在上述代码中,xexample 函数内被赋值,但由于没有用 varletconst 进行声明,JavaScript 自动将 x 视为全局变量。这种行为非常危险,因为局部变量在不知情的情况下变为了全局变量,从而导致命名冲突或其他难以调试的问题。


💯隐式声明的常见情景

在这里插入图片描述
隐式声明在 JavaScript 开发中并不少见,以下列举了一些典型的场景。


1. 赋值给未声明的变量

在这里插入图片描述

当对一个从未声明过的变量赋值时,JavaScript 会自动将其创建为全局变量:

function example() {y = 20;  // y 被隐式声明为全局变量
}
example();
console.log(y);  // 输出 20(y 变成全局变量)

在这个例子中,y 没有被任何关键字声明,而是直接被创建并赋值,因此它被隐式地提升为全局变量。这种做法会污染全局作用域,特别是在大型代码库中,隐式全局变量可能引发不可预见的冲突和错误。


2. 非严格模式下的隐式声明

在这里插入图片描述
JavaScript 中有两种模式:严格模式(strict mode)和非严格模式。在非严格模式下,未声明的变量赋值会被自动隐式创建为全局变量,但在严格模式下,这种操作会导致错误抛出。

"use strict";function example() {z = 30;  // 严格模式下会抛出 ReferenceError 错误
}
example();

严格模式通过限制开发者的某些行为,增强了代码的安全性。在严格模式中,JavaScript 不允许使用未声明的变量,因此在 "use strict"; 环境中尝试隐式声明变量将直接导致 ReferenceError 错误,这大大减少了隐式声明引发的潜在问题。


3. 函数中的变量漏掉声明

在这里插入图片描述

如果在函数内对变量直接赋值而没有声明,该变量也会被自动提升为全局变量。例如:

function fn() {w = 5;  // 忘记声明变量 w,则 w 变成全局变量
}
fn();
console.log(w);  // 输出 5(w 被提升为全局作用域)

在这个例子中,w 本应为局部变量,但由于没有使用 letvar 进行声明,它被提升为了全局变量。这种行为在多人合作和复杂项目中尤为危险,因为这会导致代码的意外交互,增加了 bug 出现的可能性。


4. for 循环中的隐式声明

在这里插入图片描述
for 循环中,通常需要显式地声明计数器变量(使用 letvarconst),但是如果漏掉这些关键字,计数器变量也会变为全局变量:

function loopTest() {for (i = 0; i < 5; i++) {console.log(i);}
}
loopTest();
console.log(i);  // 输出 5,i 成为全局变量

在这个例子中,由于 i 没有显式声明,它被隐式创建为全局变量。这种行为非常容易造成冲突,特别是如果程序中的其他部分也使用了同名变量 i


5. 使用 this 关键字隐式声明

在这里插入图片描述
在非严格模式下,函数内的 this 通常指向全局对象(在浏览器环境下为 window),从而可能隐式创建全局变量:

function createVar() {this.myVar = 100;  // 在非严格模式下,myVar 成为全局变量
}
createVar();
console.log(myVar);  // 输出 100

由于 this 指向全局对象,myVar 被隐式地创建为全局变量。在严格模式下,this 的值不再指向全局对象,因此能够避免这种隐式声明。


💯隐式声明的危害

在这里插入图片描述
隐式声明主要通过污染全局作用域对代码产生不良影响,这些影响可能体现在以下几个方面:

  1. 命名冲突:全局变量在大型代码库中极易与其他部分的变量发生命名冲突,导致变量的值被意外覆盖。
  2. 难以调试:变量共享作用域导致调试困难,尤其是当全局变量在不同模块中被修改时,追踪其生命周期和变更变得极为困难。
  3. 不可预测的行为:由于全局变量可在任何地方被修改,这增加了程序表现不一致的风险,导致不可预测的行为。
  4. 降低代码的可维护性:全局变量使代码之间的依赖变得更加隐晦,增加了代码的复杂性和维护难度。

💯如何避免隐式声明?

在这里插入图片描述

  1. 使用严格模式 ("use strict")

严格模式能够有效防止隐式声明,因为在严格模式下,对未声明的变量进行赋值会抛出 ReferenceError 错误。特别是在多人合作或者复杂项目中,启用严格模式是减少隐式声明 bug 的有效手段。

"use strict";function myFunction() {undeclaredVar = 50;  // 抛出 ReferenceError
}
myFunction();
  1. 显式声明变量

应始终使用 letconstvar 来显式声明变量,避免直接对未声明的变量赋值。尤其是在函数内部,显式声明局部变量至关重要。

function myFunction() {let a = 10;  // 正确的声明方式const b = 20;var c = 30;
}
myFunction();
  • let:适用于块作用域的声明,推荐使用以避免变量提升带来的问题。
  • const:用于声明常量,保证变量不会被重新赋值。
  • var:由于其函数作用域和变量提升的特点,已不再推荐使用。
  1. 静态分析工具

使用 ESLint 等静态分析工具来检测代码中的未声明变量。ESLint 可以通过配置规则,确保代码中不包含隐式的全局声明,并在开发阶段及时提醒开发者进行修复。

  1. 避免在全局作用域中定义变量

尽量避免在全局作用域中直接定义变量。可以通过使用 IIFE(立即执行函数表达式)或模块化代码,将变量限定在局部作用域中,从而减少对全局对象的污染。

(function() {let localVar = "This is a local variable";console.log(localVar);
})();
// localVar 无法在此作用域中访问
  1. 使用模块化编程

使用 ES6 模块化语法(如 importexport)将代码拆分为独立的模块,每个模块都有独立的作用域,这样可以有效减少全局变量的使用,避免命名冲突。

// module.js
export const myVariable = 42;// main.js
import { myVariable } from './module.js';
console.log(myVariable);

💯JavaScript 中变量作用域的深入理解

在这里插入图片描述
为了更好地理解隐式声明的危害,有必要深入理解 JavaScript 中的各种作用域类型。


1. 全局作用域

在这里插入图片描述
全局作用域中的变量可以在程序中的任何地方访问。在浏览器环境下,全局作用域的变量挂载在 window 对象上。因此,任何全局变量都可以通过 window 对象来访问。这种作用域的广泛性使得它们极易被意外覆盖,进而导致难以调试的问题。为了减少这种问题,尽量减少使用全局变量是良好的编程实践。


2. 函数作用域

在这里插入图片描述
var 声明的变量具有函数作用域,这意味着它只能在函数内部访问。如果在函数中使用 var 声明变量,那么函数外部无法访问这些变量。函数作用域的优点在于将变量限制在特定的函数上下文中,从而避免污染全局作用域。

function myFunction() {var functionScoped = "I'm function scoped";
}
console.log(functionScoped);  // 报错,functionScoped 未定义

函数作用域有一个潜在的问题是变量提升,即在函数中声明的变量会被提升到函数顶部,这使得变量在赋值前就可以被引用,从而导致一些令人困惑的行为。

function hoistingExample() {console.log(a);  // 输出 undefined,而不是报错var a = 5;
}
hoistingExample();

在这个例子中,a 的声明被提升到了函数顶部,但其赋值依然在后面,因此 console.log(a) 的输出为 undefined


3. 块作用域

在这里插入图片描述
letconst 引入了块作用域,意味着这些变量只能在其声明所在的代码块 {} 内访问。相比函数作用域,块作用域更加严格,可以帮助开发者避免变量提升和作用域污染。

{let blockScoped = "I'm block scoped";console.log(blockScoped);  // 正常输出
}
console.log(blockScoped);  // 报错,blockScoped 未定义

块作用域能够帮助我们在控制结构(如 iffor 等)中更好地管理变量的生命周期,从而编写出更加健壮且易读的代码。


💯严格模式与隐式声明的关系

在这里插入图片描述
严格模式(strict mode)是 JavaScript 在 ES5 中引入的一个特性,其目的是帮助开发者编写更加安全和高质量的代码。通过启用严格模式,许多 JavaScript 的潜在问题能够在开发时被暴露出来。在严格模式下,隐式声明是被禁止的,这意味着任何未声明的变量赋值都会导致 ReferenceError 错误。

严格模式不仅可以帮助开发者避免隐式声明的问题,还能防止其他潜在的错误,比如对只读属性的赋值、删除不可删除的属性、函数中的 thisundefined 等。严格模式通过限制语言的某些宽松特性,增强了 JavaScript 代码的安全性和可维护性。

"use strict";
function myFunction() {undeclaredVar = 100;  // ReferenceError: undeclaredVar is not defined
}
myFunction();

💯模块化与命名空间的优势

在这里插入图片描述

模块化 是应对 隐式声明全局变量污染 的有效手段。在现代 JavaScript 中,模块化代码帮助开发者将功能分割为独立的模块,从而有效减少对 全局命名空间 的污染,并提高代码的 可维护性可复用性

在没有模块系统的早期 JavaScript 开发中,开发者常使用 命名空间模式 来组织代码。命名空间是通过创建一个全局对象,将一组相关的变量和函数封装在这个对象内部,从而减少对 全局作用域 的污染。

var MYAPP = MYAPP || {};MYAPP.utilities = {printMessage: function(msg) {console.log(msg);},addNumbers: function(a, b) {return a + b;}
};MYAPP.utilities.printMessage("Hello, world!");

通过命名空间,函数和变量被封装到一个对象中,避免了直接暴露在全局作用域中的风险。尽管现代 JavaScript 已经引入了模块系统,但在某些场景下,命名空间仍然是减少全局污染的有效工具。


💯小结

在这里插入图片描述

  • 在这里插入图片描述
    JavaScript 的灵活性使其成为一种强大而有用的编程语言,但这种灵活性也带来了许多潜在的陷阱,其中 隐式声明 便是常见问题之一。
    理解 JavaScript 作用域 的特性,掌握 严格模式 的应用,充分利用现代 JavaScript 提供的模块化工具,开发者可以在享受语言灵活性的同时避免许多常见的问题,最终编写出更加 可靠和高效 的代码。

避免隐式声明的几点建议:

  1. 始终使用 letconstvar 来显式声明变量
  2. 启用严格模式("use strict",这可以有效减少隐式声明的风险。
  3. 利用 ESLint 等工具进行代码静态分析,确保在开发阶段就发现和解决隐式声明的问题。
  4. 尽量避免使用全局变量,如果必须使用,应通过模块化或命名空间的方式进行管理。
  5. 模块化编程,减少全局变量的依赖,使代码更加独立、易于维护。

在这里插入图片描述


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

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

相关文章

2024小迪安全基础入门第七课

目录 一、抓包技术-Web&App&小程序&PC-扶墙双层 二、 抓包技术-Web&App&小程序&PC-项目联动 三、抓包技术-Web&App&小程序&PC-全局协议 一、抓包技术-Web&App&小程序&PC-扶墙双层 Wireshark&#xff1a; https://www.wir…

在 PyTorch 训练中使用 `tqdm` 显示进度条

在 PyTorch 训练中使用 tqdm 显示进度条 在深度学习的训练过程中&#xff0c;实时查看训练进度是非常重要的&#xff0c;它可以帮助我们更好地理解训练的效率&#xff0c;并及时调整模型或优化参数。使用 tqdm 库来为训练过程添加进度条是一个非常有效的方式&#xff0c;本文将…

windows基础之病毒编写

声明&#xff01; 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&#…

家校通小程序实战教程02口令管理

目录 1 创建数据源2 搭建后台功能3 生成口令4 调用API总结 我们的小程序上线之后&#xff0c;必然面临家长要加入的问题。微搭有登录验证的功能&#xff0c;但是手机验证的机制是&#xff0c;如果你未注册就给你自动注册一个账号&#xff0c;如果以注册了收到验证码就可以登录系…

Git 使用技巧

1. 查看提交历史 git log 显示所有提交的详细信息 git log --oneline 查看每个版本的简要信息 git log --graph --decorate --all 显示完整提交图&#xff08;带详情&#xff09; ​​​​​​​git log --oneline --graph --all​​​​​​​ 显示分支合并图 git sh…

部署自动清理任务解决ORA-00257: archiver error. Connect internal only, until freed

使用oracle数据库的时候&#xff0c;我们一般都会开启归档&#xff0c;确保数据库的日志连续和和数据安全。但随着数据库的运行&#xff0c;归档文件会越来越多&#xff0c;最终撑满磁盘空间&#xff0c;数据库无法继续归档&#xff0c;出现“ORA-00257: archiver error. Conne…

Elasticsearch中的节点(比如共20个),其中的10个选了一个master,另外10个选了另一个master,怎么办?

大家好&#xff0c;我是锋哥。今天分享关于【Elasticsearch中的节点&#xff08;比如共20个&#xff09;&#xff0c;其中的10个选了一个master&#xff0c;另外10个选了另一个master&#xff0c;怎么办&#xff1f;】面试题。希望对大家有帮助&#xff1b; Elasticsearch中的节…

阿里发布 EchoMimicV2 :从数字脸扩展到数字人 可以通过图片+音频生成半身动画视频

EchoMimicV2 是由阿里蚂蚁集团推出的开源数字人项目&#xff0c;旨在生成高质量的数字人半身动画视频。以下是该项目的简介&#xff1a; 主要功能&#xff1a; 音频驱动的动画生成&#xff1a;EchoMimicV2 能够使用音频剪辑驱动人物的面部表情和身体动作&#xff0c;实现音频与…

Vue 的 computed 如何实现接受一个参数

在 Vue 中&#xff0c;computed 属性是基于响应式数据的 getter 方法&#xff0c;它通常用于依赖 Vue 实例的数据来计算一个值。然而&#xff0c;computed 默认是不能接受参数的&#xff0c;因为它是绑定到 Vue 实例的响应式数据的。 不过&#xff0c;如果你需要在 computed 中…

【NLP高频面题 - 分布式训练】ZeRO1、ZeRO2、ZeRO3分别做了哪些优化?

【NLP高频面题 - 分布式训练】ZeRO1、ZeRO2、ZeRO3分别做了哪些优化&#xff1f; 重要性&#xff1a;★★ NLP Github 项目&#xff1a; NLP 项目实践&#xff1a;fasterai/nlp-project-practice 介绍&#xff1a;该仓库围绕着 NLP 任务模型的设计、训练、优化、部署和应用&am…

C#基础控制台程序

11.有一个54的矩阵&#xff0c;要求编程序求出其中值最大的那个元素的值&#xff0c;以及其所在的行号和列号。 12.从键盘输入一行字符&#xff0c;统计其中有多少个单词&#xff0c;单词之间用空格分隔开。 13.输入一个数&#xff0c;判断它是奇数还是偶数&#xff0c;如果…

三六零[601360]行情数据接口

1、三六零&#xff1a;实时行情 Restful API # 测试接口&#xff1a;可以复制到浏览器打开 https://tsanghi.com/api/fin/stock/XSHG/realtime?tokendemo&ticker601360获取股票实时行情&#xff08;开、高、低、收、量&#xff09;。 请求方式&#xff1a;GET。 Python示例…

SSM--SpringMVC复习(二)

请求 URL匹配&#xff1a; RequestMapping RequestMapping 负责将请求映射到对应的控制器方法上。 RequestMapping 注解可用于类或方法上。用于类上&#xff0c;表示类中的所有响应请求的方法都以该地址作为父路径。 在整个 Web 项目中&#xff0c;RequestMapping 映射的请求…

Pydantic 数据验证

Pydantic 验证 from datetime import datetime from typing import List, Optional from pydantic import BaseModel, EmailStr, field_validator, ValidationErrordef check_name(v: str) -> str:"""Validator to be used throughout"""if …

LangChain——管道提示词 缓存

管道提示词 管道提示词可以将多个提示组合在一起。当我们想要使用部分提示时&#xff0c;这会很有用。这里可以通过PipelinePrompt来完成。 PipelinePrompt由两部分组成&#xff1a; 最终提示&#xff1a;返回的最终提示&#xff1b;管道提示&#xff1a;元组列表&#xff0c…

eclipse-git项目提示NO-HEAD

1、出现该问题的过程 本人在用eclipse拉取git代码&#xff0c;刚拉取完&#xff0c;可能还没来得及跟本地的分支合并&#xff0c;电脑就卡动了。无奈只能重启电脑&#xff0c;打开eclipse&#xff0c;maven项目后面就出现了xxx NO-HEAD的提示。 2、问题解决 根据错误提示&am…

使用OpenSSL创建CA,并基于CA创建证书

生成CA证书 生成CA证书的私钥 openssl genrsa -out ca.key 4096生成CA证书 openssl req -x509 -new -nodes -sha512 -days 3650 \-subj "/CCN/STBeijing/LBeijing/Oexample/OUPersonal/CNMyPersonal Root CA" \-key ca.key \-out ca.crt生成Server证书 证书通常包…

WPF异步UI交互功能的实现方法

前面的文章我们提及过&#xff0c;异步UI的基础实现。基本思路主要是开启新的UI线程&#xff0c;并通过VisualTarget将UI线程上的Visual(即RootVisual)连接到主线程上的UI上即可渲染显示。 但是&#xff0c;之前的实现访问是没有交互能力的&#xff0c;视觉树上的UI并不能实现…

Cross-Site Scripting(XSS)攻击

简介 XSS&#xff08;跨站脚本攻击&#xff09;是一种常见的 Web 安全漏洞&#xff0c;攻击者通过在目标网站的输入框中注入恶意脚本&#xff0c;当其他用户&#xff08;如管理员&#xff09;查看包含恶意脚本的页面时&#xff0c;脚本会在他们的浏览器中执行。XSS 攻击可以分…

linux mount nfs开机自动挂载远程目录

要在Linux系统中实现开机自动挂载NFS共享目录&#xff0c;你需要编辑/etc/fstab文件。以下是具体步骤和示例&#xff1a; 确保你的系统已经安装了NFS客户端。如果没有安装&#xff0c;可以使用以下命令安装&#xff1a; sudo apt-install nfs-common 编辑/etc/fstab文件&#…