SAP Fiori开发中的JavaScript基础知识10 - 变量作用域,变量提升

1. 背景

本文将会介绍JavaScript中两个相对复杂的概念,也即作用域和变量提升。这个概念在JavaScript中的设计和ABAP中的设计区别还是比较大的,特别是变量提升部分。第一次接触JavaScript的同学,要注意理解和区分。

2. 作用域

在JavaScript中,作用域定义了变量的可见性和生命周期。它规定了变量在何处和如何被访问。

JavaScript主要有两种类型的作用域:全局作用域和局部作用域。

2.1 全局作用域

全局作用域:在代码的任何地方都可以访问全局变量。

全局作用域是默认的作用域, 它可以包含0个或多个嵌套的局部作用域。局部作用域间可以形成层级关系。

var globalVar = "I am global!"; // 这是一个全局变量function test() {console.log(globalVar);  // 输出 "I am global!"
}test();

在上述代码中,globalVar是一个全局变量,可以在test函数内部访问。

2.2 局部作用域

局部作用域:局部变量只能在声明它们的函数或代码块内部访问, 通常就是指两个大括号范围内的作用域。


function test() {var localVar = "I am local!"; // 这是一个局部变量console.log(localVar);  // 输出 "I am local!"
}test();
console.log(localVar);  // 报错:ReferenceError: localVar is not defined

在上述代码中,localVar是一个局部变量,只能在test函数内部访问。在函数外部尝试访问localVar将会抛出错误。

此外,ES6引入了let和const关键字,它们具有块级作用域。这意味着它们的作用域被限制在最近的一对花括号(即一个代码块)中。

if (true) {let x = 5; // 这是一个块级作用域变量
}
console.log(x);  // 报错:ReferenceError: x is not defined

在上述代码中,变量x的作用域被限制在if语句的代码块中。尝试在代码块外部访问x将会抛出错误。

let 提供了更好的变量作用域控制,更严格的声明规则,以及更好的错误检查,因此在现代的 JavaScript 开发中,let应当是首选的变量声明关键字。

3. 变量提升

在 JavaScript 中,变量提升(Hoisting)是 JavaScript 默认将当前作用域(全局或函数)中的 “变量和函数声明” 移至顶部的行为

这意味着无论变量或函数在哪里声明,都会被提升到作用域的顶部。

需要注意的是,只有声明会被提升,初始化(如果变量是在声明同时进行的初始化)不会被提升。

例如:

console.log(myVar); // 输出:undefined
var myVar = 5;
console.log(myVar); // 输出:5

在上面的代码中,虽然变量 myVar 在 console.log(myVar); 之后声明和初始化,但由于变量提升,JavaScript 引擎在执行代码时会将 var myVar; 提升到顶部,所以第一个 console.log(myVar); 输出的是 undefined 而不是报错。

对于函数,提升的是整个函数体:

hoistedFunction(); // 输出:"Hello, I have been hoisted"function hoistedFunction() {console.log("Hello, I have been hoisted");
}	

在上面的代码中,尽管函数 hoistedFunction 在调用它的代码行之后声明,但由于函数提升,它仍然可以正常工作。

需要注意的是,函数表达式(包括箭头函数)和 let、const 声明的变量不会被提升:

console.log(myLetVar); // 报错:myLetVar is not defined
let myLetVar = 5;console.log(myFunction); // 报错:myFunction is not a function
var myFunction = function() {console.log("Hello, I am a function expression");
};

在上面的代码中,let 声明的变量和函数表达式都没有被提升,所以在它们声明之前尝试访问会导致错误。

3.1 最佳实践

在 JavaScript 中,理解和处理变量提升的规则十分重要,为了避免意想不到的问题,可以参考以下最佳实践。

  1. 变量和函数声明尽可能放在作用域顶部:这样可以清晰地看到哪些变量和函数可用,也可以避免由于变量提升导致的意外行为。
var myVar = 5;
function myFunction() {// 函数体
}
// 其他代码
  1. 避免在同一作用域内使用相同的变量名:这样可以避免由于变量提升导致的变量覆盖。
function myFunction() {var myVar = 5;// 其他代码var myVar = 10; // 避免这样做
}
  1. 使用 let 和 const 替代 var:let 和 const 声明的变量不会被提升,而且它们有块级作用域,这可以避免很多由于变量提升和函数作用域导致的问题。
