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