前端语言串讲 | 青训营笔记

80 阅读8分钟

前端语言基本能力

前端三剑客 ———— HTML(超文本标记语言)、CSS(级联样式表)、JS(脚本语言,用于在浏览器中增加交互性和动态效果)

image.png

HTML

HTML 不是一门编程语言,而是一种用于定义内容结构的标记语言。HTML 由一系列的元素组成,这些元素可以用来包围不同部分的内容,使其以某种方式呈现或者工作。一对标签可以为一段文字或者一张图片添加超链接,将文字设置为斜体,改变字号,等等。

CSS

和 HTML 类似,CSS 也不是真正的编程语言,甚至不是标记语言。它是一门样式表语言,这也就是说人们可以用它来选择性地为 HTML 元素添加样式。

JavaScript

image.png

数据类型

七种基本数据类型:(两大类)原始类型(Primitive)和对象类型(Object)。

> 原始类型

  1. Number(数字): 用于表示整数和浮点数。在 JS 中,所有数字都是双精度浮点数(64位),意味着 JavaScript 中并没有真正的整数类型。特殊值:Infinity(正无穷大)、-Infinity(负无穷大)和 NaN(非数值)
  2. String(字符串): String 类型表示一串字符。在 JavaScript 中,字符串是不可变的,这意味着一旦创建了一个字符串,就不能对其内容进行修改。
  3. Boolean(布尔值): Boolean 类型只有两个值:true(真)和 false(假)。
  4. Null(空值):表示一个空值或不存在的引用。通常用于表示变量没有被赋值,或表示一个空对象。
  5. Undefined(未定义):当一个变量声明了,但尚未赋值时,其默认值为 undefined,表示变量的值尚未确定。
  6. Symbol(符号): Symbol 类型是 ECMAScript 6引入的新类型。Symbol 类型的值是唯一且不可变的,主要用于创建对象的唯一属性名,以防止属性名冲突。

> 对象类型

  1. Object(对象): Object 类型用于表示复杂的数据结构,如对象、数组和函数。对象是键值对的集合,键是字符串,值可以是任何数据类型。数组是值的有序集合,而函数是可调用的代码块。

在 JavaScript 中,原始类型是不可变的基本数据类型,而对象类型(Object)是可变的引用数据类型

声明赋值

3种声明变量的方法:

juejin.cn/post/699283… juejin.cn/post/684490…

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

Object

在 JavaScript 中,Object(对象)是一种引用数据类型,用于表示一组键值对。对象可以用来存储和操作数据,它是 JavaScript 中最基本和重要的数据结构。

image.png

  • 属性访问(Property Access): 可以使用点表示法(Dot Notation)或方括号表示法(Bracket Notation)访问对象的属性。
  • 属性操作(Property Manipulation): 可以通过赋值操作符为对象添加新属性,也可以通过赋值操作符修改现有属性的值。要删除对象的属性,可以使用 delete 操作符。
  • 方法(Method): 对象的属性值可以是函数。这种类型的属性称为方法(Method)。方法通常用于表示对象的行为,它们可以访问和操作对象的其他属性。

function

1、函数声明

JS 函数声明需要以 function 关键字开头,之后为要创建的函数名称,function 关键字与函数名称之间使用空格分开,函数名之后为一个括号( ),括号中用来定义函数中要使用的参数(多个参数之间使用逗号,分隔开),一个函数最多可以有 255 个参数,最后为一个花括号{ },花括号中用来定义函数的函数体(即实现函数的代码),如下所示:

function sayHello(name){
    document.write("Hello " + name);
}

2、函数表达式

函数表达式是另一种定义函数的方法。函数表达式将一个匿名函数赋值给一个变量。

var myfunction = function name(parameter_list){  
    // 函数中的代码  
};

函数声明和函数表达式虽然看起来非常相似,但它们的运行方式是不同的,如下例所示:

declaration();         //正常输出 declaration
function declaration() {
    document.write("function declaration");
}
expression();          // 报错:Uncaught TypeError: undefined is not a function
var expression = function() {
   document.write("function expression");
};

如上例所示,如果函数表达式在定义之前被调用,会抛出异常(报错),但函数声明则可以成功运行。这是因为在程序执行前,JavaScript 会先对函数声明进行解析,因此无论是在函数声明前还是声明后调用函数都是可行的。而函数表达式则是将一个匿名函数赋值给一个变量,所以在程序还没有执行到该表达式之前,相当于函数还未定义,因此无法调用。

