当前位置: 首页 > news >正文

基础:JavaScript的怪癖之一:提升(Hoisting)

JavaScript,通常被称为“Web 语言”,是一种多功能且广泛使用的编程语言。它以其怪癖而闻名,其中之一就是 hoisting(提升)。无论你是经验丰富的开发人员还是刚刚开始你的编码之旅,理解提升对于编写干净和高效的 JavaScript 代码至关重要。

在本文中,我们将带您了解 JavaScript 中的提升概念,揭示变量和函数是如何被提升的。到最后,你不仅能掌握提升背后隐藏的机制,还能学会如何利用它为你带来优势。话不多说,让我们一起进入 JavaScript 提升的迷人世界!

什么是提升?

在我们深入研究细节之前,让我们揭开 JavaScript 中提升的神秘面纱。提升是一个后台进程,它在编译阶段将变量和函数声明移动到它们所包含作用域的顶部。这允许你在正式声明它们之前就使用它们。

想象一下,它就像一个魔术师从帽子里拿出一只兔子,兔子就是你的变量或函数,帽子就是 JavaScript 引擎,提升确保魔术师(JavaScript)总是能找到它需要的兔子(变量或函数),无论它被放在代码的什么位置。

变量提升

var 的魔力

在 JavaScript 中,用 var 声明的变量会表现出一种奇怪的提升行为,当你用 var 声明一个变量时,它会被提升到它所属的函数或全局作用域的顶部。考虑以下例子:

function hoistExample() {console.log(myVar); // Outputs: undefinedvar myVar = 42;console.log(myVar); // Outputs: 42
}
hoistExample();

hoistExample 函数中,我们尝试在声明 myVar 之前记录它的值。令人惊讶的是,第一个 console.log 语句没有抛出错误。相反,它输出了 undefined 。这是由于提升 —— myVar 的声明被移动到函数的顶部,使其在整个作用域中可访问。

let 和 const 的混合

var 的行为似乎有悖直觉,而且它经常导致意外的 bug,为了解决这个问题,JavaScript 引入了 letconst ,它们具有不同的提升机制。

function hoistExample() {console.log(myVar); // Throws a ReferenceErrorlet myVar = 42;console.log(myVar);
}
hoistExample();

使用 letconst 时,仍然会发生提升,但是变量在代码中实际声明之前不会初始化。这意味着在声明 myVar 之前尝试访问它会导致 ReferenceError 。这种行为促进了代码的更清晰和更可预测性。

函数声明 vs. 表达式

函数声明提升

就像变量一样,JavaScript 中的函数也会被提升,让我们来探讨一下在提升时函数声明和函数表达式之间的区别。

hoistMe(); // Outputs: "I'm hoisted!"
function hoistMe() {console.log("I'm hoisted!");
}

在这个例子中,我们在声明 hoistMe 函数之前调用它。由于提升,没有错误,函数按预期执行。函数声明被整体提升,使它们在作用域内的任何地方可用。

函数表达式

另一方面,函数表达式有不同的提升行为。

hoistMe(); // Throws a TypeError
var hoistMe = function () {console.log("I'm not hoisted!");
};

在这种情况下,当我们试图在 hoistMe 的声明之前调用它时,我们遇到了一个 TypeError 。函数表达式不会以与函数声明相同的方式被提升。变量 hoistMe 被提升了,但它对函数的赋值没有,这就是为什么在赋值之前调用它会导致错误。

作用域和提升

要完全理解提升,必须掌握 JavaScript 中的作用域的概念,作用域决定了变量和函数在代码中的访问位置。

全局作用域

在任何函数或代码块之外声明的变量具有全局作用域,可以在 JavaScript 代码的任何位置访问它们。

var globalVar = "I'm global!";
function accessGlobalVar() {console.log(globalVar); // Outputs: "I'm global!"
}
accessGlobalVar();

在上面的例子中, globalVaraccessGlobalVar 函数中可用,因为它具有全局作用域。

局部作用域

在函数或代码块中声明的变量具有局部作用域,只能在声明它们的作用域中访问它们。

function localScopeExample() {var localVar = "I'm local!";console.log(localVar); // Outputs: "I'm local!"
}
localScopeExample();
console.log(localVar); // Throws a ReferenceError

localScopeExample 函数中, localVar 具有局部作用域,因此在函数之外无法访问它。尝试全局访问它会导致 ReferenceError

常见的提升陷进

理解提升对于编写干净、无 bug 的代码至关重要。以下是处理提升时需要注意的一些常见陷阱:

