js需要掌握手写的方法

17 篇文章 0 订阅
5 篇文章 0 订阅
本文详细介绍了JavaScript的深拷贝实现、类继承的运用、闭包的工作原理、this在不同场景下的行为、手写bind函数、Promise在图片加载中的应用,以及快速排序、选择排序等经典算法。深入浅出地探讨了编程技术的各个方面。
摘要由CSDN通过智能技术生成

 1、手写深拷贝

   function deepClone(obj = {}) {
      if (typeof obj != "object" || obj == null) {
        return obj;
      }
      let result;
      if (obj instanceof Array) {
        result = [];
      } else {
        result = {};
      }
      for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
          result[key] = deepClone(obj[key]);
        }
      }
      return result;
    }

2、用class实现继承

    class Person {
      constructor(name) {
        this.name = name;
      }
      say() {
        console.log(`hi,${this.name}`);
      }
    }
    class Student extends Person {
      constructor(name, subject) {
        super(name);
        this.subject = subject;
      }
      study() {
        console.log(`${this.name}学习${this.subject}`);
      }
    }
    class Teacher extends Person {
      constructor(name, subject) {
        super(name);
        this.subject = subject;
      }
      teach() {
        console.log(`${this.name}老师教${this.subject}`);
      }
    }
    let laowang = new Teacher('老王','数学')
    let xiaowang = new Student('小王','英语')
    laowang.__proto__ === Teacher.prototype; // true
    Person.prototype === Teacher.prototype.__proto__; // true

3、闭包

闭包:自由变量的查找,是在函数定义的地方,向上级作用域查找不是在执行的地方查找

例如:

  函数作为返回值

    function returnFn() {
      let a = 100;
      return function () {
        console.log(a);
      };
    }
    let fn = returnFn();
    let a = 200;
    fn(); // 100

函数作为参数传递

    function consoleFn(fn) {
      let a = 100;
      fn();
    }
    let a = 200;
    function fn() {
      console.log(a);
    }
    consoleFn(fn); // 200

4、this的不同应用场景,如何取值?

当做普通函数被调用(window)

使用call  apply  bind (改变了this指向)

作为对象方法调用(对象他本身) 

在class的方法中调用(当前实例的本身)

箭头函数(他上级作用域去找)

5、手写bind函数

    function fn1(a, b, c) {
      console.log("this", this);
      console.log(a, b, c);
      return "this fn1";
    }
    Function.prototype.bind1 = function () {
      let args = Array.prototype.slice.call(arguments);
      let t = args.shift(); // 取出this
      let self = this; // fn(被执行的函数)
      return function () {
        return self.apply(t, args);
      };
    };
    let fn2 = fn1.bind({ x: 100 }, 1, 2, 3);
    fn2();
    let fn3 = fn1.bind1({ x: 200 }, 2, 3, 4);
    fn3();

6、promise加载图片

    function loadImg(src) {
      return new Promise((resolve, reject) => {
        let img = document.createElement("img");
        img.onload = () => {
          resolve(img);
        };
        img.onerror = () => {
          let err = new Error(`图片加载失败${src}`);
          reject(err);
        };
        img.src = src;
      });
    }

7、手写快速排序

      function quickSort(arr = []) {
        if (arr.length < 2) {
          return arr;
        }
        let benchmark = arr.shift();
        let len = arr.length;
        let left = [];
        let right = [];
        for (let i = 0; i < len; i++) {
          if (arr[i] < benchmark) {
            left.push(arr[i]);
          } else {
            right.push(arr[i]);
          }
        }
        function merge(left, benchmark, right) {
          return [...left, benchmark, ...right];
        }
        return merge(quickSort(left), benchmark, quickSort(right));
      }

8、选择排序

      function selectSort(arr = []) {
        if (arr.length < 2) return arr;
        let temp = [...arr];
        for (let i = 0; i < temp.length - 1; i++) {
          let minIndex = i;
          for (let j = i + 1; j < temp.length; j++) {
            if (temp[minIndex] > temp[j]) {
              minIndex = j;
            }
          }
          [temp[i], temp[minIndex]] = [temp[minIndex], temp[i]];
        }
        return temp;
      }

9、插入排序

      function insertSort(arr = []) {
        if (arr.length < 2) return arr;
        let temp = [...arr];
        let preIndex = 0;
        let currentValeu = temp[0];
        for (let i = 1; i < temp.length; i++) {
          preIndex = i - 1;
          currentValeu = temp[i];
          while (preIndex >= 0 && temp[preIndex] > currentValeu) {
            temp[preIndex + 1] = temp[preIndex];
            preIndex--;
          }
          temp[preIndex + 1] = currentValeu;
        }
        return temp;
      }

10、冒泡排序

      function bubbleSort(arr = []) {
        if (arr.length < 2) return arr;
        let temp = [...arr];
        for (let i = 0; i < temp.length - 1; i++) {
          for (let j = 0; j < temp.length - 1 - i; j++) {
            if (temp[j] > temp[j + 1]) {
              [temp[j], temp[j + 1]] = [temp[j + 1], temp[j]];
            }
          }
        }
        return temp;
      }

11、判断json环

function hasSycle(obj) {
    let arr = [];
    let ret = false;
    function judge(obj) {
        for (let key in obj) {
            let value = obj[key];
            if (typeof value == "object" && value != null) {
                if (arr.includes(value)) {
                    ret = true;
                    console.log(1, '"object"')
                } else {
                    arr.push(value);
                    judge(value);
                }
            }
        }
    }
    judge(obj);
    return ret;
}

