JavaScript | 爬虫逆向 | 掌握基础 | 01

发布于:2025-03-22 ⋅ 阅读:(101) ⋅ 点赞:(0)

一、摘要

在这里插入图片描述

实践是最好的导师

二、环境配置

在开始之前,需要确保你的计算机上已经安装了 Node.js。Node.js 是一个开源的、跨平台的 JavaScript 运行时环境,它允许你在服务器端运行 JavaScript 代码。

1. 下载

安装地址:https://nodejs.org/zh-cn/download

安装稳定版本,选择windows 64位:

根据你的操作系统(Windows、macOS 或 Linux),选择对应的安装包。
例如,如果你使用的是 Windows 系统,点击 “Windows Installer” 按钮下载 .msi 安装程序。
下载完成后,运行安装程序。在安装过程中,你可以选择默认的安装路径,也可以自定义路径。
安装程序会自动安装 Node.js 和 npm(Node.js 的包管理工具)。

在这里插入图片描述

下载好进行一直下一步即可

2. 配置环境

2.1 配置系统环境

为你刚刚安装node环境的位置

在这里插入图片描述

验证是否成功

在这里插入图片描述

2.2 pycharm环境变量

在这里插入图片描述

配置 Node.js 解释器,为前面安装node的路径

在这里插入图片描述
验证环境,新建一个脚本运行即可
在这里插入图片描述

2.3 浏览器安装

chorme浏览器

https://google.cn/intl/zh-CN_ALL/chrome/fallback/

三、JavaScript组成部分

在这里插入图片描述

JavaScript 由 ECMAScript(核心语法)、DOM(文档对象模型)、BOM(浏览器对象模型)、JavaScript 引擎、运行时环境以及庞大的生态系统组成。这些部分共同构成了完整的 JavaScript 语言体系,使其能够满足从简单的网页交互到复杂的服务器端应用程序开发的各种需求。

JavaScript 是一种功能强大的编程语言,广泛应用于 Web 开发以及其他领域。它由以下几个主要部分组成,这些部分共同构成了完整的 JavaScript 语言体系。

1.ECMAScript(核心语法)

ECMAScript 是 JavaScript 的核心规范,定义了语言的基本语法、数据类型、操作符、控制结构、函数、对象等基础特性。它是 JavaScript 的“核心”,为 JavaScript 提供了运行的基础。

1.1 数据类型

JavaScript 中有以下几种数据类型:

  1. 基本数据类型

    • String(字符串):用于表示文本数据,例如 "Hello, World!"
    • Number(数字):用于表示数值,例如 423.14
    • Boolean(布尔值):用于表示逻辑值,只有两个值:truefalse
    • Undefined(未定义):表示变量已声明但未初始化,例如 let x;
    • Null(空值):表示“无”,是一个特殊的值,例如 let y = null;
    • Symbol(ES6 新增):表示一个唯一的、不可变的数据类型,常用于对象属性的键。
    • BigInt(ES2020 新增):用于表示大于 2^53 - 1 的整数。
  2. 复杂数据类型

    • Object(对象):用于表示一组键值对的集合,例如 { name: "John", age: 25 }
    • Array(数组):用于表示一组有序的值的集合,例如 [1, 2, 3, 4, 5]
    • Function(函数):用于封装可重复使用的代码块,例如 function add(a, b) { return a + b; }

1.2 控制结构

JavaScript 提供了多种控制结构,用于控制程序的执行流程:

  • 条件语句
    if (condition) {
      // 如果条件为真,执行这里的代码
    } else if (anotherCondition) {
      // 如果另一个条件为真,执行这里的代码
    } else {
      // 如果所有条件都不满足,执行这里的代码
    }
    
  • 循环语句
    // for 循环
    for (let i = 0; i < 5; i++) {
      console.log(i);
    }
    
    // while 循环
    let i = 0;
    while (i < 5) {
      console.log(i);
      i++;
    }
    
    // do-while 循环
    let j = 0;
    do {
      console.log(j);
      j++;
    } while (j < 5);
    

1.3 函数

函数是 JavaScript 中的基本构建块,用于封装可重复使用的代码块。JavaScript 中的函数是一等公民,可以作为变量赋值、作为参数传递或作为返回值。

function add(a, b) {
  return a + b;
}

const result = add(3, 4); // 调用函数
console.log(result); // 输出 7

1.4 模块(ES6 引入)

模块用于组织和管理代码,避免命名冲突,提高代码的可维护性。

// myModule.js
export function sayHello(name) {
  return `Hello, ${name}!`;
}

// main.js
import { sayHello } from "./myModule.js";
console.log(sayHello("John")); // 输出 Hello, John!

2. DOM(文档对象模型)

DOM 是一个与平台和语言无关的接口,用于表示和操作 HTML 或 XML 文档。它将文档表示为一个树形结构,其中每个节点代表文档的一部分(如元素、属性或文本)。

2.1 DOM 树结构

HTML 文档被解析为一个 DOM 树,树的根节点是 document 对象。例如,对于以下 HTML 文档:

