Appearance
ES6中的块级上下文
除函数和对象的花括号外,如:判断体 / 循环体 / 代码块... 中出现了 let / const / function / class 关键字声明变量,则当前花括号会产生一个块级私有上下文, var 不产生块级上下,也不受块级上下文影响,可以理解为执行 到那行代码时无视 var 声明,因为已经被提升了。
块级上下文中
初始化作用域链,<自己的上下文,上级上下文>,在哪个上下文下执行创建的块级上下文,上级 上下文就是谁
变量提升 函数在块级上下文中的特殊性(ES6 和 ES5 的区别) ES5:没有块级上下文,所以在除函数和对象以外的花括号中出现 function,变量提升阶段 声明 + 定义 ES6:为了兼容 ES5,出现在除函数和对象以外的花括号中的 function,在外层上下文(注意是外层上下文,不是全局上下文)变量提升 阶段只声明,不定义。由于出现了 function,会产生块级上下文,并且进入块级上下文的第一件 事是变量提升,即声明 + 定义,并且上级上下文中也会同步进行定义, 之后块级上下文对该 function 的所有操作都只影响块级上下文。
代码执行
js
// example1
console.log(a, b, c)
{
console.log(a, b, c)
let a = 12
const b = 13
var c = 14
console.log(a, b, c)
}
console.log(a, b, c)
// example2
console.log(foo)
{
console.log(foo)
function foo () {} // 两边同步
foo = 1
console.log(foo)
}
console.log(foo)
// example10
console.log(fn)
fn()
if ('fn' in window) {
fn()
// 下行代码之前对fn做的事情有fn声明+定义,这些两边都会同步
function fn () {
console.log('fn')
}
// 之后做的事只会影响私有
fn = 2
console.log(fn)
}
fn()
// example10
console.log(fn)
if ('fn' in window) {
fn()
// 下行代码之前对fn做的事情有fn声明+定义,这些两边都会同步
function fn () {
console.log('fn')
}
// 之后做的事只会影响私有
fn = 2
console.log(fn)
}
fn()
// example11
f = function () { return true }
g = function () { return false}
~(function () {
// if (g() && [] == ![]) { // g is not a function
if (true) {
f = function () { return false }
// 这行代码之前对g的操作,同步到上级上下文中(EC(FN))
function g () { return true }
}
console.log(g())
})()
console.log(f())
console.log(g())
// if 条件里的 g 会在外层上下文,即 IIFE 中进行变量提升但不定义,执行到 if 条件时,
// 立马进行声明+定义,同时上级上下文,即 IIFE 中同步定义,之后对于 if 条件内 g 函数
// 的修改,外层上下文不会再进行同步,整个过程中对于全局对象上的 g 函数,没有造成任何影响
// example
a = 10
{
a = 20
function a () {
}
a = 30
console.log(a)
}
console.log(a)
// example
var a = 10
{
a = 20
function a () {
}
a = 30
console.log(a)
}
console.log(a)
// example
let a = 10
{
a = 20
function a () {
}
a = 30
console.log(a)
}
console.log(a)