重定义变量

当你在同一个作用域中使用 var 多次声明同一个变量时,它不会抛出错误,只是简单地重新赋给变量一个新值。

var myVar = "First declaration";
var myVar = "Second declaration";
console.log(myVar); // Outputs: "Second declaration"

这种行为会导致意想不到的后果,因为重定义变量会使代码更难理解和维护。使用 letconst 来防止意外的变量重声明。

函数重写

在 JavaScript 中,如果你多次声明同一个函数,最后一次声明将覆盖之前的任何一次声明,这可能会导致意想不到的行为和错误。

function myFunction() {console.log("First definition");
}
function myFunction() {console.log("Second definition");
}
myFunction(); // Outputs: "Second definition"

为了避免函数重写,请始终使用唯一的函数名,并保持清晰和有组织的代码结构。

代码整洁的最佳实践

既然我们已经探讨了提升的细微差别和潜在的陷阱,那么让我们深入研究一些最佳实践,以编写干净和可维护的 JavaScript 代码。

正确声明变量
为了防止与提升相关的问题,在变量的作用域顶部声明变量,如果你使用 var ,考虑切换到 letconst 来利用块作用域,这更可预测,更安全。

function cleanCodeExample() {var localVar = "I'm declared at the top";//此处显示您的其余代码
}

通过在开头声明变量,可以使代码更具可读性,并减少遇到意外情况的可能性。

组织函数
当使用函数时,请确保定义一致。在代码库中使用函数声明或函数表达式来维护统一的结构。

// 良好做法
function calculateSum(a, b) {return a + b;
}// 避免混淆函数声明和表达式
var multiply = function (a, b) {return a * b;
};

代码风格的一致性不仅可以提高代码的清晰度,还可以最大限度地减少与提升相关的问题。

总结:提升的力量

JavaScript 提升是一种隐藏的魔法,它通过将变量和函数声明移动到其作用域的顶部来优化代码,从而增强语言的行为。了解各种变量声明和函数声明的提升,可以让代码更简洁,让专家更熟练。接受并掌握这种方法可以提高代码编写的效率和优雅程度,使其成为开发人员的重要工具。总之,在编码过程中,JavaScript 的怪异之处(包括提升)应作为资产加以利用,以提高工作效率和编码技能。


原文:https://vishwasacharya.hashnode.dev/hoisting-in-javascript

相关文章:

基础:JavaScript的怪癖之一:提升(Hoisting)

JavaScript,通常被称为“Web 语言”,是一种多功能且广泛使用的编程语言。它以其怪癖而闻名,其中之一就是 hoisting(提升)。无论你是经验丰富的开发人员还是刚刚开始你的编码之旅,理解提升对于编写干净和高效…...

前端特殊字符转码

前端特殊字符转码 建议 最好不要传名称,传ID 是在不行就用这个方法 name encodeURIComponent(name),...

Python开发运维:Python3.7安装Django3.2

目录 一、理论 1.pip 2.Django 3.Pycharm国内镜像源 二、实验 1.Python3.7安装Django3.2 三、问题 1.安装django3.2报错 2.pip更新报错 一、理论 1.pip (1)概念 1)pip pip 是 Python 的包安装程序。其实,pip 就是 Pyt…...

B站双11,联手天猫暴涨2亿消费新势力

一直以来,手持高活跃、高粘性用户群体的B站是行业用来观察年轻人消费习惯的重要平台。以至于用户群体的不断壮大带动了B站的商业价值。如今B站的商业舞台越来越大,不断地向外界招手,欢迎更多品牌积极加入到这个千万年轻人聚集的内容社区。 2…...

如何选择SVM中最佳的【核函数】

参数“kernel"在sklearn中可选以下几种 选项: 接下来我们 就通过一个例子,来探索一下不同数据集上核函数的表现。我们现在有一系列线性或非线性可分的数据,我们希望通过绘制SVC在不同核函数下的决策边界并计算SVC在不同核函数下分类准确…...

RT-Thread的构建与配置系统

Kconfig:kernel config配置文件(提供系统的配置裁剪功能)Scons:构建工具env工具:主要提供构建系统所需的各种环境变量以及软件包的管理 Env Env是RT-Thread推出的开发辅助工具,针对基于RT-Thread操作系统…...

合肥中科深谷嵌入式项目实战——基于ARM语音识别的智能家居系统(一)