<!DOCTYPE html>
<html>
  <head>
    <title>My Page</title>
  </head>
  <body>
    <h1>Hello, World!</h1>
    <p>This is a paragraph.</p>
  </body>
</html>

其 DOM 树结构如下:

document
  |
  +-- html
        |
        +-- head
        |     |
        |     +-- title
        |           |
        |           +-- "My Page"
        |
        +-- body
              |
              +-- h1
              |    |
              |    +-- "Hello, World!"
              |
              +-- p
                   |
                   +-- "This is a paragraph."

2.2 DOM 操作

通过 JavaScript,可以操作 DOM 树,实现动态更新网页内容、修改样式、添加或删除元素等功能。

// 获取元素
const heading = document.querySelector("h1");
console.log(heading.textContent); // 输出 Hello, World!

// 修改元素内容
heading.textContent = "New Heading";

// 修改样式
heading.style.color = "red";

// 添加新元素
const newParagraph = document.createElement("p");
newParagraph.textContent = "This is a new paragraph.";
document.body.appendChild(newParagraph);

// 删除元素
const oldParagraph = document.querySelector("p");
document.body.removeChild(oldParagraph);

3. BOM(浏览器对象模型)

BOM 是浏览器对象模型,它提供了与浏览器窗口相关的对象和接口,用于操作浏览器窗口、管理浏览器历史记录、与浏览器插件交互等。

下面举例一下对象,后续会有在爬虫中举例别的

3.1 window 对象

window 对象是 BOM 的核心,代表浏览器窗口。它是 JavaScript 的全局对象,所有未明确指定作用域的变量和函数都属于 window 对象。

// 打开新窗口
const newWindow = window.open("https://example.com", "_blank");

// 关闭窗口
// newWindow.close();

// 获取窗口大小
console.log(window.innerWidth); // 获取窗口的内部宽度
console.log(window.innerHeight); // 获取窗口的内部高度

// 监听窗口事件
window.addEventListener("resize", () => {
  console.log("Window resized!");
});

3.2 location 对象

location 对象提供了与当前窗口的 URL 相关的信息,可以用于获取和修改当前页面的地址。

console.log(window.location.href); // 获取当前页面的完整 URL
console.log(window.location.pathname); // 获取当前页面的路径部分

// 跳转到新页面
window.location.href = "https://example.com";

// 重新加载页面
window.location.reload();

3.3 navigator 对象

navigator 对象提供了有关浏览器的信息,例如浏览器的名称、版本、用户代理字符串等。

console.log(window.navigator.userAgent); // 获取用户代理字符串
console.log(window.navigator.language); // 获取浏览器的语言

3.4 history 对象

history 对象提供了对浏览器历史记录的访问,可以用于导航历史记录。

// 后退到上一个页面
window.history.back();

// 前进到下一个页面
window.history.forward();

// 添加历史记录条目(HTML5 新增)
window.history.pushState({ state: "newState" }, "New Title", "/new-url");

四、JavaScript语言基础

本章节目录较多 以 【】来强调为目录

官方文档:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Introduction

在这里插入图片描述

建议有时间每天都阅读一下,本章节为爬虫必要掌握内容

1.【注释】

单行注释

var a = 1; // 单行注释

多行注释

console.log("你好")
/* 
var a = 1;
var a = 1;
var a = 1;
*/

2. 【语句】

var a = 1 // 
var b = 2; // 

加分号有助于避免代码省略造成错误,以及压缩代码,提升性能的作用

3. 【关键字与保留字】

在 JavaScript 中,关键字和保留字是两种特殊的词汇,它们在语法解析和代码执行中具有特殊的意义。
所以在写JavaScript代码中,定义变量的时候不要用以下内容

3.1 关键字

关键字 用途描述
break 用于终止循环或 switch 语句
case 用于 switch 语句中匹配值
catch 用于异常处理中的捕获块
class 用于定义类
const 用于声明常量
continue 用于跳过当前循环的迭代
debugger 用于调试代码
default 用于 switch 语句中的默认分支
delete 用于删除对象的属性
do 用于 do...while 循环的开始
else 用于 if 语句的分支条件
export 用于模块化导出变量、函数或类
extends 用于类继承
finally 用于异常处理中的最终执行块
for 用于循环语句
function 用于声明函数
if 用于条件语句
import 用于模块化导入变量、函数或类
in 用于 for...in 循环中检查对象的属性
instanceof 用于检查对象是否为某个类的实例
new 用于创建对象实例
return 用于从函数返回值
super 用于调用父类的构造函数或方法
switch 用于多分支条件语句
this 用于指向当前对象实例
throw 用于抛出异常
try 用于异常处理中的尝试块
typeof 用于获取变量的类型
var 用于声明变量
void 用于返回 undefined,常用于清除链接的 href
while 用于循环语句
with 用于扩展作用域链(不推荐使用)

3.2 保留字