let myLetVar = 5;
const myConstVar = 10;
  1. 避免在声明之前使用变量或函数:即使变量和函数声明会被提升,但在声明之前使用它们仍然是一种不好的实践,因为这可能会导致代码难以理解和维护。
myFunction(); // 避免这样做function myFunction() {// 函数体
}
  1. 理解函数表达式和函数声明的区别:函数表达式(包括箭头函数)不会被提升,所以在函数表达式赋值之前调用它们会导致错误。
myFunction(); // 报错:myFunction is not a functionvar myFunction = function() {// 函数体
};

3.2 变量提升的原理

JavaScript 中的变量提升(Hoisting)机制是由 JavaScript 引擎的工作方式决定的。在执行 JavaScript 代码时,JavaScript 引擎会经历两个阶段:编译阶段执行阶段

编译阶段,JavaScript 引擎会查找所有的变量和函数声明,并在内存中为它们分配空间。这就是为什么我们可以在声明之前访问变量(虽然值是 undefined),因为内存空间已经在编译阶段被分配了。

执行阶段,JavaScript 引擎开始执行代码,填充(赋值)之前在内存中分配的变量和函数。

这种机制的存在,使得在函数或全局作用域内的任何地方声明变量和函数都可以,提供了一定的灵活性。然而,这也可能导致一些意想不到的结果,因此在编写 JavaScript 代码时,最佳实践是将所有的变量和函数声明放在其作用域的顶部,以提高代码的可读性和可维护性。

4. 小结

本文详细介绍了JavaScript中作用域、变量提升的概念,并从原理和实践的角度介绍了这两个概念。希望本文对你有帮助!

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

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

相关文章

vscode安装

🌈个人主页:Rookie Maker 🏆🏆关注博主,随时获取更多关于IT的优质内容!🏆🏆 😀欢迎来到小田代码世界~ 😁 喜欢的小伙伴记得一键三连哦 ૮(˶ᵔ ᵕ ᵔ˶)ა …

商场促销--策略模式

