浏览器中的 JavaScript 执行机制
思维导图
本文为反复学习极客时间-《浏览器的工作原理与实践》-浏览器中的 JavaScript 执行机制章节中的一些思考与记录。
一些重要概念
变量提升
- 所谓的变量提升,是指在 JavaScript 代码执行过程中,JavaScript 引擎把变量的声明部分和函数的声明部分提升到代码开头的“行为”。
- 变量被提升后,会给变量设置默认值,这个默认值就是我们熟悉的 undefined。
- 从概念的字面意义上来看,“变量提升”意味着变量和函数的声明会在物理层面移动到代码的最前面,正如我们所模拟的那样。
- 但,这并不准确。实际上变量和函数声明在代码里的位置是不会改变的,而且是在编译阶段被 JavaScript 引擎放入内存中。
执行上下文
分类
- 全局执行上下文
- 函数执行上下文
- eval 执行上下文
调用栈
- 调用栈就是用来管理函数调用关系的一种数据结构
- 在执行上下文创建好后, JavaScript 引擎会将执行上下文压入栈中,通常把这种用来管理执行上下文的栈称为执行上下文栈,又称调用栈
作用域 Scope
- 定义:作用域是指在程序中定义变量的区域,该位置决定了变量的生命周期。
- 通俗地理解,作用域就是变量与函数的可访问范围,即作用域控制着变量和函数的可见性和生命周期。
分类-ES6 之前
- 全局作用域。全局作用域中的对象在代码中的任何地方都能访问,其生命周期伴随着页面的生命周期。
- 函数作用域。函数作用域就是在函数内部定义的变量或者函数,并且定义的变量或者函数只能在函数内部被访问。函数执行结束之后,函数内部定义的变量会被销毁。
ES6 新增
- 块级作用域:let/const
作用域链
- 在每个执行上下文的变量环境中,都包含了一个外部引用,用来指向外部的执行上下文,我们把这个外部引用称为outer。
- 当一段代码使用了一个变量时,JavaScript 引擎首先会在“当前的执行上下文”中查找该变量
- 如果在当前的变量环境中没有查找到,那么 JavaScript 引擎会继续在 outer 所指向的执行上下文中查找
- 把这个查找的链条就称为作用域链
- 在 JavaScript 执行过程中,其作用域链是由词法作用域决定的
词法作用域
- 指作用域是由代码中函数声明的位置来决定的
- 词法作用域是静态的作用域,通过它就能够预测代码在执行过程中如何查找标识符。
- 词法作用域是代码阶段就决定好的,和函数是怎么调用的没有关系
闭包
- 在 JavaScript 中,根据词法作用域的规则,内部函数总是可以访问其外部函数中声明的变量,当通过调用一个外部函数返回一个内部函数后,即使该外部函数已经执行结束了,但是内部函数引用外部函数的变量依然保存在内存中,我们就把这些变量的集合称为闭包。
- 比如外部函数是 foo,那么这些变量的集合就称为 foo 函数的闭包。
闭包是怎么回收的
- 如果引用闭包的函数是一个全局变量,那么闭包会一直存在直到页面关闭,但如果这个闭包以后不再使用的话,就会造成内存泄漏,
- 如果引用闭包的函数是个局部变量,等函数销毁后,在下次 JavaScript 引擎执行垃圾回收时,判断闭包这块内容如果已经不再被使用了,那么 JavaScript 引擎的垃圾回收器就会回收这块内存。
- 原则—如果该闭包会一直使用,那么它可以作为全局变量而存在;但如果使用频率不高,而且占用内存又比较大的话,那就尽量让它成为一个局部变量。
this
- 首先明确,作用域链和 this 是两套不同的系统,它们之间基本没太多联系
分类
1.全局执行上下文中的 this,指向 window 对象
2.函数执行上下文中的 this,
- 通过函数的 call/apply/bind 方法设置,this 指向 call/apply/bind 方法中的第一个参数
- 通过对象调用方法设置,this 指向对象本身
- 通过构造函数中设置,this 指向 new 的实例对象
3.eval 中的 this
this 的设计缺陷以及应对方案
1.嵌套函数中的 this 不会从外层函数中继承
- 在函数中声明一个变量 self 用来保存 this
- 使用 ES6 中的箭头函数,这是因为 ES6 中的箭头函数并不会创建其自身的执行上下文,所以箭头函数中的 this 取决于它的外部函数
2.普通函数中的 this 默认指向全局对象 window
- 如果要让函数执行上下文中的 this 指向某个对象,最好的方式是通过 call 方法来显示调用。
- 通过设置 JavaScript 的“严格模式”,在严格模式下,默认执行一个函数,其函数的执行上下文中的 this 值是 undefined
下文对闭包和 this 做一些补充介绍。
闭包
1.闭包是什么
按照 MDN-closure 的描述: MDN-Closure
函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起构成闭包(closure)。
也就是说,闭包可以让你从内部函数访问外部函数作用域。
在 JavaScript 中,每当函数被创建,就会在函数生成时生成闭包。
2.闭包的常见产生方式
(1).函数作为返回值被返回
function create() {let a = 100;return function() {console.log(a)}
}
let func = create();
let a = 200;
func();
(2).函数作为参数
function print(fn) {let b = 200;fn();
}
let b = 100;function fn() {console.log(b);
}
print(fn);
(3).在定时器、事件监听、Ajax请求、跨窗口通信、Web Workers或者任何异步中,只要使用了回调函数,实际上就是在使用闭包。
场景题
说明以下代码输出的结果,并解释原因
for (var i = 1; i <= 5; i++) {setTimeout(function timer() {console.log(i);}, i * 1000);
}
输出结果: 6 6 6 6 6
原因: 这里涉及到 JS 中 eventLoop 机制, 简单来说, 虽然循环中的五个函数是在各个迭代中分别定义的, 但是它们都被封闭在一个共享的全局作用域中, 因此实际只有一个i;并且延迟函数的回调在循环结束时才执行, 所以每次输出 6.
追问:如何改进代码,让输出数字1-5
1.立即执行函数
for (var i = 1; i <= 5; i++) {(function() {var j = i;setTimeout(function timer() {console.log(j);}, j * 1000);})();
}
// 将上面代码进行一些改进:
for (var i = 1; i <= 5; i++) {(function(j) {setTimeout(function timer() {console.log(j);}, j * 1000);})(i);
}
// 在迭代内使用 IIFE 会为每个迭代都生成一个新的作用域, 使得延迟函数的回调可以将新的作用域封闭在每个迭代内部,
// 每个迭代中都会含有一个具有正确值的变量供我们访问!
2.给定时器传入第3个参数, 作为 timer 函数的第一个函数参数
for (var i = 1; i <= 5; i++) {setTimeout(function timer(j) {console.log(j);}, i * 1000, i)
}
3.块作用域
for (let i = 1; i <= 5; i++) {setTimeout(function timer() {console.log(i);}, i * 1000);
}
闭包的作用
- 可以访问另一个函数内部的局部变量;
- 让这些变量始终保持在内存中,即闭包可以使得它诞生环境一直存在。
- 同一个闭包机制可以创建多个闭包函数出来,它们彼此没有联系,都是独立的,并且每个闭包函数可以保存自己个性化的信息。
this
极客时间-《浏览器的工作原理与实践》-[浏览器中的 JavaScript 执行机制]
11.this:从JavaScript执行上下文的视角讲清楚this
《你不知道的JavaScript》(上卷) 中对 this 的相关介绍:
判断this
可以参考 yck《前端面试手册》中的建议:
学习小体会
- 笔者曾经几次打开《你不知道的 JavaScript》(上卷),翻了翻目录,感觉里面的知识点都见过,都知道呀,就匆匆关上了,放到一边。* 因为对闭包的理解存在一些疑问,终于认真地看了这本书,发现了其中魅力之处。作者的写作方式也让读者感到 interesting,然后不禁发出和书中同样的感慨:“妈妈快来看呀,这就是闭包!”。* 另外,序言中 Shane Hudson 提到“想弄清楚事物的工作原理”,让我意识到学习知识应该要有探索的精神,不仅要知其然,还要知其所以然。前段时间有些浮躁、有些急功近利,看了一大堆面试题,很多都是浅尝辄止,流于表面。我想这应该是很多人都在走的路,但我们不能一直这样,面试题可以帮助我们完善知识体系,查漏补缺,但很多知识点都需要自己去针对性地学习、去实践,别人几句话总结出来的答案更需要我们带着批判性精神去审视,不能盲目吸收。* 如果你想从这篇文章中完全掌握闭包,那么笔者只能说:“小朋友,你还是涉世未深~”。* 想想曾经的自己,以为会背红宝书 P178 中对闭包的定义:“闭包是指有权访问另外一个函数作用域中的变量的函数”,就洋洋得意,以为拿下了闭包这个大 BOSS。不管面试官听了作何感想,反正现在看来,是自己都说服不了自己。* 学东西还是得踏踏实实的,现在能比较正确地理解和使用闭包,首先得益于极客时间-《浏览器的工作原理与实践》-[浏览器中的 JavaScript 执行机制]章节,让我以前很多模糊的概念有了清晰的认知。题外话,这个课程真的是强推,走过路过千万不要错过。然后是在一些技术博客上看到关于闭包的分析,心中存有一些疑问,于是再读《浏览器的工作原理与实践》对应内容,但并未得到解答。看到评论区中有推荐《你不知道的 JavaScript》(上卷)作为补充学习的建议,于是开始仔细阅读这本书,有了今日的收获。* 所以笔者建议认真阅读《你不知道的 JavaScript》或者《浏览器的工作原理与实践》来理解闭包,还可以参考 MDN 中对闭包的说明,然后整理出自己的学习笔记。
最后
整理了75个JS高频面试题,并给出了答案和解析,基本上可以保证你能应付面试官关于JS的提问。
有需要的小伙伴,可以点击下方卡片领取,无偿分享
相关文章:
浏览器中的 JavaScript 执行机制
思维导图 本文为反复学习极客时间-《浏览器的工作原理与实践》-浏览器中的 JavaScript 执行机制章节中的一些思考与记录。 一些重要概念 变量提升 所谓的变量提升,是指在 JavaScript 代码执行过程中,JavaScript 引擎把变量的声明部分和函数的声明部分…...
kafka集群搭建及问题
一、zookeeper集群搭建 1、创建文件夹 cd /home mkdir zookeeper 2、下载 cd zookeeper wget https://downloads.apache.org/zookeeper/zookeeper-3.8.0/apache-zookeeper-3.8.0-bin.tar.gz 解压到当前文件夹 tar -zxvf apache-zookeeper-3.8.0-bin.tar.gz 文件夹重命…...
不要忽视web渗透测试在项目中起到的重要性
在当前数字化环境中,IT的一个里程碑式增长便是公司组织和企业数字化。为了扩大市场范围和方便业务,许多组织都在转向互联网。这导致了一股新的商业浪潮,它创造了网络空间中的商业环境。通过这种方式,公司和客户的官方或机密文件都…...
Early Stopping中基于测试集(而非验证集)上的表现选取模型的讨论
论文中一般都是用在验证集上效果最好的模型去预测测试集,多次预测的结果取平均计算准确率或者mAP值,而不是单纯的取一次验证集最好的结果作为论文的结果。如果你在写论文的过程中,把测试集当做验证集去验证的话,这其实是作假的&am…...
appium ios真机自动化环境搭建运行(送源码)
appium ios真机自动化环境搭建&运行(送源码) 目录:导读 (1)安装JDK,并配置环境变量,方法如下: (2)安装Xcode、Xcode commandline tools和iOS模拟器 &…...
米尔基于ARM嵌入式核心板的电池管理系统(BMS)
BMS全称是Battery Management System,电池管理系统。它是配合监控储能电池状态的设备,主要就是为了智能化管理及维护各个电池单元,防止电池出现过充电和过放电,延长电池的使用寿命,监控电池的状态。 图片摘自网络 电池…...
Java后端项目IDEA配置代码规范检查,使用checkStyle实现
最近的Java后端项目想实现代码的规范检查,调研了一圈,终于找到了简单的方式实现:以下是常见的几种方案: 1、在客户端做 git hook,主要是用 pre-commit 这个钩子。前端项目中常见的 husky 就是基于此实现的。但缺点也很…...
Nginx_4
Nginx负载均衡 负载均衡概述 早期的网站流量和业务功能都比较简单,单台服务器足以满足基本的需求,但是随着互联网的发展,业务流量越来越大并且业务逻辑也跟着越来越复杂,单台服务器的性能及单点故障问题就凸显出来了,…...
linux Ubuntu KUbuntu 系统安装相关
系统安装 本来想快到中午的时候调试一下服务器上的http请求接收代码。我的电脑上装的是kali的U盘系统,然后我的U盘居然找不到了(然后之前安装的系统不知道是否是写入软件的原因,没办法解析DNS,我都用的转发的,这让我体验非常差。kali的系统工具很多&…...
个人信息保护认证
个人信息保护认证是证明个人信息处理者在认证范围内开展的个人信息收集、存储、使用、加工、传输、提供、公开、删除以及跨境等处理活动符合认证依据标准要求。适用范围 本规则依据《中华人民共和国认证认可条例》制定,规定了对个人信息处理者开展个人信息收集、存储…...
Negative Prompt in Stable Diffusion
必读链接:https://www.reddit.com/r/StableDiffusion/comments/z7salo/with_the_right_prompt_stable_diffusion_20_can_do/ A lot of people have noticed that Negative Prompt works wonders in 2.0, and works even better in 2.1. Negative hints are the op…...
MLX90316KGO-BDG-100-RE传感器 旋转位置 角度测量
介绍MLX90316是Tria⊗is旋转位置传感器,提供在设备表面旋转的小偶极磁铁(轴端磁铁)的绝对角位置。得益于其表面的集成磁集中器(IMC),单片设备以非接触式方式感知应用磁通量密度的水平分量。这种独特的传感原理应用于旋转位置传感器,可在机械(…...
Reflections反射包在springboot jar环境下扫描不到class排查过程
需求: 要实现指定pkg(如com.qiqitrue.test.pojo)扫描包下所有class类信息:使用代码如下 使用的版本:0.10.2(截至目前是最新版)发现只能在idea编译期间可以获取得到(也就是在开发阶段…...
黑马】后台项目171集
将近一个月没有练习了,找到之后果然打不开出了问题【问题】运行代码打开网页后,发现不能正常登录,一开始还以为是密码记错了,后来发现是数据库没有正常启动,phpstudy中的数据库一直是启动状态,关闭不了。【…...
Qt 5 架构和特点
Qt 5 模块构架: 模块:功能:Qt CoreQt 5 的核心类库,每个模块都建立在Core上Qt GUI图形用户界面开发的最基础的类库Qt Widgets提供c用户界面部件(是对Qt GUI的拓展)Qt SQL对数据库进行操作Qt Multimedia、…...
转换符说明使用方法(在printf函数中)
目录 一些常见的转换说明及打印结果: printf()的转换说明修饰符 printf()函数打印数据指令时要与代打印数据的类型相匹配才行。 如%d %c %ld......这些符号叫做转换说明。代表着数据转化成显示的形式。 一些常见的…...
针灸-基本任脉督脉
这里写自定义目录标题 丈量 同身丈下针深浅一般入穴的方法成人 幼儿 不同入穴方式现代常用针概念十二经 纳天干**天干**地支表里关系筋络任脉中脘穴:梅花灸巨阙穴廉泉穴督脉长强腰俞命门阳关悬枢脊中筋缩眼诊 癫痫至阳消渴...
信息系统与信息化
1.1 信息系统与信息化 1.1.1 信息的基本概念 信息质量属性(掌握)信息传输模型 1.1.2 信息系统的基本概念1.1.3 信息化的基本概念 信息化的五个层次信息化基本内涵信息化的基本概念(了解)六要素关系图(掌握) 1.1.4 信息系统生命周…...
解决axios异步请求问题(异步变为同步)
遇到的问题 在目前一个需求中,我需要等待axios请求完成后,判断请求是否出现异常,然后来判断是否关闭弹窗 修改后大概代码如下: async submitForm() {let flag false//表单验证,默认通过let formValidation truethis…...
【Django】云笔记项目
一、介绍 用户可在系统中记录自己的笔记,用户的数据被存储在云笔记平台;用户和用户之间的数据为隔离存储(登陆后才能使用相关笔记功能,且只能查阅自己的笔记) 二、功能拆解 1、用户模块 注册:成为平台…...
LeetCode——1797. 设计一个验证系统
一、题目 你需要设计一个包含验证码的验证系统。每一次验证中,用户会收到一个新的验证码,这个验证码在 currentTime 时刻之后 timeToLive 秒过期。如果验证码被更新了,那么它会在 currentTime (可能与之前的 currentTime 不同&am…...
java Resource
参看本文前 你要先了解 spring中的 Autowired和Qualifier 注解 如果之前没有接触过 可以查看我的文章 java spring 根据注解方式按(类型/名称)注入Bean 然后 创建一个java项目 引入spring注解方式 所需要的包 然后 在src下创建包 我们这里直接叫 Bean 在Bean下创建包 叫UserD…...
ArkTS语法(声明式UI)
页面级变量的状态管理 装饰器装饰内容说明State基本数据类型,类,数组修饰的状态数据被修改时会触发组件的build方法进行UI界面更新。Prop基本数据类型修改后的状态数据用于在父组件和子组件之间建立单向数据依赖关系。修改父组件关联数据时,…...
自动化测试实战篇(7)jmeter连接mysql数据库,实现单表、多表、三表查询,并对表中数据进行修改,删除,新增操作
Jmeter也可以连接mysql数据库,通过JDBC去调用数据库内的参数到HTTP请求中进行接口测试,可以说是相当方便 自动化测试实战篇(7)jmeter连接mysql数据库,实现单表、多表、三表查询,并对表中数据进行修改&#…...
我的网站上线了!
最近有段时间没有写原创文章了,恰好这两天正在翻阅历史文章的时候,发现文章中的图片竟然裂了?顿时冒了一身冷汗,因为每逢遇到这种情况,动辄需要花费一周的时间迁移图片。。。。。。 当我直接访问图片 url 的时候&#…...
勒索病毒整体攻击态势简单分析
声明 本文是学习2018勒索病毒白皮书政企篇. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 勒索病毒整体攻击态势 2018年,勒索病毒攻击特点也发生了变化:2017年,勒索病毒由过去撒网式无差别攻击逐步转向以服务器定…...
Vue资源(组件库、实用插件)
文章目录 一、组件库如下1、Element-ui和Element-plus插件库(PC端👇🔗)2、Ant Design vue(👇🔗)3、Vant插件库(移动端👇🔗)二、插件库如下1、正确引入图片地址(👇🔗)2、Vuex状态存储(持久化persist👇🔗)3、Better-Scroll(移动端滚动条👇🔗)4、Vue和…...
java rpc框架 中的自定义异常类型的全局处理
– 这里的dubbo 可泛指 所有rpc框架 –比如自定义异常类型是MyEx, 以及myEx可以转化为MyResult – 需求: 凡是请求链路中抛出的MyEx需要自动及时或最终转化为 自定义的MyResult返回 – 1. spring 提供 controller端的全局异常捕获. 这一步简单 – 2. dubbo 需要 将MyEx 传输回来…...
面试题:Redis的内存策略
1 Redis内存回收Redis之所以性能强,主要原因是基于内存存储,然而单节点的Redis内存不易过大,会影响主从同步和持久化性能我们可以通过修改配置文件设置Redis的最大内存:当内存存储到上限时,就无法存储更多的数据了。1.…...
idea中使用Git
目录 一、在idea中配置Git 1、打开settings,搜索git,找到本地上的git安装目录,选择git.exe 2、本地git安装目录 二、获取Git 1、本地初始化仓库 2、选中项目这层目录,点击确定 2、从远程仓库克隆 三、本地仓库操作 1、将文…...
扁平化设计网站建设/厦门seo专业培训学校
提到直播大多数人首先想到的可能是各种直播平台,比如花椒斗鱼虎牙YY ,这些直播平台中按照主播风格的不同,又可以分为美女直播、游戏直播、教育直播或者财经直播。除了开始的美女、才艺直播外,其他是直播和细分行业的结合。那么提到…...
在百度上做网站/中国联通和腾讯
我说好管理,往往是一个坏公司的结果,就是你居然都闲到了,有空把管理做到尽善尽美,其它很多成功的公司,都是丢盔卸甲,走向成功 http://v.youku.com/v_show/id_XMjY5NzE0OTg2MA.html?spma2h0j.8191423.vpoff…...
怎么做网站信息/全网关键词云查询
间隔了一周时间没写了,由于今年的股势行情貌似不错的样子,对于对股市完全不懂的我也在蠢蠢欲动,所以最近一周业余时间在“不务正业”-----学习炒股。发现学习它其实挺费神的,满脑子都是走势图,而且是神经有点受刺激的感…...
dedecms做多语言的网站/seo网站推广软件 快排
在JAVA程序中,性能问题的大部分原因并不在于JAVA语言,而是程序本身。养成良好的编码习惯非常重要,能够显著地提升程序性能。 1 尽量在合适的场合使用单例 使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率&a…...
杭州亚运村建设指挥部网站/个人怎么开跨境电商店铺
刚开始学习C#的时候就写过了,直接给地址了: 委托、匿名函数、Lambda表达式和事件的学习 委托学习续:Action、Func和Predicate...
第一ppt/长春seo主管
关机&重启命令 基本介绍shutdown shutdown -h now 表示立即关机 shutdown -h 1 表示 1 分钟后关机 shutdown -r now 立即重启 halt…...