保留字 用途描述
enum 未来可能用于枚举类型(目前未使用)
await 用于异步函数中暂停执行(在模块或严格模式下是关键字)
implements 未来可能用于接口实现(目前未使用)
interface 未来可能用于接口定义(目前未使用)
let 用于声明块级作用域变量
package 未来可能用于包管理(目前未使用)
private 用于类中的私有成员(ES2022 引入)
protected 用于类中的受保护成员(ES2022 引入)
public 用于类中的公有成员(ES2022 引入)
static 用于定义静态方法或属性
yield 用于生成器函数中暂停和恢复执行

3.3 区分关键字和保留字的原因

  1. 语法解析的需要
    • 关键字:关键字是 JavaScript 语言的核心组成部分,它们在语法解析中具有明确的语义和功能。例如,if 用于条件语句,for 用于循环语句。如果允许开发者将这些关键字用作变量名或函数名,解析器将无法正确区分它们的用途,导致语法错误。
    • 保留字:保留字是语言设计者预留的词汇,未来可能会赋予它们特定的功能。例如,enum 是一个保留字,虽然目前没有使用,但语言设计者可能在未来版本中引入枚举类型。保留这些词汇可以避免未来版本中引入新功能时与现有代码冲突。
  2. 代码可读性和一致性
    • 使用关键字和保留字作为变量名或函数名会导致代码可读性降低。例如,将 for 用作变量名,会让其他开发者难以理解代码的意图。通过区分关键字和保留字,可以确保代码的清晰性和一致性。
  3. 避免歧义
    • 关键字和保留字在语法解析中具有明确的语义,如果允许它们用作普通标识符,可能会导致解析器的歧义。例如,class 是一个关键字,用于定义类。如果允许将 class 用作变量名,解析器在遇到 class 时将无法确定它是用于定义类还是作为变量名,从而导致语法错误。
  4. 语言设计的灵活性
    • 保留字为语言的未来发展提供了灵活性。语言设计者可以在未来的版本中引入新的功能,而不用担心与现有代码冲突。例如,ES2015 引入了 letconst 作为关键字,用于声明块级作用域变量。如果这些词汇在早期版本中被用作普通标识符,那么引入新功能时就会面临兼容性问题。

4. 【变量声明与作用域】

声明方式 作用域 特性
var 函数作用域 存在变量提升,可重复声明
let 块级作用域 无变量提升,不可重复声明
const 块级作用域 无变量提升,声明后不可修改

varletconst 是 JavaScript 中用于声明变量的三种方式,它们在作用域、提升行为、可变性等方面存在显着区别。以下是它们的详细对比:

  • var:具有函数作用域或全局作用域,存在变量提升和全局污染问题,尽量少用。
  • let:具有块级作用域,不存在变量提升,可以重新赋值,适用于需要重新赋值的变量。
  • const:具有块级作用域,不存在变量提升,不能重新赋值,适用于常量或不需要重新赋值的变量。

4.1. 作用域

特性 var let const
全局作用域 声明的变量属于全局对象(windowglobal),在全局范围内可访问。 声明的变量仅在块级作用域内有效(如 {} 内)。 声明的变量仅在块级作用域内有效(如 {} 内)。
函数作用域 在函数内声明的变量仅在该函数内有效。 在函数内声明的变量仅在该函数内有效。 在函数内声明的变量仅在该函数内有效。
块级作用域 无块级作用域,变量会提升到最近的函数或全局作用域。 支持块级作用域,变量仅在 {} 内有效。 支持块级作用域,变量仅在 {} 内有效。

示例:

if (true) {
  var a = 1;
  let b = 2;
  const c = 3;
}
console.log(a); // 1,因为 var 被提升到全局作用域
console.log(b); // ReferenceError,b 仅在块级作用域内有效
console.log(c); // ReferenceError,c 仅在块级作用域内有效

4.2. 变量提升(Hoisting)

特性 var let const
变量提升 声明和初始化都会被提升到函数或全局作用域的顶部。 声明会被提升,但初始化不会。在声明之前访问会报 ReferenceError 声明会被提升,但初始化不会。在声明之前访问会报 ReferenceError
临时死区(TDZ) 无临时死区,变量会被初始化为 undefined 有临时死区,从块的开始到变量声明之前,变量不可访问。 有临时死区,从块的开始到变量声明之前,变量不可访问。

示例:

console.log(x); // undefined,var 被提升并初始化为 undefined
console.log(y); // ReferenceError,let 声明之前不可访问
console.log(z); // ReferenceError,const 声明之前不可访问

var x = 10;
let y = 20;
const z = 30;

4.3. 可变性

特性 var let const
可变性 声明的变量可以重新赋值。 声明的变量可以重新赋值。 声明的变量不能重新赋值,但对象或数组的属性或元素可以修改。
重复声明 在同一个作用域内可以重复声明同一个变量。 在同一个作用域内不能重复声明同一个变量。 在同一个作用域内不能重复声明同一个变量。

示例:

var a = 10;
var a = 20; // 合法,重复声明不会报错
console.log(a); // 20

let b = 10;
let b = 20; // SyntaxError,不能重复声明
console.log(b);

