MENU

JavaScript 学习笔寄

2022-09-27 • 笔记

随缘更新目前是想单页更新根据后面内容来吧~

只是自己的学习笔记只写了点自己觉得比较重要的内容,因为原本输出的就算 Markdown 所以就博客也发一份了,因为是学了哪一些记了哪一些可能会比较混乱,有错别字请见谅

下载原始文件(不一定同步)


事件

添加或解绑

使用 addEventListener()添加事件,使用 removeEventListener()解绑事件

const btn = document.querySelector('#button')
function fn(){
    console.log('Hello')
}
btn.addEventListener('click', fn()) // 绑定事件
btn.removeEventListener('click', fn()) // 解绑事件

事件名称

事件名称触发方式
click鼠标点击
mouseenter鼠标经过(存在冒泡)
mouseleave鼠标离开(存在冒泡)
mouseover鼠标进入(不存在冒泡)
mouseout鼠标离开(不存在冒泡)
focus获得焦点
blur失去焦点
Keydown键盘按下触发
Keyup键盘抬起触发
input用户输入触发
change输入框内容改变触发
load加载事件,接听整个页面
DOMContentLoaded加载事件,无需等待CSS、图像等资源加载完成
resize在窗口发生改变时会触发次事件

scroll 事件

需要给 window 或者 document 添加此事件,scrollLeftscrollTop获取被卷去的大小,是可读写的。document.documentElement HTML返回对象 HTML 的元素,scrollTo() 方法可以使用 元素.scrollTo(x, y)来吧页面滚动到指定位置。

resize 事件

在窗口发生改变时会触发次事件

阻止默认行为

使用 preventDefault()方法来阻止默认行为

如:阻止表单提交的默认行为

document.querySelector('form').addEventListener('submit', function (event) {
    event.preventDefault()
})

日期对象

方法作用说明
getFullYear()获得年份获取四位年份
getMonth()获得月份取值为 0 ~ 11
getDate()获取月份中的每一天不同月份取值也不相同
getDay()获取星期取值为 0 ~ 6
getHours()获取小时取值为 0 ~ 23
getMinutes()获取分钟取值为 0 ~ 59
getSeconds()获取秒取值为 0 ~ 59

获取时间戳

时间戳是 1970 年 01 月 01 日 00 时 00 分 00 秒起至现在的毫秒数,通常使用将来的时间戳减去现在的时间戳来就行倒计时

使用 getTime() 方法

const date = new Date()
console.log(date.getTime())

简写 +new Date()

console.log(+new Date())

使用 Date.now()

console.log(Date.now())

节点

节点关系和节点查找

父子节点

子元素.parentNode返回最近的一级父级节点,如果找不回返回 null
父元素.childNodes返回所有的子节点,保活文本注释等
父元素.children⭕ 仅获取所有子元素的节点,并且会返回一个伪数组
元素.nextElementSibling获取下一个兄弟节点
元素.previousElementSibling获取上一个兄弟节点

创建/追加/克隆/删除节点

使用 document.createElement('标签名')创建一个节点
如:

const divNya = document.createElement('div')

吧节点插入到父元素最后 父元素.appendChild(要插入的元素)
吧节点插入到父元素之前 父元素.insertBefore(要插入的元素,在哪个元素前面)
元素.cloneNode(布尔值)会克隆出来一个和原标签一样的元素,括号内写布尔值,true时会克隆后代节点,false克隆时不包含后代节点这是默认值
父元素.removeChild(要删除的元素)删除不需要的节点,和 CSS 中 display:none的区别是前者为删除后者为隐藏


本地存储

本地存储有 localStoragesessionStorage会以键值对的方式存储,可以在浏览器的 DevTools 的 Application 查看
localStorage能永久的存储在用户电脑本地,关闭页面也不会被删除
sessionStorage在页面关闭时数据将会被删除
.setItem(key, value)存储数据
localStorage.getItem(key)获取数据
localStorage.removeItem(key)删除数据

JSON

JSON.parse(JSON字符串)吧 JSON 字符串转换为对象
JSON.stringify(复杂数据类型)吧复杂数据类型转换为字符串
JSON.parse(JSON.stringify(复杂数据类型))可以完成不含函数的深拷贝,但是有性能问题


location 对象

location 对象拆分保存了 URL 地址的各个部分
location.href获取当前的 URL 地址,如果赋值将会跳转到赋值的 URL 地址
location.search获取地址中的参数 ?后面的部分
location.hash获取地址中的哈希值 #后面的参数
location.reload刷新页面


