Skip to content

1-js

JavaScript 的组成:

  • ECMAScript: 核心, 语言规范
  • DOM: 文档对象模型
  • BOM: 浏览器对象模型

数据类型

  • 基本数据类型: string number Boolean null undefined symble bigInt
  • 复杂数据类型: array object function date regexp set map Promise

null 和 undefined

  • null 表示一个值被定义了,定义为"空值"
  • undefined 表示根本不存在定义

基本数据类型是按值传递

传递的是===副本===, 不会修改原始数据

js
function modifyValue(x) {
    x = 10; // 修改副本
    console.log(x); // 10
}

let a = 5;
modifyValue(a);
console.log(a); // 5,原始值未改变
  • 函数中不会修改传递进来的基本类型
    • 需要修改, 要么全局变量
    • 函数返回修改后值, 调用函数重新赋值
    • 用对象/数组包装

复杂数据类型是按共享传递

传递的是内存地址的===副本=== 如果是修改对象的属性, 会影响原始数据 如果是赋值, 不会影响原始数据

  • 修改属性
js
function modifyProperty(obj) {
    obj.value = 10; // 修改对象的属性
    console.log(obj.value); // 10
}

let myObj = { value: 5 };
modifyProperty(myObj);
console.log(myObj.value); // 10,原始对象被修改
  • 重新赋值
js
function reassignReference(obj) {
    obj = { value: 10 }; // 重新赋值引用副本
    console.log(obj.value); // 10
}

let myObj = { value: 5 };
reassignReference(myObj);
console.log(myObj.value); // 5,原始对象未被修改

栈, 堆

(stack)中主要存放一些基本类型的变量和对象的引用, 其优势是存取速度比堆要快,但缺点是存在栈中的数据大小与生存期必须是确定的,缺乏灵活性,后进先出, 就像盘子

(heap )多用于复杂数据类型(引用类型)分配空间,例如数组对象、object 对象;它是运行时动态分配内存的,因此存取速度较慢。就像仓库, 需要索引

<img src="https://img.081024.xyz/20230321033721.png" alt="image-20200713144353620" />

分支语法

if else

switch-case

js
switch (expression) {
  case value1:
    // 当 expression 的结果与 value1 匹配时,执行此处语句
    [break;]
  case value2:
    // 当 expression 的结果与 value2 匹配时,执行此处语句
    [break;]
  ...
  case valueN:
    // 当 expression 的结果与 valueN 匹配时,执行此处语句
    [break;]
  [default:
    // 如果 expression 与上面的 value 值都不匹配,执行此处语句
    [break;]]
}
  • break 作用:结束该 switch 语句,所以一般情况下要加上,如果不加上则会发生穿透

      * 穿透:从上一个 case 代码快执行到下一个 case 代码快
    
    • 使用场景: 多中值执行同个代码块, 例如:
js
case 1:
case 2:
  console.log("1或2都打印")
  break

三元表达式

js
// 如果表达式成立则执行代码1,否则执行代码2
表达式?代码1:代码2
  • 一元运算符:只能操作一个值 ++ -- !
  • 二元运算符:操作两个值 1 + 1 1 > 0
  • 三元运算符:操作三个值

循环语法

for

js
for(i; i<10; i++){

}

while

js
while(条件 true/false){
  循环体/需要重复执行的代码;
}

do-while

js
do{
  循环体
}while(条件)
  • do-while 和 while 实现的循环其实是一样的,只有一个不同点:do-while 循环不管怎样先执行一次循环体代码,然后再判断条件

创建对象的三种方式

字面量

直接赋值

js
const obj = {name:"悟空",height:100,age:5000}
  • 简单粗暴
  • 不适合创建多个同样类型的对象的场景

工厂函数

函数返回

js
function createPerson(name, age, height) {
  return {
	name: name,
	age: age,
	height: height
  }
}
  1. 容易理解
  2. 失去血缘关系,无法简单分辨对象的特征

构造函数

new

markdown
构造函数的工作原理:
1. 开辟内存空间(堆)
2. 产生内部对象:this
3. 初始化属性(执行构造函数)
4. 返回对象的内存地址
js
// 1 声明函数 
function CreateStudent(name, age) {
  // 2 通过 this 赋值
  this.name = name;
  this.age = age;
}

