一些javaScript方法实现--随笔

179 阅读2分钟

工作中会使用很多语言层面自带的方法,但是不知道里面的实现原理,遇到一些,总结下来,当作这篇随笔吧

javaScript call方法

尝试下给出如下运行结果

function fn1() {
    console.log(1)
}
function fn2() {
    console.log(2)
}
fn1.call(fn2) // 输出结果为 1
fn1.call.call(fn2) // 输出结果为 2

让我们先回顾一下call的用法

fn.call(fn2, 1, 2, 3)

尝试实现call方法


Function.prototype.mycall = function (context, ...args) {
    context = context || window // 非严格模式下,指向window
    context.fn = this // 当前的this指向调用的方法
    const result = context.fn(...args) // 1.使用context.fn()来调用fn,间接地改变了this指向 2. 用result来接收返回值
    delete context.fn
    return result
}
// 以下是测试代码
function fn(a, b, c) {
	console.log(this) // {name: 'abc'}
    return a + b + c
}
fn.mycall({name: 'abc'}, 1, 2, 3)

fn1.mycall.mycall(fn2)执行过程

Function.prototype.mycall = function (context, ...args) {
    context = context || window  // 传入fn2  此时 context--->fn2
    context.fn = this // this ---> mycall ---> fn2.mycall
    // --->暂停,等待执行fn2.mycall(没有传参)
    const result = context.fn(...args) // 1.使用context.fn()来调用fn,间接地改变了this指向 2. 用result来接收返回值
    delete context.fn
    return result
}
// 执行fn2.mycall(没有传参)
Function.prototype.mycall = function (context, ...args) {
    context = context || window  //  此时 context--->window
    context.fn = this // this ---> fn2
    const result = context.fn(...args) // window.fn2()
    delete context.fn
    return result
}

箭头函数能不能用call

当然可以, 但是....由于this在箭头函数中已经按照词法作用域绑定了,所以,用call()或者apply()调用箭头函数时,无法对this进行绑定,即传入的第一个参数被忽略

防抖(debounce)

顾名思义,就是防止抖动,多次触发同一个函数,只执行最后一次

使用场景

输入框搜索自动补全, 频繁操作

使用示例(以下使用loadsh中的debounce作例子)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <input id="input">
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.20/lodash.min.js"></script>
    <script>
        const input = document.getElementById('input')
        
        input.oninput = _.debounce(() => {
            console.log(input.value)
        },1000)
     </script>
</body>
</html>

实现debounce方法

function debounce (fn, time) {
    let timer = null //定时器id
    return function(){
        window.clearTimeout(timer) // 清除定时器
        timer = setTimeout(()=>{ // 记录定时器id
          fn()
        }, time)
    }
}

节流(throttle)

在一定时间内,只允许函数执行一次
function throttle(fn, time) {
    let timer = null;
    return function() {
        if (!timer) {
            timer = setTimeout(() => {
                timer = null;
                fn()
            }, time)
        }

    }
}
// 测试
var testThrottle =  throttle(() =>  {
    console.log('我是节流')
},5000)
setInterval(() => {
    console.log('11222');
    testThrottle()
}, 500);

async await 方法