history 对象

history 对象主要用于前进、后退、历史记录等,实际中用的少
history.back() 后退页面
history.forward() 前进页面
history.go(参数)可以前进或者后退页面正数前进负数后退


局部作用域和全局作用域

作用域规定了变量能够备份访问的范围

局部作用域

只能在函数内部访问不能在外部直接访问,函数执行完毕后一般会被释放

块级作用域

{}包裹的代码块中可以使用,外部有可能无法访问,var不能产生块级作用域

全局作用域

全局作用域中声明变量其他任何作用域都可以被访问


作用域链

由作用域串联提供查找变量的机制,就近原则从内往外一级一级查找变量

let a = 1
function nya(){
    let a = 2
    console.log(a); // 就近原则 nya() 中存在变量名'a'打印 2
}
nya()

闭包 ⭕

私有化数据,让外部也能访问内部变量,但会有内存泄漏
通过 return一个函数 function可以是匿名函数不起变量名

function nya() {
    let num = 1
    return function() {
        console.log(num);
    }
}
const nyaw = nya()
nyaw() //控制台打印 1

变量提升

varfunction有变量提升会预解析提升,var只提升变量名不赋值,function提升整个函数,function的优先级比 var高如果同时 functionvar定义一个相同的变量名 function会将 var覆盖


函数中的参数

动态参数

动态参数 arguments是函数内部内置的伪数组,可以通过 for循环递归,在箭头函数中无法使用

function nya(){
    console.log(arguments)
}
nya(1,2,3)
// Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]

剩余参数

剩余参数使用三个英文句号加变量名 …变量来传参,是真数组,需要写在最后一个参数中,可以在箭头函数中使用,开发中提倡使用

function nya(...nyaw){
    console.log(nyaw)
}
nya(1,2,3)
// [1, 2, 3]

展开运算符

和剩余参数一样使用三个英文句号加变量名 …变量 可以展开为数组可以用于 Math.max等需要数值的地方

let arr = [1,2,3,4,5]
console.log (...arr) // 1 2 3 4 5

This

this 指向函数的调用者,和函数的定义方式关系不大,箭头函数要另算应为箭头函数没有自己的 this 指向

  • 函数直接调用,this 会被指向 window,因为函数全局定义默认挂载在 window 所以相当于直接通过 window 来调用
  • 函数添加给哪个对象调用 this 就会指向哪个对象,除了 bind 创建的修改 this 指向后的函数
  • 通过 new 执行函数此时函数会被当做构造函数处理,this 会被指向示例对象
  • 函数通过 call 调用 ,call 的第一个参数是 this 指向,call 的剩余参数为函数的实参
  • 函数通过 apply 调用,apply 的第一个参数是 this 指向,applycall 不同的是第二个参数为数组,数组的每一项是调用函数的实参
  • 函数通过 bind 调用会获得一个改变 this 指向后的函数需要接收它然后再执行, bind 的第一个参数是 this 指向,第二个参数和 apply 相同是数组,通过 bind 创建的函数它的 this 指向会被永久改变,不会被指向调用者
  • 箭头函数没有 this 指向,箭头函数中的 this 指向实际是上下文中的 this

箭头函数 ⭕

可以用来替换匿名函数,箭头函数的语法比函数更加简洁,箭头函数中没 this将会往上级查找

  1. 只有一个参数时可以省略小括号
  2. 只有一行代码时可以省略大括号以及无需写 return
  3. 如果只有一行省略大括号的情况下返回对象或者数组时需要英文括号包裹
  4. 箭头函数中没有 arguments但是有剩余参数,使用三个英文句号加变量名 …变量名
  5. 箭头函数中没有自己的 this会沿用上一层的 this

解构赋值 ⭕

快速批量赋值给变量的简洁语法

数组解构

遵循一一对应原则,变量如果大于单元数量时,会返回 undefined。可以直接在[]内赋值,可以使用剩余参数吧多余的数组内的单元返回赋值给变量名

基本语法

将会把左侧的数组中的单元赋值给右侧的 []变量名

let [a, b, c] = [114,514,1919] // a = 114 b=514 c=1919

多级

根据一一对应原则如下

let [a, b, [c]] = [114,514[1919]] //a = 114 b=514 c=1919

数组交换

开头必须加分号结束符

let a = 1
let b = 2
;[b,a]=[a,b]
console.log(a,b); // 2 1

对象解构

对象中找不到变量名一致的属性名时返回 undefined

基本语法

