【study】js手撕

146 阅读5分钟

一. call,apply,bind简单实现

  1. call
Function.prototype.myCall = function (obj, ...args) {
      var obj = obj || window // 这里只能用var
      const p = Symbol('p')
      obj.p = this
      const res = obj.p(...args)
      delete obj.p
      return res
 }
  1. apply
Function.prototype.myApply = function (obj, ...args) {
      var obj = obj || window
      const p = Symbol('p')
      obj.p = this
      const res = obj.p(...args[0]) // 立即执行,和apply的区别!!!!!!!
      delete obj.p
      return res
}
  1. bind
Function.prototype.myBind = function (obj) {
     var _this = this,
         arr = Array.prototype.slice.call(arguments, 1);
      return function () {
        var arr2 = Array.prototype.slice.call(arguments),
          arrSum = arr.concat(arr2);
        _this.apply(obj, arrSum)
        console.log(arrSum)
      }
 }

二. clone,deepClone的实现

  1. clone
浅拷贝:只能复制数据的第一层,第二层修改-------原数组会被修改
// 1.
obj1 = {...obj}

// 2.
obj1 = Object.assign({},obj)

/*
   Object.assign方法用来将源对象(source)的所有可枚举属性,复制到目标对象(target)。
   它至少需要两个对象作为参数,第一个参数是目标对象,后面的参数都是源对象
*/


// 3.
function clone(origin,target){
    var target = target || {};
    for(var prop in origin){
          target[prop] = origin[prop]
     }
    return target[prop]
 }
clone(obj,obj1)
  1. deepClone
深拷贝:原数组不会被修改
// 1.
obj1 = JSON.parse(JSON.stringify(obj))

// 2.
function deepclone(origin,target){
     var target = target || {},
         toStr = Object.prototype.toString,
         toArr = "[object,Array]";
     for(var prop in origin){
         if(origin.hasOwnProperty(prop)){
          // 因为 typeof null == object
          if(origin[prop] !== 'null' && typeof( origin[prop]) == 'object'){
          // 要和toArr判断是否相等
              target[prop] = toStr.call(origin[prop]) == toArr? [] : {}
              deepclone(origin[prop],target[prop])
           } else{
               target[prop] = origin[prop]
            }
          }
        }
     return target
   }
deepclone(obj,obj1)

三. promise

// promise
class myPromise {
      // 设置静态属性
      static PENDING = "待定"; static FULFILLED = "成功"; static REJECTED = "失败";
      constructor(func) {
         // 设置状态为待定
         this.status = myPromise.PENDING
         // result是传入的值
         this.result = null
         // 创建数组保存函数 判断then里面的pending状态,因为数组是先入先出
         this.resolveArr = []
         this.rejectArr = []
         // 回调
         // try catch主要是为了判断new promise的时候,throw new Error('111'),会不会在then里面输出这个111,不判断会报错
         try {
               func(this.resolve.bind(this), this.reject.bind(this))
           } catch (err) {
               this.reject(error)
            }
           }
            // resolve
            resolve(result) {
                if (this.status === myPromise.PENDING) {
                    this.status = myPromise.FULFILLED
                    this.result = result
                    // 和then里面的pending状态相关-----成功
                    this.resolveArr.forEach((callback) => {
                        callback(result)
                    })
                }
            }
            // reject
            reject(result) {
                if (this.status === myPromise.PENDING) {
                    this.status = myPromise.REJECTED
                    this.result = result
                    // 和then里面的pending状态相关-----失败
                    this.rejectArr.forEach((callback) => {
                        callback(result)
                    })
                }
            }
            // then
            // 原生规定,then里面的两个参数不是函数就会被忽略
            then(onFULFILLED, onREJECTED) {
                return new myPromise((resolve, reject) => {
                    onFULFILLED = typeof onFULFILLED === 'function' ? onFULFILLED : () => { }
                    onREJECTED = typeof onREJECTED === 'function' ? onREJECTED : () => { }
                    // pending
                    if (this.status === myPromise.PENDING) {
                        this.resolveArr.push(onFULFILLED)
                        this.rejectArr.push(onREJECTED)
                    }
                    // resolve
                    if (this.status === myPromise.FULFILLED) {
                        // resolve的时候,没有进行异步操作,而是同步下来,执行顺序会报错
                        setTimeout(() => {
                            onFULFILLED(this.result)
                        })
                    }
                    // reject
                    if (this.status === myPromise.REJECTED) {
                        setTimeout(() => {
                            onREJECTED(this.result)
                        })
                    }
                })
            }
        }
