javascript的作用域以及闭包现象
词法作用域就是定义在词法阶段的作用域,换句话说,也就是js的作用域时在定义阶段决定的,和调用无关。
1.1 作用域沿着作用链向上查找
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
//引擎执行console.log();在bar()内找不到a,向上查找,foo()也找不到,继续向上查找,在window全局中查找,找到a;
function foo(){
var b = a*2;
function bar(c){
console.log(a,b,c) // 2 4 8
}
bar(b*2);
}
var a =2;
foo(2)
</script>
</html>
1.2 函数作用域,定义函数时,会创建自己的气泡(作用域),外部作用无法直接访问。
1.3 立即执行函数 IIFE(Immediately Invoked Function Expression)
IIFE函数一般在前加上;防止()和前面的函数结合。
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
var a = 100;
(function foo(){
var a =1;
console.log(a);
})()
console.log(a); //100
</script>
</html>
1.4块级作用域
javascipt没有块级作用域,块级定义的变量会污染上一级作用域
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
for(vart i=1; i<10; i++){}
console.log(i); //10
</script>
</html>
1.5 let语法
es6引入let语法可以解决js没有块级作用域问题,强行绑定所在作用域
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
for(let i=1; i<10; i++){}
console.log(i); //报错
</script>
</html>
let声明没有预解析,而且只能声明一次
let flag = 123;
let flag = 456; // 报错
console.log(flag);
console.log(num); //报错
let num = 123;
1.6 变量提升
先有蛋后有鸡(先声明后赋值)
var a =1;分成var a 和a =2; 两步,第一步,定义声明是在编译阶段进行的,第二步赋值声明会被留在原地等待执行阶段。
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
console.log(a);
var a =1;//undefined
//第一步 var a ;第二步 console.log(a); 第三步 a =2;
</script>
</html>
函数优先
函数和变量的声明都会被提升,函数优先于变量
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
foo(); //1
var foo;
function foo(){
console.log(1);
}
foo = function(){
console.log(2);
}
</script>
</html>
1.7 动态作用域
js没有动态作用域,只有词法作用域
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
function foo(){
console.log(a) // 2
// 如果有动态作用域,此处应该打印3
}
function bar(){
var a =3;
foo();
}
var a = 2;
bar();
</script>
</html>
小练习
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
var b = 6;
function test(){
console.log(b); //undefined
var b = 5;
function a(){
var b=1;
console.log('a>>'+ b); //1
function c(){
console.log('c>>'+b);// 1
}
c();
}
a();
}
test();
</script>
</html>
2、闭包
函数在当前词法作用域之外执行,即产生了闭包。
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
</body>
<script type="text/javascript">
function foo(){
var a = 2;
function bar(){
console.log(a)
}
return bar;
}
var baz = foo();
baz(); //2
</script>
</html>