JavaScript 中的提升

更新日期: 2023-11-08阅读: 311标签: js知识


介绍

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

在本文中,我们将带您了解 JavaScript 中提升的概念,阐明变量和函数是如何提升的。最后,您不仅会掌握提升背后的隐藏机制,还会学习如何利用它来发挥自己的优势。因此,事不宜迟,让我们深入了解 JavaScript 提升的迷人世界!


什么是提升?

在深入研究细节之前,我们先来揭秘JavaScript 中提升的含义。提升是在编译阶段将变量和函数声明移动到其包含范围的顶部的幕后过程。这允许您在代码中正式声明它们之前使用它们。

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


变量提升

var 的魔力

在 JavaScript 世界中,用 声明的变量var表现出一种特殊的提升行为。当您使用 声明变量时var,它会被提升到它所属的函数或全局范围的顶部。考虑以下示例:

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

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

let 和 const 的混合

的行为var可能看起来违反直觉,并且经常会导致意想不到的错误。为了解决这个问题,JavaScript 引入了let和const,它们具有不同的提升机制。

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

使用letand 时const,提升仍然会发生,但变量在代码中实际声明之前不会初始化。这意味着在声明之前尝试访问myVar将导致ReferenceError. 这种行为可以促进更干净、更可预测的代码。


函数声明与表达式

函数声明提升

就像变量一样,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!");
};

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


作用域和提升

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

全局作用域

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

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

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

局部作用域

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

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

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


常见的提升陷进

了解提升对于编写干净且无错误的代码至关重要。以下是吊装过程中需要注意的一些常见陷阱:

执行顺序

代码的顺序会显着影响提升行为。变量和函数被提升到其包含范围的顶部,因此如果在声明变量或函数之前使用它,则可能会遇到意外的行为或错误。

console.log(orderMattersVar); // Outputs: undefined
var orderMattersVar = "Hoisting can be tricky!";

在这种情况下,该console.log语句在 的声明之前运行orderMattersVar,结果是undefined。为了避免这种情况,请务必在使用变量和函数之前声明它们。

重定义变量

当您使用 在同一范围内多次声明同一变量时var,它不会引发错误。该变量只是被重新分配了一个新值。

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

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

函数重写

在 JavaScript 中,如果多次声明同名函数,最后一次声明将覆盖之前的所有声明。这可能会导致意外的行为和错误。

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

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


代码整洁的最佳实践

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

正确声明变量

为了防止与提升相关的问题,请在变量范围的顶部声明变量。如果您使用var,请考虑切换到let或const利用块作用域,这更可预测且更安全。

function cleanCodeExample() {
  var localVar = "I'm declared at the top";
  // Rest of your code here
}

通过在顶部声明变量,可以使代码更具可读性并减少遇到提升意外的机会。

组织函数

使用函数时,请确保对它们进行一致的定义。在整个代码库中使用函数声明或函数表达式来维护统一的结构。

// Good practice
function calculateSum(a, b) {
  return a + b;
}

// Avoid mixing function declaration and expression
var multiply = function (a, b) {
  return a * b;
};

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


总结

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

作者:Vishwas Acharya 


链接: https://www.fly63.com/article/detial/12546

classList的使用,原生js对class的添加,删除,修改等方法的总结,以及兼容操作

classList是一个DOMTokenList的对象,用于在对元素的添加,删除,以及判断是否存在等操作。以及如何兼容操作

js原型链,Javascript重温OOP之原型与原型链

js的原型链,得出了一个看似很简单的结论。对于一个对象上属性的查找是递归的。查找属性会从自身属性(OwnProperty)找起,如果不存在,就查看prototype中的存在不存在。

讲解JavaScript 之arguments的详解,arguments.callee,arguments.caller的使用方法和实例

arguments是什么?在javascript 中有什么样的作用?讲解JavaScript 之arguments的使用总结,包括arguments.callee和arguments.calle属性介绍。

WebSocket的原理及WebSocket API的使用,js中如何运用websocket

WebSocket是HTML5下一种新的协议,为解决客户端与服务端实时通信而产生的技术。其本质是先通过HTTP/HTTPS协议进行握手后创建一个用于交换数据的TCP连接

javascript对dom的操作总汇,js创建,更新,添加,删除DOM的方法

HTML文档在浏览器解析后,会成为一种树形结构,我们需要改变它的结构,就需要通过js来对dom节点进行操作。dom节点(Node)通常对应的是一个标题,文本,或者html属性。

深入理解JS中引用类型和基本类型

javascript中基本类型指的是那些保存在栈内存中的简单数据段,即这种值完全保存在内存中的一个位置。 引用类型指那些保存在堆内存中的对象,意思是变量中保存的实际上只是一个指针,这个指针指向内存中的另一个位置,该位置保存对象。

深入理解Javascript中apply、call、bind方法的总结。

apply 、 call 、bind 三者都是用来改变函数的this对象的指向的;第一个参数都是this要指向的对象,也就是想指定的上下文;都可以利用后续参数传参;bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用 。

理解js中prototype和__proto__和的区别和作用?

在js中有句话叫一切皆对象,而几乎所有对象都具有__proto__属性,可称为隐式原型,除了Object.prototype这个对象的__proto__值为null。Js的prototype属性的解释是:返回对象类型原型的引用。每个对象同样也具有prototype属性,除了Function.prototype.bind方法构成的对象外。

js中“=”,“==”,“===”的使用和深入理解

Js支持“=”、“==”和“===”的运算符,我们需要理解这些 运算符的区别 ,并在开发中小心使用。它们分别含义是:= 为对象赋值 ,== 表示两个对象toString值相等,=== 表示两个对象类型相同且值相等

JS的变量作用域问题,理解js全局变量和局部变量问题

js的变量分为2种类型:局部变量和全局变量。主要区别在于:局部变量是指只能在变量被声明的函数内部调用,全局变量在整个代码运行过程中都可以调用。值得注意的js中还可以隐式声明变量,而隐式声明的变量千万不能当做全局变量来使用。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!