// promise.all

function customPromiseAll(promises) {
  return new Promise((resolve, reject) => {
    if (!Array.isArray(promises)) {
      return reject('Argument should be an array');
    }

    let result = [];
    let count = 0;

    // 遍历每一个 Promise
    promises.forEach((promise, index) => {
      // 将每一个元素通过 Promise.resolve 转成 Promise 处理,
      // 因为数组里可能是非 Promise 对象
      Promise.resolve(promise)
        .then(value => {
          result[index] = value; // 保存结果到相应的位置
          count++;
          // 当所有 Promise 都完成时,resolve 外层的 Promise
          if (count === promises.length) {
            resolve(result);
          }
        })
        .catch(error => {
          // 只要有一个 Promise 拒绝,reject 外层的 Promise
          reject(error);
        });
    });
  });
}

// 测试
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const p3 = new Promise((resolve, reject) => setTimeout(resolve, 1000, 3));

customPromiseAll([p1, p2, p3])
  .then(result => {
    console.log(result); // [1, 2, 3]
  })
  .catch(error => {
    console.log(error);
  });

四. 继承

   <script>
        // ES5
        function Parent(name,age){
            this.name = name;
            this.age = age;
        }

        Parent.prototype.call = function(){
            console.log("我可以打电话!!!")
        }

        function Son(name,age,like){
            Parent.call(this,name,age)
            this.like = like;
        }

        Son.prototype = new Parent;
        Son.prototype.constructor = Son;


        Son.prototype.wife = function(){
            console.log("beautiful")
        }

        // const res = new Son("cxk",22,"zzt")
      


        // ES6
        class Parent{
            constructor(name,age){
                this.name = name;
                this.age = age;
            }
            call(){
                cosole.log("我可以打电话!!!")
            }
        }

        class Son extends Parent{
            constructor(name,age,sex){
                super(name,age);
                this.sex = sex;
            }
            game(){
                console.log("我可以打游戏!!!")
            }
        }

        // const res = new Son("cxk",18,"zzt")
   
    </script>

五. 防抖和节流

  <script>
        function debounce(func, wait, immediate) {
            let timeout;
            return function () {
                let _this = this;
                let args = arguments;

                clearTimeout(timeout);
                if (immediate) {
                    let callNow = !timeout;
                    timeout = setTimeout(function () {
                        timeout = null
                    }, wait)
                    if (callNow) func.apply(_this, args)
                } else {
                    timeout = setTimeout(function () {
                        func.apply(_this, args)
                    }, wait)
                }
            }
        }
        
        // 防抖例子:在el-tree的搜索框内,设置防抖
        // 进行防抖处理,避免频繁触发函数执行
        const filterTrigger = _.debounce(() => {
            treeDialogRef.value.filter(filterText.value);
        }, 500);


        // * @param type 1 表时间戳版,2 表定时器版
        function throttle(func, wait, type) {
            if (type === 1) {
                let old = 0;
            } else if (type === 2) {
                let timeout;
            }
            return function () {
                let _this = this;
                let args = arguments;
                if (type === 1) {
                    let now = Date.now();
                    if (now - old > wait) {
                        func.apply(_this, args)
                        old = now
                    }
                } else if (type === 2) {
                    // 条件
                    if (!timeout) {
                        timeout = setTimeout(() => {
                            // 先null
                            timeout = null
                            func.apply(_this, args)
                        }, wait)
                    }
                }
            }
        }
    </script>

六. 数组的扁平化flat

 <script>
    var arr = [1, 2, [3, 4, [5]]]
    // console.log(arr.flat(Infinity))

    function flatten(arr) {
      let result = [];
      for (let i = 0; i < arr.length; i++) {
        if (Array.isArray(arr[i])) {
          result = result.concat(flatten(arr[i]));
        } else {
          result = result.concat(arr[i]);
        }
      }

      return result;
    }

    console.log(flatten(arr))
  </script>

