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是具有重新声明的特性,所以这种操作有可能会无意中覆盖一个已经存在的全局变量。
- html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width,initial-scale=1.0">
- <title>Titletitle>
- head>
-
- <body>
- <script type="text/javascript">
- var creditCardNo = '123456789';
- debugger
- console.log(window.creditCardNo);
- script>
- body>
-
- html>
鉴于以上情况,如果我们在全局作用域中使用let 或 const ,则会在全局作用域下创建一个新的绑定,但是该绑定不会成为window对象的属性,通过这种方式,是可以解决覆盖window对象属性的问题。