深入理解JS | 青训营笔记

195 阅读7分钟

JS的基本概念

诞生:1995年,Brendan Eich开发

  1. 借鉴C语言的基本语法
  2. 借鉴Java语言的数据类型和内存管理
  3. 借鉴Scheme语言,将函数提升到"第一等公民”(first class)的地位
  4. 借鉴Self语言,使用基于原型 (prototype)的继承机制

发展:

  1. Mocha>1995.9.LiveScript >1995.12 JavaScript
  2. 1997年6月,第一版ECMAScript发布
  3. 1999年12月,第三版ECMAScript发布
  4. 2009年12月,第五版ECMAScript发布
  5. 2009 年,Ryan 创建了Nodejs
  6. 2010年,Isaac基于node.js写出了npm
  7. 2015年6月,第六版ECMAScript发布

JS的基本概念-数据类型



图片.png


JavaScript中有7种基本数据类型,以及1个复杂数据类型:

  1. Number(数字型):表示数值,包括整数和浮点数;
  2. String(字符串型):表示文本字符序列,通常用单引号或双引号括起来;
  3. Boolean(布尔型):只有两个值,true和false,用于逻辑判断;
  4. Undefined(未定义型):表示变量被声明了但没有赋值,默认值是 undefined;
  5. Null(空值型):表示故意赋值为空的变量,其值为 null;
  6. Symbol(符号型):在ES6中新增,通过Symbol()函数创建唯一的、不可变的值;
  7. BigInt(大整数型):在ES10中新增,用于精度较高的整数计算。
  8. Object(对象型):表示一组键值的集合,可以存储多种类型的数据,并提供了方法来操作这些数据。

JS的基本概念-作用域

在 JavaScript 中,作用域是指变量在代码中的可访问范围。常见的作用域包括全局作用域和函数作用域。

全局作用域表示变量可以在整个程序代码中被访问。如果一个变量不是在任何一个函数内部定义的,那么它就是在全局作用域中定义的。可以使用 var、let 或 const 关键字声明全局变量,例如:

var globalVar = 'This is a global variable';

function test() {
  console.log(globalVar); // 输出:This is a global variable
}

test();


函数作用域表示变量只能在函数内部被访问,这种作用域在函数被执行时才会创建,并在函数执行结束后销毁。可以使用 var、let 或 const 关键字声明函数内部的变量,例如:

function test() {
  var localVar = 'This is a local variable';
  console.log(localVar); // 输出:This is a local variable
}

test();
console.log(localVar); // 报错:localVar is not defined


在 ES6 中引入了块级作用域概念,即 let 和 const 声明的变量具有块级作用域,仅在其声明的花括号{}内有效。例如:

for (let i = 0; i < 5; i++) {
  console.log(i); // 输出:0 1 2 3 4
}

console.log(i); // 报错:i is not defined


JS的基本概念-变量提升

变量声明(var、let、const):变量声明会被提升到当前作用域的顶部,并被赋值为 undefined(如果是 var 声明的变量)或保持未定义(如果是 let 或 const 声明的变量),直到代码运行到实际声明语句位置。

例如:

console.log(a); // 输出:undefined
var a = 10;

console.log(b); // 报错:b is not defined
let b = 20;


函数声明:函数声明也会被提升到当前作用域的顶部,可以在声明之前调用函数。

例如:

foo(); // 输出:Hello, world!
function foo() {
  console.log('Hello, world!');
}

  • 但仅针对函数声明而言,函数表达式不会被提升。

虽然变量和函数声明会被提升,但它们并不是真正的代码执行,只是在当前作用域中被提前声明。



JS是怎么执行的

图片.png

JavaScript 的执行过程可以进一步细分为以下几个步骤:

  1. 词法分析:将代码分解成单独的词法单元,例如关键字、变量名、操作符等。
  2. 语法分析:将词法单元组织成语法结构,例如语句、表达式等。这个过程会生成抽象语法树(AST)。
  3. 代码生成:将 AST 转换成可执行的字节码或机器码。
  4. 执行代码:按顺序执行生成的字节码或机器码。

