javascript_javascript吊装

javascript

In this article, we’ll go through concept of hoisting, it’s definition and implementation.

在本文中,我们将介绍起重的概念,定义和实现。

Hoisting represents a system or mechanism by which variables and functions are moved to the top of the scope before the code is being executed.

提升表示一种系统或机制,通过该系统或机制,变量和函数在执行代码之前被移至作用域的顶部。

That means, that we have access to the variables and/or function no matter where in scope they are written. Consider the following example

这意味着,无论在何处写入变量和/或函数,我们都可以访问它们。 考虑以下示例

console.log(name)
var name = "Adam" // "undefined"

Here, in the first line, we try to console log the name variable, which is declared only on the second line. So, by an idea, hoisting will mean that this var name = “Adam” is taken to the top of the context before console.log(name) even runs. In that case, why does this technique prompt us with undefined? If JavaScript doesn’t see this code, it would give us ReferenceError and, vice versa, if it sees this variable, the value of the name variable would be returned as a string Adam. But we get neither error nor the value, instead, we get something in the middle (if we’re allowed to say so), the undefined. What’s the issue? To uncover this, first, we need to step back and remember what variables contain. In the example above, we not only declared a variable but also assigned it to some value, thus, we can say, that the variable above is declaration + assignment (to familiarize yourself a bit more with this topic, you can check out this post). JavaScript allows us to both declare and assign variables in the same line, but in its invisible world, it takes these two steps separately. As you might know, if we only declare a variable without assigning it, it will be undefined while typeof variable // “undefined” (we’re getting to the point). That means that hoisting takes to the top of the scope only declaration, without assignment! The example below makes it crystal clear how the Hoisting works:

在这里,在第一行中,我们尝试控制台记录名称变量,该变量仅在第二行中声明。 因此,从某种意义上讲,吊装意味着在console.log(name)甚至运行之前,将此var name =“ Adam”带到上下文的顶部。 在那种情况下,为什么此技术会提示我们未定义? 如果JavaScript没有看到此代码,它将给我们提供ReferenceError ,反之亦然,如果看到此变量,则将name变量的值作为字符串Adam返回。 但是我们既没有错误也没有值,相反,我们在中间得到了一些东西(如果可以这样说的话),即undefined 。 怎么了为了揭示这一点,首先,我们需要退后一步,并记住变量包含的内容。 在上面的示例中,我们不仅声明了一个变量,而且还为它分配了一些值,因此,可以说,上面的变量是声明+赋值(要使您对本主题有更多的了解,可以查看一下这篇文章。 )。 JavaScript允许我们在同一行中声明和分配变量,但是在其不可见的世界中,它分别采取了这两个步骤。 如您所知,如果仅声明变量而不分配变量,则在typeof变量//“未定义”时将是未定义的(到此为止)。 这意味着吊装仅在声明的范围之内,而无需分配! 下面的示例使吊装工作非常清晰:

var name; // "undefined"
console.log(name)
name = "Adam"

So, we might say, that Hoisting doesn’t take the whole variable at the top, but parses (or, rather, references) its declaration only. Imagine if you attend a concert with your friend, but for some reason the security guard only lets your friend in, separating and leaving you outside, explaining that even you’re always together like twin brothers, only one of you has access… That’s a bit weird.

因此,我们可以说,提升并不是将整个变量放在顶部,而是仅解析(或引用)其声明。 想象一下,如果您与朋友一起参加音乐会,但是出于某种原因,保安人员只会让您的朋友进去,将您分开并留在外面,并解释说,即使您总是像孪生兄弟一样在一起,只有你们一个人可以进入……有点奇怪。

Another thing to mention about Hoisting is that the place when the variables and functions are hoisted is different related to whether we use a global scope or function scope (simply, the area between curly braces, {…}). The function below fully demonstrates the hoisting concept in functions.

关于提升的另一件事是,提升变量和函数的位置与我们使用全局作用域还是函数作用域(简单来说,花括号之间的区域,{…})有关。 以下功能充分说明了起重概念。

function personalInfo() {
var firstName = 'Adam';
var lastName;console.log(firstName);
console.log(lastName);
console.log(address);
console.log(mobile);
console.log(dateOfBirth);lastName = 'Smith';
var address = 'planet earth';
mobile = 1234567890;
};personalInfo();// Adam
// undefined
// undefined
// ReferenceError: mobile is not defined
// ReferenceError: dateOfBirth is not defined

In the first line in function scope which reads var firstName = ‘Adam’, doesn’t require hoisting while it was both declared and assigned at the top of the scope, before being invoked (console.log(firstName)). The lastName variable was declared before invocation but assigned after it, that’s why it’s undefined (this is the best illustration of hoisting). The address variable is both declared and assigned after being called, so the JavaScript only takes declaration at the top and again prompts us with undefined. Another interesting example is when we call a variable that was nor declared neither assigned (dateOfBirth). And the last example of the mobile variable will give us an Uncaught ReferenceError, while when we declare a variable without explicitly putting var, let, or const keywords before the name, it becomes a global variable, which is not visible in the function’s scope if put after calling, but is accessible once we move it outside of function scope into the global scope. Even if we put this global mobile variable after function but before calling it, it will be visible.