3、箭头函数

ECMAScript 6(ES2015)引入的一种简洁的函数语法。箭头函数使用 => 符号,它可以使代码更简洁、易读。

const greet = (name) => {
  console.log("Hello, " + name); 
};

三剑客在浏览器中的运行

image.png

  1. HTTP 请求:浏览器向服务器发送请求,获取网页的 HTML、CSS、JavaScript 文件以及其他资源(如图片、字体等)。
  2. 构建 DOM 树:浏览器解析 HTML 文件,构建一个 DOM(Document Object Model)树。DOM 树是一个以节点形式表示的 HTML 文档结构。每个节点代表 HTML 文档中的一个元素、属性或文本。
  3. 计算 CSS 树:浏览器解析 CSS 文件,构建一个 CSSOM(CSS Object Model)树。CSSOM 树是一个以节点形式表示的 CSS 规则结构。
  4. 排版(Layout):浏览器将 DOM 树和 CSSOM 树结合,生成一个渲染树(Render Tree)。渲染树包含了 DOM 中的可见元素及其对应的 CSS 规则。接着,浏览器会计算渲染树中每个节点的位置和大小,这个过程称为排版或布局(Layout)。
  5. 渲染合成:浏览器将渲染树中的各个节点分层,创建渲染层(Render Layers)。每个层包含一个或多个节点,具有独立的绘制和合成上下文。
  6. 绘制(Painting):浏览器根据渲染层绘制每个节点的视觉效果(如文本、颜色、图像、边框、阴影等),生成位图(Bitmaps)。绘制过程可能会在 GPU(图形处理器)上完成,以提高性能。
  7. 合成(Compositing):浏览器将渲染层的位图合成为一个完整的屏幕图像,然后显示在屏幕上。合成过程通常由 GPU 完成,以实现高效的图像合成。

在这个过程中,JavaScript 代码的解析与执行可能穿插在各个阶段,因为 JavaScript 可以操作 DOM、CSSOM 和浏览器 API,从而改变页面的内容、样式和交互行为。这些变化可能需要浏览器重新执行排版、绘制和合成等任务。因此,在编写 JavaScript 代码时,应尽量减少对 DOM 和 CSSOM 的操作,以提高页面性能。

前端语言的协作配合

CSS in HTML

image.png

JS in HTML

image.png

JavaScript 是单线程的,意味着在一个时间点只能执行一个任务。为了处理异步操作和事件回调,JavaScript 引入了事件循环(Event Loop)。事件循环使用任务队列(Task Queues)来管理要执行的任务。任务队列分为两种类型:宏任务队列(Macro-Task Queue)和微任务队列(Micro-Task Queue)。

  1. 宏任务队列(Macro-Task Queue): 宏任务队列存放宏任务(Macro-Task),它们通常是由外部事件触发的较大的任务。例如:

  • setTimeout 和 setInterval 的回调函数
  • I/O 操作(如文件读写、网络请求等)的回调函数
  • 用户交互事件(如点击、滚动等)的回调函数
  • 其他异步 API 的回调函数

事件循环会按顺序执行宏任务队列中的任务。当一个宏任务执行完毕后,事件循环会检查微任务队列,执行其中的所有任务,然后再执行下一个宏任务。

  1. 微任务队列(Micro-Task Queue): 微任务队列存放微任务(Micro-Task),它们通常是 JavaScript 代码中产生的较小的、需要尽快执行的任务。例如:

  • Promise 的 then、catch 和 finally 回调函数
  • async/await
  • MutationObserver 的回调函数
  • 其他微任务 API

当事件循环执行一个宏任务后,它会检查微任务队列。在执行下一个宏任务之前,事件循环会一直执行微任务队列中的所有任务,直到微任务队列为空。这意味着在两个宏任务之间,JavaScript 会尽可能多地执行微任务。

事件循环的执行顺序如下:

  1. 从宏任务队列中取出一个任务并执行。
  2. 检查微任务队列,执行其中的所有任务。
  3. 如果有必要,进行渲染操作(如更新 DOM、执行动画等)。
  4. 返回第 1 步,重复执行。

通过区分宏任务和微任务,事件循环可以实现对异步操作和事件回调的有效管理。微任务队列确保了在宏任务之间可以尽快执行一些紧急的、短小的任务,从而提高了整体性能。

image.png