一、创建变量的7种方式:
1、var
2、function 创建变量(函数名是一个变量
3、let
4、const 创建常量
5、import 基于es6 的模块规范导出需要的信息
6、class 基于 es6 创建的类
7、Symbol 创建唯一值
二、var与let有什么区别
1、let不允许在相同的作用域下重复声明,而var允许;
2、let会产生块级作用域,var不会。
3、var有变量提升,而let没有;
4、let没有暂时性死区问题;
5、let创建的全局变量没有给window设置对应的属性;
变量提升机制
当浏览器开辟出供代码执行的栈内存后,代码并没有自上而下立即执行,而是继续做了一些事情:把当前作用域中所有带var/function关键字的进行提前的声明和定义。
b() // call b
console.log(a) // undefined
var a = 'Hello world'
function b() {console.log( 'call b')
}
以上输出是因为函数和变量提升的原因 。通常提升的解释是说将声明的代码移动到了顶部, 这其实没有什么错误,便于大 家理解 。但是更准确的解释应该是:在生成执行环境时,会有两个阶段 。第⼀个阶段是创建的阶段, JS 解释器会找出需要提升的变量和函数, 并且给他们 提前在内存中开辟好空间, 函数的话会将整个函数存⼊内存中, 变量只声明并且赋值为 undefined ,所以在第⼆个阶段,也就是代码执行阶段, 我们可以 直接提前使用。
b( ) // call b second
function b() {console.log( 'call b fist')
}
function b() {console.log( 'call b second')
}
var b = 'Hello world'
var 会产生很多错误,所以在 ES6中引⼊了 let 。 let 不能在声明前使用,但是这并不是常说的 let 不会提升, let 提升了,在第⼀阶段内存也已经为他开辟好了空间(但是只声明并未赋值初始化),但是因为这个声明的特性导致了并不能在声明前使用。
关于变量提升的演示题
示例1:下面代码能否实现点击某个按钮,body的背景色改为按钮对应的颜色,若不能,如何改进
<body>
<button class="red">红</button>
<button class="green">绿</button>
<button class="blue">蓝</button>
</body>
<script>var body = document.querySelector('body')var buttons = document.querySelector('button')var arr = ['red','green','blue']for(var i = 0; i<buttons.length;i++){buttons[i].onclick = function (){body.style.background = arr[i]}}
</script>
答案当然是不能,因为通过var定义的变量,在for循环中的i是全局的,变量提升、3次循环过后,i=3,因为点击每个都相当于点击最后一个,要实现就需要将var变成let。
示例2:
var a = 1;
function test() {console.log(a);if(false) {var a = 2;}
}
test();
Javascript分为预处理阶段和执行阶段,尽管if里面的语句不会被执行,但是在预处理阶段还是会将其提升,因此最终还是undefined。
函数会先去找自己内部的变量,内部有就不会往外面找,内部没有才去外面找