块级上下文
当代浏览器既要支持ES5的语法,也要支持ES6的语法「块级上下文」,所以导致有些代码出现了“特殊的效果”。
- 函数,对象以外的大括号(循环,判断,和 { } )中出现了以 let/ const/ function/ class声明的方式,就是出现块级上下文。
- var 既不会产生块级上下文,也不会受块级上下文影响。
练习题1:
//此处打印foo undefined
{
//此处打印foo function foo() {}
function foo() {}
foo = 1;
//此处打印foo 1
}
console.log(foo); // function foo() {}
答案解析:
- foo = 1 ,只是把块级上文中foo 改成了1, 全局上下文中foo 依然是 fn()。
- 函数对象以外的代码块中,function 和 var声明的变量都要进行变量提升,但是function只声明不定义了。
练习题2:
{
function foo() { 1 }
foo = 1;
function foo() { 2 }
}
console.log(foo);
解析
console.log(foo); //=>undefined
{
/*
EC(BLOCK)
VO(BLOCK)
foo -> 0x001
-> 0x002
-> 1
作用域链:<EC(BLOCK),EC(G)>
变量提升:
function foo() { 1 }; 这两行代码即在全局声明过,也在私有块中声明过
function foo() { 2 };
*/
console.log(foo); //=>函数{2}
function foo() { 1 } //上面对foo的操作同步给全局一份、断开和全局的联系 全局foo=函数2
foo = 1; //把私有的foo改为1
function foo() { 2 } //上面对foo的操作同步给全局一份、断开和全局的联系 全局foo=1
console.log(foo); //=>1
}
console.log(foo); //=>1
形参赋值默认值问题
var x = 1;
function func(x,y=function{x=2}){
x = 3;
y();
console.log(x);
};
func(5);
console.log(x);
图形解析:
2.
var x = 1;
function func(x,y=function{x=2}){
var x = 3;// 此处多了一个var
y();
console.log(x);
};
func(5);
console.log(x);
图形解析:
错误更正:函数默认值堆0x001的[[scope]]:EC(FUNC),函数声明时所处的上下文,而不是自身。
- ** 不要轻易使用形参赋值默认值。
- 如果想使用默认值使用逻辑 “或”(
||
),比如
var x = 1;
function func(x,y){
var date = x || 0;
var yy = y || "";
};
- 第三题和第二题类似,多声明了一个变量y
var x = 1;
function func(x,y=function{x=2}){
var x = 3;
var y = function{x=4}
y();
console.log(x);
};
func(5);
console.log(x);
图形解析:
debuger执行到func(5)时的浏览器
运行到var y = function{x=4}
,块级上下文中的x值改为3
var y = function{x=4}
直接跳过,执行有y(),走到 console.log(x)
后,块级上下文中的x改为4。