前端工程师--手写js一些常见的code。有一定的基础,不然看不懂

冒泡算法

 function bul(arr1) {
    
    
        let temp = 0;
        let arr = arr1;
        let a = document.getElementById('a');
        for (let i = 0; i < arr.length - 1; i++) {
    
      //外循环,控制次数
            for (let j = 0; j < arr.length - 1 -i; j++) {
    
      //每次得到最大的数,循环次数就要减1
                if (arr[j] > arr[j + 1]) {
    
    
                    temp = arr[j + 1];
                    arr[j + 1] = arr[j];
                    arr[j] = temp;
                }
            }
        }
        a.innerHTML = arr;
    }

去重(多种思路)

	//1. es6
    var unique = arr => [...new Set(arr)]
    //2. es5
    function unique(arr) {
    
    
    var res = arr.filter(function(item, index, array) {
    
    
        return array.indexOf(item) === index
    })
    return res
}

扁平化数组(多种思路)

// 1. es6,循环递归
const flatten = (arr) => {
    
    
    let res = [];
    // item:当前元素 index:当前元素的下标 arrs:当前元素所属数组
    arr.forEach((item, index, arrs) => {
    
    
        if (Array.isArray(item)) {
    
    
            res = res.concat(flatten(item))
        } else {
    
    
            // res.push(arrs[index])
            res.push(item)
        }
    })
    return res;
}

// 2. api
console.log(arr.flat(Infinity)); 

//3. 解构
const filter3 = (arr) => {
    
    
    while (arr.some(item => Array.isArray(item))) {
    
    
        arr = [].concat(...arr);
    }
    return arr
}

// 4. 看起来高级一点的reduce
const filter2 = (arr) => {
    
    
    return arr.reduce((pre, cur) => {
    
    
        return pre.concat(Array.isArray(cur) ? filter2(cur) : cur)
    }, [])
}

防抖节流

核心思路:单位时间内只有一个定时器进入了宏任务队列
场景:发送请求,屏幕滚动,窗口大小缩小的时候要执行的代码
防抖:

function debound (fn,delay){
    
    
	let timer = null;
	return  (...args)=>{
    
    
	clearTimeout(timer)
	timer = setTimeout(
	()=>{
    
    
	fn.apply(this,arg)
}
,delay)
}
}

节流:

  const throttle = (fn, delay = 500) => {
    
    
        let flag = true;
        return (...args) => {
    
    
            if (!flag) return;
            flag = false;
            setTimeout(() => {
    
    
                fn.apply(this, args);
                flag = true;
            }, delay);
        };
    };

手写bind

思路:通过自定义属性将自己的this先存起来
bind函数的特点
// 特点 1. 改变this指向 2. 不影响原对象的返回 3. 接收多个参数 4. 自己返回的是一个函数

 Function.prototype.Mybind = (ctx,args)=>{
    
    
	  // 1. 将方法挂载到传入的ctx上去 2. 挂载之后调用  3. 将属性删除
        return (...args2) => {
    
    
            // 表示独一无二的值最大的用法是用来定义对象的唯一属性名。
            // Symbol值不能与其他类型的值进行运算
            // Symbol 值不可以和其他类型值进行混合运算,否则会报错
            // Symbol 值如果想要作为属性名,那就不能再用点运算符,因为点运算符后面跟的总是字符串
            // 在对象内部使用Symbol 值作为属性名的时候,必须要将值放在方括号中
            let fn = Symbol(1);
            ctx[fn] = this;
            ctx[fn](...args.concat(args2));
            delete ctx[fn];
        }
}

深拷贝/浅拷贝

思路:判断当前item项是数组还是对象,都不是直接复制,是的话就递归

function copyObj(obj) {
    
    
	let newObj = null
	Array.isArray(obj) ? newObj = [] : newObj = {
    
    }
	for(let key in obj) {
    
    
		if(type obj[key] === 'object') {
    
    
			newObj[key] = copyObj(obj[key])
		}else {
    
    
		newObj[key] = copyObj(obj[key])
		}
}
return newObj
}

手写promise All

思路:循环调用传进来的peomise数组,有一个promise失败整个promise就是失败的

const PromiseAll = (iterator) =>{
    
    
    // 使他变成数组
    let promises = Array.from(iterator);  
    // 记录成功的promise
    let index = 0;
    // 记录成功的结果;
    let res = [];
    return new Promise((reslove,reject)=>{
    
    
        // 1.遍历传进来的promise
        for (let key in promises) {
    
    
            promises[key]
            .then((result) => {
    
    
                res[key] = result;
                if (++index === promises.length) {
    
    
                    reslove(res);
                }
            }).catch((err) => {
    
    
                // 3.一旦有错误的就变为reject
                reject(err);
            });
        }
    })
}

试下手写一个promiseNot(单纯考一下个人学习能力)

两数之和

function addTwo(num,tar){
    
    
	let map = new Map()
	for(let i = 0; i<num.length;i++) {
    
    
		if(map.has(tar-num[i])){
    
    
			return [tar-num[i] , i]
		}else {
    
    
			map.set(num[i],i)
	}
}
	return []
}

手写反转数组

思路:双指针并置换头尾,注意处理中间值,不然又会反转一遍

 function reverse(arr) {
    
    
        let mid = Math.floor(arr.length / 2)
        let end = arr.length - 1
        for (let i = 0; i < mid ; i++) {
    
    
            let temp = arr[i]
            arr[i] = arr[end]
            arr[end] = temp       
            end--
        }
        return arr
    }


//  ps:大佬的代码。我也看不懂
  // 算法类型
    //     var reverse = function(x) {
    
    
    //     let res = 0;
    //     while(x){
    
    
    //         res = res * 10 + x % 10;
    //         if(res > Math.pow(2, 31) - 1 || res < Math.pow(-2, 31)) return 0;
    //         x = ~~(x / 10);
    //     }
    //     return res;
    // };

new关键字实现的过程

思路:
new 会产生一个新对象;
新对象需要能够访问到构造函数的属性,所以需要重新指定它的原型;
构造函数可能会显示返回;

	let obj= new Object()
	 Constructor = [].shift.call(arguments);
    obj.__proto__ = Constructor.prototype;
    var ret = Constructor.apply(obj, arguments);
    
    // ret || obj 这里这么写考虑了构造函数显示返回 null 的情况
    return typeof ret === 'object' ? ret || obj : obj;

猜你喜欢

转载自blog.csdn.net/work33/article/details/127143528