概要
这篇专题旨在模拟实现 Javascript 语言中原生提供的或者某些库封装的实用函数如:call、apply、bind、map、fiter 等等
实现 call 方法
// 实现 call 和 apply 方法的关键在于将方法本身作为属性传递给指定的 this,并在指定的 this 上手动调用方法本身
Function.prototype.call2 = function(arg, ...args) {
const context = arg || window
context._fn_call = this
const result = context._fn_call(...args)
delete context._fn_call
return result
}
模拟实现 apply 方法
// 实现 call 和 apply 方法的关键在于将方法本身作为属性传递给指定的
Function.prototype.apply2 = function(arg, args = []) {
const context = arg || window
context._fn_apply = this
const result = context._fn_apply(...args)
delete context._fn_apply
return result
}
实现 bind 方法
Function.prototype.bind2 = function (arg, ...args) {
const context = arg || window
context._fn_bind = this
return function (...argsInner) {
const result = context._fn_bind(...args.concat(argsInner))
delete context._fn_apply
return result
}
}
实现 map 方法
Array.prototype.map2 = function (fn) {
const result = []
for (let item of this) {
result.push(fn(item))
}
return result
}
const arr = [1,2,3,4]
console.log(arr.map2(v => v * 2))
// [2,4,6,8]
模拟实现 filter 方法
Array.prototype.filter2 = function (fn) {
const result = []
for (let item of this) {
if (fn(item)) {
result.push(item)
}
}
return result
}
console.log(arr.filter2(item => item % 2 === 0))
// [2, 4]
实现 once 函数
某些场景下,当希望函数只执行一次时,可以通过以下函数实现
function once (fn) {
let flag = false
return function (...args) {
if (!flag) {
flag = true
return fn(...args)
}
return
}
}
function log () {
console.log('foo')
}
const foo = once(log)
foo()
foo()
foo()
// foo , foo只会打印一次
实现 debounce 防抖函数
// 该函数通过第三个参数控制 fn 函数是否立即执行
function debounce(fn, time, immediate) {
let timeout, result
const debounced = function() {
const args = arguments
const that = this
if (timeout) clearTimeout(timeout)
if (immediate) {
const callnow = !timeout
timeout = setTimeout(function() {
timeout = null
}, time)
if (callnow) result = fn.apply(that, args)
} else {
timeout = setTimeout(function() {
result = fn.apply(that, args)
}, time)
}
return result
}
debounced.cancel = function() {
clearTimeout(timeout)
timeout = null
}
return debounced
}
实现节流函数
节流函数的原理:即使你持续通过操作触发事件,每隔一段时间,只执行一次事件
function throttle(fn, wait) {
let previos = 0
let result
return function() {
const now = +new Date()
if (now - wait > previos) {
result = fn.apply(this, arguments)
previos = now
return result
}
}
}
实现对象的浅拷贝函数
function copy(obj) {
if (typeof obj !== 'object') return
const newObj = obj instanceof Array ? [] : {}
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = obj[key]
}
}
return newObj
}
实现对象的深拷贝函数
function copy(obj) {
if (typeof obj !== 'object') return
const newObj = obj instanceof Array ? [] : {}
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = typeof obj[key] === 'object' ? copy(obj[key]) : obj[key]
}
}
return newObj
}
实现多维数组扁平化
Note:处于数组的多层深拷贝会消耗性能,该函数设计为直接修改原数组
const arr = [1, [2, [3, 4]]];
function flatten(arr) {
while (arr.some(item => Array.isArray(item))) {
arr = [].concat(...arr)
}
return arr
}
console.log(flatten(arr))
// [ 1, 2, 3, 4 ]