吧左侧对象中的属性名赋值给右侧 {}的变量名

let {userName} = {userName:'橘纸柚'}

多级

多级对象中嵌套和数组解构差不多使用冒号':'来连接

let {userName,site:{blog}} = {
    userName: '橘纸柚',
    site: {
        blog: 'lovemen.cc'
    }
}

更名

如果数组中的变量名已经被占用可以使用英文冒号进行更名

let {userName:MyName,site:{blog:BlogUrl}} = {
    userName: '橘纸柚',
    site: {
        blog: 'lovemen.cc'
    }
}

逻辑短路

如果左边短路右边的代码就不执行

&&左边为 false 就短路
||左边为 true 就短路


创建对象的三种方法

字面量

通过字面量来创建对象,这是最常用的方法

const obj = {uname: '橘纸柚'}

new Object()

通过 new Object()来创建函数,通过字面量创建时也会经过 new Object()

const obj = new Object({uname:'橘纸柚'})

构造函数 ⭕

构造函数是一种特殊的函数,主要用来初始化对象,可以理解为是一个对象的模板可以用来创建多个类似的对象。JavaScript 实现面向对象需要借助于构造函数,直接创建方法存在浪费内存的问题。

声明构造函数

构造函数推荐驼峰命名法首字母开头大写用于与普通函数的区分,构造函数里的 this指向实例对象。推荐键的取名和形参相同。

function Nya(uname,age){
    this.uname = uname;
    this.age = age;
}

使用

称之为实例化对象,构造函数通常和 new一起使用,实参的使用方法和普通函数一样没有传入实参则 undefined

function Nya(uname,age){
    this.uname = uname;
    this.age = age;
}
const juzi = new Nya('JuziYou',18)

成员

实例对象的成员称为实例成员,只有实例对象可以使用
构造函数的成员称为静态成员,只有构造函数可以使用

function Nya(uname,age){
    this.uname = uname;
    this.age = age;
}
const juzi = new Nya('JuziYou',18)
Nya.baka = 'YES'
console.log(juzi.baka) // undefined
console.log(Nya.baka) // YES
console.log(Nya.uname) // undefined

原型对象 ⭕

prototype是每一个构造函数都有的一个属性指向了一个对象称为原型对象,在原型中构造函数和实例中的 this 指向实例化对象。原型是所有当前构造函数 new出来的对象的方法,可以吧那些不变的方法都放在里面节省内存

function Nya(uname,age){
    this.uname = uname;
    this.age = age;
}
Nya.prototype.say = function(){
    console.log('Nya!');
}
const juzi = new Nya('JuziYou',18)
juzi.say() // 将会在控制台打印 Nya!

内置构造函数

其中的 BooleanStringNumber既是包装类型又是方法

Object

Object是内置构造函数通常用于创建对象,不过推荐使用字面量来创建对象

PS: Object.prototype.toString.call(对象) 可以获取一个对象的数据类型

for(let key in obj){}

for(let key in obj){}用于遍历对象,'let key'的'key'为成员的键值,'obj'是目标数组

Object.keys

Object.keys(obj)将会返回一个真数组

const nya = {
    name: 'JuziYou',
    age: 18
}
console.log(Object.keys(nya)); // ['name', 'age']

Object.values

Object.values(obj)将会返回一个真数组

const nya = {
    name: 'JuziYou',
    age: 18
}
console.log(Object.values(nya)); // ['JuziYou', 18]

Object.assign

Object.assign(obj,{key:value})常用于数组拷贝也可以用于成员的添加

const nya = {
    name: 'JuziYou',
}
const nya2 = {
    age: 18
}
console.log(Object.assign(nya,nya2)); // {name: 'JuziYou', age: 18}
console.log(Object.assign(nya,nya2,{baka:'YES'})); // {name: 'JuziYou', age: 18, baka:'YES'}

Object.create

MDN文档
根据现有的对象 A 来创建一个 prototype 为对象 B 的对象,新对象 A 的 prototype 拥有所有对象 A 的属性和方法,一般只用一个参数就是传入对象 A

// 示例 一个对象需要数组的 prototype
const newObj = Object.create(Array.prototype)

Object.setPrototypeOf

MDN文档
用于修改对象的 prototype 指向,第一个参数是需要修改的对象,第二个参数为指向的 prototype

// 示例 一个对象 prototype 需要指向到数组的 prototype
const obj = {}
Object.setPrototypeOf(obj, Array.prototype)

Array

Array是内置的构造函数用于创建数组,不过推荐使用字面量创建数组

方法作用
.push()向数组尾部添加一个单元
.unshit()向数组头部添加一个单元
.pop()删除数组最后一个单元
.shift()删除数组第一个单元
.splice(索引开始值, 删除单元数,追加单元)从索引开始值的位置删除n个单元数
.reverse()吧数组排序颠倒

Array.from()

Array.from()可以将为数组转换为数组,转换对象必须带 lengthlength如果小于数量将会略去后面的,如果多余数量将会写入 undefined

Array.isArray

判断一个对象是否为数组,返回一个布尔值

Array.isArray([]) // true
Array.isArray({}) // false

reduce

reduce返回函数累计处理的结果通常用于求和等

索引号和原数组为可选变量。起始值如果不写将会使用数组的第 0 个值并且从第二个值开始遍历

arr.reduce(function(累计值prev, 当前元素item, 索引号index, 原数组original){}, 起始值)

forEach

forEach用于遍历数组,不会返回,通常用于遍历、输出、打印值。索引号和原数组为可选变量

arr.forEach(function(当前元素item, 索引号index, 原数组original){})

filter

filter用于遍历筛选数组,return会返回值可以声明一个变量接收。索引号和原数组为可选变量

arr.filter(function(当前元素item, 索引号index, 原数组original){})

map

map用于迭代数组,经常用于处理数据,return会返回值可以声明一个变量接收。索引号和原数组为可选变量

arr.map(function(当前元素item, 索引号index, 原数组original){})

join

join用于吧数组转化为字符串。索引号和原数组为可选变量

let arr = [1,2,3,4,5]
console.log(arr.join('')) // 12345
console.log(arr.join('/')) // 1/2/3/4/5

find

find将会查找符合条件的第一个元素,如果找不到将会返回 undefined。比如数组 [1,1,4,5,1,4]查找 4将会循环到下标 3 的 4 后结束,查找 9将会返回 undefined

arr.find(function(元素值、元素的索引,原数组){})

some

some将会检查数组中是否有任意一个符合条件返回布尔值,不符合将会返回 false符号将会返回 true

arr.some(function(元素值,元素的索引,原数组){})

every

every将会查找数组是否都符合条件返回布尔值,不符合将会返回 false符号将会返回 true

arr.every(function(元素值,元素的索引,原数组){})

sort

sort比对重排数组,返回后会直接重排数组

比如:ab为对比的两个值

arr.every(function(a,b){return a - b})

at

at 接收一个整数为参数可以是正整数也可以是负整数,正整数与下标获取相同,负整数从 -1 开始从数组中最后一个元素开始

const arr = [1,2,3,4,5]
console.log(arr.at(0)) // 1
console.log(arr.at(-1)) // 5

String

  1. length获取字符串的长度,如 'JuziYou'.length将会得到 7
  2. split(分隔符)将会吧字符串转换为数组,如 'Neko_Nya'.split('_')将会得到数组 ['Neko','Nya'],如果分隔符为空字符串 ''将会吧每个字符转换为数组,如 '橘纸柚'.split('')将会得到数组 ['橘','纸','柚']
  3. substring(起始索引,结束索引)用于字符截取,如 '123456'.substring(2,4)将会截取字符串 34。如果只有一个参数将会截取起始索引之后的全部字符如 '123456'.substring(2)将会得到字符串 3456
  4. startsWith(检测字符串,检测位置索引号)用于检测是否为某串字符开头,检测位置索引号为可选项将会从此索引号开始检测忽略之前的,将会返回布尔值。
  5. includes(搜索字符串,检测位置索引号)判断一个字符串是否包含在另一个字符串中,检测位置索引号为可选项,将会返回布尔值

Number

toFixed(保留字符串位数)设置保留小数位的长度,如设置为 2将会保留两位,四舍五入


Ajax

常见状态码

状态码描述说明
200OK请求成功
201Created资源在服务器端已成功创建
400Bad Request客户端请求方式或者参数错误
401Unauthorized客户端身份认证不通过
404Not Found客户端请求的资源不存在
500Internal Server Error服务器内部错误

Axios

Axios 是一个基于 promise 的网络请求库,可以方便的完成 ajax 请求
官方文档地址:https://axios-http.com/zh/docs/intro

基地址

axios.defaults.baseURL设置基地址

axios.defaults.baseURL = 'https://api.uuz.bid'

常用写法

method设置请求方式如 GETPOST
url设置请求地址如果设置了基地址直接写地址即可如 /api/nya/api/nya
methodGET时使用 params写请求参数
methodPOST时使用 data写请求参数
headers设置请求头

如:

axios({
    method:'GET', // 发送GET请求
    url:'/userdata', // 请求地址(设置了基地址)
    params:{
      uname: userName // 发送载荷
    },
    headers: {
      Authorization: token // 服务器需要Authorization请求头验证token
    }
}).then(res=>{
    console.log(res.data); // 没有错误
}).catch(err=>{
    console.log(err); // 有错误
})

XMLHttpRequest()

这是原生的 Ajax 方式,不过实际中都用请求库比较多所以就简单记一下
MDN 传送门:https://developer.mozilla.org/zh-CN/docs/Glossary/AJAX

const xhr = new XMLHttpRequest() // NEW 一个 XMLHttpRequest()
xhr.open('GET','https://api.uuz.bid/random/?json=y') // GET请求数据
xhr.onload = function(){ //准备接受数据
    console.log(xhr.responseText); //打印返回的数据
}
xhr.send() //发送请求

Promise

Promise是一个构造函数,可以通过 new创建一个 Promise实例对象,代表一个异步的操作

语法

Promise构造函数包含一个参数带有两个回调值 resolve(解析)和 reject(拒绝)
如果正常则调用 resolve,否则调用 reject

const np = new Promise((resolve, reject) => {})

.then()方法用来预先指定成功和失败的回调函数,失败的回调函数为可选
return的返回值可以是Promise对象也可以是具体的值,但是都会被处理成Promise方便后面的链式调用
形参resolve()reject()的传参将会传到.then()里的函数内
.catch()捕获错误,参数为一个函数回调值err(错误)

如:

const np = new Promise((resolve, reject) => {
    resolve('juzi')
}).then(
    res=>{
        console.log(res) // 控制台打印juzi
        return 'Nya'
    }
).then(
    res=>{
    console.log(res) // 控制台打印Nya
}
).catch(err=>{
    console.log(err)
})

中断 Promise 链

直接 return new Promise(()=>{})返回一个初始的 Promise 实例

Promise.all()

回并行发起 Promise 异步操作,全部的操作结束后才会下一步的 .then()

const promiseAll = [
   axios({method: 'GET',url: 'XXXXXX'}),
   axios({method: 'GET',url: 'XXXXXX'}),
   axios({method: 'GET',url: 'XXXXXX'})
]
Promise.all(promiseAll).then(res => {
    console.log(res)
}).catch(err => {
    console.log(err)
})

Promise.allSettled

Promise.all 差不多,只不过它无论成功失败都会返回一个成功状态的 Promise

Promise.race()

回并行发起 Promise 异步操作,只要有任意一个返回了值就立即进入下一步 .then()

const promiseAll = [
   axios({method: 'GET',url: 'XXXXXX'}),
   axios({method: 'GET',url: 'XXXXXX'}),
   axios({method: 'GET',url: 'XXXXXX'})
]
Promise.race(promiseAll).then(res => {
    console.log(res)
}).catch(err => {
    console.log(err)
})

Promise.any

Promise.all 差不多,它可以获取到异步处理成功最快的那一个


async await

async await 相当于是 Generator 的语法糖,它可以解决回调地狱问题,写起来也比 Promise更清楚,await必须在 async的函数内,错误需要使用 try catch 来获取

  • async 相当于修饰 await 就近的函数,被 async 修饰的函数会变成一个 Promise,如果内部 return 一个数据也会被 Promise 包装 resolve
  • await 一般用于修饰 Promise 如果不是就会吧后面的内容包装为 Promiseresolve,下面的代码相当于放在了 .then 的成功回调中,所以 await 相当于微任务
// 比如await从API里取用户数据并打印
(async () => {
    const userData = await axios({
        method: 'GET',
        url: '/user',
        params: {
            user: 'JuziYou'
        }
    })
    try {
        console.log(userData.data)
    } catch (err) {
        console.log(err.response.data.message)
    }
})()

Generator

Generator 是 ES6 的,作用是将函数暂停交出控制权,是一种异步的解决方案 async await 相当于是它的语法糖,只要在函数声明和函数名中间加 * 那就是一个 Generator 函数,会在函数内的 yield 暂停它的返回值是外面调用 .next() 传入的值, yield 后跟随的值会被传出去到 .next() 返回值的 value,需要一个常量接收函数返回的 Generator 实例,然后使用 常量名.next() 就会向下执行,可以通过返回值的 done 确认是否完成