深入理解JS | 青训营笔记

132 阅读7分钟

深入理解JS

1. JS基本概念

  • 什么是JS

JS是JavaScript的简称,是一种脚本语言,用于在网页上实现交互和动态效果。JS可以在网页上操作HTML和CSS,以及处理用户输入和输出。它是一种解释性语言,可以直接嵌入到HTML文档中,也可以作为单独的文件引用到HTML文档中。JS具有良好的跨平台性,可以在不同的操作系统和浏览器上运行。它是前端开发中不可或缺的一部分。

  • JS诞生

image.png

  • JS发展 image.png

  • 进程跟线程

image.png 进程:在浏览器中,每个标签页都是一个独立的进程。每个进程都有自己的内存空间和运行环境,可以独立地执行JavaScript代码和渲染页面。这样可以保证每个标签页的运行不会相互影响,同时也提高了浏览器的稳定性和安全性。

线程:在JavaScript中,线程是进程中的一个执行单元,负责执行程序中的指令。常见的线程包括渲染线程、JS引擎线程、事件触发线程等。其中,渲染线程负责将HTML、CSS和JavaScript代码转换成页面展示给用户,JS引擎线程负责执行JavaScript代码,事件触发线程负责处理用户的交互事件。这些线程可以并行执行,提高了JavaScript的执行效率和响应速度。

1.1 数据类型

在JavaScript中,数据类型可以分为基本数据类型和引用数据类型,具体如下:

  1. 基本数据类型:包括数字(Number)、字符串(String)、布尔值(Boolean)、空(Null)、未定义(Undefined)。
  2. 引用数据类型:包括对象(Object)、数组(Array)、函数(Function)等。

其中,基本数据类型的值是不可变的,一旦创建就无法改变。而引用数据类型的值是可变的,可以随时添加、修改或删除其中的属性和方法。

需要注意的是,在JavaScript中,所有的数据类型都是对象,包括基本数据类型。这是因为JavaScript采用了面向对象的编程思想,将基本数据类型封装成了对应的包装对象,例如数字类型被封装为Number对象,字符串类型被封装为String对象等。这样可以使得基本数据类型也具有对象的特性,例如可以调用对应的方法和属性。

image.png

1.2 作用域

在JavaScript中,作用域是指变量和函数的可访问范围。JavaScript中的作用域分为全局作用域和局部作用域。

  1. 全局作用域:在函数外部声明的变量和函数都属于全局作用域,可以在代码的任何地方被访问。全局作用域的变量和函数可以被任何函数或代码块访问。
  2. 局部作用域:在函数内部声明的变量和函数都属于局部作用域,只能在函数内部被访问。局部作用域的变量和函数不能被函数外部的代码访问,也不能被其他函数访问。

在JavaScript中,函数是一个独立的作用域,函数内部声明的变量和函数都属于函数的局部作用域。当函数被调用时,会创建一个新的局部作用域,函数执行完毕后,局部作用域会被销毁。

JavaScript采用了词法作用域,也就是静态作用域。在词法作用域中,变量的作用域在函数定义时就已经确定,而不是在函数调用时确定。这意味着函数内部可以访问函数外部的变量,但是函数外部不能访问函数内部的变量。

image.png

1.3 变量提升

image.png

2. JS是怎么执行的

image.png

在JavaScript中,执行上下文是指JavaScript代码被执行时所处的环境。每个执行上下文都包含了当前代码执行所需的信息,例如变量、函数、对象等。JavaScript代码执行时,会依次进入不同的执行上下文。

JavaScript中的执行上下文分为三种类型:

  1. 全局执行上下文:当JavaScript代码开始执行时,会首先进入全局执行上下文。全局执行上下文是整个JavaScript程序的最外层执行上下文,包含了所有全局变量和函数声明。
  2. 函数执行上下文:每当函数被调用时,都会创建一个新的函数执行上下文。函数执行上下文包含了函数内部的变量、函数和参数等信息。
  3. eval执行上下文:在使用eval函数执行代码时,会创建一个新的eval执行上下文。

每个执行上下文都有一个变量对象(Variable Object),它包含了当前执行环境中的所有变量和函数声明。在全局执行上下文中,变量对象是全局对象;在函数执行上下文中,变量对象是活动对象(Activation Object)。

在JavaScript代码执行时,执行上下文会被创建、压入执行上下文栈中,并在执行完毕后被弹出。执行上下文栈是一个后进先出(LIFO)的数据结构,它决定了代码执行的顺序。当代码执行时,JavaScript引擎会从执行上下文栈的顶部取出当前的执行上下文,执行其中的代码,然后将其弹出。

image.png image.png

3. JS的进阶知识点

3.1 闭包

闭包是指一个函数能够访问并操作它外部函数作用域中的变量,即使外部函数已经执行完毕并返回了,这个函数仍然可以访问外部函数的变量。通俗地说,闭包就是在函数内部定义的函数,它可以访问外部函数的变量,并且可以在外部函数执行完毕后继续访问这些变量。

在JavaScript中,闭包可以用来实现许多有用的功能,例如模块化、私有变量、缓存等。

下面是一个简单的闭包示例:

function outer() {
  var count = 0;

  function inner() {
    count++;
    console.log(count);
  }

  return inner;
}

var closure = outer();
closure(); // 输出1
closure(); // 输出2
closure(); // 输出3

在这个例子中,outer函数返回了一个内部函数inner,并且inner函数可以访问outer函数的变量count。当outer函数执行完毕后,count变量的作用域被销毁,但是inner函数仍然可以访问并操作count变量,因为它形成了一个闭包。

需要注意的是,闭包会导致内存泄漏问题,因为闭包会持有外部函数的变量,导致这些变量无法被垃圾回收。因此,在使用闭包时需要注意内存管理,避免出现内存泄漏问题。

3.2 this

在JavaScript中,this是一个关键字,它指向当前函数的执行上下文。this的值在函数被调用时确定,根据调用方式的不同,this的值也会有所不同。

在JavaScript中,this的值可以分为以下几种情况:

  1. 全局上下文中的this:在全局上下文中,this指向全局对象(在浏览器中是window对象,在Node.js中是global对象)。
  2. 函数上下文中的this:在函数中,this的值取决于函数的调用方式。如果函数是作为对象的方法调用,this指向该对象;如果函数是作为普通函数调用,this指向全局对象;如果函数是作为构造函数调用,this指向新创建的对象;如果函数是通过callapply方法调用,this指向传入的第一个参数。
  3. 箭头函数中的this:在箭头函数中,this的值由外层作用域决定,而不是由函数调用方式决定。

下面是一些示例代码:

var name = 'global';

function foo() {
  console.log(this.name);
}

var obj = {
  name: 'object',
  foo: foo
};

foo(); // 输出'global'

obj.foo(); // 输出'object'

var bar = {
  name: 'bar'
};

foo.call(bar); // 输出'bar'

var baz = () => {
  console.log(this.name);
};

baz(); // 输出'global'

var qux = {
  name: 'qux',
  baz: baz
};

qux.baz(); // 输出'qux'

需要注意的是,this是一个非常容易出错的概念,特别是在复杂的代码中。在使用this时,需要仔细考虑函数的调用方式以及作用域链等因素,避免出现意外的结果。

3.3 垃圾回收

image.png