深入理解JS | 青训营笔记

103 阅读7分钟

JS的基本概念

一般情况下可以根据声明变量的特点,将语言分为静态语言和动态语言:

  • 静态语言:  在使用之前就需要确认其变量数据类型的称为静态语言;
  • 动态语言:  相反的,在运行过程中需要检查数据类型的语言称为动态语言。

JavaScript 就是一门动态语言,因为在声明变量之前并不需要确认其数据类型。

对于一个变量,我们既可以给他设置为一个数字,也可以给他设置为一个字符串,还可以让字符串类型的变量和数值类型的变量相加。在这个过程中,可以发生隐式的类型转化。弱类型语言可以发生隐式类型转换,而强类型语言不能发生隐式类型转换。

JavaScript是一种弱类型、动态的语言。

数据类型

image.png juejin.cn/post/700833…

  1. Undefined

Undefined 类型表示未定义,它的类型只有一个值,就是 undefined。任何变量在赋值前是 Undefined 类型、值为 undefined,可以用全局变量 undefined 来表达这个值。可以通过以下方式来得到 undefined:

  • 声明了一个变量,但没有赋值
  • 引用未定义的对象属性
  • 函数定义了形参,但没有传递实参
  • 执行 void 表达式
  1. Null

Null 数据类型和 Undefined 类似,只有一个值 null,表示变量被置为空对象,而非一个变量最原始的状态。null 是 JavaScript 保留关键字,而 undefined 只是一个常量。也就是说可以声明名称为 undefined 的变量,但将 null 作为变量使用时则会报错。

在 Javascript 规范中提到,要比较相等性之前,不能将 null 和 undefined 转换成其他任何值,并且规定null 和 undefined 是相等的。null 和 undefined都代表着无效的值。

  1. Boolean

Boolean 数据类型只有两个值:true 和 false,分别代表真和假。很多时候我们需要将各种表达式和变量转换成 Boolean 数据类型来当作判断条件。

  1. String

String 用于表示字符串,String 有最大长度是 253 - 1,这个所谓的最大长度并不是指字符数,而是字符串的 UTF16 编码长度。 字符串的 charAt、charCodeAt、length 等方法针对的都是 UTF16 编码。所以,字符串的最大长度,实际上是受字符串的编码长度影响的。

JavaScript 中的字符串是永远无法变更的,一旦构造出来,就无法用任何方式改变其内容,所以字符串具有值类型的特征。

  1. Number

Number 类型表示数字。JavaScript 中的 Number 类型有 18437736874454810627(即 264-253+3) 个值。JavaScript 中的 Number 类型基本符合 IEEE 754-2008 规定的双精度浮点数规则,但是 JavaScript 为了表达几个额外的语言场景(比如为了不让除以 0 出错,而引入了无穷大的概念),规定了几个例外情况:

  • NaN,占用了 9007199254740990,这原本是符合 IEEE 规则的数字,通常在计算失败时会得到该值。要判断一个变量是否为 NaN,则可以通过 Number.isNaN 函数进行判断。
  • Infinity,无穷大,在某些场景下比较有用,比如通过数值来表示权重或者优先级,Infinity 可以表示最高优先级或最大权重。
  • -Infinity,无穷小。
  1. Symbol

Symbol 是 ES6 中引入的新数据类型,它表示一个唯一的常量,通过 Symbol 函数来创建对应的数据类型,创建时可以添加变量描述,该变量描述在传入时会被强行转换成字符串进行存储。基于以上特性,Symbol 属性类型比较适合用于两类场景中:常量值和对象属性

  1. BigInt

BigInt 可以表示任意大的整数。

  1. Object

Object 是 JavaScript 中最复杂的类型,它表示对象。在 JavaScript 中,对象的定义是属性的集合。简单地说,Object 类型数据就是键值对的集合,键是一个字符串(或者 Symbol) ,值可以是任意类型的值; 复杂地说,Object 又包括很多子类型,比如 Date、Array、Set、RegExp。

其实,JavaScript的几个基本数据类型在对象类型中都有一个对应的类:

  • Number;
  • String;
  • Boolean;
  • Symbol。

对于 Number 类,1 与 new Number(1) 是完全不同的值,一个是 Number 类型, 一个是对象类型。Number、String 和 Boolean 构造器是两用的:当跟 new 搭配时,它们产生对象;当直接调用时,它们表示强制类型转换。Symbol 函数比较特殊,直接用 new 调用它会抛出错误,但它仍然是 Symbol 对象的构造器。

作用域

作用域是可访问变量的集合,限制了变量的可访问性和可见性。

image.png

  • 全局作用域中的对象在代码中的任何地方都可以访问,其生命周期伴随着页面的生命周期。
  • 函数作用域是在函数内部定义的变量或者函数,并且定义的变量或者函数只能在函数内部被访问。函数执行结束之后,函数内部定义的变量会被销毁。
  • 块级作用域。块级作用域就是使用一对大括号包裹的一段代码,比如函数、判断语句、循环语句,甚至一个单独的{}都可以被看作是一个块级作用域(注意,对象声明中的{}不是块级作用域)。简单来说,如果一种语言支持块级作用域,那么其代码块内部定义的变量在代码块外部是访问不到的,并且等该代码块中的代码执行完成之后,代码块中定义的变量会被销毁。

变量提升

变量提升(Hoisting)被认为是, Javascript中执行上下文 (特别是创建和执行阶段)工作方式的一种认识。在 ECMAScript® 2015 Language Specification 之前的JavaScript文档中找不到变量提升(Hoisting)这个词。

从概念的字面意义上说,“变量提升”意味着变量和函数的声明会在物理层面移动到代码的最前面,但这么说并不准确。实际上变量和函数声明在代码里的位置是不会动的,而是在编译阶段被放入内存中。

  1. var:存在变量提升,代码块外部可调用
  2. let:不存在变量提升,存在块级作用域
  3. const:不存在变量提升,存在块级作用域,赋值后值不可变

JS执行过程

image.png

image.png 全局执行上下文:代码开始执行时就会创建,将他压执行栈的栈底,每个生命周期内只有一份

函数执行上下文:当执行一个函数时,这个函数内的代码会被编译,生成变量环境、词法环境等,当函数执行结束的时候该执行环境从栈顶弹出

image.png

image.png

问:创建执行上下文的时候做了什么?

答:绑定this,创建词法环境,创建变量环境

词法环境:基于ECMAScript代码的词法嵌套结构来定义标识符和具体变量和函数的关联。一个词法环境由环境记录器和一个可能的引用外部词法环境的空值组成

变量环境:变量环境和词法环境的一个不同就是前者被用来存储函数声明和变量(let和const)绑定,后者只用来存储var变量绑定

Outer:指向外部环境变量的一个指针

JS进阶知识点

闭包

闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment词法环境)的引用的组合。换而言之,闭包让开发者可以从内部函数访问外部函数的作用域。在 JavaScript 中,闭包会随着函数的创建而被同时创建。

developer.mozilla.org/zh-CN/docs/…

this

developer.mozilla.org/zh-CN/docs/…

image.png

垃圾回收

developer.mozilla.org/zh-CN/docs/…

image.png