手写 promise.all
function pAll (_promises) {
return new Promise((resolve, reject) => {
// Iterable => Array
const promises = Array.from(_promises)
// 结果用一个数组维护
const r = []
const len = promises.length
let count = 0
for (let i = 0; i < len; i++) {
// Promise.resolve 确保把所有数据都转化为 Promise
Promise.resolve(promises[i]).then(o => {
// 因为 promise 是异步的,保持数组一一对应
r[i] = o;
// 如果数组中所有 promise 都完成,则返回结果数组
if (++count === len) {
resolve(r)
}
// 当发生异常时,直接 reject
}).catch(e => reject(e))
}
})
}
手写 getType
获取任意数据的数据类型
/**
* 获取任意数据的数据类型
*
* @param x 变量
* @returns 返回变量的类型名称(小写字母)
*/
function getType(x) {
// 获取目标数据的私有属性 [[Class]] 的值
const originType = Object.prototype.toString.call(x); // 以字符串为例:'[object String]'
// 获取类型属性值中' '的下标
const spaceIndex = originType.indexOf(" ");
// 截取类型属性值中' '到末尾']'之间的字符串
const type = originType.slice(spaceIndex + 1, -1); // 以字符串为例:'String'
// 将字符串转换为小写
return type.toLowerCase(); //以字符串为例:'string'
}
手写深拷贝 deepClone
/**
* 深拷贝
* @param {Object} obj 要拷贝的对象
*/
function deepClone(obj = {
}) {
if (typeof obj !== 'object' || obj == null) {
// obj 是 null ,或者不是对象和数组,直接返回
return obj
}
// 初始化返回结果
let result
if (obj instanceof Array) {
result = []
} else {
result = {
}
}
for (let key in obj) {
// 保证 key 不是原型的属性
if (obj.hasOwnProperty(key)) {
// 递归调用!!!
result[key] = deepClone(obj[key])
}
}
// 返回结果
return result
}
手写数组反转 arrReverse
function arrReverse(arr) {
let newArr = [];
arr.forEach(function (item) {
newArr.unshift(item);
});
return newArr;
}
手写类 class
https://blog.csdn.net/weixin_41192489/article/details/139442546
手写解析 url 中的参数
function getUrlParam(name) {
let params_str = location.search.substring(1);
let params_dic = {
};
params_str.split("&").forEach((item) => {
let paramItem_list = item.split("=");
if (paramItem_list.length === 2) {
params_dic[paramItem_list[0]] = paramItem_list[1];
}
});
return decodeURIComponent(params_dic[name]);
}
手写栈和队列
https://blog.csdn.net/weixin_41192489/article/details/139586917
手写深度比较 lodash.isEqual
https://sunshinehu.blog.csdn.net/article/details/136690162
手写简易 jQuery
考虑插件和扩展性
class jQuery {
constructor(selector) {
const result = document.querySelectorAll(selector)
const length = result.length
for (let i = 0; i < length; i++) {
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)
})
}
// 扩展很多 DOM API
}
// 插件
jQuery.prototype.dialog = function (info) {
alert(info)
}
// 扩展
class myJQuery extends jQuery {
constructor(selector) {
super(selector)
}
// 扩展自己的方法
addClass(className) {
}
style(data) {
}
}
使用
const $p = new jQuery('p')
$p.get(1)
$p.each((elem) => console.log(elem.nodeName))
$p.on('click', () => alert('clicked'))
手写 bind,call,apply
https://blog.csdn.net/weixin_41192489/article/details/136553536
手写闭包-缓存数据
// 闭包隐藏数据,只提供 API
function createCache() {
const data = {
} // 闭包中的数据,被隐藏,不被外界访问
return {
set: function (key, val) {
data[key] = val
},
get: function (key) {
return data[key]
}
}
}
// data变量在函数外无法被访问,即外界无法直接修改它,实现了数据的隐藏
const c = createCache()
c.set('a', 100)
console.log( c.get('a') )
手写简易的 ajax
function ajax(url) {
const p = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open('GET', url, true)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
resolve(
JSON.parse(xhr.responseText)
)
} else if (xhr.status === 404 || xhr.status === 500) {
reject(new Error('404 not found'))
}
}
}
xhr.send(null)
})
return p
}
手写通用的事件绑定函数
https://blog.csdn.net/weixin_41192489/article/details/136610476