背景

因为ES5的时候没有块级作用域,所以ES5规定不能再if这样的块中声明函数,但是为了兼容各大浏览器并没有严格遵守这条规定。

ES6的时候引入了块级作用域,规定在块级作用域中声明函数就相当于使用let来声明变量一样。但是又因为浏览器端的兼容问题,标准中说明浏览器端的实现可以不完全遵守,有自己的行为,如下:

  • 允许在块级作用域内声明函数。
  • 函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
  • 同时,函数声明还会提升到所在的块级作用域的头部。
if (false) {function a() {}
}
console.log(a);

上面输出 undefined这表明了上面两条,一个是允许在块级作用域内声明函数,一个是块级作用域内声明类似于var。

if (true) {console.log(a);function a() {}
}

输出函数a,这表明了第三条:函数声明会提升到所在块级作用域的头部。

问题和信息

上面现有的理论并不够解释下面的现象:

var a;{a = 5;function a() {}a = 0;console.log(a);
}
console.log(a);

chrome最新版输出的是:第一个console输出的是0,第二个console输出的是5

先陈述下依据已知的三条理论得出上面代码几个不合理的现象:

  1. 首先稍微变通就知道如下代码:
{function a() {}
}console.log(a);

这里打印了a是一个函数,穿透了块级作用域。上面并没有解释这种现象。

  1. a = 0;的赋值并没有影响到块外部的a。

解释上面两个问题,还需要额外的信息(信息来自stackoverflow高赞回答,原文在参考链接中):

function enclosing() {{function compat() {}}
}// works the same asfunction enclosing() {var compat₀ = undefined; // function-scoped{let compat₁ = function compat() {}; // block-scopedcompat₀ = compat₁;}
}

上面对块中的函数声明引入的额外的概念,更加清晰明了的解释了底层做了什么。

首先额外引入的信息本身也存在一些问题。少了函数会提升到当前块作用域顶部,我认为应该如下修改:

function enclosing() {var compat₀ = undefined; // function-scoped{function compat() {}let compat₁ = compat; // block-scopedcompat₀ = compat₁;}
}

这样就修复了没有函数提升的问题。

猜想

根据额外补充的知识加上自己的想象力得到如下结果:

var a₀;{// 这部分被提升function a() {}let a₁ = a;a₀ = a;// 这部分被提升ENDa₀ = 5;a₁ = 0;console.log(a₁);
}
console.log(a₀);

a₀ 和 a₁ 都是a在不同位置的不同分身。

参考

  • let 和 const 命令
  • What are the precise semantics of block-level functions in ES6?

ES6中块级作用域下的函数声明相关推荐

  1. [ES6] 细化ES6之 -- 块级作用域

    所谓的块级作用域,可能是一个{},一个代码块,一句话 let关键字 let 与 var 区别 区别 var let 变量提升 有 无 作用域 全局作用域.函数作用域 全局作用域.函数作用域和块级作用域 ...

  2. es6 ie不兼容 函数_ES6:什么是块级作用域?

    在 ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景. 我们先来看一下下面这种情况:内层变量可能会覆盖外层变量. var txt = '外层变量-->你好呀';func ...

  3. es6中的块级作用域

    块级作用域 凡是带{}都是块级作用域,if(){} for(){} 对象{} 1.在块级作用域下,var 和function跟在window下一样, function有个特殊的一点,在块级作用域下会提 ...

  4. ES6 块级作用域详解

    什么是块级作用域 ES6 中新增了块级作用域.块作用域由 { } 包括,if 语句和 for 语句里面的 { } 也属于块作用域. 为什么需要块级作用域 第一种场景:内部变量会覆盖外部变量 var t ...

  5. 搭建Babel运行环境,Traceur ES6模板,块级作用域,let和const命令

    搭建Babel运行环境 Babel(http://babeljs.io/)可用于将使用ES6语法的脚本转化为ES5语法的脚本,基本功能的安装步骤如下: 1.安装node解释器和npm包管理工具 2.安 ...

  6. javascript中作用域、全局作用域、局部作用域、隐式全局变量、块级作用域、作用域链、预解析

    作用域 作用域指的是代码的作用范围,按照作用域划分变量可分为全局变量和局部变量:作用域可分为: 全局作用域: 指全局变量作用的范围:全局变量指的是通过var在函数外面声明的变量,在js中任何位置都可以 ...

  7. 块级作用域和函数作用域

    函数作用域与块级作用域 函数作用域:在函数内部声明的变量只能影响到变量所在函数体本身,无法从外部对函数内部的变量进行调用,被称为'函数作用域' 块级作用域:ES6 引入了 let 和 const 关键 ...

  8. ES6-2 块级作用域与嵌套、let、暂行性死区

    注意,写在开头 function test(x = 1) {var x // 不报错console.log(x) } function test1(x = 1) {let x = 10 // 报错co ...

  9. java区块作用域_ES6-let、const和块级作用域

    1.介绍 总的来说,ES6是在ES2015的基础上改变了一些书写方式,开放了更多API,这样做的目的最终还是为了贴合实际开发的需要.如果说一门编程语言的诞生是天才的构思和实现,那它的发展无疑就是不断填 ...

最新文章

  1. CentOS 6虚拟机安装
  2. 4月机器学习热文出炉,这10篇文章你读了吗?
  3. 深度:生成模型(GAN)的最新进展
  4. 使用ilmerge实现.net程序静态链接
  5. 使用jclouds在S3上分段上传
  6. CSS中越界问题经典解决方案
  7. PS特效:图像碎片化
  8. 【clickhouse】clickhouse 表引擎 之 AggregatingMergeTree
  9. 翻译: 构建基于卡尔曼滤波器的 IMU 用速度数据改进 IMU 姿态估计
  10. ssm图书馆管理系统
  11. matlab 广义特征,特征值 特征向量 广义特征值 matlab
  12. hdu 1880 魔咒词典 (字符串哈希)
  13. vue 免费个人博客模板
  14. 春天里,阳光下,无限的哀思和想念
  15. 计算机数据备份到u盘,技术给你说Win10系统怎么把数据备份到U盘的完全处理手段...
  16. 开始使用 Elasticsearch (1)
  17. ipv6内网穿透,有ipv6地址外网无法访问
  18. c语言windows画五角星,C/C++画一个巨型五角星
  19. MATLAB科学绘图-MATLAB画图技巧与实例(一):常用函数
  20. 我们为什么这么拼?(转载自微信)

热门文章

  1. ltp-ddt eth_iperf_tcp iperf dualtest遇到的问题
  2. Spring Boot 学习笔记(三)Spring boot 中的SSM
  3. Nginx 怎么给一台服务器,配置两个域名?详细的解说+截图教程
  4. Linux查看系统信息的一些命令及查看已安装软件包的命令
  5. vertical-align属性详解
  6. 发布单机端DELPHI程序访问MySQL必备文件
  7. iOS全局变量与属性的内存管理
  8. linux中常用的头文件
  9. 根本不存在 DIV + CSS 布局这回事
  10. Linux 命令简单介绍第一课笔记