分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 网页技术

You Don't Know JS: Scope & Closures (第4章: Hoisting)

发布时间:2023-09-06 02:16责任编辑:彭小芳关键词:暂无标签

Chapter4: Hoisting

变量附加到哪个层次的scope,由它们在哪里和如何声明(let, var)来决定。

Function scope/Block scope都有相同的法则:任何变量在一个scope内声明,则这个变量附加到这个作用域上。

但有一个细节问题:当声明declarations出现在一个作用域中的不同的位置的时候,scope附加如何与declarations协作?


Chicken or The Egg?

temptation: a strong desire to have or do sth even thought you know you should not(邪念,诱惑人的事物)

当程序执行时,JS 代码被一行行,从上到下的顺序被解译。但有例外:

a = 2;var a;console.log( a ); ?输出2

可是:

console.log( a );var a = 2; ?
//输出undefined

怎么回事? 一个先有鸡还是先有蛋的问题。 the declaration是蛋, assignment是鸡。


The Compiler Strikes Again 编译器又罢工了

Engine实际是先编译JS code,在interprtes it之前。 

编译器先声明变量,然后Engine在Scope中查询这个变量,如果发现就分配它。 

所以思考事情的最好的方式是:

所有的声明declarations,包括变量和函数,被首先处理processed。在你的代码被执行executed前。

var a = 2; 其实是2个statements: var a;和a = 2;

var a 是声明,在编译阶段被处理;

a = 2是assignment, 会留在执行阶段execution phase处理。

所以,前2个例子就可以理解了:

//第一个例子:var a;a = 2;console.log(a); ??// 2//第二个例子:var a;console.log(a); ?//undefineda = 2;

结论:先有蛋(declarations),后有?? assignment. 

  1. 只有声明自身会被hoisted!! 
  2. 另外, hoisting是per-scope,只在声明所在的作用域内hoisting它。
  3. 函数表达式不是声明!!所以不会hoisting它!
  1. foo(); // not ReferenceError, but TypeError!var foo = function bar() { ???// ...};
    Uncaught TypeError: foo is not a function

    解释:
    var foo被提升hoisting,但它没有value。
    使用foo(),就是认为foo的值是函数,用()执行函数。
    typeof foo //undefined
    所有,提示?,foo不是一个函数,不能使用()!
    (表达式和声明的区分见第三章,Function as Scope)

另一个例子: 

foo(); // TypeError ,foo is not a functionbar(); // ReferenceError, (bar是函数,但是)bar is not definedvar foo = function bar() { ???// ...};

等同于:
var foo;foo(); // TypeErrorbar(); // ReferenceErrorfoo = function() {var bar = ...self... ??????// 证明作为表达式,bar 只在内部{ .. }被使用}

  


Functions First

  • 先函数声明hoisting,再变量声明hoisting。
  • 多重/副本 var声明会被忽略。 但可以重写函数声明。
foo(); // 3function foo() {          //hoisting ,第一行 ???console.log( 1 );}var foo = function() {  ???????//多重var声明,被忽略,不会hoisting。 ???console.log( 2 );       //这里重写了foo函数。};function foo() {          //hoisting,第二行     ???console.log( 3 );}foo() ??//输出2 

ES7最新版:块内函数声明, 要小心使用!foo没有hoisting到全局作用域!!


Review

var a = 2;其实是2部分,var a 是在编译阶段处理, =2在执行阶段处理

所有声明都首先被处理!在它们执行前!

分配, 甚至分配一个函数表达式,都不会被hoisted!

小心duplicate declarations。尤其是混合了正常的var声明和函数声明,要避免这种使用!

写代码先写声明,是好的习惯!!

You Don't Know JS: Scope & Closures (第4章: Hoisting)

原文地址:https://www.cnblogs.com/chentianwei/p/9739698.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved