30 KiB
Executable File
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 表示根本不存在定义
基本数据类型是按值传递
传递的是===副本===, 不会修改原始数据
function modifyValue(x) {
x = 10; // 修改副本
console.log(x); // 10
}
let a = 5;
modifyValue(a);
console.log(a); // 5,原始值未改变
- 函数中不会修改传递进来的基本类型
- 需要修改, 要么全局变量
- 函数返回修改后值, 调用函数重新赋值
- 用对象/数组包装
复杂数据类型是按共享传递
传递的是内存地址的===副本=== 如果是修改对象的属性, 会影响原始数据 如果是赋值, 不会影响原始数据
- 修改属性
function modifyProperty(obj) {
obj.value = 10; // 修改对象的属性
console.log(obj.value); // 10
}
let myObj = { value: 5 };
modifyProperty(myObj);
console.log(myObj.value); // 10,原始对象被修改
- 重新赋值
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 对象;它是运行时动态分配内存的,因此存取速度较慢。就像仓库, 需要索引

分支语法
if else
switch-case
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 代码快
- 使用场景: 多中值执行同个代码块, 例如:
case 1:
case 2:
console.log("1或2都打印")
break
三元表达式
// 如果表达式成立则执行代码1,否则执行代码2
表达式?代码1:代码2
- 一元运算符:只能操作一个值
++
--
!
- 二元运算符:操作两个值
1 + 1
1 > 0
- 三元运算符:操作三个值
循环语法
for
for(i; i<10; i++){
}
while
while(条件 true/false){
循环体/需要重复执行的代码;
}
do-while
do{
循环体
}while(条件)
- do-while 和 while 实现的循环其实是一样的,只有一个不同点:do-while 循环不管怎样先执行一次循环体代码,然后再判断条件
创建对象的三种方式
字面量
直接赋值
const obj = {name:"悟空",height:100,age:5000}
- 简单粗暴
- 不适合创建多个同样类型的对象的场景
工厂函数
函数返回
function createPerson(name, age, height) {
return {
name: name,
age: age,
height: height
}
}
- 容易理解
- 失去
血缘关系
,无法简单分辨对象的特征
构造函数
new
构造函数的工作原理:
1. 开辟内存空间(堆)
2. 产生内部对象:this
3. 初始化属性(执行构造函数)
4. 返回对象的内存地址
// 1 声明函数
function CreateStudent(name, age) {
// 2 通过 this 赋值
this.name = name;
this.age = age;
}
// 3 通过 new 来创建对象
const obj = new CreateStudent("悟能", 83);
console.log(obj);
优点:
- 可以方便的创建对象
- 拥有血缘关系
- 还有后续更多的优势
缺点:
- 可能会浪费内存空间:在构造函数中给属性增加方法,会导致每个对象都会保存一份方法
解决: 将方法单独存储一份,让对象中的属性指向方法
// 但造成了污染全局变量的问题
function myLog(){
console.log(1)
}
function Test(){
this.log= myLog
}
构造函数的本质就是函数, 但与普通函数不同:
- 构造函数名字是大驼峰法(首字母大写)
- 会在函数体中直接使用this(this就代表对象自己)
- 构造函数通常不需要给返回值:默认有返回值,是一个对象
定义函数的三种方式
声明式
function 函数名 (){}
fn()
function fn(参数..){
console.log("这是函数声明")
return 返回值
}
- ==函数声明可以先调用,再声明==
表达式
const 函数名=function (){}
const fn = function() {
console.log("这是函数表达式")
}
fn()
- ==函数表达式必须先声明,再调用==
构造函数
new Function ()
// Function是系统内置的一个构造函数
// 创建函数:new Function(动态参数,都需要使用引号,最后一个参数代表函数体)
const fn1 = new Function("a1", "a2", "alert(a1+a2)")
fn1(1,2)
高阶函数
arguments 关键字
在函数内部使用, 获取所有的实参
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__
是非标准属性, 只是为了方便我们开发的时候查看数据
实际用来获取原型的方法
const obj = {}
const proto = Object.getPrototypeOf(obj)
原型链
- ==所有的构造函数都是Function的实例==
- Object的顶端是 null
console.log(Object.prototype.__proto__ === null)
- student 实例的 constructor 属性是从它的原型继承来的
使用
把属性或者方法挂到构造函数的原型上, 使得所有实例都能共享该属性或方法
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种
- 函数调用模式
- 方法调用模式
- 构造函数调用模式
- 上下文调用模式(借用方法模式)
函数调用模式
如果一个函数不是一个对象的属性时,就是被当做一个函数来进行调用的。此时this指向了window
function fn(){
console.log(this) // 指向window
}
fn()
方法调用模式
当一个函数被保存为对象的一个属性时,我们称之为一个方法。当一个方法被调用时,this被绑定到当前对象
const obj = {
sayHi:function(){
console.log(this) //在方法调用模式中,this指向调用当前方法的对象。
}
}
obj.sayHi()
- 简写
const obj = {
sayHi(){
console.log(this)
}
}
obj.sayHi()
构造函数调用模式
如果函数是通过new关键字进行调用的,此时this被绑定到创建出来的新对象上
function Person(){
console.log(this)
}
Person() //this指向window
let p = new Person() //this指向Person
方法借用模式/上下文模式
apply, bind, call, 可以改变this
/** apply 、bind、call 这三个函数的第一个参数都是 this 的指向对象,第二个参数差别就来了:
** apply 所有参数都必须放在一个数组里
** bind 参数用逗号隔开,返回是函数需要执行
** call 参数用逗号分隔
apply call 立刻调用, bind 返回函数可以延迟执行
**/
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
指向全局对象
console.log(this) // window
- 在函数内部,
this
的指向在函数定义的时候是不能确定的,只有函数执行的时候才能确定 - 谁调用它, 就指向谁
function show(){
console.log(this) // window
}
show()
const a = 18
const obj = {
a: 19,
b: {
a: 20,
c: function () {
console.log(this.a)
}
}
}
obj.b.c() // 20
- 在方法中,
this
指代该调用方法的对象
const obj ={
name:"小白",
say:function(){
console.log(this)
}
}
obj.say() // {name:"小白",say:f}
- 箭头函数: 箭头函数自己没有this, this向上级找
//箭头函数没有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
let arr = [1, 2, 3]
console.log(arr instanceof Array) //true
console.log(arr.constructor === Array) //true
//arr没有constructor, 就向上到它的原型找 arr.__proto__.constructor
//typeof 可以找到基础数据类型, 数组,对象, 函数都不准确, 输出object
console.log(typeof (a)); //number
console.log(typeof (arr)); //object
对象的键使用变量
//在键使用中括号的时候, 可以设为变量
const key = test
const obj = {[key]: 'a'}
console.log(obj) // {test: 'a'}
内置对象的方法
Array
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 方法
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 方法
Math.ceil(数字) // 向上取整
Math.floor(数字) // 向下取整
Math.max(数字1,数字2,...) // 求最大值
Math.min(数字1,数字2,...) // 求最小值
Math.random() // 返回 (0,1) 之间的小数
Math.abs(数字) // 绝对值
regexp 方法
// 创建
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
编码解码
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
encodeURIComponent(str) // 对 URI 的组件(如查询参数)进行编码
decodeURIComponent(encodedURI)
const param = 'name=John Doe';
const encodedParam = encodeURIComponent(param);
console.log(encodedParam); // 输出: name%3DJohn%20Doe
闭包
函数能够记住并访问它被创建时的作用域,即使这个函数在作用域之外执行
function outer() {
let x = 10; // outer 函数的局部变量
function inner() {
console.log(x); // inner 函数访问 outer 函数的局部变量
}
return inner;
}
const closureFunc = outer(); // outer 函数执行完毕,但 x 仍然被 inner 函数记住
closureFunc(); // 输出: 10
- 函数:闭包的核心是一个函数(如
inner
)。 - 作用域:这个函数能够访问它被创建时的作用域(如
outer
函数中的x
)。 - 记忆:即使外部函数(如
outer
)已经执行完毕,闭包仍然可以访问它的作用域。
闭包可以用于:
- 创建私有变量。
- 实现函数柯里化(Currying)。
- 柯里化: 一个函数 f(a, b, c) 转换为 f(a)(b)(c) 的形式
- 在异步编程中保留上下文。
缺点:
- 可能带来内存泄漏
- 额外的内存开销和性能损耗
解决:
- 及时释放 = null
使用:
- 防抖
- 下载任务
reduce
会循环当前的数组, 侧重于 "滚雪球"
// 语法
数组.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 导入映射
<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 格式
<script type="module" src="main.js"></script>
<script type="module">
import { greet } from './greet.js';
greet('World');
</script>
- 模块脚本默认是延迟执行的,类似于
<script defer>
。它们会在 HTML 文档解析完成后按顺序执行,不会阻塞页面渲染。 - 如果需要动态加载模块,可以使用 import () 函数。它返回一个 Promise,可以在运行时加载模块。
// 动态加载模块
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 文档中的标签
- 节点
.childNodes 子节点
.firstChild 第一个子节点
.lastChild 最后一个子节点
.nextSibling 下一个节点
.previousSibling 上一个节点
.parentNode 元素的父节点, 一定是一个元素, 只有元素才有子节点
- 元素
.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) | 移除子元素 |
克隆
元素.cloneNode(布尔)
false:默认,浅克隆
true:深克隆
事件的注册
事件的三要数: 事件源, 事件类型, 处理函数
box.onclick = function () {
alert('单击事件')
};
常见的事件: onclick, dblclick, onmouseover, onmouseout
事件监听
特性 | 事件注册(on 属性) |
事件监听(addEventListener ) |
---|---|---|
绑定方式 | 直接为 on 属性赋值 |
使用 addEventListener 方法 |
多个处理函数 | 不支持,后赋值的函数会覆盖之前的函数 | 支持,可以为同一个事件绑定多个处理函数 |
事件阶段 | 仅支持冒泡阶段 | 支持捕获和冒泡阶段(通过第三个参数控制) |
移除事件 | 将 on 属性赋值为 null |
使用 removeEventListener 方法 |
- 注册事件
element.addEventListerner(type, fn [, option])
// 第三个参数如果是布尔值: 默认false, 冒泡阶段进行;true 捕获阶段进行
// 如果是对象
// `capture`(布尔值):是否在捕获阶段执行事件处理函数(默认 `false`)。
// `once`(布尔值):事件处理函数是否只执行一次(默认 `false`)。
// `passive`(布尔值):是否忽略事件处理函数中的 `preventDefault()`(默认 `false`)。改善滚屏性能
// `signal`(`AbortSignal`):用于移除事件监听器的信号。
冒泡: 从里往外传递, 直到 windows
- 当一个元素接收到事件的时候,会把他接收到的事件传给父级,一直传到window (注意这里传递的仅仅是事件并不传递所绑定的事件函数。所以如果父级没有绑定事件函数,就算传递了事件也不会有什么表现但事件确实传递了。)
- 利用: 事件委托, 在外层监听, 减少数量; 通过e.target拿到触发事件的元素
捕获: 从外往里传递
- 移除事件
element.removeEventListener()
- 手动触发事件
element.dispatchEvent(event)
- 阻止事件的默认行为/传播
event.preventDefault(); // 阻止默认行为
event.stopPropagation(); // 阻止事件传播
offset 获取真实高宽和位置
/* offsetWidth与offsetHeight:获取的是元素的实际宽高 = width + border + padding
1.可以获取行内及内嵌的宽高
2.获取到的值是一个number类型,不带单位
3.获取的宽高包含border和padding
4.只能读取,不能设置
*/
element.offsetWidth
element.offsetHeight
/* offsetParent:获取最近的定位父元素 (自己定位参照的父元素)
1.如果元素自身是固定定位,则定位父级是null
2.如果元素自身是非固定定位,并且所有的父元素都没有定位,那么他的定位父级是body
3.body的定位父级是null
*/
element.offsetParent
/*
offsetLeft: 元素的 border 左边最外一条边 到其 最近定位父元素的 padding 左边一条边 的距离
offsetTop: 元素的 border 上边最外一条边 到其 最近定位父元素的 padding 上边一条边 的距离
*/
element.offsetLeft
element.offsetTop
requestAnimationFrame
- 屏幕刷新时(通常是60hz)更新动画, 优化性能
- 运行在后台或者
<iframe>
会停止工作
requestAnimationFrame(callback)
// 使用 setTimeout 实现动画
function animateTimeout() {
// 动画逻辑
setTimeout(animateTimeout, 1000 / 60); // 手动设置帧率
}
animateTimeout();
// 使用 requestAnimationFrame 实现动画
function animateRAF() {
// 动画逻辑
requestAnimationFrame(animateRAF); // 自动优化帧率
}
animateRAF();
BOM
window 窗口对象
指当前浏览器窗口, js 中的顶级对象
- 常用方法
// window可以省略
window.alert()
window.open()
window.close()
- 事件
window.onload = fn // 界面上的内容加载完毕触发
window.onbeforeunload = fn // 界面关闭前触发
window.onunload = fn // 关闭的那一瞬间触发
location 地址栏
包含 url 信息
- 常用的方法
location.assign('你要打开的新网页的url')
location.replace('要替换的网页url')
location.reload()
history 历史记录
history.forward()
history.backup()
navigator 浏览器信息
console.log ( navigator );//navigator对象
console.log ( navigator.appVersion ); //当前浏览器版本信息
console.log ( navigator.platform ); //当前浏览器的硬件平台
console.log ( navigator.userAgent ); //当前浏览器信息
screen 屏幕信息
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
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%
打开数据库
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);
};
添加数据
- 通过事务向对象存储空间添加数据
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);
};
读取数据
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);
};
更新数据
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);
};
删除数据
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 这部分内容,看个简单用法:
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
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
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
let searchParam=new URLSearchParams('aaa=bbb&ccc=ddd');[...searchParam.entries()];//[[aaa,bbb],[ccc,ddd]][...searchParam.values()];//[bbb,ddd][...searchParam.keys()];//[aaa,ccc]
json的格式
除了对象格式, 还有数组格式, 布尔值, 数字, 字符串, null
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)))