七. 冒泡排序

 var arr = [9, 78, 2, 5, 6, 90]
    function Bubble(arr) {
        for (let i = 0; i < arr.length - 1; i++) {
             for (let j = 0; j < arr.length - 1 - i; j++) {
                 if (arr[j] > arr[j + 1]) {
                     const temp = arr[j]
                     arr[j] = arr[j + 1]
                     arr[j + 1] = temp
                  }
              }
          }
        return arr
 }
console.log(Bubble(arr))

八.reduce

    const list = [1,2,3,4,5] 

    Array.prototype.myReduce = function(fn, initValue) {
        let hasInitValue = initValue !== undefined;
        let value = hasInitValue ? initValue : this[0];

        for(var i = hasInitValue ? 0 : 1; i< this.length; i++) {
            value = fn(value,this[i],i,this)
        }

        return value;
    }


    const res = list.myReduce((prev,next)=> {
        return prev + next
    },0)

    console.log(res)

九.map,every,some,filter,find,unshift

 const list = [1,2,3,4,5] 
 
    Array.prototype.myMap = function(fn) {
        var arr = []
        for(var i = 0 ; i < this.length; i++) {
            var f = fn(this[i], i , this)
            arr.push(f)
        }
        return arr;
    }

    const res = list.myMap((item,index,array)=> {
        return item+1;
    })

    console.log(res) // [2,3,4,5,6]

const list = [1,2,3,4,5] 

     Array.prototype.myEvery = function(fn) {
        var flag = true;
        for(var i = 0 ; i < this.length; i++) {
            flag = fn(this[i]);
            if (!flag) {
                return false;
            }
        }
        return flag;
     }

     const res = list.myEvery((item)=> {
        return item > 0
     })

     console.log(res) // true
    const list = [1,2,3,4,5] 

     Array.prototype.mySome = function(fn) {
        for(var i = 0 ; i < this.length; i++) {
            flag = fn(this[i]);
            if (flag) {
                return flag;
            }
        }
        return false;
     }

     const res = list.mySome((item)=> {
        return item > 3
     })

     console.log(res) // true
 const list = [1,2,3,4,5] 

     Array.prototype.myFilter = function(fn) {
        let arr = [];
        for(var i = 0 ; i < this.length; i++) {
            var flag = fn(this[i]);
            if (flag) {
                arr.push(this[i])
            }
        }
        return arr;
     }

     const res = list.myFilter((item)=> {
        return item > 3
     })

     console.log(res) // [4,5]
  const list = [1,2,3,4,5] 

     Array.prototype.myFind = function(fn) {
        for(var i = 0 ; i < this.length; i++) {
            var flag = fn(this[i]);
            if (flag) {
                return this[i]
            }
        }
     }

     const res = list.myFind((item)=> {
        return item > 3
     })

     console.log(res) // 4
const arr = [1,2,3]

arr.myUnshift(5) // 5,1,2,3
Array.prototype.myUnshift = function(fn) {
   const len = argumentts.length;
   for (let i =  len - 1; i >= 0; i--) {
      const element = argument[i]
      this.splice(0,0,element)
   }
  return this.length;
}

十.获取指定范围内的随机数

function fn(min,max){
//(min, max)
return Math.round(Math.random() * (max -min -2) + min + 1)
//[min, max]
return Math.round(Math.random() * (max -min) + min)
//(min, max]
return Math.ceil(Math.random() * (max -min) + min)
//[min, max)
return Math.floor(Math.random() * (max -min) + min)
}

十一.获取100以内的质数

let count;
for (let i = 2; i < =100; i++) {
    for(let j = 1 ; j < i; j++) {
       if (i % j === 0) {
          count++
       }
    }
    
    // 从1开始,到自身都没%完,自身整除 count === 2
    if (count === 2) {
       console.log(i)
    }
    
    count = 0
}

十二.提取url参数

let url = 'https://hddhdhdhhd?a=1&b=2&c=3hdeueu'

function queryUrlParams(url) {
   let urls = url.split('?')[1]
   const urlSearchParams = new URLSearchParams(urls);
   const params = object.formEntries(urlSearchParams.entries())
   
   return params
}

十三.数组随机排序

var arr = [1,2,3,4,5,6]

function result(arr) {
   for(let i = 0 ; i < arr.length; i++) {
       let randomIndex = parseInt(Math.random() * arr.length)
   
       let curNum = arr[i]
       arr[i] = arr[randomIndex]
       arr[randomIndex] = curNum
   }
   
   return arr
}

arr.sort(() => Math.random() - 0.5)