基于ARM语音识别的智能家居系统 我们接下来带大家完成基于语音识别的智能家居系统嵌入式项目实战,使用到stm32开发板,讯飞的离线语音识别,我们在此之前,我们先学习一些Linux系统的基本操作。 。 一、Linux简介 在嵌入式开发中&am…...

Git的简介以及基本使用

目录 一.Git的简介 拓展:Git与SVN的区别(各自的优点与缺点) 二.Git文件的4种状态 三.Git的常用命令 搭建完成之后,将项目文件也上传之后,现在模拟其他人来下载这个代码 今天就分享到这啦!!…...

django安装数据库

使用pip安装django pip3 install django注意我使用的是python3所以用pip3安装,如需安装指定版本 django ..* 检测是否安装成功,不报错,则安装成功 # python3 # import django下边这是报错的 django迁移数据库 再mysql中简历数据库 CREATE DATABA…...

springboot--外部环境配置

外部环境配置 前言1、配置优先级配置文件优先级如下(后面的覆盖前面的)测试 2、外部配置3、导入配置4、属性占位符 前言 场景:线上应用如何快速修改配置,并引用最新配置? springBoot 使用配置优先级外部配置 简化配置…...

『MySQL快速上手』-④-表的操作

文章目录 1.创建表2.查看表结构3.修改表4.删除表 1.创建表 语法格式如下: CREATE TABLE table_name ( field1 datatype, field2 datatype, field3 datatype ) character set 字符集 collate 校验规则 engine 存储引擎;说明: field 表示列名&#xff1…...

2023年10月Web3行业月度发展报告区块链篇 |陀螺研究院

10月是加密动荡的一月,围绕比特币现货ETF市场激荡不断,先有Cointelegraph“假消息”搅动市场以致合约遭血洗1.89亿美元,后有灰度、DCTT接二连三释放利好,市场情绪迅速激化,流动性显著提升,USDT 总市值突破8…...

【TES745D】青翼自研基于复旦微的FMQL45T900全国产化ARM核心模块(100%国产化)

板卡概述 TES745D是一款基于上海复旦微电子FMQL45T900的全国产化ARM核心板。该核心板将复旦微的FMQL45T900(与XILINX的XC7Z045-2FFG900I兼容)的最小系统集成在了一个87*117mm的核心板上,可以作为一个核心模块,进行功能性扩展&…...

初次给外贸客户发邮件范文

以下是一米软件给大家整理的一份初次给外贸客户发邮件的示例范文。请根据您的具体情况和需求进行个性化调整。 cssCopy code 主题:初次问候与合作机会 尊敬的[客户的名字], 我希望这封邮件能找到您并使您一切安好。我是[您的名字],代表[您的公司名]。我…...

C语言中的多种形式的循环结构

C语言提供了多种循环结构&#xff0c;包括for循环、while循环、do-while循环和foreach循环等。 //for循环 for (int i 0; i < 10; i) { printf("%d\n", i); } //while循环 int i 0; while (i < 10) { printf("%d\n", i); i; } //do-wh…...

7天入门python系列之第二天python 基础语法

第2天主要是学习Python的基础知识 编者打算开一个python 初学主题的系列文章&#xff0c;用于指导想要学习python的同学。关于文章有任何疑问都可以私信作者。对于初学者想在7天内入门Python&#xff0c;这是一个紧凑的学习计划。但并不是不可完成的。第二天开始python 基础知…...

【星海出品】flask 与docker

import os from flask import Flask, request from flask import Response, make_response, jsonify import cv2 import base64 import io import uuid from main import eye ​ app Flask(__name__)​ app.route(/, methods[GET, POST]) # 添加路由blend def upload_file():…...

Oracle的to_date()函数解决sql语句日期格式问题

项目场景&#xff1a; 提示&#xff1a;oracle中sql语句日期格式&#xff1a; 如&#xff1a;to_date(‘2023-01-01 13:14:20’,‘yyyy-MM-dd HH:mm:ss’) //错误写法 问题描述 改变一&#xff1a;24小时制 to_date(‘2005-01-01 13:14:20’,‘yyyy-MM-dd HH24:mm:ss’) //错…...

Vue实现面经基础版案例(路由+组件缓存)

一、面经基础版-案例效果分析 1.面经效果演示 2.功能分析 通过演示效果发现&#xff0c;主要的功能页面有两个&#xff0c;一个是列表页&#xff0c;一个是详情页&#xff0c;并且在列表页点击时可以跳转到详情页底部导航可以来回切换&#xff0c;并且切换时&#xff0c;只有…...

