柯里化
function createCurry(func, args) {
const varargity = func.length
const varargs = args || []
return function () {
var_args = [].slice.apply(arguments)
args.push(..._args)
if (args.length < argity) {
return createCurry.call(this, func, args)
}
return func.apply(this, args)
}
}页面滚动到具体元素
const dom = $('#id')
dom.scrollIntoView({
behavior: 'smooth', // 滚动行为:丝滑
block: 'start', // 显示位置
})cookies
读取: document.cookie 返回全部可读取的cookie组成的字符串;每个由 '; ' 进行组合,然后里面每一对的形式为 key=value domain: 访问 a.com, 则 domain 也只能设置在 a.com 或者其子域下(顶级 ‘/’),不能够跨域设置 cookie
function getCookieByKey(key) {
const obj = document.cookie.split('; ').reduce((acc, cookie) => {
const [name, value] = cookie.split('=')
acc[name] = JSON.parse(decodeURIComponent(value))
return acc
}, {})
return obj[key]
}事件循环
JavaScript是一门单线程语言,它运行在浏览器的渲染主线程中,而渲染主线程只有一个。 但是渲染主线程承担着诸多工作如:渲染页面等。 如果所有代码都是同步的话,如果一个代码卡住了,就会导致主线程代码的阻塞,从而导致运行性能效率受到极大的影响。 所以浏览器采用了异步的方式
过去
异步任务又分为宏任务和微任务;JavaScript 引擎遵循事件循环的机制,在执行完当前宏任务后,会检查微任务队列,执行其中的微任务,然后再取下一个宏任务执行。这个过程不断循环,形成事件循环。
宏任务有:
- I/O操作,如文件读写、数据库数据读写等
- setTimeout、setInterval
- setImmediate(Node.js环境)
- requestAnimationFrame
微任务有:
- Promise的then、catch、finally
- async/await中的代码
- MutationObserver
- process.nextTick(Node.js 环境)
现在
每个任务都有一个任务类型,同一个类型的任务必须在一个队列里,不同类型的任务分属于不同的队列,在一次事件循环中,浏览器可以根据实际情况从不同队列中取出任务执行。 大概有以下几个的队列DOM操作、用户交互、网络请求、网页导航和渲染
同时浏览器必须准备好一个微队列,微队列中的任务优先于所有其他任务执行
在目前的Chrome实现中,至少包含了以下队列
| 队列类型 | 描述 | 优先级 |
|---|---|---|
| 微队列 | 用于存放需要最快执行的任务 | 最高 |
| 交互队列 | 用于存放用户操作后产生的事件处理任务 | 高 |
| 延时队列 | 用于存放计时器到达后的回调任务 | 中 |
| 网络队列 | 用于处理网络活动产生的任务 | 中 |
requestAnimationFrame
- 自动适应当前设备的刷新率,以获得更平滑的动画效果。
- 在不活动的标签页或隐藏的元素上自动暂停动画,以节省计算资源。
- 与其他浏览器优化技术(如垂直同步)协同工作,以提高动画性能
requestIdleCallback
该函数将在浏览器空闲时期被调用。这使开发者能够在主事件循环上执行后台和低优先级工作,而不会影响延迟关键事件,如动画和输入响应
正则 前瞻
密码规则正则表达式,必须包含字母+数字+特殊字符(这里特殊字符为!@#$),长度为8-16位
^(?=.*\d)(?=.*[a-zA-Z])(?=.*[!@#$])[\da-zA-Z!@#$]{8,16}$
前瞻(?=)
| 正则表达式 | 字符串 | 匹配结果 |
|---|---|---|
| abc(?=123) | abc123 | abc |
| abc(?=123) | kabc1234 | abc |
| abc(?=123) | abc12 | 不匹配 |
| abc(?=123) | abcc123 | 不匹配 |
负前瞻(?!)
| 正则表达式 | 字符串 | 匹配结果 |
|---|---|---|
| abc(?!123) | abc123 | 不匹配 |
| abc(?!123) | abc1233 | 不匹配 |
| abc(?!123) | abc12 | abc |
| abc(?!123) | abcc123 | abc |
后顾(?<=)
| 正则表达式 | 字符串 | 匹配结果 |
|---|---|---|
| (?<=abc)123 | abc123 | 123 |
| (?<=abc)123 | kabc1234 | 123 |
| (?<=abc)123 | abc12 | 不匹配 |
| (?<=abc)123 | abcc123 | 不匹配 |
负后顾(?<!)
| 正则表达式 | 字符串 | 匹配结果 |
|---|---|---|
| (?<!abc)123 | abc123 | 不匹配 |
| (?<!abc)123 | kabc1234 | 不匹配 |
| (?<!abc)123 | ab1234 | 123 |
| (?<!abc)123 | abcc123 | 123 |
Reflect.get | Proxy.get.receiver
let obj ={a:1}
var pObj=new Proxy(obj,{
get(target,key,receiver){
return receiver
}
})
console.log(pObj.getReceiver); // pObj {a: 1}
let child = Object.create(pObj); // 创建一个对象,并且继承 pObj 的全部属性(不是地址引用)
console.log(child.getReceiver); // child {}
Reflect.get(target, propertyKey[, receiver])
// target 需要取值的目标对象
// propertyKey 需要获取的值的键值
// receiver 如果 target 对象中指定了 getter,receiver 则为 getter 调用时的this值。
Reflect.get({get name(){return this.un_exist}}, 'name', {un_exist: 'exist'}) // existObserver
IntersectionObserver
提供了一种异步观察目标元素与其祖先元素或顶级文档视口(viewport)交叉状态的方法。其祖先元素或视口被称为根(root)。
const intersectionObserver = new IntersectionObserver(
(entries) => {
// 如果 intersectionRatio 为 0,则目标在视野外,
// 我们不需要做任何事情。
if (entries[0].intersectionRatio <= 0) return
loadItems(10)
console.log('Loaded new items')
},
{
threshold: 0.5,
}
)
// 开始监听
intersectionObserver.observe(document.querySelector('.scrollerFooter'))ResizeObserver
const observer = new ResizeObserver((entries) => {})
observer.observe(document.querySelect('#app'))