JavaScript进阶知识点作用域详解

目录
  • JavaScript进阶讲解一
  • 一、浏览器的内核
    • 1.常见的浏览器内核
  • 二、JavaScript引擎
    • 2.1.为什么需要JavaScript引擎?
    • 2.2.常见的JavaScript引擎
  • 三、V8引擎
    • 3.1.官方定义
    • 3.2.解析过程图示
  • 四、JS的执行过程
    • 4.1 普通代码执行
    • 4.1 函数如何执行?
  • 五、作用域提升理解undefined

JavaScript进阶讲解一

接下来,我会给大家讲解js中让人让人迷惑的知识点,比如: 作用域、函数、闭包、面向对象、ES新特性、事件循环、微任务、宏任务、内存管理、Promise、await、 asnyc、防抖、节流等等。

一、浏览器的内核

1.常见的浏览器内核

Gecko:早期被Netscape和Mozilla Firefox浏览器浏览器使用。 Trident:微软开发,被IE4~IE11浏览器使用。 Webkit:苹果基于KHTML开发、开源的,用于Safari,Google Chrome之前也在使用。 Blink:是Webkit的一个分支,Google开发,目前应用于Google Chrome、Edge、Opera等。

二、JavaScript引擎

2.1.为什么需要JavaScript引擎?

高级的编程语言都是需要转成最终的机器指令来执行,我们编写的JavaScript无论你交给浏览器或者Node执行,最后都是需要被CPU执行,但是CPU只认识自己的指令集,也就是所谓的机器语言,才能被CPU所执行,所以我们需要JavaScript引擎帮助我们将JavaScript代码翻译成CPU指令来执行。

2.2.常见的JavaScript引擎

SpiderMonkey、Chakra、JavaScriptCore、V8... 现使用最多的是v8引擎

三、V8引擎

3.1.官方定义

  • V8是用C ++编写的Google开源高性能JavaScript和WebAssembly引擎,它用于Chrome和Node.js等。
  • 它实现ECMAScript和WebAssembly,并在Windows 7或更高版本,macOS 10.12+和使用x64,IA-32, ARM或MIPS处理器的Linux系统上运行。
  • V8可以独立运行,也可以嵌入到任何C ++应用程序中。

3.2.解析过程图示

四、JS的执行过程

  • 初始化全局对象(GO -》 Global Object): js引擎在执行代码之前,会在堆内存中创建一个全局对象,将window属性指向自己,也会将Date、Array、String、Number、setTimeout、和你自己定义的全局变量这些放到GO中(当然你自己定义的还未执行 所以值是underfind)(这也是为什么我们可以使用window.及Data这些函数或类的原因)
  • 执行上下文栈(ECS -》Execution Context Stack): 它是用于执行代码的调用栈,执行的是全局的代码块(GEC -》 Global Execution Context),也就是说GEC 会被放到ECS中执行
  • GEC(这里面就有VO,这里指向GO)被放入到ECS中
  • GEC开始执行代码(从上往下依次执行)

4.1 普通代码执行

其实在GEC开始执行代码后 如果只是一些变量,还是很好理解的,比如

console.log(a); // undefined
var a = 100

这里为什么不报错 而是undefined,其实我们上面已将说的很明白了,因为在创建GO对象的时候 我们定义的全局变量会被添加到GO中 且值是undefined。这也是var的作用域提升。

4.1 函数如何执行?

如果我们执行时遇到函数怎么办呢?

foo()
function foo() {
  console.log(100);
}
// foo()

看上面函数 不论我们foo在哪里调用 他都是可以正确执行的。而不会和变量那样显示 undefined或者报错,这是为什么呢? 其实在GO创建时(编译时,代码还未开始执行),当他遇到有函数的定义时,就会根据函数体创建一个函数执行上下文(FEC,在这里也会有个VO,这里的VO指向AO)并且压入到ESC中,存的是一个内存地址,不在是undefined。 所以当代码开始执行时 执行到foo()时,他就能在GO中找到那个内存地址

五、作用域提升理解undefined

var n = 100
function foo() {
   n = 200
}
foo()
console.log(n); // 200
var n = 100
function foo() {
  console.log(n); // undefined
  return
  var n = 200
 }
 foo()

第一个大家应该都知道,所以不赘述,我们主要来看看为什么第二个打印的是undefined。看下图可得,在编译时,我们的函数会指向一个内存地址,开辟一个空间(AO),所以代码执行时,他会在AO中查找,找不到会在上一级查找(作用域链)

function foo() {
      console.log(a);// undefined
      var a = 100
      console.log(a);// 100
    }
    var a = 100
    foo()
