《每天十分钟》-红宝书第4版-执行上下文与作用域

news/2024/11/13 4:22:13/

先阅读一段晦涩难懂的文字

执行上下文(以下简称“上下文”)的概念在 JavaScript 中是颇为重要的。变量或函数的上下文决定 了它们可以访问哪些数据,以及它们的行为。每个上下文都有一个关联的变量对象(variable object), 而这个上下文中定义的所有变量和函数都存在于这个对象上。虽然无法通过代码访问变量对象,但后台 处理数据会用到它。 全局上下文是最外层的上下文。根据 ECMAScript 实现的宿主环境,表示全局上下文的对象可能不一 样。在浏览器中,全局上下文就是我们常说的 window 对象(第 12 章会详细介绍),因此所有通过 var 定 义的全局变量和函数都会成为 window 对象的属性和方法。使用 let 和 const 的顶级声明不会定义在全局上下文中,但在作用域链解析上效果是一样的。上下文在其所有代码都执行完毕后会被销毁,包括定义在它上面的所有变量和函数(全局上下文在应用程序退出前才会被销毁,比如关闭网页或退出浏览器)。

上下文中的代码在执行的时候,会创建变量对象的一个作用域链(scope chain)。这个作用域链决定 了各级上下文中的代码在访问变量和函数时的顺序。代码正在执行的上下文的变量对象始终位于作用域 链的最前端。如果上下文是函数,则其活动对象(activation object)用作变量对象。活动对象最初只有 一个定义变量:arguments。(全局上下文中没有这个变量。)作用域链中的下一个变量对象来自包含上 下文,再下一个对象来自再下一个包含上下文。以此类推直至全局上下文;全局上下文的变量对象始终 是作用域链的最后一个变量对象。

再看示例

var color = "blue"; 
function changeColor() { if (color === "blue") { color = "red"; } else { color = "blue"; } 
} 
changeColor();

对这个例子而言,函数 changeColor()的作用域链包含两个对象:一个是它自己的变量对象(就
是定义 arguments 对象的那个),另一个是全局上下文的变量对象。这个函数内部之所以能够访问变量
color,就是因为可以在作用域链中找到它。

作用域链增强

function buildUrl() { let qs = "?debug=true"; with(location){ let url = href + qs; } return url; 
}

这里,with 语句将 location 对象作为上下文,因此 location 会被添加到作用域链前端。
buildUrl()函数中定义了一个变量 qs。当 with 语句中的代码引用变量 href 时,实际上引用的是
location.href,也就是自己变量对象的属性。在引用 qs 时,引用的则是定义在 buildUrl()中的那
个变量,它定义在函数上下文的变量对象上。而在 with 语句中使用 var 声明的变量 url 会成为函数
上下文的一部分,可以作为函数的值被返回;但像这里使用 let 声明的变量 url,因为被限制在块级作
用域(稍后介绍),所以在 with 块之外没有定义。

变量声明

  1. 使用 var 的函数作用域声明
    在使用 var 声明变量时,变量会被自动添加到最接近的上下文。在函数中,最接近的上下文就是函
    数的局部上下文。在 with 语句中,最接近的上下文也是函数上下文。

提一个面试常问的问题

var 声明会被拿到函数或全局作用域的顶部,位于作用域中所有代码之前。这个现象叫作“提升”
(hoisting)
。提升让同一作用域中的代码不必考虑变量是否已经声明就可以直接使用。可是在实践中,提升也会导致合法却奇怪的现象,即在变量声明之前使用变量。

通过在声明之前打印变量,可以验证变量会被提升。声明的提升意味着会输出 undefined 而不是
Reference Error:
console.log(name); // undefined 
var name = 'Jake'; 
function temp() { console.log(name); // undefined var name = 'Jake'; 
}
  1. 使用 let 的块级作用域声明
if (true) { let a; 
} 
console.log(a); // ReferenceError: a 没有定义
while (true) { let b; 
}
console.log(b); // ReferenceError: b 没有定义
function foo() { let c; 
} 
console.log(c); // ReferenceError: c 没有定义// 这没什么可奇怪的// var 声明也会导致报错
// 这不是对象字面量,而是一个独立的块
// JavaScript 解释器会根据其中内容识别出它来
{ let d; 
} 
console.log(d); // ReferenceError: d 没有定义
var a; 
var a; 
// 不会报错
{ let b; let b; 
} 
// SyntaxError: 标识符 b 已经声明过了
for (var i = 0; i < 10; ++i) {} 
console.log(i); // 10 
for (let j = 0; j < 10; ++j) {} 
console.log(j); // ReferenceError: j 没有定义
  1. 使用 const 的常量声明
    除了 let,ES6 同时还增加了 const 关键字。使用 const 声明的变量必须同时初始化为某个值。
    一经声明,在其生命周期的任何时候都不能再重新赋予新值。
