当前位置:网站首页>什么,你告诉我?作用域也分种类?
什么,你告诉我?作用域也分种类?
2022-08-04 14:31:00 【默海笑】
思维导图

作用域分类
静态作用域(核心:写在哪儿)
不同的编程语言采用的作用域种类也不同。js使用的是静态作用域也就是词法作用域。另外一种叫作动态作用域,仍有一些编程语言在使用(比如 Bash 脚本、Perl 中的一些模式等)。
动态作用域(核心:在哪执行)
动态作用域在运行时被动态确定的,而不是在写代码时进行静态确定的形式。
function foo() {
console.log(a); // 静态:2 动态:3
}
function bar() {
var a = 3;
foo();
}
var a = 2;
bar();
静态作用域中:foo函数就会找定义foo函数的作用域,去找到a = 2。
动态作用域中:foo函数就会找执行foo函数的作用域,去找到a = 3。
词法阶段
词法作用域的定义
词法作用域就是定义在词法阶段的作用域。就是源代码写在哪个位置来决定的,一旦写下就作用域就确定了(除了欺骗词法)。
作用域气泡
类似套娃的玩具,这里借用《你不知道的js》的图。

包含着整个全局作用域,其中只有一个标识符:foo。 包含着 foo 所创建的作用域,其中有三个标识符:a、bar 和 b。 包含着 bar 所创建的作用域,其中只有一个标识符:c。
查找
遮蔽效应
也就是就近原则,在最内侧的作用域里就能找到变量,就不会去找外侧作用域的同名变量,换句话就是,内侧作用域变量会覆盖外侧作用域同名变量。
全局变量
全局变量会自动成为全局对象(比如浏览器中的 window 对象)的属性,因此可以不直接通过全局对象的词法名称,而是间接地通过对全局对象属性的引用来对其进行访问
var num = 0
function foo() {
var num = 1;
console.log(num); // 1
function fxx() {
let num = 2;
console.log(num); // 2
console.log(window.num); // 0
}
fxx();
}
foo();
一级表示符
词法作用域查找只会查找一级标识符,比如 a、b 和 c。如果代码中引用了 foo.bar.baz, 词法作用域查找只会试图查找 foo 标识符,找到这个变量后,对象属性访问规则会分别接 管对 bar 和 baz 属性的访问。
欺骗词法
欺骗词法作用域的方法会在词法分析器处理过后依然可以修改作用域
eval
修改作用域
书写一段字符串作为eval函数的参数,就可以当做在最初就写在源代码位置了的“钉子户”。也就是以动态插入代码块到源代码的任意位置,达到修改早已决定了的作用域。
function foo(str, a) {
eval(str); // 欺骗!
console.log(a, b);
}
var b = 2;
foo("var b = 3;", 1); // 1, 3
引擎会认为最初我们书写的代码是这样的
function foo(a) {
var b = 3;
console.log(a, b);
}
var b = 2;
foo(1); // 1, 3
无论何种情况,eval(..) 都可以在运行期修改书写期的词法作用域。
严格模式
注意: 在严格模式的程序中,eval(..) 在运行时有其自己的词法作用域,意味着其 中的声明无法修改所在的作用域。
function foo(str) {
"use strict";
eval(str);
console.log(a); // ReferenceError: a is not defined
}
foo("var a = 2");
setTimeout,setInterval,new Function
setTimeout(..) 和 setInterval(..) 的第一个参数可以是字符串,字符串的内容可以被解释为一段动态生成的 函数代码。这些功能已经过时且并不被提倡。不要使用它们!(《你不知道的js》)
new Function(..) 函数的行为也很类似,最后一个参数可以接受代码字符串,并将其转 化为动态生成的函数
with
创建新的作用域
with 通常被当作重复引用同一个对象中的多个属性的快捷方式,可以不需要重复引用对象本身。
function foo(obj) {
with (obj) {
a = 2;
}
}
var o1 = {
a: 3,
};
var o2 = {
b: 3,
};
foo(o1);
console.log(o1.a); // 2
foo(o2);
console.log(o2.a); // undefined
console.log(a); // 2——不好,a 被泄漏到全局作用域上了!
with 块可以将一个对象处理为词法作用域,但是这个块内部正常的 var 声明并不会被限制在这个块的作用域中,而是被添加到 with 所处的函数作用域中。
注意: 严格模式下with是禁用的。
性能
修改作用域会造成:
1、 编译时的优化会失效
2、对标识符位置判断失败
小结:
欺骗词法作用域的方法会在词法分析器处理过后依然可以修改作用域。但是js就是在编译时js引擎进行优化,一旦改变了作用域那么这些优化大多也毁于一旦。
参考
《你不知道的js(上卷)》
边栏推荐
- 杭电校赛(逆袭指数)
- MySQL【触发器】
- 宣传海报
- G.登山小分队(暴力&dfs)
- idea removes spark logs
- Bluetooth Technology|In the first half of the year, 1.3 million charging piles were added nationwide, and Bluetooth charging piles will become the mainstream of the market
- How to fall in love with a programmer
- NPDP|作为产品经理,如何快速提升自身业务素养?
- 快解析结合千方百剂
- 实际工作中的高级技术(训练加速、推理加速、深度学习自适应、对抗神经网络)
猜你喜欢
随机推荐
1403. Minimum Subsequence in Non-Increasing Order
【剑指offer59】队列的最大值
广告电商系统开发功能只订单处理
郑轻新生校赛和中工选拔赛题解
技术分享| 融合调度系统中的电子围栏功能说明
Bluetooth Technology|In the first half of the year, 1.3 million charging piles were added nationwide, and Bluetooth charging piles will become the mainstream of the market
word2003按空格键为什么会出现小数点
idea removes spark logs
数据库恢复
四平方和,激光炸弹
利用决策树找出最优特征组合
Set partition minimum difference problem (01 knapsack)
Centos7 install mysql version rapidly
兆骑科创创新创业大赛活动举办,线上直播路演,投融资对接
[in-depth study of 4 g / 5 g / 6 g project - 50] : URLLC - 16 - the 3 GPP URLLC agreement, specification, technical principle of depth interpretation - 10 - high reliability technology - 1 - low codin
leetcode: 212. Word Search II
【HMS core】【Media】【视频编辑服务】 在线素材无法展示,一直Loading状态或是网络异常
7 天能找到 Go 工作吗?学学 Go 数组和指针试试
Go 语言快速入门指南: 变量和常量
Technology sharing | Mini program realizes audio and video calls









