最近在整理面试题,到了手写题这部分,也是重写了一遍加复习,也修改了一部分以前没有注意到的问题,我自认写的还是比较详尽的了,如果有异议的地方,欢迎大家一起讨论,一定要提出来!我不想面试才知道我的问题呜呜呜!
作为自身复习使用,所以并没有添加过多的注释,如果有不明白的可以私信或者评论哦。
这章只是纯粹的函数实现,并没有测试用例,有需求可以自行测试哈。
create
function myCreate(prototype) {
const F = {}
F.prototype = prototype
return new F()
}
instance
function myInstance(left, right) {
const prototype = right.prototype
// let proto = left.__proto__
let proto = Object.getPrototype(left)
while (left) {
if (left === right) return true
left = Object.getPrototype(left)
}
return false
}
compose
function compose(fns) {
if (fns.length === 0) return v => v
if (fns.length === 1) return fns[0]()
return fns.reduce((prev, cur) => (...args) => prev(cur(...agrs)))
}
new
function myNew(Ctor, ...args) {
if (typeof Ctor !== 'function') {
throw new TypeError('Error')
}
const instance = Object.create(Ctor.prototype)
const res = Ctor.apply(instance, args)
if (res && (typeof res === 'object' || typeof res === 'function')) {
return res
}
return instance
}
getType
function getType(target) {
if (target === null) return 'null'
if (typeof target !== 'object') {
return typeof target
}
return Object.prototype.toString.call(target).slice(8, -1)
}
call
Function.prototype.myCall = function(context, ...args) {
if (typeof this !== 'function') throw new TypeError('Error')
if (!context || (typeof context !== 'object' && typeof context !== 'function')) {
context = window
}
const fn = Symbol()
context[fn] = this
const res = context.fn(...args)
delete context[fn]
return res
}
apply
Function.prototype.myApply = function(context, args) {
if (typeof this !== 'function') throw new TypeError('Error')
if (!Array.isArray(args)) throw new TypeError('Error')
if (!context || (typeof context !== 'object' && typeof context !== 'function')) {
context = window
}
const fn = Symbol()
context[fn] = this
const res = context.fn(...args)
delete context[fn]
return res
}
bind
Function.prototype.myBind = function(context, ...args1) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
if (!context || (typeof context !== 'object' && typeof context !== 'function')) {
context = window
}
const fn = this
const resFn = function(...args2) {
return fn.call(this instance resFn ? this : context, ...args1, ...args2)
// 注释为降级策略
// if (this instance resFn) {
// this.fn = fn
// return this.fn(...args)
// } else {
// context.fn = fn
// return context.fn(...args)
// }
}
resFn.prototype = Object.create(this.prototype)
// function F() {}
// F.prototype = this.prototype
// resFn.prototype = new F()
return resFn
}
flat
Array.prototype.myFlat = function(depth) {
if (!Array.isArray(this)) throw new TypeError('Error')
let res = this.slice()
while (depth-- > 0) {
res.reduce(
(prev, cur) => Array.isArray(cur) ? [...prev, ...cur] : [...prev, cur]
, [])
}
return res
}
setInterval
function mySetInterval(fn, timeout) {
let timer = null
function interval (){
fn()
timer = setTimeout(interval, timeout)
}
setTimeout(interval, timeout)
return {
clearInterval: () => {
clearTimeout(timer)
timer = null
}
}
}
function mySetInterval(fn, timeout) {
let prev = Date.now()
let timer = null
function interval() {
if (Date.now() - prev >= timeout) {
fn()
prev = Date.now()
}
timer = requestAnimationFrame(interval)
}
interval()
return {
myClearInterval: () => {
cancelAnimationFrame(timer)
timer = null
}
}
}
throttle
// 使用定时器
function throttle(fn, timeout) {
let timer
return function() {
if (timer) return
let context = this
// fn(...args) 第一次就执行放这里
timer = setTimeout(() => {
fn.call(context, ...args)
timer = null
}, timerout)
}
}
// 使用时间戳
function throttle(fn, timeout) {
let prev = Date.now()
return function(...args) {
let context = this
if (Date.now() - start >= timeout) {
fn.call(context, ...args)
start = Date.now()
}
}
}
debounce
function debounce(fn, timeout) {
let timer
return function(...args) {
let context = this
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
fn.call(context, ...args)
}, timeout)
}
}
// requestAnimationFrame 实现防抖
function debounce(fn, timeout) {
let prev = Date.now()
function tick(...args) {
let context = this
if (Date.now() - satrt >= timeout) {
fn.call(context, ...args)
}
timer = requestAnimationFrame(tick)
}
const timerID = {
id: requestAnimationFrame(tick)
}
return timerID
}
// 使用 cancelAnimationFrame(timerID.id) 可销毁
// 首次执行的防抖函数
function immediateDebounce(fn, timeout, immediate) {
let timer
return function(...args) {
const context = this
if (timer) clearTimeout(timer)
if (immediate) {
let callNow = !timer
timer = setTimeout(() => {
timer = null
}, timeout)
if (callNow) fn.call(context, ...args)
} else {
timer = setTimeout(() => {
fn.call(context, ...args)
}, timeout)
}
}
}
curry
function curry(fn, ...args1) {
let len = fn.length
return function(...args2) {
let args = [...args1, ...args2]
if (args.length >= len) return fn(...args)
return curry(fn, ...args)
}
}
function add(...args1) {
let args = [...args1]
const fn = function(...args2) {
args.push(...args2)
return fn
}
fn.toString = function() {
if (!args.length) return
return args.reduce((prev, cur) => prev + cur, 0)
}
return fn
}
map
Array.prototype.myMap = function(fn, context) {
if (!Array.isArray(this)) throw new TypeError('Error')
let arr = new Array(this.length)
for (let i = 0; i < this.length; i++) {
if (i in this) {
arr[i] = fn.call(context, this[i], i, this)
}
}
return arr
}
reduce
Array.prototype.myReduce = function(fn, initialValue, context) {
if (!Array.isArray(this)) throw new TypeError('Error')
let arr = new Array(this.length)
let i = initialValue ? 0 : 1
let sum = initialValue || this[0]
for (; i < this.length; i++) {
sum = fn.call(context, sum, this[i], i, this)
}
return sum
}
iterator
const obj = { a: 1, b: 2 }
obj[Symbol.iterator] = function() {
let keys = Object.keys(this)
let ind = 0
return {
next() {
if (ind < keys.length) return { done: false, value: obj[keys[ind++]] }
return { done: true, value: undefined}
}
}
}
obj[Symbol.iterator] = function*() {
const keys = Object.keys(this)
for (let key of keys) {
yield obj[key]
}
}