12、手写call函数

      Function.prototype.myCall = function (context, ...args) {
        context.fn = this; // fn(被执行的函数)
        console.log(context, args);
        let ret = args.length > 1 ? context.fn(...args) : context.fn();
        delete context.fn;
        return ret;
      };
      function fn1(a, b, c) {
        console.log("this", this);
        console.log(a, b, c);
        return "this fn1";
      }
      fn1.myCall({ x: 100 }, 1, 2, 3);

13、add(1)(2)(3,4)

        function add() {
            let args = Array.prototype.slice.call(arguments);
            let fn = function () {
                let arg_fn = Array.prototype.slice.call(arguments);
                return add.apply(null, args.concat(arg_fn));
            }
            fn.toString = function () {
                return args.reduce(function (a, b) {
                    return a + b;
                })
            }
            return fn;
        }

14、自定义事件监听

class EventListeners {
    constructor() {
        this.events = {};
    }
    $on(eventName, callback) {
        if (!this.events[eventName]) {
            this.events[eventName] = callback;
        } else {
            console.error('已存在相同事件,请重新定义')
        }
    }

    $emit(eventName, ...args) {
        this.events[eventName].apply(this, args);
    }

    $once(eventName, callback) {
        const self = this

        function fn() {
            self.$off(eventName)
            callback.apply(self, arguments)
        }
        this.$on(eventName, fn)
    }

    $off(eventName) {
        delete this.events[eventName]
    }
}

15、时间格式化


function timeFormat(timestamp = null, fmt = "yyyy-mm-dd") {
  timestamp = parseInt(timestamp);
  // 如果为null,则格式化当前时间
  if (!timestamp) timestamp = Number(new Date());
  if (timestamp.toString().length == 10) timestamp *= 1000;
  let date = new Date(timestamp);
  let ret;
  let opt = {
    "y+": date.getFullYear().toString(), // 年
    "m+": (date.getMonth() + 1).toString(), // 月
    "d+": date.getDate().toString(), // 日
    "h+": date.getHours().toString(), // 时
    "M+": date.getMinutes().toString(), // 分
    "s+": date.getSeconds().toString(), // 秒
    // 有其他格式化字符需求可以继续添加,必须转化成字符串
  };
  for (let k in opt) {
    ret = new RegExp("(" + k + ")").exec(fmt);
    if (ret) {
      fmt = fmt.replace(
        ret[1],
        ret[1].length == 1 ? opt[k] : opt[k].padStart(ret[1].length, "0")
      );
    }
  }
  return fmt;
}

16、手写promise


const statusPending = 'pending'
const statusFulfilled = 'fulfilled'
const statusRejected = 'rejected'
class MyPromise {
    value = undefined // 成功返回值
    reason = undefined// 失败返回值
    successCallbacks = [] //pending时 成功回调函数存储
    failCallbacks = [] // pending时 失败回调函数存储
    status = statusPending
    constructor(fn) {
        const resolveFun = (value) => {
            if (this.status === statusPending) {
                this.value = value
                this.status = statusFulfilled
                this.successCallbacks.forEach(fn => fn(this.value))
            }
        }
        const rejectFun = (reason) => {
            if (this.status === statusPending) {
                this.reason = reason
                this.status = statusRejected
                this.failCallbacks.forEach(fn => fn(this.reason))
            }

        }
        try {
            fn(resolveFun, rejectFun)
        } catch (error) {
            rejectFun(error)
        }
    }
    then(fn1, fn2) {
        fn1 = typeof fn1 === "function" ? fn1 : (e) => { e }
        fn2 = typeof fn2 === "function" ? fn2 : (e) => { e }

        return new MyPromise((resolve, reject) => {
            const fn3 = () => {
                try {
                    let res = fn1(this.value)
                    resolve(res)
                } catch (error) {
                    reject(error)
                }

            }
            const fn4 = () => {
                try {
                    let res = fn1(this.reason)
                    reject(res)
                } catch (error) {
                    reject(error)
                }

            }
            if (this.status == statusPending) {
                this.successCallbacks.push(() => {
                    fn3()
                })
                this.failCallbacks.push(() => {
                    fn4()
                })
            }
            if (this.status == statusFulfilled) {
                fn3()
            }
            if (this.status == statusRejected) {
                fn4()
            }
        })
    }
    catch(fn) {
        return this.then(null, fn)
    }
    finally(fn) {
        return this.then(val => {
            fn()
            return val
        }).catch((err) => {
            fn()
            return err
        })
    }
}

MyPromise.resolve = (value) => {
    return new MyPromise((
        resolve, reject
    ) => {
        resolve(value)
    })
}

MyPromise.reject = (reason) => {
    return new MyPromise((
        resolve, reject
    ) => {
        reject(reason)
    })
}
MyPromise.all = (promiseList = []) => {
    return new MyPromise((resolve, reject) => {
        const resP = []// 存储promiseList 结果
        const len = promiseList.length
        let resolveedCount = 0
        promiseList.forEach((p) => {
            p.then(data => {
                resP.push(data)
                resolveedCount++
                if (resolveedCount == len) {
                    resolve(resP)
                }
            }).catch(err => {
                reject(err)
            })
        })
    })
}
MyPromise.race = (promiseList = []) => {
    return new MyPromise((resolve, reject) => {
        let resolved = false
        promiseList.forEach((p) => {
            p.then(data => {
                if (!resolved) {
                    resolve(data)
                    resolved = true
                }
            }).catch(err => {
                reject(err)
            })
        })
    })
}


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值