function foo() {
      console.log(a);// 100
    }
    var a = 100
    foo()

我们在来看这两个,相信大家已经明白了第一个输出的原因,我们再来看看第二个为什么是100,而不是undefined,其实这个原因很简单,他就是作用域链,很明显我们的AO中没有a的定义,所以他会在上一层中找, 而这里的上一层就是GO,此时GO中的a已经是100了 所以找到的a就是100。

大家来思考下下面这个会是什么呢?

var a = 1
    function foo1() {
      console.log(a);
    }
    function foo2() {
      var a = 2
      console.log(a);
      foo1()
    }
    foo2()
    console.log(a);

到此这篇关于JavaScript进阶讲解一作用域的文章就介绍到这了,更多相关js作用域内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 深入理解JavaScript 中的匿名函数((function() {})();)与变量的作用域

    匿名函数:没有实际名字的函数. 匿名函数的作用: 1.通过匿名函数可以实现闭包,关于闭包在后面的文章中会重点讲解.在这里简单介绍一下:闭包是可以访问在函数作用域内定义的变量的函数.若要创建一个闭包,往往都需要用到匿名函数. 2.模拟块级作用域,减少全局变量.执行完匿名函数,存储在内存中相对应的变量会被销毁,从而节省内存.再者,在大型多人开发的项目中,使用块级作用域,会大大降低命名冲突的问题,从而避免产生灾难性的后果.自此开发者再也不必担心搞乱全局作用域了. 本章节重点给大家介绍JavaScrip

  • JavaScript进阶(二)词法作用域与作用域链实例分析

    本文实例讲述了JavaScript词法作用域与作用域链.分享给大家供大家参考,具体如下: 一.作用域 域表示的就是范围,即作用域,就是一个名字在什么地方可以使用,什么时候不能使用.想了解更多关于作用域的问题推荐阅读<你不知道的JavaScript上卷>第一章(或第一部分),从编译原理的角度说明什么是作用域.概括的说作用域就是一套设计良好的规则来存储变量,并且之后可以方便地找到这些变量. 1.1 块级作用域 在C.Java.C#等编程语言中,下面的语法报错(伪代码) { var num = 12

  • javascript基础进阶_深入剖析执行环境及作用域链

    执行环境 执行环境定义了变量或函数有权访问的其他函数,决定了他们各自的行为.每个执行环境都有一个与之关联的变量对象. 变量对象 环境中定义的所有变量和函数都保存在这个对象中. 全局执行环境 全局执行环境是最外围的一个执行环境.在web浏览器中,全局执行环境被认为是Window对象,因此所有全局变量和函数都是作为window对象的属性和方法创建的. 每个函数都有自己的执行环境. 作用域链 当代码在一个环境中执行,会创建变量对象的一个作用域链. 用途:保证对执行环境有权访问的所有变量和函数有序访问.

  • JavaScript进阶知识点作用域详解

    目录 JavaScript进阶讲解一 一.浏览器的内核 1.常见的浏览器内核 二.JavaScript引擎 2.1.为什么需要JavaScript引擎? 2.2.常见的JavaScript引擎 三.V8引擎 3.1.官方定义 3.2.解析过程图示 四.JS的执行过程 4.1 普通代码执行 4.1 函数如何执行? 五.作用域提升理解undefined JavaScript进阶讲解一 接下来,我会给大家讲解js中让人让人迷惑的知识点,比如: 作用域.函数.闭包.面向对象.ES新特性.事件循环.微任务

  • Python进阶_关于命名空间与作用域(详解)

    写在前面 如非特别说明,下文均基于Python3 命名空间与作用于跟名字的绑定相关性很大,可以结合另一篇介绍Python名字.对象及其绑定的文章. 1. 命名空间 1.1 什么是命名空间 Namespace命名空间,也称名字空间,是从名字到对象的映射.Python中,大部分的命名空间都是由字典来实现的,但是本文的不会涉及命名空间的实现.命名空间的一大作用是避免名字冲突: def fun1(): i = 1 def fun2(): i = 2 同一个模块中的两个函数中,两个同名名字i之间绝没有任何

  • 基于Python闭包及其作用域详解

    关于Python作用域的知识在python作用域有相应的笔记,这个笔记是关于Python闭包及其作用域的详细的笔记 如果在一个内部函数里,对一个外部作用域(但不是全局作用域)的变量进行引用,那么内部函数就被称为闭包(closure),而这个被内部函数引用的变量则被成为自由变量 闭包和函数调用没多少相关,而是关于使用定义在其他作用域的变量 命名空间和作用域 我们把命名空间看做一个大型的字典类型(Dict),里面包含了所有变量的名字和值的映射关系.在 Python 中,作用域实际上可以看做是"在当前

  • javascript中正则表达式语法详解

    好久都没有写博客了,主要是太懒了,尤其是在阳春三月,风和日丽的日子,太阳暖暖的照在身上,真想美美的睡上一觉.就导致了这篇博客拖到现在才开始动笔,javascript的正则这一块也不是什么新的东西,主要是以前本人一遇到写正则的需求就开始头大,头疼,网上剽窃,东拼西凑,反正就是各种不适应,所以我打算系统的把正则表达式看一遍,一来是自己有所提升,这一块知识点的查漏补缺,二来是给大家分享一下.好了,下面我们直接进入主题: 正则是匹配字符串特定模式的一种表达式,官方是这样说的,但我的理解不外乎就是匹配字符

  • javascript中Promise使用详解

    目录 一.首先,要知道为什么要用Promise语法? 二.接着,来了解一下回调地狱(Callback Hell) 三.最后,也是本章的重头戏,Promise的基本使用 (一) resolve函数 (二) rejected函数 (三)Promise的API 1. then 2. catch 3. finally 4. Promise.all 5. Promise.race 四.最后 前言: 做过前端开发的都知道,JavaScript是单线程语言,浏览器只分配给JS一个主线程,用来执行任务,但是每次

  • JavaScript代码优化技巧示例详解

    目录 引言 提炼函数 函数参数化 使用策略模式替换“胖”分支 提炼变量 内联变量 封装变量 拆分阶段 拆分循环 拆分变量 分解条件表达式 合并条件表达式 以卫语句取代嵌套条件表达式 将查询函数和修改函数分离 引言 我们先引入一句话: 代码主要是为了写给人看的,而不是写给机器看的,只是顺便也能用机器执行而已. 代码和语言文字一样是为了表达思想.记载信息,所以写得清楚能更有效地表达.本文多数总结自<重构:改善既有代码的设计(第2版)>我们直接进入正题,上代码! 提炼函数 what 将一段代码提炼到

  • 基于JavaScript表单脚本(详解)

    什么是表单? 一个表单有三个基本组成部分: 表单标签:这里面包含了处理表单数据所用CGI程序的URL以及数据提交到服务器的方法. 表单域:包含了文本框.密码框.隐藏域.多行文本框.复选框.单选框.下拉选择框和文件上传框等. 表单按钮:包括提交按钮.复位按钮和一般按钮:用于将数据传送到服务器上的CGI脚本或者取消输入,还可以用表单按钮来控制其他定义了处理脚本的处理工作. JavaScript与表单间的关系:JS最初的应用就是用于分担服务器处理表单的责任,打破依赖服务器的局面,尽管目前web和jav

  • JSP 中Spring Bean 的作用域详解

    JSP 中Spring Bean 的作用域详解 Bean元素有一个scope属性,用于定义Bean的作用域,该属性有如下五个值: 1>singleton: 单例模式,在整个spring IOC容器中,单例模式作用域的Bean都将只生成一个实例.一般Spring容器默认Bean的作用域为singleton 2>prototype: 与singleton相反, 每次通过容器的getBean()方法获取该作用域下的Bean时都将产生一个新的Bean实例 3>request: 对于同一次Http

  • JavaScript数据结构链表知识详解

    最近在看<javascript数据结构和算法>这本书,补一下数据结构和算法部分的知识,觉得自己这块是短板. 链表:存储有序的元素集合,但不同于数组,链表中的元素在内存中不是连续放置的.每个元素由一个存储元素本身的节点和一个指向下一个元素的引用(也称指针或链接)组成. 好处:可以添加或移除任意项,它会按需扩容,且不需要移动其他元素. 与数组的区别: 数组:可以直接访问任何位置的任何元素: 链表:想要访问链表中的一个元素,需要从起点(表头)开始迭代列表直到找到所需的元素. 做点小笔记. funct

  • JavaScript里 ==与===区别详解

    1.对于string,number等基础类型,==和===是有区别的 1)不同类型间比较,==之比较"转化成同一类型后的值"看"值"是否相等,===如果类型不同,其结果就是不等 2)同类型比较,直接进行"值"比较,两者结果一样 2.对于Array,Object等高级类型,==和===是没有区别的 进行"指针地址"比较 3.基础类型与高级类型,==和===是有区别的 1)对于==,将高级转化为基础类型,进行"值&quo

随机推荐