在函数范围的第一行中,读取var firstName ='Adam'时,不需要在其被声明并分配到该范围的顶部之前对其进行吊装( console.log(firstName) )。 lastName变量是在调用之前声明的,但在调用之后分配的,这就是为什么它未定义的原因(这是提升的最佳例证)。 address变量在被调用后既被声明又被分配,因此JavaScript仅在顶部声明,然后再次用undefined提示我们。 另一个有趣的示例是,当我们调用一个既未分配也未声明的变量( dateOfBirth )。 移动变量的最后一个示例将为我们提供Uncaught ReferenceError ,而当我们声明一个变量时未在名称之前显式放置varletconst关键字时,它将成为全局变量,如果在变量范围内不可见放在调用之后,但是一旦我们将其移出函数范围到全局范围就可以访问。 即使我们将此全局移动变量放在函数之后但在调用之前,它也将可见。

function personalInfo() {
console.log(mobile);
};
mobile = 1234567890; // outside of function scope, in global scope
personalInfo();
// 1234567890

Regardless of that, it was called before it was declared, as far as the variable is also hoisted globally, it can now be invoked.

不管怎样,它在声明之前就被调用了,只要该变量也被全局提升,现在就可以调用它了。

With the introduction of ECMAScript 2015, the let keyword is now thoroughly substituting var-s, which has scope issues. Now when we declare a variable by let, it won’t return undefined, but ReferenceError instead.

随着ECMAScript 2015的推出, let关键字现在已完全替代var -s,后者存在范围问题。 现在,当我们通过let声明变量时它不会返回undefined ,而是返回ReferenceError

function differenceBetweenVarLetConst() {
console.log(firstName);
console.log(lastName);
console.log(address);
var firstName = 'Adam';
let lastName = 'Smith';
const address= 'planet earth';
}differenceBetweenVarLetConst();
// undefined;
// Uncaught ReferenceError: can't access lexical declaration 'lastName' before initialization;
// Uncaught ReferenceError: can't access lexical declaration 'address' before initialization;

So, let is more specific, and not only in case of var-related scope issues but also by explicitly complaining in form of error that it was initiated after it was called. Both let and const is uninitialized when tried to be hoisted, whereas var remains undefined.

因此, let是更具体的,不仅在与var有关的范围问题的情况下,而且还通过以错误的形式显式地抱怨在调用它之后启动它。 尝试吊起时, letconst都未初始化,而var仍未定义

Function declaration vs function expression

函数声明与函数表达式

The last difference in hoisting behavior is vividly underlined when comparing function declaration vs function expression. Which one of them is hoisted? Function expression, unlike function declaration, is a function stored in a variable. Consider the following examples.

比较函数声明和函数表达式时,生动地强调了提升行为的最后一个区别。 其中哪一个被吊起? 与函数声明不同,函数表达式是存储在变量中的函数。 考虑以下示例。

// function declaration
declaration(); // called before initialization, hoisted
function declaration() {
console.log('function declarations are hoisted')
}
// function declarations are hoisted// function expression
expression(); // called before initialization, not hoisted
let expression = function() {
console.log('you will not see this message while function exressions are not hoisted')
};// Uncaught ReferenceError: can't access lexical declaration 'expression' before initialization;

It becomes obvious that function declarations are seamlessly hoisted compared to that of function expressions, so, keep that in mind next time you decide to write a function!

很明显,与函数表达式相比,函数声明是无缝提升的,因此,下次决定编写函数时,请记住这一点!

Conclusion

结论

The takeaways of this article are that the JavaScript engine takes variable declarations to the top of its environment, which can be both global and local scopes. It can be quite informative depending on whether it returns undefined or ReferenceError. In case of undefined, it says that the variable is created, it exists, but it’s assigned after the invocation and it’s declared as var (no matter if it was declared before). In the case of ReferenceError, JavaScript points out that the variable we try to call is not visible while it was neither declared nor assigned, or it’s declared+assigned with let or const. Also remember, that only function declarations are hoisted. To avoid these issues, always declare and assign variables at the top, before calling them!

本文的要点是,JavaScript引擎将变量声明带到其环境的顶部,该声明可以是全局作用域,也可以是局部作用域。 根据返回的是undefined还是ReferenceError,它可以提供很多信息。 如果为undefined ,则表示已创建该变量,该变量存在,但在调用后分配该变量,并将其声明为var (无论之前是否声明)。 在ReferenceError的情况下,JavaScript指出,我们尝试调用的变量在未声明或未赋值的情况下不可见,或者使用letconst进行了声明+赋值。 还要记住,只有函数声明会被提升。 为避免这些问题,请始终在调用它们之前在顶部声明并分配变量!

翻译自: https://medium.com/swlh/javascript-hoisting-e37dcb23899e

javascript

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值