执行上下文与作用域

每个上下文都有一个关联的变量对象,而这个上下文中定义的所有变量和函数都存在于这个对象中。
全局上下文是最外层的上下文,在游览器中,全局上下文就是window对象,所有var定义的全局变量和函数都会成为window对象的属性和方法。使用let和const的顶级声明不会定义在全局上下文中,但在作用域解析上效果是一样的。

    var a = 1;
    console.log(window.a); // 1
    let b = 12;
    console.log(window.b); // undefined
    const c = 13;
    console.log(window.c); // undefined

每个函数调用都有自己的上下文,代码执行流进入函数的时候会把函数的上下文推到一个上下文栈;执行完毕后,上下文栈回弹出该函数上下文,将控制权返还给执行的执行上下文。上下文在其所有的代码都执行完毕后会被销毁,比如关闭网页,函数执行。如果通过作用域链没找到某个标识符,则通常会报错。

    var color = "red";
    function test1() {
      let color1 = "green";
      function test2() {
        let color2 = "orange";
        console.log(color2, color1, color); // orange green red,可以访问test2局部上下文,test1局部上下文和全局上下文
      }
      test2();
      console.log(color1, color); // 可以访问test1局部上下文和全局上下文
    }
    test1();
    console.log(color); // // 可以访问全局上下文

作用域增强
某些语句能在作用域最前端临时添加一个上下文,这个上下文在代码执行后会被删除。

  • try/catch语句
  • with语句

对with语句来说,会向作用域链前端添加指定的对象。
对catch语句来说,则会创建一个新的变量对象,这个变量对象会包含要抛出的错误对象的声明。

function buildUrl() { 
 let qs = "?debug=true"; 
 with(location){ // 将 location 对象作为上下文
 let url = href + qs; // 这里的href相当于location.href,qs无法在location上下文找到,则会通过作用域链向上一层查找,然后找到了qs="?debug=true"
 } 
 return url; // 像这里使用 let 声明的变量 url,因为被限制在块级作用域,所以在 with 块之外没有定义
}

变量提升

  • 使用var的函数作用域声明

使用var声明变量时,变量会被自动添加到最接近的上下文。如果没有声明就被初始化,那么就会自动添加到全局上下文。
var声明会被拿到函数或全局作用域的顶部,位于作用域中所有代码之前,这种就做“提升”。

    function test() {
      var a = 1; // 使用var声明,会被添加到最近的上下文
      b = 2; // 没有使用var声明就被初始化会被添加到全局上下文
      console.log(a, b); // 1 2
    }
    test();
    console.log(b); // 2
    // console.log(a); // 报错,a is not defined 2
    /*
		此处相当于
		var c;
		console.log(c);
		c=3;
		console.log(c);
	*/
    console.log(c); // undefined
    var c = 3; // 变量提升了
    console.log(c); // 3

  • 使用let的块级作用域声明

作用域是块级的,由最近的一对包含花括号界定。
let和var的一个不同之处是在同一作用域内let不能声明2次,否则会抛错。
let 的行为非常适合在循环中声明迭代变量。使用 var 声明的迭代变量会泄漏到循环外部,这种情况应该避免。
严格来说let在运行时也会被提升,但是因为“暂时性死区”的关系,不能在声明之前使用let变量。

  • 使用const的常量声明

一经声明,在其生命周期的任何时候不能重新赋值新值。
也是具有块级作用域的。
但是对象来说引用的也是指向对象的指针,该引用值不可修改,但对象的键则不受限制如果想要整个对象都不能修改,可以使用Object.freeze(),这样给属性赋值时虽然不会报错,但也会静默失败。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈梵阿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值