const c = 10;
c = 20; // TypeError,不能重新赋值
console.log(c);

const obj = { x: 1 };
obj.x = 2; // 合法,对象的属性可以修改
console.log(obj); // { x: 2 }

5. 【数据类型】

在 JavaScript 中,数据类型分为原始数据类型引用数据类型。引用数据类型是 JavaScript 中非常重要的概念,理解它对于编写高效的爬虫代码、处理动态数据以及应对反爬虫机制至关重要。

  • 原始数据类型:直接存储在栈内存中,变量保存的是实际的值。

  • 引用数据类型:实际数据存储在堆内存中,变量保存的是堆内存的地址(引用)。

扩展阅读

5.1. 原始类型(Primitive Types)

数据类型 描述 示例 常见方法
Number 数值类型,包括整数和浮点数 42, 3.14 toFixed(), toString()
String 字符串类型 "Hello", 'World' charAt(), toUpperCase(), split()
Boolean 布尔类型,truefalse true, false Boolean(value)
Null 表示空值 null -
Undefined 表示未定义的值 undefined -
Symbol 唯一且不可变的值(ES6引入) Symbol('desc') -
5.1.1. String(字符串)
  • 常用方法:
    • length:获取字符串的长度。
      const str = "Hello, World!";
      console.log(str.length); // 输出 13
      
    • charAt(index):获取指定索引位置的字符。
      console.log(str.charAt(7)); // 输出 "W"
      
    • toUpperCase()toLowerCase():将字符串转换为大写或小写。
      console.log(str.toUpperCase()); // 输出 "HELLO, WORLD!"
      console.log(str.toLowerCase()); // 输出 "hello, world!"
      
    • includes(searchString, position):检查字符串是否包含指定子字符串。
      console.log(str.includes("World")); // 输出 true
      console.log(str.includes("world")); // 输出 false
      
    • replace(searchValue, replaceValue):替换字符串中的内容。
      console.log(str.replace("World", "JavaScript")); // 输出 "Hello, JavaScript!"
      
    • split(separator, limit):将字符串分割成数组。
      console.log(str.split(", ")); // 输出 ["Hello", "World!"]
      
5.1.2. Number(数字)
  • 常用方法:
    • toFixed(digits):将数字格式化为指定小数位数的字符串。
      const num = 123.456;
      console.log(num.toFixed(2)); // 输出 "123.46"
      
    • toString():将数字转换为字符串。
      console.log(num.toString()); // 输出 "123.456"
      
    • toPrecision(digits):将数字格式化为指定精度的字符串。
      console.log(num.toPrecision(3)); // 输出 "1.23e+2"
      
    • Math.floor()Math.ceil()Math.round():分别用于向下取整、向上取整和四舍五入。
      console.log(Math.floor(num)); // 输出 123
      console.log(Math.ceil(num)); // 输出 124
      console.log(Math.round(num)); // 输出 123
      
5.1.3. Boolean(布尔值)
  • 常用方法:
    • Boolean(value):将值转换为布尔类型。
      console.log(Boolean("")); // 输出 false
      console.log(Boolean("Hello")); // 输出 true
      console.log(Boolean(0)); // 输出 false
      console.log(Boolean(42)); // 输出 true
      
5.1.4. Undefined
  • 特点:
    • 表示变量已声明但未初始化。
    • 常用于检查变量是否未赋值。
      let x;
      console.log(x === undefined); // 输出 true
      
5.1.5. Null
  • 特点:
    • 表示故意赋予变量的空值。
    • 常用于表示“无值”。
      let y = null;
      console.log(y === null); // 输出 true
      
5.1.6. Symbol(符号)
  • 特点:
    • 表示一个唯一的、不可变的数据类型,常用于对象属性的键。
    • Symbol(description):创建一个新的 Symbol。
      const mySymbol = Symbol("mySymbol");
      console.log(mySymbol); // 输出 Symbol(mySymbol)
      
      

5.2. 引用类型(Reference Types)

数据类型 描述 示例 常见方法
Object 键值对集合 { name: "Alice", age: 25 } Object.keys(), Object.values(), Object.assign()
Array 有序的元素集合 [1, "two", true] push(), pop(), map(), filter()
Function 可执行的代码块 function greet() { console.log("Hello!"); } call(), apply(), bind()
Date 表示日期和时间 new Date() getFullYear(), getMonth(), setFullYear()
RegExp 正则表达式,用于字符串匹配 /pattern/ test(), exec()
Map 键值对集合,键可以是任意类型 new Map([[1, "one"], [2, "two"]]) set(), get(), has(), delete()
Set 唯一值的集合 new Set([1, 2, 3]) add(), has(), delete()
5.2.1. Object(对象)
  • 常用方法:
  • 这个将会是重点,原型链时候会详细讲,也可以看我另外一篇没有重构的文章 https://blog.csdn.net/weixin_44238683/article/details/118503753
    • Object.keys(obj):获取对象的所有键。
      const obj = { a: 1, b: 2, c: 3 };
      console.log(Object.keys(obj)); // 输出 ["a", "b", "c"]
      
    • Object.values(obj):获取对象的所有值。
      console.log(Object.values(obj)); // 输出 [1, 2, 3]
      
    • Object.entries(obj):获取对象的所有键值对。
      console.log(Object.entries(obj)); // 输出 [["a", 1], ["b", 2], ["c", 3]]
      
    • Object.assign(target, ...sources):将多个源对象的属性复制到目标对象。
      const target = { a: 1 };
      const source = { b: 2, c: 3 };
      console.log(Object.assign(target, source)); // 输出 { a: 1, b: 2, c: 3 }
      
