手写代码汇总
手写深拷贝
/**** @param {Object} obj 要拷贝的对象* @returns*/function deepClone (obj = {}) {if (typeof obj !== 'object' || obj == null) {// 如果不是对象或者数组,直接返回值return obj}// 初始化返回结果let resultif (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函数
// 手写bindFunction.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)中的fn1const self = this// 返回一个函数return function () {return self.apply(t, args)}}
手写jQuery,并考虑插件和拓展性 ```javascript class jQuery { constructor(selector) {
const result = document.querySelectorAll(selector)const length = result.lengthfor (let i = 0; i < length; i++) {// 保存DOM节点this[i] = result[i]}this.length = lengththis.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加载一张图片```javascriptconst 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 = valuethis.resolveCallbacks.forEach(fn => fn(this.value))}}const rejectHandler = (reason) => {if (this.state === 'pending') {this.state = 'rejected'this.reason = reasonthis.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) => vfn2 = typeof fn2 === 'function' ? fn2 : (e) => eif (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```javascriptfunction 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))
