作用域
作用域: 可访问变量的的集合
作用域最大的用处就是隔离变量,不同的作用域下同名变量不会有冲突
作用域类型
全局作用域、函数作用域、ES6中新增了块级作用域
函数作用域
是指声明在函数内部的变量,函数作用域在函数定义的时候就决定了
块级作用域
- 块级作用域由 { }包括,if语句和for语句里面的{ }也属于块作用域
- let和const具有块级作用域
- 块级作用域可以嵌套,内层作用域可以访问外层作用域,但外层作用域不能访问内层作用域
- 块级作用域允许在块级作用域内声明函数
- 块级作用域对函数声明的作用域的限制,函数声明只能在顶层作用域和函数作用域中声明
var let const 的区别
- var 定义的变量,没有块的概念,可以跨块访问,可以变量提升
- let 定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问,无变量提升,不可重复声明
- const 用来定义常量,使用时必须初始化(即必须赋值),只能在块级作用域里访问,而且不能修改,无变量提升,不可重复声明
- es5实现let
(function(){
var c =3
console.log(c) //1
})()
console.log(c) //c is not defined
- ES5实现const
我们必须先了解JavaScript中对象的数据属性和访问器属性。
数据属性
定义在对象内部的数据有四个特征:
configurable:是否可以被 delete 删除或者改变特征值
enumerable:是否能通过 for-in 循环遍历返回属性
writable:是否可以修改属性的值
value:保存这个属性的数据值
访问器属性
指以下四个属性:
configurable:能否通过 delete 删除,能否修改属性特性
enumerable:能否通过 for-in 循环返回属性
getter:读取属性时调用的函数,默认为 undefined
setter:写入属性时调用的函数,默认为 undefined
function _const(key, value) {
window[key] = value;
Object.defineProperty(window, key, {
enumerable: false,
configurable: false,
get: function () {
return value;
},
set: function (newValue) {
if (newValue !== value) {
throw TypeError("这是只读变量,不可修改");
} else {
return value;
}
},
});
}
作用域链
当查找变量的时候,首先会从当前上下文的变量对象(作用域)中查找,如果没有找到,就会从父级的执行上下文的变量对象中查找,如果还没找到,一直找到全局上下文的变量对象,也就是全局对象。这样由多个执行上下文的变量对象构成的链表就叫做作用域链