手写代码汇总
手写深拷贝
/**
*
* @param {Object} obj 要拷贝的对象
* @returns
*/
function deepClone (obj = {}) {
if (typeof obj !== 'object' || obj == null) {
// 如果不是对象或者数组,直接返回值
return obj
}
// 初始化返回结果
let result
if (obj instanceof Array) {
result = []
} else {
result = {}
}
// 遍历obj key是键名
for (let key in obj) {
// 保证key不是原型的属性
if (obj.hasOwnProperty(key)) {
// 递归调用 遇到对象或者数组会再深入一层
result[key] = deepClone(obj[key])
}
}
// 返回结果
return result
}
手写bind函数
// 手写bind
Function.prototype.myBind = function () {
// 将参数拆解为数组
const args = Array.prototype.slice.call(arguments)
// 获取fn1.bind({ x: 100 }, 10, 20, 30)中的 { x: 100}
// 即bind要绑定的对象。
// 即参数第一项,让第一项弹出,剩下的就是参数。
const t = args.shift()
// fn1.bind({ x: 100 }, 10, 20, 30)中的fn1
const self = this
// 返回一个函数
return function () {
return self.apply(t, args)
}
}
手写jQuery,并考虑插件和拓展性 ```javascript class jQuery { constructor(selector) {
const result = document.querySelectorAll(selector)
const length = result.length
for (let i = 0; i < length; i++) {
// 保存DOM节点
this[i] = result[i]
}
this.length = length
this.selector = selector
} get (index) {
return this[index]
} each (fn) {
for (let i = 0; i < this.length; i++) {
const elem = this[i]
fn(elem)
}
} on (type, fn) {
return this.each(elem => {
elem.addEventListener(type, fn, false)
})
} }
// 插件 jQuery.prototype.dialog = function (info) { alert(info) } // 复写 class myJQuery extends jQuery{ constructor(selector) { super(selector) } // 新写一些方法 dialog (infp) { alert(info) } }
4. 手写promise加载一张图片
```javascript
const url = 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic1.win4000.com%2Fwallpaper%2F8%2F5453005f74be2.jpg&refer=http%3A%2F%2Fpic1.win4000.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1666593868&t=73f0cc5600170de46f2c82f95ba7e8b4'
function loadImg (src) {
return new Promise((reslove, reject) => {
const img = document.createElement('img')
img.onload = () => {
reslove(img)
}
img.onerror = () => {
reject(new Error('图片加载失败'))
}
img.src = src
})
}
loadImg(url).then(img => {
console.log(img.width);
return img
}).then(img => {
console.log(img.height);
}).catch(e => console.log(e))
手写promise ```javascript class MyPromise { // 属性 state = ‘pending’ // 状态 value = undefined // 成功后的值 reason = undefined // 失败的原因 resolveCallbacks = [] // pending状态下。存储成功的回调 rejectCallbacks = [] // pending状态下。存储失败的回调
// 构造函数 constructor(fn) {
const resolveHandler = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled'
this.value = value
this.resolveCallbacks.forEach(fn => fn(this.value))
}
}
const rejectHandler = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected'
this.reason = reason
this.rejectCallbacks.forEach(fn => fn(this.reason))
}
}
try {
fn(resolveHandler, rejectHandler)
} catch (err) {
rejectHandler(err)
}
}
// 方法 then (fn1, fn2) {
// 当pending状态下,fn1和fn2会存储到callbacks里
// 判断是不是函数
fn1 = typeof fn1 === 'function' ? fn1 : (v) => v
fn2 = typeof fn2 === 'function' ? fn2 : (e) => e
if (this.state === 'pending') {
return new MyPromise((resolve, reject) => {
// 往数组里面加一个回调函数 状态变化的时候执行
this.resolveCallbacks.push(() => {
try {
// 计算新值
const newValue = fn1(this.value)
resolve(newValue)
} catch (err) {
reject(err)
}
})
this.rejectCallbacks.push(() => {
try {
// 计算新值
const newReason = fn2(this.reason)
reject(newReason)
} catch (err) {
reject(err)
}
})
})
}
if (this.state === 'fulfilled') {
return new MyPromise((resolve, reject) => {
try {
// 计算新值
const newValue = fn1(this.value)
resolve(newValue)
} catch (err) {
reject(err)
}
})
}
if (this.state === 'rejected') {
return new MyPromise((resolve, reject) => {
try {
// 计算新值
const newReason = fn2(this.reason)
reject(newReason)
} catch (err) {
reject(err)
}
})
}
}
catch (fn) {
// catch是then的一个语法糖,只能传入失败的回调,then可以传入两个
return this.then(null, fn)
} }
// 全局静态函数 MyPromise.resolve = function (value) { return new MyPromise((resolve, reject) => resolve(value)) } MyPromise.reject = function (reason) { return new MyPromise((resolve, reject) => reject(reaon)) } // 传入promise数组,等到所有的都fulfilled之后,返回新的promise MyPromise.all = function (promiseList = []) { return new MyPromise((resolv, reject) => { const result = [] const length = promiseList.length let resolvedCount = 0 promiseList.forEach(p => { p.then(data => { result.push(data) resolvedCount++
if (resolvedCount === length) {
// 已经遍历到了最后
resolv(result)
}
}).catch(err => {
reject(err)
})
})
})
} // 传入promise数组,只要有一个fulfilled即可返回 MyPromise.race = function (promiseList = []) { let resolved = false return new MyPromise((resolve, reject) => { promiseList.forEach(p => { p.then(data => { if (!resolved) { resolve(data) resolved = true } }).catch(err => { reject(err) }) }) }) }
6. 手写Ajax
```javascript
function ajax (url) {
const p = new Promise((reslove, reject) => {
const xhr = new XMLHttpRequest()
xhr.open('GET', url, true)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
reslove(JSON.parse(xhr.responseText))
} else if (xhr.status === 404) {
reject(new Error('404 not found'))
}
}
}
// 只有send才可以改变状态
xhr.send(null)
})
return p
}
const url = './text.json'
ajax(url)
.then(res => console.log(res))
.catch(err => console.error(err))