Title: js没那么简单(2)--作用域链 · Issue #15 · wython/wython.github.io · GitHub
Open Graph Title: js没那么简单(2)--作用域链 · Issue #15 · wython/wython.github.io
X Title: js没那么简单(2)--作用域链 · Issue #15 · wython/wython.github.io
Description: 前言 作用域链是js的一个概念,和执行上下文相关。关于执行上下文的描述,在上一篇文章《js没那么简单(1)-- 执行上下文》已经说了。 讨论作用域链的意义在于: js的作用域关系和作用域链息息相关 作用域链是闭包的基础 作用域链对后面理解垃圾回收也有一定关系 静态vs动态 讨论作用域链之前,不妨先来搞几个头脑风暴。关于静态和动态,我们经常会听到,js是一门动态语言,我们也经常会听到,js是一门静态作用域语言,我们还经常听到,CMD是一种动态模块规范。于是乎,我们发现,静...
Open Graph Description: 前言 作用域链是js的一个概念,和执行上下文相关。关于执行上下文的描述,在上一篇文章《js没那么简单(1)-- 执行上下文》已经说了。 讨论作用域链的意义在于: js的作用域关系和作用域链息息相关 作用域链是闭包的基础 作用域链对后面理解垃圾回收也有一定关系 静态vs动态 讨论作用域链之前,不妨先来搞几个头脑风暴。关于静态和动态,我们经常会听到,js是一门动态语言,我们也经常会听到,js是一...
X Description: 前言 作用域链是js的一个概念,和执行上下文相关。关于执行上下文的描述,在上一篇文章《js没那么简单(1)-- 执行上下文》已经说了。 讨论作用域链的意义在于: js的作用域关系和作用域链息息相关 作用域链是闭包的基础 作用域链对后面理解垃圾回收也有一定关系 静态vs动态 讨论作用域链之前,不妨先来搞几个头脑风暴。关于静态和动态,我们经常会听到,js是一门动态语言,我们也经常会听到,js是一...
Opengraph URL: https://github.com/wython/wython.github.io/issues/15
X: @github
Domain: patch-diff.githubusercontent.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"js没那么简单(2)--作用域链","articleBody":"### 前言\r\n作用域链是js的一个概念,和**执行上下文**相关。关于执行上下文的描述,在上一篇文章[《js没那么简单(1)-- 执行上下文》](https://juejin.im/post/6854573217592541197)已经说了。\r\n\r\n讨论作用域链的意义在于:\r\n1. js的作用域关系和作用域链息息相关\r\n2. 作用域链是闭包的基础\r\n3. 作用域链对后面理解垃圾回收也有一定关系\r\n\r\n#### 静态vs动态\r\n讨论作用域链之前,不妨先来搞几个头脑风暴。关于静态和动态,我们经常会听到,js是一门动态语言,我们也经常会听到,js是一门静态作用域语言,我们还经常听到,CMD是一种动态模块规范。于是乎,我们发现,静态和动态,似乎,在不同语义下,对同个语言描述也是不同的。\r\n\r\n1. 我们之所以说js是动态编程语言,是基于js的变量定义描述的,意思是,js可以在运行时变量类型是允许改变的。噢,很好理解,因为js的var确实支持运行时不同类型的改变。如一下代码:\r\n```javascript\r\nvar a = 1\r\na = 'string'\r\n```\r\n\r\n这是可以的。\r\n\r\n2. 我们之所以说js是静态作用域,是因为我们发现js的作用域好像不是在运行时定义。仿佛是在我们写好代码就定义好了。如以下代码:\r\n\r\n``` javascript\r\nvar a = 2;\r\nfunction back() {\r\n\tconsole.log(a);\r\n}\r\n\r\nfunction next() {\r\n\tvar a = 3;\r\n back(); // 2 but not 3\r\n}\r\n\r\nnext()\r\n```\r\n确实是:有点闭包那味,但是却和闭包不同。\r\n\r\n3. 我们之所以说CMD是动态模块规范,是因为require导入的模块,竟然能运行时改变。如以下代码:\r\n```javascript\r\nlet moduleAorB = null;\r\n\r\nif () {\r\n\tmoduleAorB = require('a')\r\n} else {\r\n\tmoduleAorB = require('b')\r\n}\r\n```\r\n相反,举一反三,我们知道import必须在一开始导入,且不给更改,所以import是静态模块。\r\n\r\n这时候。我们渐渐懂了静态和动态的含义了,他讲的是在一开始就定义,或者在运行时才确定的一个边界。那这个和我们这次要聊的作用域链有关系吗?是有关系的,因为js是静态作用域。\r\n\r\n### 词法作用域\r\n词法作用域的意思是:指在词法阶段确定的作用域,叫词法作用域。通过前面文章描述。我们知道词法阶段是编译原理一开始解析代码的阶段,所以词法解析意味着代码写完就确定了作用域,所以我们说词法作用域就是静态作用域。\r\n\r\n所以我们前面的例子:\r\n```javascript\r\nvar a = 2;\r\nfunction back() {\r\n console.log(a);\r\n}\r\n\r\nfunction next() {\r\n var a = 3;\r\n back(); // 2 but not 3\r\n}\r\n\r\nnext()\r\n```\r\n\r\n结果之所以是2,而不是3 的原因。是因为back函数,在声明时就确定了其所在上级作用域是全局作用域。所以在执行时候,即使执行作用域是在next里面,依然先访问到自己作用域的上级作用域。这是因为他在词法阶段就确定了其上级作用域是全局作用域。\r\n\r\n这是词法作用域的基本特性。\r\n\r\n### 作用域链\r\n再一次提到作用域链,那这一次。我们直接认为,作用域链是执行上下文里面的一个变量[[scope]]。而我们前面提到,执行上下文是在词法阶段确定的结构。所以作用域链也是在词法阶段确定的关系。\r\n\r\n在v8源码中,scope链变量在词法解析被描述为如链表一般的结构,可以通过out_scope拿到该环境下的上一层作用域链。\r\n\r\n在简单情况下。我们可以将其抽象的看成是执行上下文中的一个变量[[scope]],scope可以通过outer拿到上一层的作用域链。\r\n\r\n那么假如一个声明在全局环境下的函数,其上下文环境应该如图所示:\r\n\r\n\r\n作用域链最大的意义在于,定义环境所能访问的上级环境。进而会有后续闭包的说法。\r\n\r\n```javascript\r\nvar a = 2;\r\nfunction back() {\r\n console.log(a);\r\n}\r\n\r\nfunction next() {\r\n var a = 3;\r\n back(); // 2 but not 3\r\n}\r\n\r\nnext()\r\n```\r\n对于上面这段代码执行时的上下文顺序跟作用域顺序是不一样的,在next运行后,back也进入执行上下文,他们的上下文关系是这样的:\r\n\r\n\r\n但是他们的作用域链关系是这样的:\r\n\r\n\r\n也就是说,两个函数的直接上级作用域都是全局上下文,原因是因为他们都是声明在全局环境中。假如你希望next函数访问到back函数的上下文,你应该在back函数中声明next函数。那这个时候next称做back的闭包。关于闭包的细节,不仅仅在于我们这里简单去在函数中声明另一个函数。更在于在垃圾回收中,如何让闭包不被回收,是更值得探讨的问题。\r\n\r\n另外,在浏览器控制台,可以通过打断点,看到当前所处点作用域链集合:\r\n\r\n\r\n关于作用链,我的认识就是这样。the end\r\n\r\n\r\n\r\n","author":{"url":"https://github.com/wython","@type":"Person","name":"wython"},"datePublished":"2020-08-20T02:29:53.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":0},"url":"https://github.com/15/wython.github.io/issues/15"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:7f4ba300-009a-2304-9459-ccfca89f80c5 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | D198:140E58:64ED778:82956D7:69756230 |
| html-safe-nonce | f58ae2c14906cce91d801a98621833f7eece4996c15d7fcbf095ea858952e276 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJEMTk4OjE0MEU1ODo2NEVENzc4OjgyOTU2RDc6Njk3NTYyMzAiLCJ2aXNpdG9yX2lkIjoiMTY1MjU5MzUwMDQ2NzA2MTI5NiIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | 5961c6528a8abbb3e36b4b22249f4a8bcf90e6210e457a2bca0b1930836a1ccc |
| hovercard-subject-tag | issue:682317190 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/wython/wython.github.io/15/issue_layout |
| twitter:image | https://opengraph.githubassets.com/7b1597af9f9a2bdbd715d0bf9ec480c7299e432ddd1ac5bc17eff72f621adfff/wython/wython.github.io/issues/15 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/7b1597af9f9a2bdbd715d0bf9ec480c7299e432ddd1ac5bc17eff72f621adfff/wython/wython.github.io/issues/15 |
| og:image:alt | 前言 作用域链是js的一个概念,和执行上下文相关。关于执行上下文的描述,在上一篇文章《js没那么简单(1)-- 执行上下文》已经说了。 讨论作用域链的意义在于: js的作用域关系和作用域链息息相关 作用域链是闭包的基础 作用域链对后面理解垃圾回收也有一定关系 静态vs动态 讨论作用域链之前,不妨先来搞几个头脑风暴。关于静态和动态,我们经常会听到,js是一门动态语言,我们也经常会听到,js是一... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | wython |
| hostname | github.com |
| expected-hostname | github.com |
| None | 4a4bf5f4e28041a9d2e5c107d7d20b78b4294ba261cab243b28167c16a623a1f |
| turbo-cache-control | no-preview |
| go-import | github.com/wython/wython.github.io git https://github.com/wython/wython.github.io.git |
| octolytics-dimension-user_id | 15258919 |
| octolytics-dimension-user_login | wython |
| octolytics-dimension-repository_id | 142893945 |
| octolytics-dimension-repository_nwo | wython/wython.github.io |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 142893945 |
| octolytics-dimension-repository_network_root_nwo | wython/wython.github.io |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 488b30e96dfd057fbbe44c6665ccbc030b729dde |
| ui-target | canary-2 |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width