1.var申明
- 如果变量未经申明就被初始化了,那么他就会自动被添加到全局上下文。
function add(num1, num2){
var sum = num1 + num2;
return sum;
}
let result = add(10,30);
console.log(sum);//报错,sum在这里不是有效变量
function add(num1, num2){
sum = num1 + num2;//sum未经申明就直接初始化了,被自动添加到全局上下文
return sum;
}
let result = add(10,30);
console.log(sum);//返回结果30
- var申明的变量会被拿到函数或全局作用域的顶部。
console.log(name);//输出undefined
var name = "Tom"
等价于:
var name;
console.log(name)//输出undefined
name = "Tom";
2.let申明
- var变量可以重复声明,let重复申明会报错。
var a;
var a;//不会报错
{
let b;
let b;//会报错
}
- 再循环中申明迭代变量应当用let,var会被泄露到循环外部。
for(var i = 0;i<10;i++){}
console.log(i)//10
for(var j = 0;j<10;j++){}
console.log(j)//ReferenceError:j没有定义
3.const申明
- const申明变量的同时必须先给他赋值。
const a;//SyntaxErrot:常量申明时没有初始化
- const与let一样,也在块级发挥作用。
- const申明的原始值不能够改动,const申明的引用值也不能够再被重新赋值为其他引用值,但可以改变其对象的属性。
const obj1 = {};
obj1.name="Tom";
console.log(obj1.name);//输出结果为Tom
- 如果想让const申明的对象不能修改,可以使用Object.freeze。这样再给其对象属性赋值的时候不会报错,但是会静默失败。
const obj = Object.freeze({});
obj.name = "Tom";
console.log(obj.name);//输出undefined
- 开发实践表明,如果开发流程并不会因此而受很大影响,就应该尽可能的多使用const申明,除非确实需要一个将来会重新赋值的变量。这样可以从根本上保证提前发现重新赋值导致的bug。
4.标识符查找
var color = "blue";
function getColor(){
let color = "red";
{
let color = "green";
return color;//返回的color为green
}
}
- 在执行到return语句的时候,引用了变量color。于是开始在局部上下文中搜索这个标识符,结果找到了值为green的color变量。因为变量已经找到了,所以搜索停止。否则向更上一级上下文继续搜索,直到全局上下文为止。
- 局部变量color神明之后,在这个块中的任何代码都无法访问到全局上下文的变量(上面例子中值为blue的color),除非使用window.color。