JavaScript作用域
- 作用域:变量可作用的区域
- 全局作用域:在函数以外的区域
- 私有作用域:以函数为划分的区域
- 作用域链:函数会限制变量的作用域范围,而函数内是可以再嵌套函数的,函数的层层嵌套,就形成了一个作用域链。
- 当函数内使用某个变量的时候,会按照如下过程找到该变量:
- 先从自身所在作用域去查找,如果没有再从上级作用域当中去查找,直到找到全局作用域当中。
- 如果其中有找到,就不会再往上查找,直接使用。
- 如果都没有找到,那么就会报引用错误提示变量没有定义。
- 如果在函数内部声明的变量没有使用关键字就会被挂到 window 上。
- 变量提升:预解析、预编译
- var 只声明不定义
- function 既声明又定义
- 预编译:
- 生成 AO 对象;
- 把形参和变量声明的名作为 AO 对象的属性名,值统一;
- 实参值传到形参当中;
- 在函数体找函数声明,值赋予函数体;
- 全局预编译:
- 生成 Go 对象;
- 把形参和变量声明的名作为 AO 对象的属性名,值统一;
- 实参值传到形参当中;
- 在函数体找函数声明,值赋予函数体;
- return:下面的代码虽然不执行,但是变量会提升,下面的代码进行变量提升,return 后面的代码不进行变量提升
function fn(){ console.log(a); return function f1(){ } var a=3; } fn();
- 如果预编译进入 if 语句时 var 和 function(函数)都是只声明不提升
- 自执行函数在当前所在的作用域中不进行变量提升,自执行函数自己所形成的私有作用域照常进行
function f2(){ console.log("f2"); } // 自执行函数在此处不进行变量提升 (function (){ console.log(a);// undefined, 照常进行变量提升 var a=3; })();
- 判断一个对象有没有该属性用 in
"d" in window//判断window中有没有d
; - let 和 const 这两个是没有变量提升的都是声明一个变量
const 声明的变量指针是不能改的
const num = 300; num = 200;
会报错
- const 声明变量必须赋值否则会报错
const num//会报错,没有初始值
- 在全局上下文中,基于 var 声明的变量是直接放在 GO(window)中,而基于 let 声明的变量是放在 VO(G)中 的,和 GO 没关系
- var 存在的变量提升,let 不存在变量提升
- var 允许重复声明,而 let 是不允许的[而且在词法分析阶段就过不去]
- let 会产生块级上下文,var 不会
- 关于暂时性死区问题:typeof 检测一个未声明的变量,不会报错,结果是 undefined 在 let 声明前使用就会报错
但是在加入了块级作用域的时候 let 和 const 之后,在其被声明之前对块中的 let 和 const 进行 typeof 操作会报错
-
- ECStack:execution context stack 执行环境栈
- heap:堆
- VO(G):variable object stack 执行环境栈
- GO:Global object 全局对象
- AO:Activation Object 执行上下文
-
console.log(a, b);//undefined undefined var a = 12, b = 12; function fn() { // undefined 12 console.log(a, b); var a = b = 13; console.log(a, b); // 13 13 } fn(); console.log(a, b); // 12 13
18. 电脑显卡挂壁了,准备去修电脑,新电脑坑爹
闭包
-
全局栈内存页面关闭是会被释放,普通函数一般调用结束会被释放
-
闭包让你可以在一个内层函数中访问到其外层函数的作用域
-
闭包什么时候产生?
- 函数嵌套函数
- 被嵌套的函数内部引用了外部函数的形参或者变量
- 外部函数被调用
- 优点:
- 延长了局部变量的生命周期
- 可以通过闭包实现一些高级一点的功能
-
用 setTimeout 实现 setInterval
function fn(){
console.log(666);
setTimeout(()=>{
fn()
},1000)
}
fn();
- 同步先执行,完成之后再执行异步
- 上级作用域:就是看这个函数是在哪个作用域创建的
- 全局变量:全局作用域下的变量;私有变量:私有作用域下的变量(形参,私有作用域下声明的变量)
- 预编译:函数形成一个私有作用域,形参赋值–>变量提升–>代码从上到下执行
- let 和 const 在声明之前都是不能使用的,如果使用会进入暂时性死区
- let 不能重复声明,能识别块级作用域,有暂时性死区
- const 声明的是一个常量,其他等同于 let
- this 执行主体:谁让这个函数执行。
- 全局下的 this 是 window
- 事件绑定高中对应的函数的 this 是绑定的那个函数
- 箭头函数中没有 this 和 arguments,他是把这两个关键字当做普通变量去对待。
- 函数执行,里面的 this 是谁就看执行前边有没有点,点前面是谁 this 就是谁,没点就是 window
- 自执行函数中的 this 就是 window