快速通关作用域!

news/2024/10/30 15:21:40/

作用域

变量作用域

一个变量的作用域(scope)是程序源代码中定义这个变量的区域。全局变量拥有全局作用域,在 JavaScript 代码中的任何地方都是可以访问的。然而在函数内声明的变量只能在函数体内访问,它们是局部变量,作用域是局部性的。函数参数也是局部变量,它们只能在函数体内访问。

在函数体内,局部变量的优先级高于同名的全局变量。如果在函数内声明一个局部变量或者函数参数中带有的变量和全局变量重名,那么全局变量就会被局部变量所覆盖。

var scope = 'global'function checkscope() {var scope = 'local'return scope
}checkscope() // 'local'

函数作用域和声明提前

JavaScript 的函数作用域是指在函数内声明的所有变量在函数体内任何地方都是可以访问的,这意味着变量在声明之前就可以访问了。JavaScript 的这个特性被非正式的称为声明提前(hoisting),即 JavaScript 函数内声明的所有变量(不包含赋值)都被提升至函数体的顶部。声明提前这步操作是在 JS 引擎预编译时进行的,也就是在代码开始运行之前。

function test() {var i = 2if (true) {var j = 0for (var k = 0; k < 10; k++) {}console.log(k) // 10}console.log(j) // 0
}test()

以上代码,在不同位置定义了变量 i、j、k,但是它们都在同一个函数作用域内。由于声明提前的特性,这三个变量在函数体内任何地方都是可以访问的。

声明提前后相当于下图的效果:

function test() {var ivar kvar ji = 2if (true) {j = 0for (k = 0; k < 10; k++) {}console.log(k) // 10}console.log(j) // 0
}test()

作用域链

如果将一个局部变量看做是自定义实现的对象的属性的话,那么可以换个角度来解读变量作用域。每一段 JavaScript 代码(全局代码或函数)都有一个与之关联的作用域链(scope chain)。这个作用域链是一个对象或者链表,这组对象定义了这段代码作用域中的变量。在这里涉及到了链表的概念,本来也是打算留在数据结构算法再讲的,但是这里用到了就简单介绍一下什么是链表。

:::tip 超前知识
链表是有序的数据结构,链表中的每个部分称为节点。每个节点都包含两个属性,一个是 value 主要存放当前节点的数据,另外一个是 next 主要用来指向下一个节点。
:::

作用域链查找过程

var x = 10
var y = 10function a() {var y = 20function b() {var y = 30console.log(x)}b()
}a()

从上面的代码我们可以得出,全局对象 window 上存在 x 和 y 属性。当前存在三个作用域,一个是全局作用域,一个作用域 a、另外一个是作用域 b。

链表结构如下

链表代码如下

var window = {value: {x: 10,y: 10},next: null
}var a = {value: {y: 20},next: window
}var b = {value: {x: 30},next: a
}

当 JavaScript 需要查找变量 x 的值的时候(这个过程称为变量解析 variable resolution),它会从链表的第一个对象开始查找,如果这个对象有一个名为 x 的属性,则会直接使用这个属性的值,如果第一个对象中不存在名为 x 的属性,则会继续查找下一个对象(通过链表节点的 next),以此类推(链表的最后一个对象就是全局对象)。如果作用域链上没有任何一个对象含有 x 的属性,那么就会认为这段代码的作用域链上不存在 x,并最终抛出一个引用错误异常 Uncaught ReferenceError: x is not defined。

作用域链创建过程

当定义一个函数时,它实际上会保存一个作用域链(每个函数都有独立的作用域链)。

正常形式

var x = 10
var y = 10function a() {var x = 20
}

链表形式

var window = {value: {x: 10,y: 10},next: null
}var a = {value: null,next: window
}

例如上图,我们定义了函数 a,这个时候我们还没有进行调用。函数 a 的作用域链为:a -> window

正常形式

var x = 10
var y = 10function a() {var x = 20
}a()

链表形式

var window = {value: {x: 10,y: 10},next: null
}var a = {value: {x: 20},next: window
}

当调用这个函数时,它就会创建一个新执行上下文环境(对象)来存储它的局部变量,并将这个对象添加至刚才所保存的作用域链上。

原文链接:菜园前端


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

相关文章

你还在观望吗?Creator3D小鲜肉《小鸭快跑》新鲜出炉!

date: 2019-10-16 摘要 CocosCreator 的 3D 版本正式上线&#xff01; 激动干嘛? 愣着啊! KUOKUO 正好手里有个小鸭子模型&#xff0c;于是就把它做成了一个小游戏。 正文 风骚的走位 系统事件来监听触摸 cc.systemEvent.on(SystemEventType.TOUCH_START, (e: EventTouch) >…

Python简笔画——用Turtle库画一只《穿红靴子的小鸭》

《穿红靴子的小鸭》这幅画临摹了ins博主inky.diary的小鸭水彩画&#xff0c;并做了一些调整。 用Python的Turtle库画画&#xff0c;难度不大&#xff0c;熟悉了基础函数后&#xff0c;新手可以快速入门。基础函数可以参考博文《Python标准库之turtle库——基础函数详解》。在绘…

小鸭五笔 3.3 版

『小鸭五笔』是一款以五笔为主的中文输入法软件&#xff0c;并提供了拼音辅助输入功能。 1.支持Windows7 x86/x64 2.支持GB18030标准&#xff08;可输入GBK字符集21004字及CJK-A扩充区6582字&#xff1b;安装后另行下载支持超大字符集码表可输入CJK、CJK-A、CJK-B&#xff08;共…

【计算思维题】少儿编程 蓝桥杯青少组计算思维题真题及解析第1套

少儿编程 蓝桥杯青少组计算思维题真题及解析第1套 1、多多观察一个立体图形,从不同的角度看到的形状如下图所示: 这个立体图形可能是 答案:D 考点分析:考查小朋友们的观察能力和推理能力,从前面视角看ABCD都符合,从右面视角看可以排除ABC,只有答案D,从上面视角可以…

中国电子学会青少年编程能力等级测试图形化一级编程题:小鸡与鸭妈拥抱

「青少年编程竞赛交流群」已成立&#xff08;适合6至18周岁的青少年&#xff09;&#xff0c;公众号后台回复【Scratch】或【Python】&#xff0c;即可进入。如果加入了之前的社群不需要重复加入。 我们将有关编程题目的教学视频已经发布到抖音号21252972100&#xff0c;小马老…

用python画小鸭_python中的鸭子类型(协议)和接口

定义 1. 接口(interface) 学过静态语言的同学一定对接口的概念并不陌生&#xff0c;它类似于我们家里用的插座标准&#xff0c;要用电器时&#xff0c;我们得先查看对应的插头是否和插座孔匹配。也正因为此&#xff0c;接口给我们提供了很大的方便&#xff0c;比如&#xff0c;…

mysql小鸭子_可读代码编写炸鸡十一 - 小黄鸭从你的心里游到脑子里

可读代码编写炸鸡十一 - 小黄鸭从你的心里游到脑子里 多选参数推荐搜索 数据结构与算法 可读代码编写 Java Redis MySQL 大家好&#xff0c;我是多选参数的大炮。 可读代码编写的炸鸡很快要写到头了&#xff0c;从一开始的尝试到现在的倒计时&#xff0c;还是有一些成就感的。当…

小鸭

那是在我五岁的时候&#xff0c;那年我妈妈去了外地打工&#xff0c;就剩下爸爸在家靠骑黄包车来养活我。有一天&#xff0c;爸爸带着一只黄毛小鸭回来。他告诉我说是从一辆装运鸭子的大货车上掉下来的&#xff0c;他恰好经过&#xff0c;于是就把它带了回来。 爸爸还嘱咐我说&…