作用域
什么是作用域 作用域就是可访问变量的集合。作用域分为全局作用域,函数作用域,es6新增了块级作用域。
什么是词法作用域 函数作用域在函数声明时就已经确定
什么是作用域链 当一个块或函数写在另一个块或函数内的时候,就发生了作用域的嵌套,在当前作用域找不到变量时就会去外层作用域找,直到找到变量或到了全局作用域,就是作用域链
什么是执行上下文
作用域是对执行上下文通俗易懂的描述,就是变量赋值访问修改的环境。每个执行上下文都有一个关联对象,记录着这个上下文所有的变量和函数,全局上下文的关联对象就是window
什么是闭包 闭包就是能读取另一个函数内部变量的函数
什么是暂时性死区 let,const没有变量提升,声明前不能用。注意:let和const声明的变量不会成为window的属性
letconstvar区别 const声明必须初始化值
闭包题
- 注意var和let
for (var i = 0; i < 5; i++) {
console.log('a', i)
setTimeout(() => {
console.error(i)
}, 1000);
}
for (let i = 0; i < 5; i++) {
console.log('b', i)
setTimeout(() => {
console.error(i)
}, 1000);
}
function outside() {
var arr = [];
for (let i = 0; i < 3; i++) {
arr[i] = function inside() {
return i;
}
console.log("a", arr[i]());
}
return arr;
}
var outerArr = outside();
console.log("b", outerArr[0]());
console.log("b", outerArr[1]());
console.log("b", outerArr[2]());
var nAdd
function f1() {
var n=999;
nAdd=function(){n+=1}
function f2(){
console.error(n);
}
return f2;
}
var result=f1();
result();
nAdd();
result();
在这段代码中,result实际上就是闭包函数f2。函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被垃圾回收机制(garbage collection)回收。 nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。
- 每次return的都是新函数
function outerFun() {
var a=0;
function innerFun() {
a++;
console.error(a);
}
return innerFun;
}
var obj=outerFun();
obj();
obj();
var obj2=outerFun();
obj2();
obj2();
- 变量提升
function outerFun() {
// 没有var
a = 0;
console.error(a);
}
var a=4; // 变量提升
outerFun();
console.error(a);
当函数内部直接写 a = 0(没有 var/let/const)时: JavaScript 会沿着作用域链向上查找 a的声明。 找到全局的 var a = 4(已经提升到最上边),于是直接修改了全局变量 a(而非创建一个新的局部变量)。
function f(x) {
var g = function () { return x; }
return g;
}
var h = f(1);
console.error(h());
let i = 0
function increase(){
i++
console.log(`courrent counter is ${i}`)
return i
}
increase()
increase()
increase()
- 隐藏变量
function a() {
let i = 0
function b() {
i++
console.log(`courrent counter is ${i}`)
return i
}
return b
}
const increase = a()
increase()
increase()
increase()
function createCounter() {
let i = 0
return function() {
i++
return i
}
}
let increase1 = createCounter()
let increase2 = createCounter()
console.log(increase1())
console.log(increase1())
console.log(increase2())
console.log(increase2())
function createCounter() {
let count = 0;
function increase() {
count++;
}
let message = `Count is ${count}`;
function log() {
console.log(message, count);
}
return [increase, log];
}
const [increase, log] = createCounter();
increase();
increase();
increase();
log();
function fun(n, o) {
console.log(o)
return {
fun: function(m) {
return fun(m, n)
}
}
}
var a = fun(0); a.fun(1); a.fun(2); a.fun(3);
var b = fun(0).fun(1).fun(2).fun(3)
var c = fun(0).fun(1); c.fun(2); c.fun(3)