浏览器中的 JavaScript 执行机制

news2024/10/6 0:35:21

思维导图

本文为反复学习极客时间-《浏览器的工作原理与实践》-浏览器中的 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的提问。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/333759.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

你可能还不知道的 console.log 替代品

通过使用 javascript 对象的破坏能力&#xff0c;您可以这样做&#xff1a;const{ log } console; log("hi"); log("testing");你可以将log函数更改为您想要的任何其他名称&#xff0c;如下所示&#xff1a;const{log: myLog } console; myLog("hi&qu…

vue插槽 Slots

一、插槽是什么&#xff1f; 插槽就是子组件中的提供给父组件使用的一个占位符&#xff0c;用<slot></slot> 表示, 父组件可以在这个占位符中填充任何模板代码&#xff0c;如 HTML、组件等&#xff0c;填充的内容会替换子组件的<slot></slot>标签。 简…

OpenSergo Spring Cloud Alibaba 带来的服务治理能力

作者&#xff1a;十眠、牧思 Spring Cloud 应用为何需要服务治理 随着微服务技术的发展&#xff0c;微服务(MicroServices) 的概念早已深入人心&#xff0c;越来越多的公司开始使用微服务架构来开发业务应用。 如果采用得当&#xff0c;微服务架构可以带来非常大的优势。微服…

IDEA与eclipse桌面配置基础(笔记)

在eclipse中配置jdk Window–>Preferences–>java–>installed JREs–>add–>Standard VM–>选择jdk安装路径就好了 设置字符集编码为utf-8&#xff0c;防止中文乱码 设置字符集编码为UTF-8&#xff1a;Window–>Preferences–>General–>Workspace…

第四次工业革命新十年:看跨越智能化鸿沟的联想范式

十年前&#xff0c;GE推出全球第一个工业互联网平台Predix&#xff1b;同年&#xff0c;在2013汉诺威工业博览会上&#xff0c;德国正式推出工业4.0概念。由此&#xff0c;全球开启了以工业4.0和工业互联网为核心的第四次工业革命浪潮&#xff0c;智能技术成为了第四次工业革命…

4N25光耦合器:简单的应用电路

4N25光耦合器&#xff1a;简单的应用电路 介绍 4N25是一款6引脚光电晶体管耦合器。本文根据其传动特性介绍了 4N25 的非线性和线性应用。 4N25概述 光电耦合器4N25的内部电路结构如图1所示。 图1.4N25内部电路结构 该芯片为双列直插式器件&#xff0c;外引线为6根&#xff0…

Dart语法学习-基础-类

Classes Using constructors 使用构造函数创建对象。 构造函数名称可以是 ClassName 或 ClassName.identifier。 例如&#xff0c;以下代码使用 Point() 和 Point.fromJson() 构造函数创建 Point 对象&#xff1a; class Point {var x;var y;Point(int this.x, int this.y);…

Java --- Integer.parseInt()

parseInt() 方法是java.lang 包下Integer 类的一个方法。 Java Integer parseInt() 方法共有三种不同类型&#xff0c;可以根据其参数进行区分。 用法: 以下是 parseInt() 方法的声明&#xff1a; public static int parseInt (String s) public static int parseInt (Strin…

捐赠物品管理系统-php mysql

目 录 第一章 引言 1 1.1研究背景 1 1.2研究现状 1 1.3 系统相关技术与环境简介 1 1.3.1 PHP 1 1.3.2 Apache 2 1.3.3 MySQL数据库 2 1.3.4 运行环境 Windows 3 1.3.5 appserv 3 1.3.6 Dreamweave8 3 1.3.7 EditPlus 4 第二章 需求分析…

前端必备开发编译器详解

一、前言 前端开发编译器有很多&#xff0c;例如&#xff1a;WebStorm、VS Code、HBuilder X、Sublime Text等等。在这里就不一一介绍了&#xff0c;这里主要讲解VS Code和HBuilder X 编译器。 二、VS Code Visual Studio Code (简称 VS Code) 是一款免费开源的现代化轻量级…