const a; // SyntaxError: 常量声明时没有初始化
const b = 3; 
console.log(b); // 3 
b = 4; // TypeError: 给常量赋值

const 声明只应用到顶级原语或者对象。换句话说,赋值为对象的 const 变量不能再被重新赋值
为其他引用值,但对象的键则不受限制。

const o1 = {}; 
o1 = {}; // TypeError: 给常量赋值
const o2 = {}; 
o2.name = 'Jake'; 
console.log(o2.name); // 'Jake'

如果想让整个对象都不能修改,可以使用 Object.freeze(),这样再给属性赋值时虽然不会报错,
但会静默失败:

const o3 = Object.freeze({}); 
o3.name = 'Jake'; 
console.log(o3.name); // undefined
  1. 标识符查找
var color = 'blue'; 
function getColor() { return color; 
} 
console.log(getColor()); // 'blue'

2023年最后一天晚上(12.31) 先抄写到这,过去一年因为很多事耽误了不少,中断抄经时常有,希望新的一年顺利!

从今诸事愿、胜如旧。人生强健,喜一年入手。 休辞最后、饮酴酥酒。


http://www.ppmy.cn/news/1287113.html

相关文章

编程笔记 html5cssjs 011 HTML页面划分

编程笔记 html5&css&js 011 HTML页面划分 HTML的框架、区块和布局是什么&#xff0c;它们之前的关系是怎样的&#xff1f;框架注意 接下来要看一下网页内的划分。通过框架、区块及布局等方式&#xff0c;将网页从一个长方形整体划分为若干个部分&#xff0c;以合理展示…

【elk-day01】es和kibana搭建及验证---Mac-Docker

Mac系统使用Docker下载搭建和验证eskibana Docker下载安装es安装es验证kibana安装kibana验证 Docker下载安装 Docker Desktop官网安装下载地址 说明一下为什么要安装desktop版本的docker&#xff0c;因为docker作为工具使用&#xff0c;我们需要的是开箱即用&#xff0c;没有必…

WPF 消息日志打印帮助类:HandyControl+NLog+彩色控制台打印+全局异常捕捉

文章目录 前言相关文章Nlog配置HandyControl配置简单使用显示效果文本内容 全局异常捕捉异常代码运行结果 前言 我将简单的HandyControl的消息打印系统和Nlog搭配使用&#xff0c;简化我们的代码书写 相关文章 .NET 控制台NLog 使用 WPF-UI HandyControl 控件简单实战 C#更改…

用linux中定时任务Crontab,向企业微信群通过机器人发送消息

1.使用yum命令安装Crontab&#xff1a;这个很关键&#xff0c;没有安装的话会提示命令not found yum install vixie-cron yum install crontabs 注&#xff1a;vixie-cron软件包是cron的主程序&#xff1b; crontabs软件包是用来安装、卸装、或列举用来驱动 cron 守护进程的表…

企业招商与迅腾文化:精准触达消费者的奥秘

企业招商与迅腾文化&#xff1a;精准触达消费者的奥秘 在当今的商业环境中&#xff0c;企业招商的成功与否往往取决于品牌与消费者之间的有效沟通。如何根据市场变化和企业战略部署通过迅腾文化助力一步步精确触达目标受众&#xff0c;传递品牌的核心价值和独特卖点&#xff0…

Java版商城:Spring Cloud+SpringBoot b2b2c电子商务平台,多商家入驻、直播带货及免 费 小程序商城搭建

随着互联网的快速发展&#xff0c;越来越多的企业开始注重数字化转型&#xff0c;以提升自身的竞争力和运营效率。在这个背景下&#xff0c;鸿鹄云商SAAS云产品应运而生&#xff0c;为企业提供了一种简单、高效、安全的数字化解决方案。 鸿鹄云商SAAS云产品是一种基于云计算的软…

postman使用-03发送请求

文章目录 请求1.新建请求2.选择请求方式3.填写请求URL4.填写请求参数get请求参数在params中填写&#xff08;填完后在url中会自动显示&#xff09;post请求参数在body中填写&#xff0c;根据接口文档请求头里面的content-type选择body中的数据类型post请求参数为json-选择raw-选…

vscode调试 反汇编c/c++ 查看汇编代码gdb/lldb

先看下流程&#xff01; 先看下流程&#xff01; 有问题请留言&#xff01; 文章目录 必备F5开启调试左侧侧边栏->确保打开回调栈右键函数栈->查看反汇编 方法二&#xff1a;手动输入命令查看 必备 使用c/c 插件&#xff0c;这应该是必备的。 F5开启调试 左侧侧边栏-&…