JS作用域和作用域链

作用域和作用域链

作用域:

函数执行会形成一个私有作用域(栈内存),为代码执行提供一个环境

闭包

  • 形成一个私有作用域,使里面的私有变量不受外部影响
  • 函数执行,有一个地方可以把变量存储起来,以后想要使用的时候可以拿出来

全局变量

全局对象是最顶层的对象,在浏览器环境指的是window对象。在ES5中,全局对象的属性与全局变量是等价的。

私有变量

在私有作用域中,只有一下两种情况是私有变量

  • 声明过的变量(带VAR/FUNCTION)
  • 形参也是私有变量
    剩下的都不是自己私有变量,都需要基于作用域链的机制向上查找
var a = 12, b = 13, c = 14;
function fn(a){
    console.log(a, b, c);
    var b = c = a = 20;
    console.log(a, b, c);
}
fn(a);
console.log(a, b, c);

-> 12,undefined,14
-> 20,20,20
->12,13,20

fn(a)中: a(形参),b(VAR定义)为私有变量,a,b的改变不影响外部的a,b。c为外部变量,c改变会影响到全局下的c也改变

暂时性死区

基于LET创建变量,会把大部分{}当做一个私有作用域(类似函数的私有作用域),在这里也是重新检查语法规范,看一下是否是基于新语法创建的变量,如果是按照新语法规范来解析

var a = 12;
if(true){
    console.log(a);
    let a = 13;
}

-> Uncaught ReferenceError: a is not defined

使用LET创建变量,未执行到创建语句时,使用变量会报错。

在原有浏览器渲染机制下,基于typeof等逻辑运算符检测一个未被声明过的变量,不会报错,返回undefined

console.log(typeof a);

-> undefined

如果当前变量是基于ES6语法处理,在没有声明这个变量的时候,使用typeof检测会直接报错,不会是undefined,解决了原有的JS的死区问题

console.log(typeof a);
let a = 12;

-> ReferenceError: Cannot access 'a' before initialization,无法在初始化之前访问’a‘

作用域链查找

当前函数执行,形成一个私有作用域A,A的上级作用域是谁,和他在哪创建(定义)的有关系,在哪创建,他的上级作用域就是谁。

var num = 12;
function fn(){
    var num = 120;
    return function(){
        console.log(num);
    }
}
var f = fn();
f();

function(){
    var num = 1200;
    f():
}()

-> 120
-> 120

ARGUMENTS

arguments:参数集合
arguments.callee:函数本身
arguments.callee.caller:当前函数在哪执行,caller就是谁(记录的是他执行的宿主环境),在全局下执行CALLER的结果是null

posted @ 2020-09-09 10:54  lemon-Xu  阅读(253)  评论(0编辑  收藏  举报