那些手写js

277 阅读2分钟
随着前端技术的快速迭代,现在大厂的要求也在不断提高。各种算法、原理等成为了与心仪企业的阻隔。结合了自
己的面试经验,做了如下总结。

一、排序相关(是根据出现频率整理的顺序)

  • 冒泡排序

    function BubbleSort(arr) {
        if(arr.length > 0){
            let len = arr.length;
            for(let end = len - 1; end > 0; end--){
                for(let i = 0; i < end; i++) {
                    if(arr[i] > arr[i + 1]){
                        [arr[i],arr[i+1]] = [arr[i+1],arr[i]];
                }
            }
        }
        return arr;
        }else{  
            return [];
        }    
    }
    
  • 快速排序

    function quickSort(arr) {
        if(arr.length > 0){
            quick(arr, 0, arr.length - 1);
        }else{
            return [];
        }}
    function quick(arr, firstVal, lastVal){
      if(firstVal < lastVal){
          //随机找一个值,然后和最后一个值进行交换,将经典排序变为快速排序
          let i = firstVal + Math.floor(Math.random() * (lastVal - firstVal + 1)),
          j = lastVal;
          [arr[i],arr[j]] = [arr[j],arr[i]]
          let tempArr = partition(arr, firstVal, lastVal, arr[lastVal]);
          quick(arr, firstVal, tempArr[0]);
          quick(arr, tempArr[1], lastVal);
      }
    }
    //返回的值是小于区域的最大索引和大于区域的最小索引
    function partition(arr, firstVal, lastVal, num){
        let less = firstVal - 1;
        let more = lastVal + 1;
        let cur = firstVal;
        while(cur < more){
            if(arr[cur] < num){
                [arr[less+1],arr[cur]] = [arr[cur],arr[less+1]];
            }else if(arr[cur] > num) {
                [arr[more-1],arr[cur]] = [arr[cur],arr[more-1]];
            }else{
                cur++;
            }
        }
        return [less, more];
    }
    
  • 选择排序

    function SelectionSort(arr) {
        if(arr == null || arr.length < 0) {
            return [];
        }    
        for(var i = 0; i < arr.length - 1; i++) { 
           var minIndex = i;
            for(var j = i + 1; j < arr.length; j++) {
                minIndex = arr[j] < arr[minIndex] ? j : minIndex;
            }
            [arr[i],arr[minIndex]] = [arr[minIndex],arr[i]];
        }
        return arr;
    }
    
  • 插入排序

    function insertSort(arr) {
        if(arr == null  || arr.length <= 0){
            return [];    }
        var len = arr.length;
        for(var i = 1; i < len; i++) {
            for(var j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {
                [arr[j],arr[j+1]] = [arr[j+1],arr[j]];
            }
        }
        return arr;
    }
    

二、手写实现call、apply、bind

  • call: fn.call(context, 1, 2, 3, 4)

      Function.prototype.MyCall = function(content){
        const self = content || window;
        const args = Array.from(arguments).slice(1);
        const self.fn = this;
           const result = arguments.length > 1 ? self.fn(...args) : self.fn();
           delete self.fn;
         return result;
      }
    
  • apply: fn.apply(context, [1, 2, 3, 4])

      Function.prototype.MyApply = function(content,args = []){
        const self = content || window;
        self.fn = this;
         const result = args.length > 0?self.fn(args):self.fn();
        delete self.fn;
        return result;
      }
    
  • bind: fn.bind(context, 1, 2)(3, 4)

     Function.prototype.MyBind = function(content){
       const self = this;
       const args = Array.from(arguments).slice(1);
       return function F(){
         if(this instanceof F){
           return new self(...args,...arguments);
         }else{
           const doubleArgs = args.concat(arguments);
           return self.apply(content,doubleArgs);
         }
       }
     }
    

其中context为this指向,三种形式的结果是一致的。call与apply参数形式不同,bind返回的是一个未执行的方法,执行的时候可以继续传参,实现了函数的柯里化。

三、手写promise

Promise 的三种状态:fulfilled(执行态)、rejected(拒绝态)、pending(等待态)。

  • 成功时,不可转为其他状态,且必须有一个不可改变的值(value)

  • 失败时,不可转为其他状态,且必须有一个不可改变的原因(reason)

    function Promise(excutor) {
    	let self = this;
    	self.status = 'pending';
    	self.value = null;
    	self.reason = null;
    	self.onFulfilledCallbackArr = [];
    	self.onRejectedCallbackArr = [];
    
    	function resolve(value) {
    		if (self.status === 'pending') {
    			self.value = value;
    			self.status = 'fulfilled';
    			self.onFulfilledCallbackArr.forEach(item => item());
    		}
    	}
    
    	function reject(reason) {
    		if (self.status === 'pending') {
    			self.reason = reason;
    			self.status = 'rejected';
    			self.onRejectedCallbackArr.forEach(item => item());
    		}
    	}
    	try {
    		excutor(resolve, reject);
    	} catch (err) {
    		reject(err);
    	}
    }
    
    Promise.prototype.then = function(onFulfilled, onRejected) {
    	onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function(data) {
    		resolve(data)
    	};
    	onRejected = typeof onRejected === 'function' ? onRejected : function(err) {
    		throw err
    	};
    	let self = this;
    	if (self.status === 'fulfilled') {
    		return new Promise((resolve, reject) => {
    			try {
    				let x = onFulfilled(self.value);
    				if (x instanceof Promise) {
    					x.then(resolve, reject);
    				} else {
    					resolve(x);
    				}
    			} catch (err) {
    				reject(err);
    			}
    		})
    	}
    	if (self.status === 'rejected') {
    		return new Promise((resolve, reject) => {
    			try {
    				let x = onRejected(self.reason);
    				if (x instanceof Promise) {
    					x.then(resolve, reject);
    				} else {
    					resolve(x);
    				}
    			} catch (err) {
    				reject(err);
    			}
    		})
    	}
    	if (self.status === 'pending') {
    		return new Promise((resolve, reject) => {
    			self.onFulfilledCallbackArr.push(() => {
    				let x = onFulfilled(self.value);
    				if (x instanceof Promise) {
    					x.then(resolve, reject);
    				} else {
    					resolve(x);
    				}
    			});
    			self.onRejectedCallbackArr.push(() => {
    				let x = onRejected(self.reason);
    				if (x instanceof Promise) {
    					x.then(resolve, reject);
    				} else {
    					resolve(x);
    				}
    			})
    		})
    	}
    };
    Promise.prototype.catch = function(fn) {
    	return this.then(null, fn);
    };
    
    
    
    

四、手写防抖节流

juejin.cn/post/687587…

五、手写new

juejin.cn/post/687329…

六、运算符

juejin.cn/post/688182…

七、常用的ES6+ 

juejin.cn/post/687593…