Skip to content

柯里化

javascript
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)
    }
}

页面滚动到具体元素

javascript
const dom = $('#id')
dom.scrollIntoView({
    behavior: 'smooth', // 滚动行为:丝滑
    block: 'start', // 显示位置
})

cookies

读取: document.cookie 返回全部可读取的cookie组成的字符串;每个由 '; ' 进行组合,然后里面每一对的形式为 key=value domain: 访问 a.com, 则 domain 也只能设置在 a.com 或者其子域下(顶级 ‘/’),不能够跨域设置 cookie

javascript
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)abc123abc
abc(?=123)kabc1234abc
abc(?=123)abc12不匹配
abc(?=123)abcc123不匹配

负前瞻(?!)

正则表达式字符串匹配结果
abc(?!123)abc123不匹配
abc(?!123)abc1233不匹配
abc(?!123)abc12abc
abc(?!123)abcc123abc

后顾(?<=)

正则表达式字符串匹配结果
(?<=abc)123abc123123
(?<=abc)123kabc1234123
(?<=abc)123abc12不匹配
(?<=abc)123abcc123不匹配

负后顾(?<!)

正则表达式字符串匹配结果
(?<!abc)123abc123不匹配
(?<!abc)123kabc1234不匹配
(?<!abc)123ab1234123
(?<!abc)123abcc123123

Reflect.get | Proxy.get.receiver

ts
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'}) // exist

Observer

IntersectionObserver

提供了一种异步观察目标元素与其祖先元素或顶级文档视口(viewport)交叉状态的方法。其祖先元素或视口被称为根(root)。

ts
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

ts
const observer = new ResizeObserver((entries) => {})
observer.observe(document.querySelect('#app'))