执行上下文: 当前代码被解析和执行的环境
全局执行上下文
只有一个,不在函数内的变量
函数执行上下文
调用函数时创建函数执行上下文
eval执行上下文
运行在eval函数中的代码
执行上下文的生命周期
创建阶段
创建变量,初始化arguments 提升函数声明和变量声明
创建作用域链
确定this的指向
执行阶段
变量赋值 执行代码
回收阶段
执行上下文出栈 ,回收变量
示例:
function foo() {
let name = "duoduo";
function getName() {
return name;
}
return getName
}
let func = foo();
let name = func();
console.log(name)
调用foo创建函数执行上下文,创建name变量 、声明getName函数 ,返回getName的引用
在执行完let func = foo()后 foo创建的执行上下文出栈 ,一般变量也会随之销毁(name),但getName引用了name变量,变量不会销毁 相当于封装了一个私有变量
如果私有变量使用不当,会造成内存泄漏
使用完后,对func=null;回收name变量
定时器打印输出
for (var i = 0; i < 5; i++){
setTimeout(() => {
console.log(i)
},i*1000)
}
输出 5 5 5 5 5
i是var声明的,是全局变量,不能生成块级作用域,每一次循环都会覆盖上一次i的值
使用函数创建作用域
for (var i = 0; i < 5; i++){
(function(i){
setTimeout(() => {
console.log(i)
},i*1000)
})(i)
}
立即执行函数生成函数作用域 保留上一次循环生成的变量i
函数作为参数
var a = 'duoduo'
function foo(){
var a = 'foo'
function fo(){
console.log(a)
}
return fo
}
function f(p){
var a = 'f'
p()
}
f(foo())//foo
a是全局变量,
- 调用f函数,
- 调用foo函数 foo: 创建a变量 ,声明函数fo,返回fo的引用
f: 创建a变量,执行p函数,即执行fo函数,因为fo函数引用了一个私有变量 a ='foo',输出foo,f执行上下文出栈
防抖
//多次点击,最后一次生效
function debounce(fn, delay) {
let timer = null;
return function() {
if (timer) clearTimeout(timer);
timer = setTimeout(() => { fn.apply(this, arg) },delay)
}
}
节流
//有效时间内,第一次触发的有效
function throttle(fn, delay) {
let canRun = true;
return function () {
if (!canRun) return;
canRun = false;
setTimeout(() => {
fn.apply(this,arguments)
},delay)
}
}
闭包作用:
- 保护函数的私有变量不受外部的干扰。形成不销毁的栈内存。
- 保存,把一些函数内的值保存下来。闭包可以实现方法和属性的私有化