Javascript 的作用域存在的两种情况
情况一:函数内部
function enterYourChoice(flag){
// var有变量提升的作用,相当于在此处写了一个 let choice;
if(flag){
var choice = "yes";
}
else {
console.log(choice); // undefined 并没有报错哦! 神奇不?
}
return null;
}
enterYourChoice(false);
console.log(choice)
运行结果如下:
else中的 choice没有报错的原因是因为, var变量具有变量提升的机制。
在 函数作用域和全局作用域 中 通过var声明的变量,无论在哪声明,都会被当成在当前作用域顶部声明的变量,这就是var变量大名鼎鼎的变量提升机制。
多个函数嵌套的作用域:
情况二:语句块中
{
let a =1;
}
console.log(a)
同理,a变量出了语句块,同样会报错 ReferenceError: a is not defined 。
{
let a =1;
}
a= 2;
console.log(a)
但是,奇怪的是,我没有定义它,又使用了它。并没有报错,因为这种未定义就使用的情况,对于JS来说它就又变成了一个全局变量。在这里如同我们写了一个window.a;
(吐槽:不得不说,JS是一个语法很Uglily的语言,丝毫不影响它的流行;就如同C# 是一门语法很优雅的语言,但是同样丝毫不影响它的日薄西山。)
一般情况下,window 对象的内置属性都拥有全局作用域,例如 window.name、window.location、window.top 等等。全局作用域有个弊端:如果我们写了很多行 JS 代码,变量定义都没有用函数包括,那么它们就全部都在全局作用域中。这样就会 污染全局命名空间, 容易引起命名冲突。
变量声明:
在同一作用域下,用var 声明的变量,是可以不断重新声明的,let 做不到,const 更做不到。let虽做不到重复声明,但可以做到重新赋值;const 作为常量,连重新赋值都做不到。
var a = 1;
var a ='a';
console.log('var 重新声明,重新赋值,都没有问题');
let b = 1;
let b =2;
console.log("let 重新声明,有问题");
let c = 1;
c =2;
console.log("重新赋值,没有有问题");
const d = 'd';
d=3;
console.log("作为常量,不赋值 或 重新赋值,绝对都有问题");
使用const 声明的对象,对象本身 不可修改,但是对象的属性和值是可以修改的。
const person = {
name:'zhangsan'
};
person.name='lili';
person.age=18;
delete person.age;
person = {};// TypeError: Assignment to constant variable. 类型错误:指派了一个常量。
全局块作用域的绑定:
在全局作用域中使用var声明的变量或对象,将成为浏览器环境中的window对象的属性,由于var是具有重新声明的特性,所以这种操作有可能会无意中覆盖一个已经存在的全局变量。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Title</title>
</head>
<body>
<script type="text/javascript">
var creditCardNo = '123456789';
debugger
console.log(window.creditCardNo);
</script>
</body>
</html>
鉴于以上情况,如果我们在全局作用域中使用let 或 const ,则会在全局作用域下创建一个新的绑定,但是该绑定不会成为window对象的属性,通过这种方式,是可以解决覆盖window对象属性的问题。