uniapp打开外部链接方式

uniapp打开外部链接方式 1、H5&#xff0c;打开方式 window.location.href url 2、APP&#xff0c;打开方式 plus.runtime.openURL(url)...

WSL 开发环境搭建指南:Java 11 + 中间件全家桶安装实战

在WSL&#xff08;Windows Subsystem for Linux&#xff09;环境下一站式安装开发常用工具&#xff0c;能极大提升工作效率。接下来我将分步为你介绍如何在WSL中安装Java 11、Maven、Redis、MySQL、Nacos、RabbitMQ、RocketMQ、Elasticsearch&#xff08;ES&#xff09;和Node.…...

linux系统与shell 笔记

Linux 系统 Linux 是一种开源的操作系统内核&#xff0c;基于 Unix 设计&#xff0c;具有多用户、多任务、高稳定性和安全性的特点。它广泛应用于服务器、嵌入式设备和个人计算机领域。Linux 系统的核心组件包括内核、系统库、工具链和用户界面&#xff08;如命令行或图形界面…...

【解决办法】Git报错error: src refspec main does not match any.

在命令行中使用 Git 进行 git push -u origin main 操作时遇到报错error: src refspec main does not match any。另一个错误信息是&#xff1a;error: failed to push some refs to https://github.com/xxx/xxx.git.这是在一个新设备操作时遇到的问题&#xff0c;之前没有注意…...

PostgreSQL日常运维

目录 一、PostgreSQL基础操作 1.1 登录数据库 1.2 数据库管理 1.3 数据表操作 二、数据备份与恢复 2.1 备份工具pg_dump 2.2 恢复工具pg_restore与psql 2.3 备份策略建议 三、模式&#xff08;Schema&#xff09; 3.1 模式的核心作用 3.2 模式操作全流程 四、远程连…...

Rust 学习笔记:关于闭包的练习题

Rust 学习笔记&#xff1a;关于闭包的练习题 Rust 学习笔记&#xff1a;关于闭包的练习题问题 1问题 2以下程序能否通过编译&#xff1f;若能&#xff0c;输出是&#xff1f;以下程序能否通过编译&#xff1f;若能&#xff0c;输出是&#xff1f;考虑该 API&#xff0c;空白处填…...

Golang|etcd服务注册与发现 策略模式

etcd 是一个开源的 分布式键值存储系统&#xff08;Key-Value Store&#xff09;&#xff0c;主要用于配置共享和服务发现。 ETCD是一个键值&#xff08;KV&#xff09;数据库&#xff0c;类似于Redis&#xff0c;支持分布式集群。ETCD也可以看作是一个分布式文件系统&#xff…...

集星云推短视频矩阵系统的定制化与私有化部署方案

在当今数字化营销时代&#xff0c;短视频矩阵系统成为众多企业和机构拓展影响力、实现精准营销的关键工具。集星云推短视频矩阵系统凭借其强大的功能和灵活的定制性&#xff0c;为企业提供了全方位的解决方案。 一、API接口定制&#xff1a;无缝对接自有系统 集星云推短视频矩…...

每日一题——提取服务器物料型号并统计出现次数

提取服务器物料型号并统计出现次数 一、题目描述&#x1f4a1; 输入描述&#xff1a;&#x1f4e4; 输出描述&#xff1a; 二、样例示例&#x1f3af; 示例1&#x1f3af; 示例2 三、解题思路1. 子串提取策略&#xff1a;正则匹配2. 统计策略&#xff1a;哈希映射3. 输出策略 四…...

DexGarmentLab 论文翻译

单个 专家 演示 装扮 15 任务 场景 2500+ 服装 手套 棒球帽 裤子 围巾 碗 帽子 上衣 外套 服装-手部交互 捕捉 摇篮 夹紧 平滑 任务 ...... 投掷 悬挂 折叠 ... 多样化位置 ... 多样化 变形 ... 多样化服装形状 类别级 一般化 类别级(有或没有变形) 服装具有相同结构 变形 生…...

【Linux网络编程】传输层协议TCP,UDP

目录 一&#xff0c;UDP协议 1&#xff0c;UDP协议的格式 2&#xff0c;UDP的特点 3&#xff0c;面向数据报 4&#xff0c;UDP的缓冲区 5&#xff0c;UDP使用注意事项 6&#xff0c;基于UDP的应用层协议 二&#xff0c;对于报文的理解 三&#xff0c;TCP协议 1&…...