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 function

var myFunction = function() {
  // 函数体
};

3.2 变量提升的原理

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

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

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

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

4. 小结

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

  • 22
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十年铸器

给作者赏杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值