在执行代码的过程中,引擎会维护一个执行上下文栈,每当执行一个函数时,就会创建一个执行上下文,将其压入栈中,待执行完毕后,再将其弹出栈。执行上下文包括函数的作用域、变量、参数等信息。在执行函数时,引擎会从栈顶取出对应的执行上下文,并将其设置为当前执行上下文。



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

  • 创建变量对象:JavaScript引擎会在进入执行上下文时创建一个变量对象,用于存储在当前上下文中声明的变量和函数。

  • 确定作用域链:JavaScript引擎会在创建变量对象后,根据当前上下文的嵌套关系,确定作用域链。

  • 确定this的值:JavaScript引擎会根据当前函数的调用方式,确定this的值。



JS的进阶知识点


JS的进阶知识点-闭包

闭包通常由两部分组成:内部函数和外部函数。当内层函数引用外层函数中的变量时,JavaScript 引擎会创建一个闭包,将这些变量保存起来以备后续使用,并且保证内层函数对这些变量的修改不会影响到外层函数和其他函数对这些变量的访问。

function add() {
  var count = 0; // 外层函数 add 的局部变量
  function plusOne() {count += 1;} // 内层函数 plusOne 引用了 count
  plusOne(); // 第一次调用 plusOne 函数后,count 变量的值加 1,变成 1
  return function () {count += 1; return count;} // 返回闭包函数,通过闭包访问 count 变量
}

var counter = add(); // 调用 add 函数,返回闭包函数并将其赋值给 counter
console.log(counter()); // 输出 2,counter 函数引用了外层函数 add 中的变量 count
console.log(counter()); // 输出 3
console.log(counter()); // 输出 4

在这段代码中,内层函数 plusOne() 引用了外层函数 add() 中的变量 count,因此 count 变成了闭包。当 add() 返回时,它返回了一个指向闭包中变量 count的匿名函数。这样,外界可以通过调用闭包函数持续地增加 count 的值,并且这些对外层函数 add() 中的 count 值的修改都被保存下来。


JS的进阶知识点-this



图片.png

普通函数的this指向windows



图片.png

对象调用指向对象

先赋值再调用



图片.png

创建临时对象

将this指向临时对象

执行构造函数

返回临时对象


JS的进阶知识点-垃圾回收

图片.png



总结


JavaScript是一门广泛应用于Web前端开发的脚本语言,它可以用于创建动态网页、响应用户交互、实现客户端数据验证和动态效果等。JS的发展历程可以追溯到1995年,由网景公司的Brendan Eich创造。目前,JS已经成为Web前端开发的核心技术之一,得到了广泛应用。
  • JS的语言特点
    JS是一门解释型脚本语言,不需要编译,直接在浏览器中解释执行。它支持面向对象编程和函数式编程范式,具有动态类型、弱类型、灵活性、可扩展性、易学易用等特点。JS还支持闭包、原型链、异步编程等高级特性,可用于开发复杂应用程序。

  • JS的数据类型
    JS的数据类型包括基本数据类型和复杂数据类型。基本数据类型包括数字、字符串、布尔值、null和undefined。复杂数据类型包括对象、数组和函数。JS的数据类型可以动态转换,如将数字转换为字符串,将字符串转换为布尔值等。

  • JS的作用域和闭包
    JS的作用域分为全局作用域和局部作用域。变量的作用域可以通过关键字var、let、const等来定义。JS中的闭包是指在函数内部定义函数,并返回该函数的引用。闭包可以访问该函数内部的变量和函数,从而实现了数据的封装和保护。

  • JS的垃圾回收
    JS的垃圾回收是指自动回收不再使用的内存空间,包括标记清除和引用计数算法。现代浏览器还采用了增量标记、分代回收等优化技术,提高了垃圾回收的效率和性能。

所以JavaScript 是一门强大、灵活、易用的语言,可以实现各种类型的应用程序。掌握 JavaScript 的基础知识、语法和常用框架,可以实现各种类型的应用程序。