5.2.2. Array(数组)
  • 常用方法:
    • push(element):向数组末尾添加元素。
      const arr = [1, 2, 3];
      arr.push(4);
      console.log(arr); // 输出 [1, 2, 3, 4]
      
    • pop():从数组末尾移除元素。
      arr.pop();
      console.log(arr); // 输出 [1, 2, 3]
      
    • shift():从数组开头移除元素。
      arr.shift();
      console.log(arr); // 输出 [2, 3]
      
    • unshift(element):向数组开头添加元素。
      arr.unshift(1);
      console.log(arr); // 输出 [1, 2, 3]
      
    • slice(start, end):从数组中提取部分元素。
      console.log(arr.slice(1, 3)); // 输出 [2, 3]
      
    • map(callback):对数组中的每个元素执行回调函数,并返回新数组。
      const doubled = arr.map((num) => num * 2);
      console.log(doubled); // 输出 [2, 4, 6]
      
    • filter(callback):过滤数组中的元素,返回符合条件的元素组成的新数组。
      const filtered = arr.filter((num) => num > 2);
      console.log(filtered); // 输出 [3]
      
    • reduce(callback, initialValue):对数组中的元素进行累积操作。
      const sum = arr.reduce((acc, num) => acc + num, 0);
      console.log(sum); // 输出 6
      
5.2.3. Function(函数)
  • 常用方法:
    • call(context, ...args):调用函数,并指定上下文。
      function greet() {
        console.log(`Hello, ${this.name}!`);
      }
      greet.call({ name: "Alice" }); // 输出 "Hello, Alice!"
      
    • apply(context, argsArray):调用函数,并指定上下文和参数数组。
      greet.apply({ name: "Bob" }, []); // 输出 "Hello, Bob!"
      
    • bind(context):创建一个新函数,并绑定指定的上下文。
      const greetAlice = greet.bind({ name: "Alice" });
      greetAlice(); // 输出 "Hello, Alice!"
      
5.2.4. Date(日期)
  • 常用方法:
    • new Date():创建一个表示当前日期和时间的日期对象。
      const now = new Date();
      console.log(now); // 输出当前日期和时间
      
      
    • getFullYear()getMonth()getDate():获取日期的各个部分。
      console.log(now.getFullYear()); // 输出当前年份
      console.log(now.getMonth() + 1); // 输出当前月份(从 0 开始)
      console.log(now.getDate()); // 输出当前日期
      
    • setFullYear(year, month, date):设置日期。
      now.setFullYear(2025, 11, 25);
      console.log(now); // 输出 2025-12-25
      
    • getTime():获取当前时间戳。
      const now = new Date();
      console.log(now); // 输出当前日期和时间,例如:2024-05-28T12:34:56.789Z
      console.log(now.getTime()); // 输出当前时间的时间戳,例如:1717000000000
      
5.2.5. RegExp(正则表达式)
  • 常用方法:
    • test(string):测试字符串是否匹配正则表达式。
      const regex = /hello/i;
      console.log(regex.test("Hello, World!")); // 输出 true
      
    • exec(string):执行正则表达式匹配,返回匹配结果。
      const match = regex.exec("Hello")
      
      
      

6 【函数定义与调用】

函数是 JavaScript 中的基本构建块,它是一段可以重复使用的代码,用于执行特定任务。函数可以接受输入参数,并返回一个值。在 JavaScript 中,函数既可以作为独立的实体存在,也可以作为对象的方法被调用。

6.1. 函数的定义

函数的定义方式主要有以下几种:

6.1.1. 函数声明(Function Declaration)

函数声明是通过 function 关键字定义一个函数。这种方式定义的函数会被提升(hoisting),即可以在声明之前调用。

语法:

function functionName(parameters) {
  // 函数体
}

示例:

function greet(name) {
  console.log(`Hello, ${name}!`);
}

greet("Alice"); // 输出 "Hello, Alice!"
6.1.2. 函数表达式(Function Expression)

函数表达式是将函数赋值给一个变量。这种方式定义的函数不会被提升,因此必须在声明之后调用。

语法:

const functionName = function(parameters) {
  // 函数体
};

示例:

const greet = function(name) {
  console.log(`Hello, ${name}!`);
};

greet("wenwenc9"); // 输出 "Hello, wenwenc9!"
6.1.3. 箭头函数(Arrow Function)

箭头函数是 ES6 引入的一种更简洁的函数写法。它没有自己的 this 上下文,而是继承自外部作用域。