// 3 通过 new 来创建对象
const obj = new CreateStudent("悟能", 83);

console.log(obj);

优点:

  1. 可以方便的创建对象
  2. 拥有血缘关系
  3. 还有后续更多的优势

缺点:

  1. 可能会浪费内存空间:在构造函数中给属性增加方法,会导致每个对象都会保存一份方法

解决: 将方法单独存储一份,让对象中的属性指向方法

js
// 但造成了污染全局变量的问题
function myLog(){
	console.log(1)
}

function Test(){
	this.log= myLog
}

构造函数的本质就是函数, 但与普通函数不同:

  1. 构造函数名字是大驼峰法(首字母大写
  2. 会在函数体中直接使用this(this就代表对象自己)
  3. 构造函数通常不需要给返回值:默认有返回值,是一个对象

定义函数的三种方式

声明式

function 函数名 (){}

js
fn()
function fn(参数..){
  console.log("这是函数声明")
  return 返回值
}
  • ==函数声明可以先调用,再声明==

表达式

const 函数名=function (){}

js
const fn = function() {
  console.log("这是函数表达式")
}
fn()
  • ==函数表达式必须先声明,再调用==

构造函数

new Function ()

js
// Function是系统内置的一个构造函数
// 创建函数:new Function(动态参数,都需要使用引号,最后一个参数代表函数体)
js
const fn1 = new Function("a1", "a2", "alert(a1+a2)")
fn1(1,2)

高阶函数

arguments 关键字

在函数内部使用, 获取所有的实参

js
fucntion add(){
 let sum = 0
 for (let i = 0; i < arguments.length; i++){
   let value = arguments[i]
   if(isNaN(value)){
     return false
   }
   sum += Number(value)
 }
 return sum
}

原型 prototype

当函数定义完毕,系统就会自动创建原型

  • 原型本质是一个对象,理解为 定义构造函数 的时候, JavaScript 自动帮我们添加的
  • 所有构造函数的实例,共享一个原型
  • 原型上一般用来挂载函数

实例的__proto__属性

  • 实例的 __proto__ 属性 等于 构造函数的 prototype
  • 实例的 __proto__ 是非标准属性, 只是为了方便我们开发的时候查看数据

实际用来获取原型的方法

js
const obj = {}
const  proto = Object.getPrototypeOf(obj)

原型链

  • ==所有的构造函数都是Function的实例==
  • Object的顶端是 null console.log(Object.prototype.__proto__ === null)
  • student 实例的 constructor 属性是从它的原型继承来的 image-20201107122039097|655x801

使用

把属性或者方法挂到构造函数的原型上, 使得所有实例都能共享该属性或方法

js
function CreateStu(name,age){
 this.name=name
 this.age=age
}

const stu1 = new CreateStu('张三', 18)

Object.getPrototypeOf(stu1).say = function(){
  console.log('hello')
}

/**
//或者
stu1.__proro__.say = function(){
  console.log('hello')
}

// 或者
stu1.constructor.prototype.say = function(){
  console.log('hello')
}
*/

const stu2 = new CreateStu('李四', 20)
stu2.say()

作用域

作用域有三种: 全局作用域global, 局部作用域local, 块级作用域block

  • 全局作用域: 函数外部的作用域
  • 全局变量: 可以在任意地方使用, 如果页面不关闭,那么变量所占用的内存就不会释放,就会占空间,消耗内存
  • 局部作用域: 函数内部的作用域
  • 局部变量:在函数内部使用
  • 块级作用域: 使用一对大括号包裹的一段代码
  • es6中新增 let const
  • ==var声明的变量会产生变量提升,没有块的概念, 可以跨块访问, 不能跨函数访问==
  • let 和 const定义的变量是有块级作用域的,只能在当前块作用域访问

函数的四种调用模式与this

根据函数内部this的指向不同,可以将函数的调用模式分成4种

  1. 函数调用模式
  2. 方法调用模式
  3. 构造函数调用模式
  4. 上下文调用模式(借用方法模式)

函数调用模式

如果一个函数不是一个对象的属性时,就是被当做一个函数来进行调用的。此时this指向了window

js
function fn(){
  console.log(this) // 指向window 
}
fn()

方法调用模式

当一个函数被保存为对象的一个属性时,我们称之为一个方法。当一个方法被调用时,this被绑定到当前对象

js
const obj = {
  sayHi:function(){
    console.log(this) //在方法调用模式中,this指向调用当前方法的对象。
  }
}
obj.sayHi()
  • 简写
js
const obj = {
  sayHi(){
    console.log(this)
  }
}
obj.sayHi()

构造函数调用模式

如果函数是通过new关键字进行调用的,此时this被绑定到创建出来的新对象上

js
function Person(){
  console.log(this)
}
Person() //this指向window
let p = new Person() //this指向Person

方法借用模式/上下文模式

apply, bind, call, 可以改变this

js
/** apply 、bind、call   这三个函数的第一个参数都是 this 的指向对象,第二个参数差别就来了:
 ** apply 所有参数都必须放在一个数组里
 ** bind 参数用逗号隔开,返回是函数需要执行
 ** call 参数用逗号分隔
 
 apply call 立刻调用, bind 返回函数可以延迟执行
**/
js
const name = '小王', age=17
const obj = {
  name: '小张',
  objAge: this.age,
  myFun: function(fm, t){
    console.log(this.name + '年龄' + this.age, "来自" + fm + "去往" + t)
  }
}
const db = {
  name = '德玛',
  age: 99
}

obj.myFun.apply(db,['成都','上海']);      // 德玛 年龄 99  来自 成都去往上海  
obj.myFun.bind(db,'成都','上海')();       // 德玛 年龄 99  来自 成都去往上海, bind返回的是个函数
obj.myFun.call(db,'成都','上海');    // 德玛 年龄 99  来自 成都去往上海

this

  • 单独使用,this 指向全局对象
js
console.log(this) // window
  • 在函数内部,this 的指向在函数定义的时候是不能确定的,只有函数执行的时候才能确定
  • 谁调用它, 就指向谁
js
function show(){
  console.log(this) // window
}
show()
js
const a = 18
const obj = {
  a: 19,
  b: {
	a: 20,
	c: function () {
	  console.log(this.a)
	}
  }
}
obj.b.c() // 20
  • 在方法中,this 指代该调用方法的对象
js
const obj ={
	name:"小白",
	say:function(){
		console.log(this)
	}
}
obj.say() // {name:"小白",say:f}
  • 箭头函数: 箭头函数自己没有this, this向上级找
js
//箭头函数没有funtion关键字, 所以里面没有this关键字
//浏览器断点调试,可以发现this是undefined
//箭头函数中非要用this, this向上级找
let obj = {
    fn1: function () {
        console.log('我是function函数输出的this: ', this)
    },
    fn2: () => console.log('我是箭头函数输出的this: ', this)
}

obj.fn1()  //输出obj, function函数中, 谁调用函数, this指的就是谁
obj.fn2()  //输出windows, 箭头函数不会产生this, 向上找, obj是个对象, 再向上就是window
  • 借调函数不能改变箭头函数里面的this
  • 要改变this, 可以通过改变它的上级

判断对象属于哪个构造函数

instanceof, constructor, typeof

js
let arr = [1, 2, 3]
console.log(arr instanceof Array) //true
js
console.log(arr.constructor === Array) //true
//arr没有constructor, 就向上到它的原型找 arr.__proto__.constructor
js
//typeof 可以找到基础数据类型, 数组,对象, 函数都不准确, 输出object
console.log(typeof (a)); //number
console.log(typeof (arr)); //object

对象的键使用变量

js
//在键使用中括号的时候, 可以设为变量
const key = test
const obj = {[key]: 'a'}
console.log(obj) // {test: 'a'}

内置对象的方法

Array

js
let c = a.concat(b) // 连接两个或多个数组

let b = [1, 2, 3].join() // 拼接成字符串

a.shift() // 删除第一个元素, 返回第一个元素的值

a.unshift('the', 'start') // 往头部插入一个或多个, 返回新的长度

a.pop() // 删除最后一个元素, 返回被删除元素的值

a.push('the','end') // 往最后插入一个或多个, 返回新的长度

a.splice(index, howmany , item1 , ..... , itemX) // 删除或添加元素. 
// 第一个参数是开始的位置
// 删除的数量, 不写则删除index到结尾, 可以是0
// 后面的是要插入的元素
// 如果删除了元素, 则返回的是含有被删除元素的数组

let b = a.slice(start, end) // 切片, 截取一部分, 浅拷贝

let value = a.find((value, index) => return value > 18) // 返回第一个满足条件的元素, 没有符合的返回undefined

let index = a.findIndex((value, index) => return value > 18) // 返回第应该满足条件的元素的下标, 没有符合的返回-1

let index = a.indexOf('test', 0) // 从头开始找, 是否能找到该元素, 找到返回第一次出现的下标, 没有返回-1. 第二个参数是开始找的位置, 默认是下标0可以不写

let index = a.lastIndexOf('test', a.length - 1) // 从结尾往前找, 是否能找到该元素, 找到返回第一次出现的下标, 没有返回-1. 第二个参数是开始找的位置, 默认是数组的长度减1可以不写

let boolean = a.some((value, index) => value > 18) // 满足条件返回true

a.sort() // 排序, 小到大
a.sort((a, b) => a - b) // 小到大
a.sort((a, b) => b - a) // 大到小

a.reverse() // 颠倒顺序

// 遍历
a.forEach((value, index) => {
  console.log(`下标${index}, 值为${value}`)
})

// 过滤
let b = a.filter((value, index)=>{
  return value > 0
})

// 映射
let b = a.map((value, index)=>{
  return value + 1
})

string 方法

js
let len = str.length()

let newStr = str.replace('a', 'b') // 字符替换替换

let uStr = str.toUpperCase() // 全大写

let lStr = str.toLowerCase() // 全小写

let index = str.indexOf('a') // 某个字符首次出现的位置, 没有找到返回 -1

let arr = "a,b,c,d,e".split(",");   // 转数组, 按逗号分隔

str.trim() // 移除两端空格

let str2 = str.substring(indexStart [, indexEnd]) // 截取部分

math 方法

js
Math.ceil(数字)             // 向上取整 
Math.floor(数字)            // 向下取整 
Math.max(数字1,数字2,...)    // 求最大值
Math.min(数字1,数字2,...)    // 求最小值
Math.random()              // 返回 (0,1) 之间的小数
Math.abs(数字)              // 绝对值

regexp 方法

js
// 创建
let re = new RegExp("\\w+");
let re = /\w+/;

let str="Is this all there is?";
let patt1=/is/gi;   // 修饰符, g全局, i忽略大小写

part1.test(str) // test方法, 满足时返回true

编码解码

js
encodeURI(URI) // 对整个 URI 进行编码, 不会编码 URI 中的保留字符(如 :、/、?、&、= 等)
decodeURI(encoded)


const uri = 'https://example.com/path?name=John Doe';
const encodedURI = encodeURI(uri);
console.log(encodedURI); // 输出: https://example.com/path?name=John%20Doe
js
encodeURIComponent(str) // 对 URI 的组件(如查询参数)进行编码
decodeURIComponent(encodedURI)

const param = 'name=John Doe';
const encodedParam = encodeURIComponent(param);
console.log(encodedParam); // 输出: name%3DJohn%20Doe

闭包

函数能够记住并访问它被创建时的作用域,即使这个函数在作用域之外执行

js
function outer() {
    let x = 10; // outer 函数的局部变量

    function inner() {
        console.log(x); // inner 函数访问 outer 函数的局部变量
    }

    return inner;
}

const closureFunc = outer(); // outer 函数执行完毕,但 x 仍然被 inner 函数记住
closureFunc(); // 输出: 10
  1. 函数:闭包的核心是一个函数(如 inner)。
  2. 作用域:这个函数能够访问它被创建时的作用域(如 outer 函数中的 x)。
  3. 记忆:即使外部函数(如 outer)已经执行完毕,闭包仍然可以访问它的作用域。

闭包可以用于:

  • 创建私有变量。
  • 实现函数柯里化(Currying)。
    • 柯里化: 一个函数 f(a, b, c) 转换为 f(a)(b)(c) 的形式
  • 在异步编程中保留上下文。

缺点:

  • 可能带来内存泄漏
  • 额外的内存开销和性能损耗

解决:

  • 及时释放 = null

使用:

  • 防抖
  • 下载任务

reduce

会循环当前的数组, 侧重于 "滚雪球"

js
// 语法
数组.reduce((val, item)=>{return ...}, 初始值)
// 把每次 函数体的结果, 返回到val里, 参与下次滚雪球
// 始始值只在第一次时使用

const arr = [1, 2, 3, 4, 5]
const total = arr.reduce((val, item)=>{return val + item}, 0)
console.log(total)

DOM

script 标签进阶

type=importmap 导入映射

js
<script type="importmap">
  {
    "imports": {
      "shapes": "./shapes/square.js",
      "shapes/square": "./modules/shapes/square.js",
      "https://example.com/shapes/square.js": "./shapes/square.js",
      "https://example.com/shapes/": "/shapes/square/",
      "../shapes/square": "./shapes/square.js"
    }
  }
</script>
  • <script type="importmap">:定义了一个 import map,类型为 importmap。浏览器会解析这个 JSON 对象,并在后续的模块导入过程中使用这些映射。
  • "imports":这是 import map 的主要部分,用于定义模块的映射关系。

兼容性: chrome >= 89, firefox >=108, safari >=16.4

type=module

ES Module 格式

html
<script type="module" src="main.js"></script>
js
<script type="module">
  import { greet } from './greet.js';
  greet('World');
</script>
  • 模块脚本默认是延迟执行的,类似于 <script defer>。它们会在 HTML 文档解析完成后按顺序执行,不会阻塞页面渲染。
  • 如果需要动态加载模块,可以使用 import () 函数。它返回一个 Promise,可以在运行时加载模块。
js
// 动态加载模块
if (condition) {
  import('./greet.js').then((module) => {
    module.greet('World');
  });
}

getElementBy与querySelector

getElementBy 方法返回的结果是 HTMLCollection,是动态的, 以后每一次在Javascript函数中使用这个变量的时候都会再去访问一下这个变量对应的html元素, 性能比较好

querySelector 方法返回的结果是 NodeList, 选出来的元素及元素数组是静态的,不会随着文档操作而改变, 使用比较方便

设置带-的样式

用 js 设置样式时, 如果样式的属性有 -, 则应该转换成大驼峰

attribute 标签的属性

用 . 语法更加简单, 但无法删除属性名

  • 获取属性:元素.getAttribute ( "id" )
  • 设置属性:元素.setAttribute('属性名',属性值)
  • 删除属性:元素.removeAttribute('属性名')

无法获取的属性:

  • 行外属性
  • 不属性标签标准属性的自定义属性

节点和元素

节点 是 DOM 树中的基本单位,代表 DOM 中的任何对象, 可以是元素、文本、注释、属性等 元素 是节点的一种特定类型,表示 HTML 或 XML 文档中的标签

  • 节点
js
.childNodes 子节点
.firstChild 第一个子节点
.lastChild 最后一个子节点
.nextSibling  下一个节点
.previousSibling 上一个节点

.parentNode 元素的父节点, 一定是一个元素, 只有元素才有子节点
  • 元素
js
.children 子元素, 是动态的 HTMLCollection
.firstElementChild 第一个子元素
.lastElementChild 最后一个子元素
.previousElementSibling 上一个兄弟元素
.nextElementSibling 下一个兄弟元素

增删改

语法示例描述
document.createElement()document.createElement('li')创建空标签元素
父元素.appendChild(子元素)ul.appendChild(li)添加子元素
父元素.insertBefore(子元素)ul.insertBefore(元素A,元素B)将元素A插入到元素B的前面
父元素.replaceChild(子元素)ul.replaceChild(元素A,元素B)元素A替换元素B
父元素.removeChild(子元素)ul.removeChild(li)移除子元素

克隆

js
元素.cloneNode(布尔)
	false:默认,浅克隆
	true:深克隆

事件的注册

事件的三要数: 事件源, 事件类型, 处理函数

js
box.onclick = function () {
    alert('单击事件')
};

常见的事件: onclick, dblclick, onmouseover, onmouseout

事件监听

特性事件注册(on 属性)事件监听(addEventListener
绑定方式直接为 on 属性赋值使用 addEventListener 方法
多个处理函数不支持,后赋值的函数会覆盖之前的函数支持,可以为同一个事件绑定多个处理函数
事件阶段仅支持冒泡阶段支持捕获和冒泡阶段(通过第三个参数控制)
移除事件将 on 属性赋值为 null使用 removeEventListener 方法
  • 注册事件
js
element.addEventListerner(type, fn [, option])

// 第三个参数如果是布尔值: 默认false, 冒泡阶段进行;true 捕获阶段进行
// 如果是对象
//    `capture`(布尔值):是否在捕获阶段执行事件处理函数(默认 `false`)。
//    `once`(布尔值):事件处理函数是否只执行一次(默认 `false`)。
//    `passive`(布尔值):是否忽略事件处理函数中的 `preventDefault()`(默认 `false`)。改善滚屏性能
//    `signal`(`AbortSignal`):用于移除事件监听器的信号。

冒泡: 从里往外传递, 直到 windows

  • 当一个元素接收到事件的时候,会把他接收到的事件传给父级,一直传到window (注意这里传递的仅仅是事件并不传递所绑定的事件函数。所以如果父级没有绑定事件函数,就算传递了事件也不会有什么表现但事件确实传递了。)
  • 利用: 事件委托, 在外层监听, 减少数量; 通过e.target拿到触发事件的元素

捕获: 从外往里传递

  • 移除事件
js
element.removeEventListener()
  • 手动触发事件
js
element.dispatchEvent(event)
  • 阻止事件的默认行为/传播
js
event.preventDefault(); // 阻止默认行为
event.stopPropagation(); // 阻止事件传播

offset 获取真实高宽和位置

js
/* offsetWidth与offsetHeight:获取的是元素的实际宽高 = width + border + padding

1.可以获取行内及内嵌的宽高
2.获取到的值是一个number类型,不带单位
3.获取的宽高包含border和padding
4.只能读取,不能设置

*/

element.offsetWidth
element.offsetHeight
js
/* offsetParent:获取最近的定位父元素  (自己定位参照的父元素)

1.如果元素自身是固定定位,则定位父级是null
2.如果元素自身是非固定定位,并且所有的父元素都没有定位,那么他的定位父级是body
3.body的定位父级是null

*/
element.offsetParent
js
/*
  offsetLeft: 元素的 border 左边最外一条边 到其 最近定位父元素的 padding 左边一条边 的距离
  offsetTop: 元素的 border 上边最外一条边 到其 最近定位父元素的 padding 上边一条边 的距离
 */
 
 element.offsetLeft
 element.offsetTop

|400x293

|401x293

|426x439

requestAnimationFrame

  1. 屏幕刷新时(通常是60hz)更新动画, 优化性能
  2. 运行在后台或者 <iframe> 会停止工作
js
requestAnimationFrame(callback)
js
// 使用 setTimeout 实现动画
function animateTimeout() {
  // 动画逻辑
  setTimeout(animateTimeout, 1000 / 60); // 手动设置帧率
}
animateTimeout();

// 使用 requestAnimationFrame 实现动画
function animateRAF() {
  // 动画逻辑
  requestAnimationFrame(animateRAF); // 自动优化帧率
}
animateRAF();

BOM

window 窗口对象

指当前浏览器窗口, js 中的顶级对象

  • 常用方法
js
// window可以省略
window.alert()
window.open()
window.close()
  • 事件
js
window.onload = fn // 界面上的内容加载完毕触发
window.onbeforeunload = fn // 界面关闭前触发
window.onunload = fn // 关闭的那一瞬间触发

location 地址栏

包含 url 信息

  • 常用的方法
js
location.assign('你要打开的新网页的url')
location.replace('要替换的网页url')
location.reload()

history 历史记录

js
history.forward()
history.backup()
js
console.log ( navigator );//navigator对象
console.log ( navigator.appVersion );    //当前浏览器版本信息
console.log ( navigator.platform );      //当前浏览器的硬件平台
console.log ( navigator.userAgent );    //当前浏览器信息

screen 屏幕信息

js
screen.width // 屏幕宽度
screen.height // 屏幕高度

screen.availWidth // 可用宽度
screen.availHeight // 可用高读

如果要获取视口的宽高 window.innerWidth window.innerHeight

web apis

web storage api

localStorage

容量通常为 5 mb sessionStorage 也是 5 mb cookies 4 k

js
localStorage.setItem(key, value)
localStorage.getItem(key)
locclStorage.removeItem(key)
locclStorage.clear()

sessionStorage

  • 页面会话结束时被清除
  • 每个标签页都有独立的 sessionStorage, 即使他们的 url 相同

indexDB

空间

  • 异步操作, 不会阻塞主线程
  • 键值存储, 支持复杂数据类型
  • 事务支持: 事务更新是指将多个数据库操作(如插入、更新、删除)组合成一个逻辑单元,确保这些操作要么全部成功,要么全部失败
  • 大容量:
    • Safari: 1 G
    • firefox: 2 G
    • chrome: 单域名 60% 磁盘空间, 总 80%

打开数据库

js
const request = indexedDB.open("MyDatabase", 1);

request.onupgradeneeded = (event) => {
    const db = event.target.result;
    // 创建对象存储空间(类似于表)
    if (!db.objectStoreNames.contains("users")) {
        db.createObjectStore("users", { keyPath: "id" });
    }
};

request.onsuccess = (event) => {
    const db = event.target.result;
    console.log("数据库打开成功");
};

request.onerror = (event) => {
    console.error("数据库打开失败", event.target.error);
};

添加数据

  • 通过事务向对象存储空间添加数据
js
const transaction = db.transaction("users", "readwrite");
const store = transaction.objectStore("users");

const user = { id: 1, name: "John", age: 25 };
const request = store.add(user);

request.onsuccess = () => {
    console.log("数据添加成功");
};

request.onerror = (event) => {
    console.error("数据添加失败", event.target.error);
};

读取数据

js
const transaction = db.transaction("users", "readonly");
const store = transaction.objectStore("users");

const request = store.get(1); // 根据主键读取数据

request.onsuccess = () => {
    const user = request.result;
    console.log("读取数据成功", user);
};

request.onerror = (event) => {
    console.error("读取数据失败", event.target.error);
};

更新数据

js
const transaction = db.transaction("users", "readwrite");
const store = transaction.objectStore("users");

const user = { id: 1, name: "John", age: 30 }; // 更新 age
const request = store.put(user);

request.onsuccess = () => {
    console.log("数据更新成功");
};

request.onerror = (event) => {
    console.error("数据更新失败", event.target.error);
};

删除数据

js
const transaction = db.transaction("users", "readwrite");
const store = transaction.objectStore("users");

const request = store.delete(1); // 根据主键删除数据

request.onsuccess = () => {
    console.log("数据删除成功");
};

request.onerror = (event) => {
    console.error("数据删除失败", event.target.error);
};

fetch api

websocket api

另建笔记

URLSearchParams

https://developer.mozilla.org/zh-CN/docs/Web/API/URLSearchParams

URLSearchParams 是处理 URL 上的参数串的,主要处理形如 AAA=BBB&CCC=DDD 这部分内容,看个简单用法:

js
let searchParam=new URLSearchParams('aaa=bbb&ccc=ddd')
searchParam.get('aaa');//结果:bbb

配合 location 的用法,一般是先取出 location. search:let searchParam=new URLSearchParams (location.search.substr (1))。

主要用法

has, get, getAll

js
let searchParam=new URLSearchParams('aaa=bbb&ccc=ddd&aaa=kkk')searchParam.has('ccc');//truesearchParam.get('aaa');//bbbsearchParam.getAll('aaa');//[bbb,kkk]

toString, append, set, delete

js
let searchParam=new URLSearchParams('aaa=bbb&ccc=ddd&aaa=kkk')searchParam.delete('aaa');//删除aaa的keysearchParam.toString();//ccc=dddsearchParam.append('eee','fff');//增加eee=fffsearchParam.toString();//ccc=ddd&eee=fffsearchParam.set('ccc','kkk');//设置ccc=kkksearchParam.toString();//ccc=kkk&eee=fff

entries, values, keys

js
let searchParam=new URLSearchParams('aaa=bbb&ccc=ddd');[...searchParam.entries()];//[[aaa,bbb],[ccc,ddd]][...searchParam.values()];//[bbb,ddd][...searchParam.keys()];//[aaa,ccc]

json的格式

除了对象格式, 还有数组格式, 布尔值, 数字, 字符串, null

js
console.log(JSON.parse(JSON.stringify([1,2,3])))
console.log(JSON.parse(JSON.stringify(123)))
console.log(JSON.parse(JSON.stringify('abc')))
console.log(JSON.parse(JSON.stringify(null)))