深入理解JS | 青训营笔记

81 阅读6分钟

一、JS的基本概念

1. 什么是JS

JS(JavaScript)是一种轻量级的脚本语言,通常用于前端网页的动态效果、表单验证、异步请求等,也可以用于后端开发(Node.js),甚至是桌面应用程序(Electron、NW.js)和移动应用程序(React Native)。JS可以让网页更加生动和交互。

JS由ECMAScript、DOM和BOM三部分组成。

  • ECMAScript:JS的核心基础语言,涵盖变量、数据类型、运算符、函数、循环、流程控制等。从ES6开始,JS新增了很多语法糖,提供了更加方便的编程方式。
  • DOM(Document Object Model):文档对象模型,是一种跨平台和语言无关的API,能够让开发者将HTML文档当作树形结构处理,方便开发者进行操作。
  • BOM(Brower Object Model):浏览器对象模型,提供了一些访问浏览器功能的API接口,比如location、navigator、history等。

2. 变量

JS变量是指一段内存中的存储空间,其值可以在代码中被访问和修改。声明变量的方式有三种:

  • var:ES5及以前版本的声明变量的方式。var声明的变量是函数级作用域,不支持块级作用域。
  • let:ES6新增的声明变量的方式。let声明的变量是块级作用域,支持变量的重新赋值。
  • const:ES6新增的声明变量的方式。const声明的变量是块级作用域,不支持变量的重新赋值,但是声明的对象和数组可以修改属性。
var a = 10;
let b = 'hello';
const c = [1, 2, 3];

console.log(a); // 10
console.log(b); // 'hello'
console.log(c); // [1, 2, 3]

a = 20;
b = 'world'
c[0] = 4;

console.log(a); // 20
console.log(b); // 'world'
console.log(c); // [4, 2, 3]

3. 数据类型

JS有7种数据类型:

  • Number:数值型,包括整数、浮点数和NaN(表示不是数值)。
  • String:字符串型,由一串字符组成。
  • Boolean:布尔型,有两个取值True和False。
  • Undefined:未定义型,表示变量未被声明或变量值未被赋值。
  • Null:空值型,表示没有值。
  • Object:对象型,由多个属性和方法组成。
  • Symbol:符号型,ES6新增的数据类型,表示唯一的、不可变的值。
const a = 123;
const b = 'hello';
const c = true;
let d;
const e = null;
const f = { name: 'John', age: 20 };
const g = Symbol();

console.log(typeof a); // 'number'
console.log(typeof b); // 'string'
console.log(typeof c); // 'boolean'
console.log(typeof d); // 'undefined'
console.log(typeof e); // 'object'
console.log(typeof f); // 'object'
console.log(typeof g); // 'symbol'

4. 运算符

JS支持多种运算符:

  • 算数运算符:+、-、*、/、%、++、--。
  • 比较运算符:==、===、!=、!==、<、<=、>、>=。
  • 逻辑运算符:&&(与)、||(或)、!(非)。
  • 位运算符:&、|、^、~、<<、>>、>>>。
  • 赋值运算符:=、+=、-=、*=、/=、%=。
  • 条件运算符(三目运算符):condition ? val1 : val2。
let a = 10;
let b = 20;

console.log(a + b); // 30
console.log(a < b); // true
console.log(a === b); // false
console.log((a > b) || (a === 10)); // true
console.log(~a); // -11
console.log(a += 5); // 15
console.log(a > b ? 'a大于b' : 'a小于等于b'); // 'a小于等于b'

5. 函数

JS中函数是一种可重复利用的代码片段,可以接收参数,执行特定的任务。函数可以无参或多参,也可以有返回值或没有返回值。函数声明的方式有两种:

  • 函数声明式
  • 函数表达式
// 声明式函数
function add(a, b) {
    return a + b;
}

// 表达式函数
const subtract = function(a, b) {
    return a - b;
};

console.log(add(10, 20)); // 30
console.log(subtract(30, 10)); // 20

6. 对象

JS中对象是一种复合类型,可以存储多个属性和方法。属性可以是基本数据类型、对象、函数等等。对象属性名可以是字符串或Symbol类型。

const person = {
    name: 'John',
    age: 20,
    address: {
        province: 'Guangdong',
        city: 'Shenzhen'
    },
    sayHello() {
        console.log(`Hello, my name is ${this.name}, I'm ${this.age} years old.`);
    }
};

console.log(person.name); // 'John'
console.log(person.address.city); // 'Shenzhen'
person.sayHello(); // 'Hello, my name is John, I'm 20 years old.'

二、JS是如何执行的

JS的执行分为两个阶段:

  • 解析:JS代码被读入到浏览器中,解析成语法树。
  • 执行:根据语法树,逐行执行代码,实现代码的具体功能。

1. 解析阶段

解析阶段分为两个部分:

  • 分词/词法分析:将整个代码字符串拆分成有意义的代码块,即词法单元。
  • 解析/语法分析:将词法单元构建成抽象语法树(Abstract Syntax Tree,AST),即语法树。

词法单元通常是一个关键字、标识符、运算符或者符号,如下:

const a = 10;
const b = 20;

a + b;

上面的代码会首先被拆成以下词法单元:

const、a、=、10、;、const、b、=、20、;、a、+、b、;

然后JS引擎将词法单元构建成语法树:

    +
  /   \
a     b

2. 执行阶段

JS引擎在执行时,会逐行执行语法树上的节点,将语法树转化为操作系统能够执行的机器码,实现代码的具体功能。在执行过程中,JS会自上而下、自左而右依次执行语句,遇到函数调用、异步请求等情况时,JS引擎会将这些代码放入一个任务队列,并在合适的时机执行。这种方式被称为事件循环机制。

在执行阶段,JS也会对变量和函数进行变量提升,将变量和函数的声明提升到作用域顶部,保证变量可以在声明之前被使用。

三、JS的进阶知识点

1. this指针

在JS中,this是一个关键字,代表当前对象。this指针的指向由函数的调用方式决定。当函数作为对象的方法调用时,this指向的是对象本身;当函数独立调用时,this指向的是全局对象,在浏览器中通常是window对象;当使用bind、call或apply方法显式指定函数的this指向时,this就指向绑定的对象。

2. 闭包

闭包是指一个函数可以访问其声明时的作用域,即使该函数在其他作用域中调用也同样可行。闭包可以用来创建私有变量,以及延长变量生命周期等。

3. 原型和原型链

在JS中,每个对象都有一个原型对象,原型对象又包含一个指向另一个原型对象的指针,因此形成了一个原型链。原型链的作用是让函数表现出继承的特性,可以实现类似于面向对象中的继承关系。

4. 异步编程

JS中的异步编程通常使用回调函数、Promise和ES6中引入的async/await等方式实现。异步编程可以大大提高程序的性能和用户体验,避免程序因为等待I/O操作而被阻塞。

5. 模块化

JS中的模块化机制可以让程序的各个模块之间解耦,提高代码的复用性和可维护性。目前使用最广泛的模块化标准是CommonJS和ES6 Modules。

6. 函数式编程

函数式编程是一种以函数为基本组件的编程范式,强调无副作用和不可变性等概念。JS可以使用高阶函数、闭包等方法实现函数式编程的思想。