语法:

const functionName = (parameters) => {
  // 函数体
};

示例:

const greet = (name) => {
  console.log(`Hello, ${name}!`);
};

greet("Charlie"); // 输出 "Hello, Charlie!"
6.1.4. 方法(Method)

方法是定义在对象上的函数。它可以通过对象调用,并且在方法内部,this 指向该对象。

语法:

const object = {
  methodName(parameters) {
    // 函数体
  }
};

示例:

const user = {
  name: "Alice",
  greet() {
    console.log(`Hello, ${this.name}!`);
  }
};

user.greet(); // 输出 "Hello, Alice!"
6.1.5. 匿名函数(Anonymous Function)

匿名函数是没有名字的函数,通常用于作为参数传递或立即调用。

示例:

const greet = function(name) {
  console.log(`Hello, ${name}!`);
};

greet("David"); // 输出 "Hello, David!"
6.1.6. 立即调用的函数表达式(IIFE)

立即调用的函数表达式是一种在定义后立即执行的函数。它通常用于创建局部作用域,避免变量污染全局作用域。

语法:

(function(parameters) {
  // 函数体
})(arguments);

示例:

(function(name) {
  console.log(`Hello, ${name}!`);
})("Eve"); // 输出 "Hello, Eve!"

6.2. 函数的调用

函数的调用是通过函数名后跟一对圆括号 () 来完成的。调用时可以传递参数,并且函数可以返回值。

6.2.1. 普通调用

直接通过函数名调用。

示例:

function add(a, b) {
  return a + b;
}

const result = add(3, 4); // 调用函数并传递参数
console.log(result); // 输出 7
6.2.2. 作为方法调用

通过对象调用方法时,this 指向该对象。

示例:

const user = {
  name: "Alice",
  greet() {
    console.log(`Hello, ${this.name}!`);
  }
};

user.greet(); // 输出 "Hello, Alice!"
6.2.3. 使用 callapplybind 调用

这些方法可以明确指定函数的上下文(this)。

  • call(context, ...args):调用函数,并指定上下文和参数。
  • apply(context, argsArray):调用函数,并指定上下文和参数数组。
  • bind(context, ...args):创建一个新函数,并绑定指定的上下文和部分参数。

示例:

function greet(message) {
  console.log(`${message}, ${this.name}!`);
}

const user = { name: "Alice" };

greet.call(user, "Hello"); // 输出 "Hello, Alice!"
greet.apply(user, ["Hi"]); // 输出 "Hi, Alice!"

const greetAlice = greet.bind(user, "Hey");
greetAlice(); // 输出 "Hey, Alice!"

6.3. 函数的高级用法

6.3.1. 函数作为参数

函数可以作为参数传递给另一个函数。

示例:

function execute(func, value) {
  return func(value);
}

function double(x) {
  return x * 2;
}

const result = execute(double, 5); // 将 double 函数作为参数传递
console.log(result); // 输出 10
6.3.2. 函数作为返回值

函数可以作为另一个函数的返回值。

示例:

function createMultiplier(factor) {
  return function(number) {
    return number * factor;
  };
}

const double = createMultiplier(2); // 返回一个函数
const triple = createMultiplier(3); // 返回另一个函数

console.log(double(5)); // 输出 10
console.log(triple(5)); // 输出 15
6.3.3. 高阶函数

高阶函数是接受函数作为参数或返回函数的函数。

示例:

function higherOrderFunction(func) {
  return function(...args) {
    console.log(`Calling ${func.name} with arguments: ${args}`);
    return func(...args);
  };
}

