-
使用
call / apply
指定this
-
返回一个绑定函数
-
当返回的绑定函数作为构造函数被
new
调用,绑定的上下文指向实例对象 -
设置绑定函数的
prototype
为原函数的prototype
Function.prototype.myBind = function(context, …args) {
const fn = this
const bindFn = function (…newFnArgs) {
fn.call(
this instanceof bindFn ? this : context,
…args, …newFnArgs
)
}
bindFn.prototype = Object.create(fn.prototype)
return bindFn
}
模拟new
-
创建一个新的空对象
-
把
this
绑定到空对象 -
使空对象的
__proto__
指向构造函数的原型(prototype
) -
执行构造函数,为空对象添加属性
-
判断构造函数的返回值是否为对象,如果是对象,就使用构造函数的返回值,否则返回创建的对象
const createNew = (Con, …args) => {
const obj = {}
Object.setPrototypeOf(obj, Con.prototype)
let result = Con.apply(obj, args)
return result instanceof Object ? result : obj
}
模拟instanceOf
- 遍历左边变量的原型链,直到找到右边变量的 prototype,如果没有找到,返回
false
const myInstanceOf = (left, right) => {
let leftValue = left.proto
let rightValue = right.prototype
while(true) {
if(leftValue === null) return false
if(leftValue === rightValue) return true
leftValue = leftValue.proto
}
}
深拷贝(简单版)
-
判断类型是否为原始类型,如果是,无需拷贝,直接返回
-
为避免出现循环引用,拷贝对象时先判断存储空间中是否存在当前对象,如果有就直接返回
-
开辟一个存储空间,来存储当前对象和拷贝对象的对应关系
-
对引用类型递归拷贝直到属性为原始类型
const deepClone = (target, cache = new WeakMap()) => {
if(target === null || typeof target !== ‘object’) {
return target
}
if(cache.get(target)) {
return target
}
const copy = Array.isArray(target) ? [] : {}
cache.set(target, copy)
Object.keys(target).forEach(key => copy[key] = deepClone(obj[key], cache))
return copy
}
深拷贝(尤雨溪版)
vuex源码
- 原理与上一版类似
function find(list, f) {
return list.filter(f)[0]
}
function deepCopy(obj, cache = []) {
// just return if obj is immutable value
if (obj === null || typeof obj !== ‘object’) {
return obj
}
// if obj is hit, it is in circular structure
const hit = find(cache, c => c.original === obj)
if (hit) {
return hit.copy
}
const copy = Array.isArray(obj) ? [] : {}
// put the copy into cache at first
// because we want to refer it in recursive deepCopy
cache.push({
original: obj,
copy
})
Object.keys(obj).forEach(key => copy[key] = deepCopy(obj[key], cache))
return copy
}
函数防抖
-
this
继承自父级上下文,指向触发事件的目标元素 -
事件被触发时,传入
event
对象 -
传入
leading
参数,判断是否可以立即执行回调函数,不必要等到事件停止触发后才开始执行 -
回调函数可以有返回值,需要返回执行结果
const debounce = (fn, wait = 300, leading = true) => {
let timerId, result
return function(…args) {
timerId && clearTimeout(timerId)
if (leading) {
if (!timerId) result = fn.apply(this, args)
timerId = setTimeout(() => timerId = null, wait)
} else {
timerId = setTimeout(() => result = fn.apply(this, args), wait)
}
return result
}
}
函数节流(定时器)
const throttle = (fn, wait = 300) => {
let timerId
return function(…args) {
if(!timerId) {
timerId = setTimeout(() => {
timerId = null
return result = fn.apply(this, …args)
}, wait)
}
}
}
函数节流(时间戳)
const throttle = (fn, wait = 300) => {
let prev = 0
let result
return function(…args) {
let now = +new Date()
if(now - prev > wait) {
prev = now
return result = fn.apply(this, …args)
}
}
}
函数节流实现方法区别
| 方法 | 使用时间戳 | 使用定时器 |
| — | — | — |
| 开始触发时 | 立刻执行 | n秒后执行 |
| 停止触发后 | 不再执行事件 | 继续执行一次事件 |
数组去重
const uniqBy = (arr, key) => {
return […new Map(arr.map(item) => [item[key], item])).values()]
}
const singers = [
{ id: 1, name: ‘Leslie Cheung’ },
{ id: 1, name: ‘Leslie Cheung’ },
{ id: 2, name: ‘Eason Chan’ },
]
console.log(uniqBy(singers, ‘id’))
// [
// { id: 1, name: ‘Leslie Cheung’ },
// { id: 2, name: ‘Eason Chan’ },
// ]
原理是利用Map
的键不可重复
数组扁平化(技巧版)
const flatten = (arr) => arr.toString().split(‘,’).map(item => +item)
数组扁平化
const flatten = (arr, deep = 1) => {
return arr.reduce((cur, next) => {
return Array.isArray(next) && deep > 1 ?
[…cur, …flatten(next, deep - 1)] :
[…cur, next]
},[])
}
函数柯里化
const currying = (fn) {
_curry = (…args) =>
args.length >= fn.length
-
? fn(…args)
- (…newArgs) => _curry(…args, …newArgs)
}
原理是利用闭包把传入参数保存起来,当传入参数的数量足够执行函数时,就开始执行函数
发布订阅EventEmitter
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-vAiD4rjK-1715885133026)]
[外链图片转存中…(img-Xfm7QZMO-1715885133026)]
[外链图片转存中…(img-y9RBqc9c-1715885133026)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!