论文阅读:Tube Convolutional Neural Network (T-CNN) for Action Detection in Videos

Tube Convolutional Neural Network (T-CNN) for Action Detection in Videos 文章目录Tube Convolutional Neural Network (T-CNN) for Action Detection in Videos摘要及贡献相关工作Generalizing R-CNN from 2D to 3D框架结构Tube Proposal Network&#xff08;TPN&#xff…

leetcode刷题之背包问题(01背包)

01 背包 概念&#xff1a;有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i]weight[i]weight[i]&#xff0c;得到的价值是value[i]value[i]value[i]。每件物品只能用一次&#xff0c;求解将哪些物品装入背包里物品价值总和最大。 方法1&#xff1a;暴力回溯…

综合办公系统(OA+HR+CRM)

综合办公管理系统是集OA办公系统、HR人力资源管理系统和CRM客户关系管理系统于一体的综合系统。 其架构为&#xff1a; 功能介绍 一、OA办公系统 OA办公系统主要包括个人办公、会议室管理、车辆管理、新闻公告、资产管理和文档管理模块 &#xff08;1&#xff09;个人办公 内部…

6年软件测试经历:成长、迷茫、奋斗

前言 测试工作6年&#xff0c;经历过不同产品、共事过不同专业背景、能力的同事&#xff0c;踩过测试各种坑、遇到过各种bug。测试职场生涯积极努力上进业务和技术能力快速进步过、也有努力付出却一无所得过、有对测试生涯前景充满希望认为一片朝气蓬勃过、也有对中年危机思考不…

【笔记】移动端自动化:adb调试工具+appium+UIAutomatorViewer

学习源&#xff1a; https://www.bilibili.com/video/BV11p4y197HQ https://blog.csdn.net/weixin_47498728/category_11818905.html 一、移动端测试环境搭建 学习目标 1.能够搭建java 环境 2.能够搭建android 环境 &#xff08;一&#xff09;整体思路 我们的目标是Andr…

小红书情人节大赏!热门话题各出奇招,看看哪个品牌打动了你?

情人节热度狂飙&#xff0c;实时热度值破万 以爱之名&#xff0c;传递爱意。每年情人节向来是不容错过的热门话题。我们发现&#xff0c;临近情人节&#xff0c;小红书平台的相关内容热度飙升。据千瓜数据关键词热度查询&#xff0c;2月初“情人节”热搜词热度值就已破万。 截止…

1.ORB-SLAM2中的多线程调度解析

目录 0.先修知识 1.ORB - SLAM2中的线程 2.ORBSLAM2中的互斥锁示例 0.先修知识 需要了解C中开辟多线程的方式&#xff0c;了解C中不同锁的使用方法 学习C&#xff1a;C进阶&#xff08;五&#xff09;多线程编程原理及多线程编程方法https://blog.csdn.net/qq_41694024/artic…

Java 网络编程详解

1、什么是网络编程 在网络通信协议下&#xff0c;不同计算机上运行的程序&#xff0c;可以进行数据传输。 应用场景&#xff1a;     1、即时通信 2、网游对战 3、邮件等等 Java中可以使用java.net包下的技术轻松开发出常见的网络应用程序 2、网络编程三要素 2.1 IP地址 要…

HCNP路由交换学习指南丨学习笔记丨07.BGP

07.BGP1. BGP 的基本概念1.1 BGP 对等体关系类型1.2 IBGP 水平分割原则1. BGP 的基本概念 关于 自治系统&#xff08;Autonomous System&#xff0c;AS&#xff09; 的传统定义&#xff1a;由一个单一的机构或组织所管理的一系列 IP 网络及其设备所构成的集合。 自治系统的简单…

jsp羽毛球场馆管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 jsp 羽毛球场馆管理系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql&#xff0c;…