实现一个new操作符
//实现一个new操作符
function myNew(fn,...args){
if(typeof fn !== 'function') {
throw ('fn is not a function')
}
//将对象的原型设置为fn的prototype
let res=Object.create(fn.prototype)
//使用 apply 执行构造函数 并传入参数 arguments 获取函数的返回值
let result=fn.apply(res,args)
return result
}
实现instanceof
//实现instanceof
function myInstanceof(left,right){
//如果左边不是引用数据类型
if(typeof left !== 'object' || left === null) return false
//获取左边的原型
let proto=Object.getPrototypeOf(left)
while(true){
//查找到底了
if(proto==null) return false
//相等
if(proto==right.prototype) return true
//顺着原型链继续查找
proto=Object.getPrototypeOf(proto)
}
}
实现浅拷贝
function shallowClone(obj){
//如果是基础数据类型,直接返回
if(typeof obj !== 'object' || obj==null) return obj
//如果是引用数据类型,新开辟一个地址,拷贝一层
let newObj=Array.isArray(obj) ? [] : {}
for(let key in obj){
newObj[key]=obj[key]
}
return newObj
}
实现深拷贝
function deepClone(obj){
let cloneObj=Array.isArray(obj)?[]:{};
//遍历其中的key
for(let key in obj){
if(typeof obj[key]==='object'){
//递归
cloneObj[key]=deepClone(obj[key]);
}else{
cloneObj[key]=obj[key];
}
}
return cloneObj
}
//改进版实现深拷贝
function deepClone(obj,hash=new WeakMap()){
//判断是否是引用数据类型
if(typeof obj !== 'object' || obj === null) return obj
//如果是日期类型或正则类型,直接new返回
if(obj instanceof Date){
return new Date(obj)
}
if(obj instanceof RegExp){
return new RegExp(obj)
}
//使用weakmap,解决循环引用的问题
//如果当前key已经被存储进hashmap中
if(hash.has(obj)){
return hash.get(obj)
}
let newObj=obj.constructor()
//将对象存入缓存0
hash.set(obj,newObj)
//使用Reflect.ownKeys,针对Symbol属性和不可枚举属性
for(let key of Reflect.ownKeys(obj)){
if(obj.hasOwnProperty(key)){
//检查属性是否是自身属性
//否则访问obj[key]时,会沿着原型链一直查找
newObj[key]=deepClone(obj[key],hash)
}
}
return newObj
}
实现call/apply
// 实现call/apply
//挂载到 Function.prototype上
Function.prototype.myCall = function(val,...args) {
//判断this指向,需要指向function
//谁调用这个方法,this就指向谁
if(typeof this !== 'function') {
throw new TypeError('error')
}
//获取程序执行上下文
let context=val || window
let key=Symbol('fn')
// 将当前函数绑定到 context 上
context[key] = this;
// 调用函数并获取结果
const result = context[key](...args);
// 删除临时属性
delete context[key];
return result;
}
实现bind
//手写实现bind
Function.prototype.myBind = function (fn, ...boundArgs) {
// 判断 this 指向,需要指向 function
if (typeof this !== 'function') {
throw new Error('fn is not function');
}
// 创建一个新的函数
const boundFunction = function (...args) {
// 如果 new 被使用,则 this 指向新创建的对象
const newThis = this instanceof boundFunction ? this : fn;
// 合并预设参数和实际参数
return this.apply(newThis, boundArgs.concat(args));
};
// 复制原函数的原型
const self = this;
Object.setPrototypeOf(boundFunction, self.prototype);
return boundFunction;
};
实现防抖
// 防抖:n秒后执行事件,若n秒内再次触发,则重新计时
function debounce(fn,delay){
//设置定时器
let timer = null;
return function(){
//如果还存在定时器,清除定时器后重新计时
if(timer) clearTimeout(timer);
timer=setTimeout(fn,delay)
}
}
实现节流
// 实现节流:n秒内只允许一次,若n秒内反复触发,只有一次生效
function throttle(fn,delay){
//设置开关,是否允许执行
let valid=true;
return function(){
if(!valid) return;
//一定延迟后执行
setTimeout(()=>{
fn();
valid=true;
},delay)
}
}
实现promise
//自定义promise
class MyPromise{
//定义三种状态
static PENDING = 'pending';
static FULFILLED = 'fulfilled';
static REJECTED = 'rejected';
//定义构造函数
constructor(fn){
//默认等待状态
this.status=MyPromise.PENDING;
//默认结果
this.result=null
try{
fn(this.resolve.bind(this),this.reject.bind(this))
}catch(err){
//捕获异常
this.reject(err)
}
}
//定义resolve方法
resolve(result){
if(this.status===MyPromise.PENDING){
this.status=MyPromise.FULFILLED
this.result=result
}
}
//定义reject方法
reject(result){
if(this.status===MyPromise.PENDING){
this.status=MyPromise.REJECTED
this.result=result
}
}
//定义then方法
then(resolve,reject){
//判断是否为空函数
resolve=typeof resolve==='function'?resolve:()=>{}
reject=typeof reject==='function'?reject:()=>{}
//根据当前status返回不同结果
if(this.status===MyPromise.FULFILLED){
setTimeout(()=>{resolve(this.result)})
}
if(this.status===MyPromise.REJECTED){
setTimeout(()=>{reject(this.result)})
}
}
}
实现函数柯里化
//实现函数柯里化
let currying = function (fn) {
// args保存需要复用的参数
let reuseArgs = Array.prototype.slice.call(arguments, 1)
// 定义一个保存复用参数和自身参数的数组
let args = reuseArgs
return function () {
// arguments是自身参数
if (arguments.length === 0) {
//最终执行
return fn.apply(null, args)
} else {
[].push.apply(args, arguments)
}
}
}
实现无限级目录树
function renderMenu(menuItems,parentElement){
//获取页面上的ul元素
const ul=document.createElement("ul");
//遍历menuItems数组,生成li元素
menuItems.forEach(item=>{
const li=document.createElement("li");
li.textContent=item.name;
if(item.children && item.children.length>0){
renderMenu(item.children,li);
}
ul.appendChild(li);
})
if(parentElement){
parentElement.appendChild(ul);
}
}
实现快速排序
//实现快速排序
function quickSort(arr){
//递归中止条件
if(arr.length<=1) return arr
//定义基准值,可任取,这里取数组第一项
let base=arr[0]
//基准值左侧和右侧的数组
let leftArr=[]
let rightArr=[]
//遍历数组,根据值的大小分别放入对应的数组
for(let i=1;i<arr.length;i++){
if(arr[i]<base) leftArr.push(arr[i])
else rightArr.push(arr[i])
}
//合并数组
let resArr=quickSort(leftArr).concat(base,quickSort(rightArr))
return resArr
}
实现桶排序
function bucketSort(arr,bucketNum) {
let length = arr.length;
if (length <= 1) return arr;
// 找到当前的最大值与最小值
let max = Math.max(...arr);
let min = Math.min(...arr);
//对空桶赋值
let buckets = Array.from({ length: bucketNum }, () => []);
// 计算每个桶的大小
let range = (max - min) / bucketNum+1;
// 分配数据到桶中
for (let i = 0; i < length; i++) {
let index = Math.floor((arr[i] - min) / range);
buckets[index].push(arr[i]);
}
console.log(buckets)
// 每个桶内部进行排序
// 合并桶元素
let resultArr = [];
for (let i = 0; i < bucketNum; i++) {
buckets[i].sort((a, b) => a - b);
resultArr = resultArr.concat(buckets[i]);
}
return resultArr;
}
实现计数排序
//计数排序
function countSort(arr){
let length=arr.length
let max=Math.max(...arr)
let min =Math.min(...arr)
//创建计数数组
let countArr=new Array(max-min+1).fill(0)
//遍历数组,统计每个数字出现的次数
for(let i=0;i<length;i++){
countArr[arr[i]-min]++
}
//遍历计数数组,根据次数生成结果数组
let resultArr=[]
for(let i=0;i<countArr.length;i++){
for(let j=0;j<countArr[i];j++){
resultArr.push(i+min)
}
}
return resultArr
}
实现Promise.all()
如果参数中传入的不是promise对象,会隐式转换为promise对象并视为fuilled状态;如果某个promise不resolve也不reject,promise.all会永久等待
Promise.myAll = function (args) {
if(!Array.isArray(args)){
throw new Error('args is not a array')
}
// 成功和失败的结果
let res, rej;
const promise = new Promise((resolve, reject) => {
res = resolve;
rej = reject;
});
// 记录接收的promise对象的数量
let count = 0;
// 每个promise返回的结果数组
const result = [];
// 需要完成的Promise总数
const total = args.length;
// 如果args为空,直接返回成功
if (total === 0){
res([])
return promise
}
args.forEach((i, index) => {
Promise.resolve(i).then(
data => {
result[index] = data;
count++;
// 所有Promise都完成时,调用resolve
if (count === total) {
res(result);
}
},
error => {
// 任一Promise失败,则立即拒绝整个Promise.myAll
rej(error);
}
);
});
return promise;
};
手写实现Promise.any
Promise.myAny=function(args){
if(!Array.isArray(args)){
throw new Error('args is not a array')
}
let res,rej
//为了方便的在方法内部访问resolve和reject
const promise=new Promise((resolve,reject)=>{
res=resolve
rej=reject
})
//存储结果
let result=[]
let count=0
let total=args.length || 0
if(total==0) rej('no promise')
//遍历每个传入的promise对象
args.forEach((item, index) => {
Promise.resolve(item).then(data => {
res(data); // 第一个解决的 promise 就解决整个 promise
}, err => {
count++
if(count==total) rej('all promise reject')
});
});
return promise
}
手写实现promise.race
Promise.myRace=function(args){
if(!Array.isArray(args)){
throw new Error('args is not a array')
}
let res,rej
//为了方便的在方法内部访问resolve和reject
const promise=new Promise((resolve,reject)=>{
res=resolve
rej=reject
})
//存储结果
let result=[]
let count=0
let total=args.length
if(total==0) rej('no promise')
//遍历每个传入的promise对象
args.forEach((item, index) => {
Promise.resolve(item).then(data => {
res(data); // 第一个解决的 promise 就解决整个 promise
}, err => {
rej(err); // 第一个拒绝的 promise 就拒绝整个 promise
});
});
return promise
}
手写实现async/await
搞清楚async await本质是使用Generator实现的,async返回的是promise对象
function myAsync(generatorFunc) {
// 创建生成器函数实例
const gen = generatorFunc.apply(this, arguments);
// 返回一个 Promise 对象
return new Promise((resolve, reject) => {
// 创建 step 函数
function step(val) {
let result;
try {
result = gen.next(val);
} catch (err) {
return reject(err);
}
if (result.done) {
return resolve(result.value);
} else {
//将value转换为promise对象,继续链式调用
return Promise.resolve(result.value).then(
val => step(val),
err => step(err)
);
}
}
// 初始调用 step 函数
step();
});
}
实现数组扁平化
function flatten(arr){
if(!Array.isArray(arr)){
throw new Error('arr is not a array')
}
//递归实现,注意初始化pre为[]
return arr.reduce((pre,cur)=>{
return pre.concat(Array.isArray(cur)?flatten(cur):cur)
},[])
}
实现对象扁平化
function flatten(object){
var result={}
//pre是前缀
function format(obj,pre){
for(let key in obj){
if(typeof obj[key]=='object'){
if(pre){
format(obj[key],pre+'.'+key)
}else{
format(pbj[key],key)
}
}else{
if(pre){
result[pre+'.'+key]=obj[key]
}else{
result[key]=obj[key]
}
}
}
}
format(object,null)
return result
}