const enhancedAdd = higherOrderFunction(add);
console.log(enhancedAdd(3, 4)); // 输出 "Calling add with arguments: 3,4" 和 7
6.5.4. 函数的上下文(this

在函数中,this 的值取决于函数的调用方式。在非严格模式下,this 默认指向全局对象(浏览器中是 window,Node.js 中是 global)。在严格模式下,thisundefined

示例:

function greet() {
  console.log(`Hello, ${this.name}!`);
}

const user = { name: "Alice" };

greet.call(user); // 使用 call 明确指定 this
// 输出 "Hello, Alice!"

6.5. 函数的其他特性

6.5.1. 默认参数

ES6 引入了默认参数,允许在函数声明时为参数指定默认值。

示例:

function greet(name = "Guest") {
  console.log(`Hello, ${name}!`);
}

greet(); // 输出 "Hello, Guest!"
greet("Alice"); // 输出 "Hello, Alice!"
6.5.2. 剩余参数(Rest Parameters)

剩余参数允许将不定数量的参数表示为一个数组。

示例:

function sum(...numbers) {
  return numbers.reduce((acc, num) => acc + num, 0);
}

console.log(sum(1, 2, 3, 4)); // 输出 10
6.5.3. 展开运算符(Spread Operator)

展开运算符可以将数组或对象展开为单独的元素。

示例:

const numbers = [1, 2, 3];
console.log(Math.max(...numbers)); // 输出 3

const obj1 = { a: 1 };
const obj2 = { ...obj1, b: 2 };
console.log(obj2); // 输出 { a: 1, b: 2 }

7【语句】

在 JavaScript 中,语句是构成程序的基本单元,用于执行操作或计算。JavaScript 提供了多种语句类型,用于控制程序的流程、执行条件操作、循环执行代码块等。以下是对 JavaScript 中常见语句类型的详细介绍。

7.4.1. 表达式语句(Expression Statements)

表达式语句是最简单的语句类型,它由一个表达式组成,执行后会返回一个值。

  • 示例:
    let x = 10; // 表达式语句,赋值操作
    console.log(x); // 表达式语句,调用函数
    

7.4.2. 空语句(Empty Statements)

空语句是一个单独的分号,表示一个空的操作,通常用于跳过某些操作。

  • 示例:
    ; // 空语句
    

7.4.3. 块语句(Block Statements)

块语句由一对大括号 {} 包裹的语句序列组成,用于将多个语句组合在一起。

  • 示例:
    {
      let x = 10;
      console.log(x);
    }
    

7.4.4. 条件语句(Conditional Statements)

条件语句用于根据条件执行不同的代码块。

7.4.4.1. if 语句

if 语句用于根据条件执行代码块。

  • 语法:

    if (condition) {
      // 执行的代码块
    }
    
  • 示例:

    let x = 10;
    if (x > 5) {
      console.log("x is greater than 5");
    }
    
7.4.4.2. if...else 语句

if...else 语句用于根据条件选择执行两个代码块中的一个。

  • 语法:

    if (condition) {
      // 条件为真时执行的代码块
    } else {
      // 条件为假时执行的代码块
    }
    
  • 示例:

    let x = 10;
    if (x > 5) {
      console.log("x is greater than 5");
    } else {
      console.log("x is less than or equal to 5");
    }
    
7.4.4.3. switch 语句

switch 语句用于根据变量的值选择执行多个代码块中的一个。

  • 语法:

    switch (expression) {
      case value1:
        // 执行的代码块
        break;
      case value2:
        // 执行的代码块
        break;
      default:
        // 默认执行的代码块
    }
    
  • 示例:

    let day = 3;
    switch (day) {
      case 1:
        console.log("Monday");
        break;
      case 2:
        console.log("Tuesday");
        break;
      case 3:
        console.log("Wednesday");
        break;
      default:
        console.log("Unknown day");
    }
    

7.4.5. 循环语句(Loop Statements)

循环语句用于重复执行代码块,直到满足某个条件为止。

7.4.5.1. while 循环

while 循环在条件为真时重复执行代码块。

  • 语法:

    while (condition) {
      // 执行的代码块
    }
    
  • 示例:

    let i = 0;
    while (i < 5) {
      console.log(i);
      i++;
    }
    
7.4.5.2. do...while 循环

do...while 循环至少执行一次代码块,然后在条件为真时继续执行。

  • 语法:

    do {
      // 执行的代码块
    } while (condition);
    
  • 示例:

    let i = 0;
    do {
      console.log(i);
      i++;
    } while (i < 5);
    
7.4.5.3. for 循环

for 循环在满足条件时重复执行代码块,通常用于遍历数组或对象。

  • 语法:

    for (initialization; condition; increment) {
      // 执行的代码块
    }
    
  • 示例:

    for (let i = 0; i < 5; i++) {
      console.log(i);
    }
    
7.4.5.4. for...in 循环

for...in 循环用于遍历对象的属性。

  • 语法:

    for (variable in object) {
      // 执行的代码块
    }
    
  • 示例:

    const obj = { a: 1, b: 2, c: 3 };
    for (let key in obj) {
      console.log(key, obj[key]);
    }
    
7.4.5.5. for...of 循环

for...of 循环用于遍历可迭代对象(如数组、字符串等)的值。

  • 语法:

    for (variable of iterable) {
      // 执行的代码块
    }
    
  • 示例:

    const arr = [1, 2, 3];
    for (let value of arr) {
      console.log(value);
    }
    

7.4.6. 跳转语句(Jump Statements)

跳转语句用于改变程序的执行流程。

7.4.6.1. break 语句

break 语句用于中断循环或 switch 语句。

  • 示例:
    for (let i = 0; i < 10; i++) {
      if (i === 5) {
        break;
      }
      console.log(i);
    }
    
7.4.6.2. continue 语句

continue 语句用于跳过当前循环的迭代,继续执行下一次迭代。

  • 示例:
    for (let i = 0; i < 10; i++) {
      if (i % 2 === 0) {
        continue;
      }
      console.log(i);
    }
    
7.4.6.3. return 语句

return 语句用于从函数返回值,并结束函数的执行。

  • 示例:
    function add(a, b) {
      return a + b;
    }
    console.log(add(3, 4)); // 输出 7
    
7.4.6.4. throwtry...catch 语句

throw 语句用于抛出异常,try...catch 语句用于捕获和处理异常。

  • 语法:

    try {
      // 尝试执行的代码块
    } catch (error) {
      // 捕获异常后的处理代码块
    }
    
  • 示例:

    try {
      throw new Error("Something went wrong");
    } catch (error) {
      console.error(error.message);
    }
    

7.4.7. 其他语句

7.4.7.1. with 语句

with 语句用于扩展作用域链,但不推荐使用,因为它可能导致代码难以理解和维护。

  • 语法:

    with (object) {
      // 执行的代码块
    }
    
  • 示例:

    const obj = { a: 1, b: 2 };
    with (obj) {
      console.log(a); // 输出 1
      console.log(b); // 输出 2
    }
    
7.4.7.2. debugger 语句

debugger 语句用于在代码中设置断点,方便调试。

  • 示例:
    let x = 10;
    debugger; // 设置断点
    console.log(x);
    
7.4.7.3. label 语句

label 语句用于为语句块

8 运算符

在 JavaScript 中,运算符用于执行各种操作,包括算术运算、比较、逻辑判断等。以下是 JavaScript 中常见的运算符类型及其使用方法。

8.1 算术运算符(Arithmetic Operators)

算术运算符用于执行基本的数学运算。

运算符 描述 示例 结果
+ 加法 5 + 3 8
- 减法 5 - 3 2
* 乘法 5 * 3 15
/ 除法 5 / 3 1.6666666666666667
% 求余 5 % 3 2
++ 自增 let a = 5; a++; a 变为 6
-- 自减 let a = 5; a--; a 变为 4

8.2 比较运算符(Comparison Operators)

比较运算符用于比较两个值,并返回一个布尔值(truefalse)。

运算符 描述 示例 结果
== 等于(值相等) "2" == 2 true
=== 严格等于(值和类型都相等) "2" === 2 false
!= 不等于(值不相等) "2" != 2 false
!== 严格不等于(值或类型不相等) "2" !== 2 true
> 大于 5 > 3 true
< 小于 5 < 3 false
>= 大于等于 5 >= 3 true
<= 小于等于 5 <= 3 false

8.3 逻辑运算符(Logical Operators)

逻辑运算符用于执行逻辑判断,并返回一个布尔值。

运算符 描述 示例 结果
&& 逻辑与(AND) true && false false
` ` 逻辑或(OR)
! 逻辑非(NOT) !true false

8.4 赋值运算符(Assignment Operators)

赋值运算符用于将值赋给变量。

运算符 描述 示例 结果
= 简单赋值 let a = 5; a5
+= 加法赋值 let a = 5; a += 3; a 变为 8
-= 减法赋值 let a = 5; a -= 3; a 变为 2
*= 乘法赋值 let a = 5; a *= 3; a 变为 15
/= 除法赋值 let a = 5; a /= 3; a 变为 1.6666666666666667
%= 求余赋值 let a = 5; a %= 3; a 变为 2

8.5 三元运算符(Ternary Operator)

三元运算符是一种简化的 if...else 语句,用于根据条件返回两个值中的一个。

运算符 描述 示例 结果
? : 三元运算符 let result = condition ? value1 : value2; 根据 condition 的值返回 value1value2

8.6 位运算符(Bitwise Operators)

位运算符用于对数字的二进制表示进行操作。

运算符 描述 示例 结果
& 位与 5 & 3 1
` ` 位或 `5
^ 位异或 5 ^ 3 6
~ 位非 ~5 -6
<< 左移 5 << 1 10
>> 右移 5 >> 1 2
>>> 无符号右移 5 >>> 1 2

8.7 条件运算符(Conditional Operators)

条件运算符用于根据条件执行不同的操作。

运算符 描述 示例 结果
&& 短路与 a && b 如果 a 为真,则返回 b,否则返回 a
` ` 短路或
?? 空值合并运算符 a ?? b 如果 anullundefined,则返回 b,否则返回 a

8.8 其他运算符

还有一些其他运算符,用于特定的操作。

运算符 描述 示例 结果
typeof 返回变量的类型 typeof 5 "number"
delete 删除对象的属性 delete obj.property truefalse
in 检查对象是否有某个属性 "property" in obj truefalse

示例代码

以下是一些示例代码,展示如何使用这些运算符:

// 算术运算符
let a = 5;
let b = 3;
console.log(a + b); // 8
console.log(a - b); // 2
console.log(a * b); // 15
console.log(a / b); // 1.6666666666666667
console.log(a % b); // 2

// 比较运算符
console.log(a == b); // false
console.log(a === b); // false
console.log(a != b); // true
console.log(a !== b); // true
console.log(a > b); // true
console.log(a < b); // false
console.log(a >= b); // true
console.log(a <= b); // false

// 逻辑运算符
console.log(true && false); // false
console.log(true || false); // true
console.log(!true); // false

// 赋值运算符
let c = 5;
c += 3; // c = 8
c -= 3; // c = 5
c *= 3; // c = 15
c /= 3; // c = 5
c %= 3; // c = 2

// 三元运算符
let result = a > b ? "a is greater" : "b is greater";
console.log(result); // "a is greater"

// 位运算符
console.log(5 & 3); // 1
console.log(5