1.1 商场收银软件 package com.lhx.design.pattern.test;import java.util.Scanner;public class Test {public static void main(String[] args){System.out.println("**********************************************"); System.out.println("《大话设计模式…

vue3鼠标向下滑动,导航条改变背景颜色和logo的封装

代码中使用了element-plus组件&#xff0c;需先安装 向下滑动前 向下滑动后&#xff08;改变了logo 字体 背景颜色&#xff09; <script lang"ts" setup> import router from /router; import { ArrowDown } from element-plus/icons-vue import { ref, …

【tensorflow框架神经网络实现鸢尾花分类—优化器】

文章目录 1、前言2、神经网络参数优化器2.1、SGD2.2、SGDM2.3、Adagrad2.4、RMSProp2.5、Adam 3、实验对比不同优化器4、结果对比 1、前言 此前&#xff0c;在【tensorflow框架神经网络实现鸢尾花分类】一文中使用梯度下降算法SGD&#xff0c;对权重 w w w和偏置 b b b进行更新…

如何在Windows上安装SSH

SSH&#xff08;Secure Shell&#xff09;协议是一种强大且安全的网络协议&#xff0c;它为用户提供了一种加密的方式来远程访问和管理终端设备。在Windows操作系统中&#xff0c;安装和配置SSH服务是一个相对直接的过程&#xff0c;可以让你享受到SSH带来的便利和安全性。下面…

软件设计原则:迪米特法则

定义 迪米特法则&#xff08;Law of Demeter, LoD&#xff09;&#xff0c;又称最少知识原则&#xff0c;它指导我们在设计软件时&#xff0c;应当尽量减少对象之间的交互&#xff0c;一个对象应该对其他对象有尽可能少的了解。具体来说&#xff0c;一个对象应该只调用属于以下…

Lua脚本的使用

一、使用lua脚本扣减单个商品的库存 SpringBootTest class LuaTests {AutowiredStringRedisTemplate stringRedisTemplate;Testvoid test3() {for (int i 1; i < 5; i) {stringRedisTemplate.opsForValue().set("product."i,String.valueOf(i));}}Testvoid test…

3.写一个char类型的字符数组,对该数组访问越界时抛出异常,并做处理。

#include <iostream>using namespace std;char arr[10]"12345678"; void show(int i) {if(i>10){throw int(2);}cout << arr[i] <<endl; } int main() {int i;cin >> i;try {show(i);} catch (int) {cout << "越界" <…

【华为OD机试C++】句子逆序

《最新华为OD机试题目带答案解析》:最新华为OD机试题目带答案解析,语言包括C、C++、Python、Java、JavaScript等。订阅专栏,获取专栏内所有文章阅读权限,持续同步更新! 文章目录 描述输入描述输出描述示例1示例2代码描述 将一个英文语句以单词为单位逆序排放。例如“I am …

【Web】记录Polar靶场<困难>难度题一遍过

目录 上传 PHP是世界上最好的语言 非常好绕的命令执行 这又是一个上传 网站被黑 flask_pin veryphp 毒鸡汤 upload tutu Unserialize_Escape 自由的文件上传系统​​​​​​​ ezjava 苦海 你想逃也逃不掉 safe_include CB链 phar PHP_Deserializatio…

Centos7环境下安装MySQL8详细教程

1、下载mysql安装包 2、检查是否安装过mysql ps:因为以前用yum安装过&#xff0c;所以先用yum卸载。如果不是此方式或者没安装过则跳过 [rootlocalhost ~]# yum remove mysql 已加载插件&#xff1a;fastestmirror 参数 mysql 没有匹配 不删除任何软件包 查看是否有mysql依赖 …

6.7物联网RK3399项目开发实录-驱动开发之Camera摄像头的使用(wulianjishu666)

90款行业常用传感器单片机程序及资料【stm32,stc89c52,arduino适用】 链接&#xff1a;https://pan.baidu.com/s/1M3u8lcznKuXfN8NRoLYtTA?pwdc53f Camera 使用 简介 AIO-3399J 开发板分别带有两个 MIPI&#xff0c;MIPI 支持最高 4K 拍照&#xff0c;并支持 1080P 30fp…

Java进阶-反射的详解与应用

本文深入探讨了Java反射机制的核心概念、应用实例及其在现代Java开发中的重要性。文章首先介绍了反射的基本原理和能力&#xff0c;包括在运行时动态获取类信息、操作对象字段和方法的能力。随后&#xff0c;通过具体代码示例&#xff0c;展示了如何利用反射进行字段访问、方法…

逆序对————权值线段树+离散化写法

今天写道这么一道题&#xff0c;鉴于不太熟悉归并和树状数组&#xff0c;还是用线段树水一下&#xff08; 板子如下 #include<iostream> #include<vector> #include<algorithm> using namespace std; const int N5e510; #define int long long #define lc …

java版本学习网站又添加了一个libgdx模块

java版本学习网站之前添加了docker&#xff0c;想了想还是再把libgdx添加进去吧。 访问地址&#xff1a;想飞跃的鱼 (nanshaws.github.io) github地址&#xff1a;nanshaws/JavaLearnNote: The new features from Java 9 to Java 21 help you quickly grasp the key features …

Mysql中的那些索引

主键索引 表的主键使用的就是主键索引&#xff0c;一张表只能有一个主键索引&#xff0c;主键索引不能为null,且不能重复。 主键索引存在于B树的非叶子节点&#xff0c;叶子节点存放的是数据。 非主键索引 非主键索引也叫二级索引&#xff0c;包括有唯一索引&#xff0c;普…

工业项目能耗管理可以看这个开源项目

软件介绍 Scaphandre是一个专注于电力和能源消耗指标的计量代理&#xff0c;旨在为公司和个人提供测量技术服务功耗的便捷工具&#xff0c;并以便于理解的方式获取数据。其名字来源于法语中的潜水服或潜水器&#xff0c;象征着深入测量和揭示技术服务耗能量的意图。 功能特点 …

【攻防世界】file_include (PHP伪协议+过滤器)

打开题目环境&#xff1a; 进行PHP代码审计&#xff0c;发现这是一个文件包含漏洞。 我们尝试利用PHP伪协议中的 php://filter来读取 check.php 中的内容。 构造payload 并提交&#xff1a; 发现payload被过滤掉了&#xff0c;我们就需要尝试使用不同的转换器。 PHP各类转换…

最新AI智能系统ChatGPT网站源码V6.3版本,GPTs、AI绘画、AI换脸、垫图混图+(SparkAi系统搭建部署教程文档)

一、前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧。已支持GPT…