爆款云主机2核4G限时秒杀,88元/年起!
查看详情

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 618智算钜惠季 爆款云主机2核4G限时秒杀,88元/年起!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 首保服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      JavaScript进阶:手写代码挑战(二)

      首页 知识中心 软件开发 文章详情页

      JavaScript进阶:手写代码挑战(二)

      2025-03-18 08:31:45 阅读次数:10

      JavaScript,Object,Promise,拷贝,数组,运算符

      在现代Web开发中,JavaScript 是不可或缺的编程语言。掌握其核心功能和原理对于开发者至关重要。本文通过手写实现JavaScript的一些关键功能和算法,帮助读者深入理解其工作原理,提升编程技能。无论你是初学者还是有经验的开发者,都能从中受益。

      12 原型 继承 概念

      1. 继承
      例举几种比较常用的继承方式
      /**
       * 使用 extends 继承
       */
      ​
      // 继承类
      class Vehicle {}
      class Bus extends Vehicle {}
      ​
      let b = new Bus();
      console.log(b instanceof Bus); // true
      console.log(b instanceof Vehicle); // true
      ​
      ​
      // 继承普通构造函数
      function Person() {}
      class Engineer extends Person {}
      ​
      let e = new Engineer();
      console.log(e instanceof Engineer); // true
      console.log(e instanceof Person); // true
      ​
      ​
      /**
       * 寄生式组合继承
       */
      function Person(name) {
           = name;
      }
      function Man(name, age) {
          Person.call(this, name, age);
          this.age = age;
      }
      Man.prototype = Object.create(Person.prototype);
      Man.prototype.constructor = Man;
      ​
      const man = new Man('mxin', 18);
      console.log(man instanceof Man); // true
      console.log(man instanceof Person); // true

      13、instanceof

      /**
       * 模拟 instanceof
       * 判断 obj.__proto__ 和 __constructor.prototype 是否相等
       * @param {object} obj 实例对象
       * @param {function} __constructor 构造函数
       */
      function __instanceof(obj, __constructor) {
          const prototype = __constructor.prototype;
          obj = Object.getPrototypeOf(obj);
      ​
          while (true) {
              if (obj === null) return false;
              if (obj === prototype) return true;
              obj = Object.getPrototypeOf(obj);
          }
      }
      ​
      // ------------------------------ 测试 ------------------------------
      ​
      function C() {}
      function D() {}
      ​
      const o = new C();
      ​
      // __instanceof()
      console.log('__instanceof()');
      ​
      console.log(__instanceof(o, C));
      console.log(__instanceof(o, D));
      console.log(__instanceof(o, Object));
      ​
      // instanceof
      console.log('instanceof');
      ​
      console.log(o instanceof C);
      console.log(o instanceof D);
      console.log(o instanceof Object);

      14 object.create

      /**
       * 模拟 Object.create
       * 创建一个新对象,使用现有的对象来提供新创建的对象的__proto__
       * @param {object} prototype 新创建对象的原型对象,为 null 时 只能使用 Object.create()
       * @param {object} properties 访问器描述符,同 Object.defineProperties 第二个参数
       * @returns {object}
       */
      function __create(prototype, properties) {
          if (typeof prototype !== 'object') throw new TypeError('Error');
      ​
          function Constructor() {}
          Constructor.prototype = prototype;
      ​
          const obj = new Constructor();
      ​
          if (prototype) obj.constructor = Constructor;
      ​
          // 设置访问器描述符
          if (properties) {
              if (typeof properties !== 'object') throw TypeError('Error');
              Object.defineProperties(obj, properties);
          }
      ​
          return obj;
      }
      ​
      // ------------------------------ 测试 ------------------------------
      ​
      const person = {
          isHuman: false,
          printIntroduction: function () {
              console.log(`My name is ${}. Am I human? ${this.isHuman}`);
          },
      };
      ​
      // __create()
      console.log('__create()');
      ​
      const __me = __create(person);
      __ = '__mxin';
      __me.isHuman = true;
      __me.printIntroduction();
      ​
      // Object.create()
      console.log('Object.create()');
      ​
      const me = Object.create(person);
       = 'mxin';
      me.isHuman = true;
      me.printIntroduction();
      ​
      // 目前创建纯净空对象只有 Object.create(null) 可行,无法模拟
      const emptyObj = Object.create(null);
      console.log(emptyObj);
      // {}
      //    No properties

      15 Object.is

      • 与== 运算不同,== 运算符在判断相等前对两边的变量(如果它们不是同一类型) 进行强制转换 (这种行为的结果会将 "" == false 判断为 true), 而 Object.is不会强制转换两边的值

      • 与=== 运算也不相同, === 运算符 (也包括 == 运算符) 将数字 -0 和 +0 视为相等 ,而将Number.NaN 与 NaN 视为不相等

      /**
       * 模拟 Object.is
       * 判断两个值是否为同一个值
       * 1. 都是 undefined
       * 2. 都是 null
       * 3. 都是 true 或 false
       * 4. 都是相同长度的字符串且相同字符按相同顺序排列
       * 5. 都是相同对象(意味着每个对象有同一个引用)
       * 6. 都是数字且
       *    a. 都是 +0
       *    b. 都是 -0
       *    c. 都是 NaN
       *    d. 或都是非零而且非 NaN 且为同一个值
       * @param {*} x
       * @param {*} y
       */
      function __is(x, y) {
          if (x === y) {
              return x !== 0 || 1 / x === 1 / y;
          } else {
              return x !== x && y !== y;
          }
      }
      ​
      // ------------------------------ 测试 ------------------------------
      ​
      // __is()
      console.log('__is()');
      ​
      console.log(`__is('foo', 'foo'): ${__is('foo', 'foo')}`); // true
      console.log(`__is('foo', 'bar'): ${__is('foo', 'bar')}`); // false
      ​
      const __foo = { a: 1 };
      const __bar = { a: 1 };
      console.log(`__is(__foo, __foo): ${__is(__foo, __foo)}`); // true
      console.log(`__is(__foo, __bar): ${__is(__foo, __bar)}`); // false
      console.log(`__is(window, window): ${__is(window, window)}`); // true
      console.log(`__is([], []): ${__is([], [])}`); // false
      console.log(`__is(null, null): ${__is(null, null)}`); // true
      ​
      // 特例
      console.log(`__is(0, -0): ${__is(0, -0)}`); // false
      console.log(`__is(0, +0): ${__is(0, +0)}`); // true
      console.log(`__is(-0, -0): ${__is(-0, -0)}`); // true
      // console.log(`__is(NaN, 0 / 0): ${__is(NaN, 0 / 0)}`); // true
      ​
      ​
      // Object.is()
      console.log('Object.is()');
      ​
      console.log(`Object.is('foo', 'foo'): ${Object.is('foo', 'foo')}`); // true
      console.log(`Object.is('foo', 'bar'): ${Object.is('foo', 'bar')}`); // false
      ​
      const foo = { a: 1 };
      const bar = { a: 1 };
      console.log(`Object.is(foo, foo): ${Object.is(foo, foo)}`); // true
      console.log(`Object.is(foo, bar): ${Object.is(foo, bar)}`); // false
      console.log(`Object.is(window, window): ${Object.is(window, window)}`); // true
      console.log(`Object.is([], []): ${Object.is([], [])}`); // false
      console.log(`Object.is(null, null): ${Object.is(null, null)}`); // true
      ​
      // 特例
      console.log(`Object.is(0, -0): ${Object.is(0, -0)}`); // false
      console.log(`Object.is(0, +0): ${Object.is(0, +0)}`); // true
      console.log(`Object.is(-0, -0): ${Object.is(-0, -0)}`); // true
      console.log(`Object.is(NaN, 0 / 0): ${Object.is(NaN, 0 / 0)}`); // true

      16 new

      /**
       * 模拟 new
       * 1. 创建原型为 constructor.prototype 的新对象 obj
       * 2. 执行构造函数,this 指向 obj
       * 3. 判断构造函数返回值是否为对象,是就返回此对象
       * 4. 构造函数无返回值返回 obj
       * @param {function} constructor
       * @param  {...any} args
       * @returns {object}
       */
      function __new(constructor, ...args) {
          if (typeof constructor !== 'function') throw new TypeError('Error');
      ​
          // 创建一个空对象,指定原型为constructor.prototype
          const obj = Object.create(constructor.prototype);
      ​
          // 执行构造函数,绑定this
          const result = constructor.apply(obj, args);
      ​
          // 如果构造函数返回值是一个对象,那么返回该对象, 如果没有就返回 obj
          return result && result instanceof Object ? result : obj;
      }
      ​
      // ------------------------------ 测试 ------------------------------
      ​
      
      
      function Person(name, age) {
           = name;
          this.age = age;
      }
      ​
      // __new
      console.log('__new');
      const __mxin = __new(Person, '__mxin', 18);
      console.log(__mxin);
      // Person {name: "__mxin", age: "18"}
      //     age: "18"
      //     name: "__mxin"
      //     __proto__:
      //         constructor: ƒ Person(name, age)
      //         __proto__: Object
      ​
      // new
      console.log('new');
      const mxin = new Person('mxin', 18);
      console.log(mxin);
      // Person {name: "mxin", age: "18"}
      //     age: "18"
      //     name: "mxin"
      //     __proto__:
      //         constructor: ƒ Person(name, age)
      //         __proto__: Object

      17 浅拷贝

      几种常用方式:

      1. 自定义循环

      2. 展开运算符

      3. Object.assign()

      /**
       * 浅拷贝,无脑循环
       * @param {*} targetObj
       */
      function shallowClone(targetObj) {
          const resObj = {};
          for (let key in targetObj) {
              resObj[key] = targetObj[key];
          }
          return resObj;
      }
      ​
      // ------------------------------ 测试 ------------------------------
      ​
      console.log('shallowClone()');
      ​
      const shallowObj = {
          name: 'mxin',
          age: 18,
      };
      ​
      /**
       * 自定义方法
       */
      const a = shallowClone(shallowObj);
       = '__mxin';
      a.age = 20;
      ​
      console.log('a', a);
      // {name: "__mxin", age: 20}
      //   age: 20
      //   name: "__mxin"
      ​
      /**
       * 拓展运算符
       */
      const b = { ...a };
       = '____mxin';
      b.age = 22;
      ​
      console.log('b', b);
      // {name: "____mxin", age: 22}
      //   age: 22
      //   name: "____mxin"
      ​
      /**
       * Object.assign()
       */
      const c = Object.assign({}, shallowObj)
       = '______mxin';
      c.age = 24;
      ​
      console.log('c', c);
      // {name: "______mxin", age: 24}
      //   age: 24
      //   name: "______mxin"
      ​
      // 不影响原有对象
      console.log('shallowObj', shallowObj);
      // {name: "mxin", age: 18}
      //   age: 18
      //   name: "mxin"

      18 深拷贝

      /**
       * 深拷贝
       * 深层克隆对象结构
       * @param {object} target
       * @returns {object}
       */
      function deepClone(target) {
          // 如果不是对象,直接返回本身
          if (!isObject(target) || target === null) return target;
      ​
          // 参数类型校验情况还有很多,没有覆盖全面,可以后期拓展
          if (target instanceof Date) return new Date(target);
          if (target instanceof RegExp) return new RegExp(target);
      ​
          const obj = {};
          const stack = [
              {
                  parent: obj,
                  key: null,
                  data: target,
              },
          ];
      ​
          while (stack.length) {
              const node = stack.pop();
              const parent = node.parent;
              const key = node.key;
              const data = node.data;
      ​
              let res = key ? (parent[key] = {}) : parent;
      ​
              for (const k in data) {
                  if (data.hasOwnProperty(k)) {
                      if (isObject(data[k])) {
                          stack.push({
                              parent: res,
                              key: k,
                              data: data[k],
                          });
                      } else {
                          res[k] = data[k];
                      }
                  }
              }
          }
      ​
          return obj;
      }
      ​
      /**
       * 判断 target 是否为对象
       * @param {*} target
       */
      function isObject(target) {
          return Object.prototype.toString.call(target) === '[object Object]';
      }
      // ------------------------------ 测试 ------------------------------
      ​
      console.log('deepClone()');
      ​
      const deepObj = {
          e: {
              f: {
                  g: {
                      h: 1,
                  },
              },
          },
          i: {
              j: {
                  k: {
                      l: 2,
                  },
              },
          },
      };
      ​
      const d = deepClone(deepObj);
      d.e.f.g.h = 2;
      d.i.j.k.l = 4;
      ​
      console.log('d', d);
      ​
      // 不影响原有对象
      console.log('deepObj', deepObj);

      19 对象扁平化

      /**
       * 对象扁平化
       * 将多层嵌套的 key 合并
       * @param {object} target
       * @param {string} tempKey
       * @param {object} res
       * @returns {object}
       */
      function flattenObject(target, tempKey = '', res = {}) {
          // 使用 Object.entries() 将键值对转换成数组,确保 key 与 val 的对应关系
          for (const [key, val] of Object.entries(target)) {
              // 如果 val 是对象,保存合并后的 key 进行递归
              if (isObject(val)) {
                  const tmp = tempKey + key + '.';
                  flattenObject(val, tmp, res);
              } else {
                  // 当 val 不是对象,合并 key 并对结果对象赋值
                  const tmp = tempKey + key;
                  res[tmp] = val;
              }
          }
          return res;
      }
      ​
      /**
       * 判断 target 是否为对象
       * @param {*} target
       */
      function isObject(target) {
          return Object.prototype.toString.call(target) === '[object Object]';
      }
      ​
      // ------------------------------ 测试 ------------------------------
      ​
      console.log('flattenObject()');
      ​
      const object = {
          d: {
              e: {
                  f: {
                      g: {
                          h: 1,
                      },
                  },
              },
              i: {
                  j: {
                      k: {
                          l: 2,
                      },
                  },
              },
          },
      };
      ​
      console.log(flattenObject(object));
      // {
      //   d.e.f.g.h: 1
      //   d.i.j.k.l: 2
      // }

      20 数组扁平化

       几种常用方式:
      
      递归
      Array.prototype.flat()
      Array.prototype.reduce()
      /**
       * 数组扁平化
       * 判断数组中元素类型,如果是数组类型就递归,否则直接 push 到 res 中
       * @param {array} target
       * @param {array} res
       * @returns {array}
       */
      function flattenArray(target, res = []) {
          for (const val of target) {
              if (Array.isArray(val)) {
                  flattenArray(val, res);
              } else {
                  res.push(val);
              }
          }
          return res;
      }
      ​
      /**
       * 使用 Array.prototype.reduce()
       * @param {array} target
       */
      function flattenArrayByReduce(target) {
          const initPre = [];
          return target.reduce(
              (pre, current) =>
                  pre.concat(
                      Array.isArray(current) ? flattenArrayByReduce(current) : current
                  ),
              initPre
          );
      }
      ​
      // ------------------------------ 测试 ------------------------------
      ​
      console.log('flattenArray()');
      ​
      const array = [[0], 1, [2, [3, [4, [5, [6]]]]], [7, [8]]];
      ​
      /**
       * 递归
       */
      console.log(flattenArray(array));
      // [0, 1, 2, 3, 4, 5, 6, 7, 8]
      ​
      /**
       * Array.prototype.flat()
       */
      console.log(array.flat(Number.MAX_SAFE_INTEGER));
      // [0, 1, 2, 3, 4, 5, 6, 7, 8]
      ​
      /**
       * Array.prototype.reduce()
       */
      console.log(flattenArrayByReduce(array));
      // [0, 1, 2, 3, 4, 5, 6, 7, 8]
      ##

      21 数组去重

       

      • 使用 set

      console.log([...new Set(array)]);
      • 使用对象,或者将对象换成 map ,需要注意数组中元素的类型

      /**
       * 数组去重
       * 基于对象实现,也可以使用 Map
       * @param {array} target
       * @returns {array}
       */
      function removeDuplicate(target) {
          const temp = {};
          for (let i = 0; i < target.length; i++) {
              const item = target[i];
              if (
                  Object.prototype.toString.call(item) !== '[object Object]' &&
                  Object.prototype.toString.call(item) !== '[object Function]' &&
                  Object.prototype.toString.call(item) !== '[object Symbol]' &&
                  Object.prototype.toString.call(item) !== '[object Array]'
              ) {
                  if (temp.hasOwnProperty(item)) {
                      target[i] = target[target.length - 1];
                      target.length--;
                      i--;
                  }
              }
              temp[item] = item;
          }
          return target;
      }
      ​
      // ------------------------------ 测试 ------------------------------
      ​
      console.log('removeDuplicate()');
      ​
      const array = [
          1,
          1,
          '2',
          '2',
          true,
          true,
          false,
          false,
          undefined,
          undefined,
          null,
          null,
          Symbol('3'),
          Symbol('3'),
          {},
          {},
          [],
          [],
      ];
      ​
      console.log(removeDuplicate(array));

      22 promise

      • Promise

        • resolve

        • reject

        • then

        • catch

        • finally

      • Promise.resolve

      • Promise.reject

      • Promise.all

      • promise.race

      const isFunction = variable => typeof variable === 'function';
      ​
      // 定义Promise的三种状态常量
      const PENDING = 'pending';
      const RESOLVE = 'resolved';
      const REJECTED = 'rejected';
      ​
      class __Promise {
          constructor(fn) {
              this.__status = PENDING;
              // 储存 value,用于 __then 返回
              this.__value = null;
              // 失败队列,在 __then 时注入,resolve 时触发
              this.__rejectedQueues = [];
              // 成功队列,在 __then 时注入,resolve 时触发
              this.__resolvedQueues = [];
      ​
              try {
                  fn(this.__resolve, this.__reject);
              } catch (err) {
                  this.__reject(err);
              }
          }
      ​
          __resolve = val => {
              const run = () => {
                  if (this.__status !== PENDING) return;
                  this.__status = RESOLVE;
      ​
                  // 依次执行成功队列中的函数,并清空队列
                  const runResolved = value => {
                      let cb;
                      while ((cb = this.__resolvedQueues.shift())) {
                          cb(value);
                      }
                  };
      ​
                  // 依次执行失败队列中的函数,并清空队列
                  const runRejected = error => {
                      let cb;
                      while ((cb = this.__rejectedQueues.shift())) {
                          cb(error);
                      }
                  };
      ​
                  /*
                   * 如果 resolve 的参数为 Promise 对象,
                   * 则必须等待该 Promise 对象状态改变后当前 Promsie 的状态才会改变
                   * 且状态取决于参数 Promsie 对象的状态
                   */
                  if (val instanceof __Promise) {
                      val.__then(
                          value => {
                              this.__value = value;
                              runResolved(value);
                          },
                          err => {
                              this.__value = err;
                              runRejected(err);
                          }
                      );
                  } else {
                      this.__value = val;
                      runResolved(val);
                  }
              };
      ​
              // 异步调用
              setTimeout(run);
          };
      ​
          __reject = err => {
              if (this.__status !== PENDING) return;
      ​
              const run = () => {
                  this.__status = REJECTED;
                  this.__value = err;
                  let cb;
                  while ((cb = this.__rejectedQueues.shift())) {
                      cb(err);
                  }
              };
      ​
              setTimeout(run);
          };
      ​
          __then(onResolved, onRejected) {
              const { __value, __status } = this;
      ​
              return new __Promise((onResolvedNext, onRejectedNext) => {
                  const resolved = value => {
                      try {
                          if (!isFunction(onResolved)) {
                              onResolvedNext(value);
                          } else {
                              const res = onResolved(value);
      ​
                              if (res instanceof __Promise) {
                                  // 如果当前回调函数返回__Promise对象,必须等待其状态改变后在执行下一个回调
                                  res.__then(onResolvedNext, onRejectedNext);
                              } else {
                                  // 否则会将返回结果直接作为参数,传入下一个 __then 的回调函数,并立即执行下一个 __then 的回调函数
                                  onResolvedNext(res);
                              }
                          }
                      } catch (err) {
                          onRejectedNext(err);
                      }
                  };
      ​
                  const rejected = error => {
                      try {
                          if (!isFunction(onRejected)) {
                              onRejectedNext(error);
                          } else {
                              const res = onRejected(error);
      ​
                              if (res instanceof __Promise) {
                                  res.__then(onResolvedNext, onRejectedNext);
                              } else {
                                  onResolvedNext(res);
                              }
                          }
                      } catch (err) {
                          onRejectedNext(err);
                      }
                  };
      ​
                  if (__status === PENDING) {
                      this.__resolvedQueues.push(resolved);
                      this.__rejectedQueues.push(rejected);
                  }
      ​
                  if (__status === RESOLVE) resolved(__value);
      ​
                  if (__status === REJECTED) rejected(__value);
              });
          }
      ​
          __catch(onRejected) {
              return this.__then(null, onRejected);
          }
      ​
          __finally(cb) {
              return this.__then(
                  value => __Promise.resolve(cb()).__then(() => value),
                  reason =>
                      __Promise.resolve(cb()).__then(() => {
                          throw new Error(reason);
                      })
              );
          }
      ​
          static resolve(value) {
              // 如果参数是 __Promise 实例,直接返回这个实例
              if (value instanceof __Promise) return value;
              return new __Promise(resolve => resolve(value));
          }
      ​
          static reject(value) {
              return new __Promise((resolve, reject) => reject(value));
          }
      ​
          static all(list) {
              return new __Promise((resolve, reject) => {
                  const values = [];
                  let count = 0;
      ​
                  for (const [i, p] of list.entries()) {
                      // 数组参数如果不是 __Promise 实例,先调用 __Promise.resolve
                      this.resolve(p).__then(
                          res => {
                              values[i] = res;
                              count++;
                              // 所有状态都变成 resolved 时返回的 __Promise 状态就变成 resolved
                              if (count === list.length) resolve(values);
                          },
                          err => {
                              // 有一个被 rejected 时返回的 __Promise 状态就变成 rejected
                              reject(err);
                          }
                      );
                  }
              });
          }
      ​
          static race(list) {
              return new __Promise((resolve, reject) => {
                  list.forEach(p => {
                      this.resolve(p).__then(
                          res => {
                              resolve(res);
                          },
                          err => {
                              reject(err);
                          }
                      );
                  });
              });
          }
      }
      ​
      // ------------------------------ 测试 ------------------------------
      
      console.log('class __Promise {}');
      ​
      const p1 = new __Promise((resolve, reject) =>
          setTimeout(() => {
              resolve('mxin');
          }, 500)
      );
      const p2 = new __Promise((resolve, reject) =>
          setTimeout(() => {
              resolve('__mxin');
          }, 200)
      );
      const p3 = new __Promise((resolve, reject) => {
          setTimeout(() => {
              reject(new Error('mxin3'));
          }, 100);
      });
      ​
      // 测试 __resolve __then __finally
      new __Promise((resolve, reject) => {
          resolve('mxin');
      })
          .__then(res => {
              console.log('__resolve:', res);
          })
          .__finally(() => {
              console.log('__resolve finally');
          });
      ​
      // 测试 __reject __catch __finally
      new __Promise((resolve, reject) => {
          reject(new Error());
      })
          .__catch(e => {
              console.log('__reject:', e);
          })
          .__finally(() => {
              console.log('__reject finally');
          });
      ​
      // 测试 static resolve
      __Promise
          .resolve('mxin')
          .__then(res => console.log('static resolve:', res))
          .__finally(() => console.log('static resolve finally'));
      ​
      // 测试 static reject
      __Promise
          .reject(new Error())
          .__catch(res => console.log('static reject:', res))
          .__finally(() => console.log('static reject finally'));
      ​
      // 测试 all,可添加 p3 测试 rejected 状态
      __Promise
          .all([p1, p2])
          .__then(res => console.log('all resolve:', res))
          .__catch(e => console.log('all reject', e))
          .__finally(() => console.log('all finally'));
      ​
      // 测试 race,速度快的优先返回并结束, 添加 p3 优先 reject
      __Promise
          .race([p1, p2])
          .__then(res => console.log('race resolve:', res))
          .__catch(e => console.log('race reject', e))
          .__finally(() => console.log('race finally'));

      23 async/await

      const NEXT = 'next';
      const THROW = 'throw';
      /**
       * 模拟 async 函数
       * 1.generator 分割代码片段
       * 2.使用一个函数让其自迭代
       * 3.使用 promise 将 yield 包裹起来
       * 4.执行下一步的时机由 promise 来控制
       * @param {*} fn
       */
      function __async(fn) {
          return function () {
              // 获取迭代器实例
              const gen = fn.apply(this, arguments);
      ​
              return new Promise((resolve, reject) => {
                  // 执行下一步
                  function _next(value) {
                      __step(gen, resolve, reject, _next, _throw, NEXT, value);
                  }
                  // 抛异常
                  function _throw(err) {
                      __step(gen, resolve, reject, _next, _throw, THROW, err);
                  }
                  // 首次触发
                  _next(void 0);
              });
          };
      }
      ​
      /**
       * 执行迭代步骤,处理下次迭代结果
       * 1.将所有值promise化
       * 2.当 promise 执行完之后再执行下一步
       * 3.递归调用 next 函数,直到 done == true
       */
      function __step(gen, resolve, reject, _next, _throw, key, arg) {
          try {
              var info = gen[key](arg);
              var value = info.value;
          } catch (error) {
              return reject(error);
          }
          // 迭代完成
          if (info.done) {
              resolve(value);
          } else {
              Promise.resolve(value).then(_next, _throw);
          }
      }
      ​
      // ------------------------------ 测试 ------------------------------
      console.log('async');
      ​
      __async(function* () {
          const e = yield new Promise(resolve =>
              setTimeout(() => {
                  resolve('e');
              }, 1000)
          );
          const a = yield Promise.resolve('a');
          const d = yield 'd';
          const b = yield Promise.resolve('b');
          const c = yield Promise.resolve('c');
          return [a, b, c, d, e];
      })().then(
          res => console.log(res) // ['a', 'b', 'c', 'd', 'e']
      );

      24 并发

      /**
       * 异步分片处理并发
       * 1.通过 limitNum 限制并发的 promise 数量
       * 2.临时结果保存到 resArr 中
       * 3.start 返回 promise,全部执行完毕 finally 中 resolve 最终结果
       */
      class Limit {
          constructor(limitNum, promiseList) {
              this.resArr = [];
              this.handling = 0;
              this.resolvedNum = 0;
              this.limitNum = limitNum;
              this.promiseList = promiseList;
              this.runTime = this.promiseList.length;
          }
      ​
          handle(promise) {
              console.log(promise, this.handling);
              return new Promise((resolve, reject) => {
                  promise.then(res => resolve(res)).catch(e => reject(e));
              });
          }
      ​
          start() {
              const __this = this;
              return new Promise(resolve => {
                  const run = () => {
                      if (!__this.promiseList.length) return;
                      __this.handling += 1;
                      __this
                          .handle(__this.promiseList.shift())
                          .then(res => {
                              __this.resArr.push(res);
                          })
                          .catch(e => {
                              const error = new Error(e);
                              __this.resArr.push(error);
                          })
                          .finally(() => {
                              __this.handling -= 1;
                              __this.resolvedNum += 1;
                              if (__this.resolvedNum === __this.runTime) {
                                  resolve(__this.resArr);
                              }
                              run();
                          });
                  };
      ​
                  for (let i = 1; i <= __this.limitNum; i++) {
                      run();
                  }
              });
          }
      }
      ​
      // ------------------------------ 测试 ------------------------------
      console.log('Limit');
      ​
      const p1 = new Promise((resolve, reject) => {
          setTimeout(() => {
              resolve(1);
          }, 1000);
      });
      const p2 = new Promise((resolve, reject) => {
          setTimeout(() => {
              resolve(2);
          }, 1000);
      });
      const p3 = new Promise((resolve, reject) => {
          setTimeout(() => {
              reject(3);
          }, 2000);
      });
      const p4 = new Promise((resolve, reject) => {
          setTimeout(() => {
              resolve(4);
          }, 2000);
      });
      const p5 = new Promise((resolve, reject) => {
          setTimeout(() => {
              resolve(5);
          }, 3000);
      });
      const p6 = new Promise((resolve, reject) => {
          setTimeout(() => {
              resolve(6);
          }, 3000);
      });
      const promiseList = [p1, p2, p3, p4, p5, p6];
      ​
      const limit = new Limit(2, promiseList);
      ​
      limit.start().then(res => {
          console.log(res);
      });

      25 发布/订阅

      **
       * 事件订阅/发布
       * 1.on 收集 key 对应的回调函数依赖关系,存入 eventList
       * 2.emit 根据第一个参数判断 key 值,并执行其函数依赖
       * 3.remove 根据 key 值清空依赖
       */
      class __Event {
          constructor() {
              this.eventList = [];
          }
      ​
          on(key, fn) {
              if (!this.eventList[key]) this.eventList[key] = [];
              this.eventList[key].push(fn);
          }
      ​
          emit() {
              const key = [].shift.call(arguments);
              const fns = this.eventList[key];
      ​
              if (!fns || fns.length === 0) return false;
      ​
              for (const fn of fns) {
                  fn.apply(this, arguments);
              }
          }
      ​
          remove(key) {
              if (!this.eventList[key]) return false;
              this.eventList[key] = null;
              delete this.eventList[key];
          }
      }
      ​
      // ------------------------------ 测试 ------------------------------
      // Event
      console.log('Event');
      ​
      const __event = new __Event();
      ​
      __event.on('name', val => {
          console.log(`info: ${val}`);
          // info: mxin
      });
      ​
      __event.on('name', val => {
          console.log(`info2: ${val}`);
          // info2: mxin
      });
      ​
      // 触发事件,上面两个回调执行对应代码
      __event.emit('name', 'mxin');
      ​
      // 移除事件
      __event.remove('name');
      ​
      // 事件被移除,不再触发
      __event.emit('name', 'mxin');

      26 防抖

      /**
       * 防抖
       * 事件高频触发,间隔 wait 时长执行回调
       * @param {*} fn
       * @param {*} wait
       */
      function debounce(fn, wait) {
          let timeout;
          return function () {
              let __this = this,
                  args = arguments;
              if (timeout) clearTimeout(timeout);
              timeout = setTimeout(() => {
                  fn.apply(__this, args);
              }, wait);
          };
      }
      ​
      // ------------------------------ 测试 ------------------------------
      ​
      // debounce()
      console.log('debounce()');
      ​
      window.onresize = debounce(function () {
          console.log('改变窗口大小完毕 1000ms 后触执行');
      }, 1000);

      27 节流

      /**
       * 节流
       * 高频事件触发,间隔 delay 时间执行一次回调
       * @param {*} fn
       * @param {*} delay
       */
      function throttle(fn, delay) {
          const prevTime = Date.now();
          return function () {
              const curTime = Date.now();
              if (curTime - prevTime > delay) {
                  fn.apply(this, arguments);
                  prevTime = curTime;
              }
          };
      }
      ​
      // ------------------------------ 测试 ------------------------------
      ​
      // throttle()
      console.log('throttle()');
      ​
      window.onresize = throttle(function () {
          console.log('间隔 1000ms 执行一次');
      }, 1000);

      28 柯里化

      /**
       * 柯里化
       * 把接受多个参数的函数变换成接受一个单一参数的函数
       * 并返回接受余下的参数且返回结果的新函数
       */
      function curry() {
          const args = [...arguments];
      ​
          const fn = function () {
              args.push(...arguments);
              return fn;
          };
      ​
          fn.toString = () => {
              return args.reduce((pre, current) => pre + current);
          };
          return fn;
      }
      ​
      // ------------------------------ 测试 ------------------------------
      ​
      // curry
      console.log('curry()');
      ​
      console.log(curry(1)(2)(3)); // 6
      console.log(curry(1, 2, 3)(4)); // 10
      console.log(curry(1)(2)(3)(4)(5)); // 15
      console.log(curry(2, 6)(1)); // 9

      29 vue Reactive ​

      const reactiveMap = new WeakMap();
      const targetMap = new WeakMap();
      const effectStack = [];
      ​
      /**
       * 副作用函数
       * @param {*} fn
       */
      function effect(fn) {
          try {
              // 将需要执行的effect入栈
              effectStack.push(fn);
      ​
              // 执行该effect,进入proxy的get拦截
              return fn();
          } finally {
              // 依赖收集完毕及所有get流程走完,当前effect出栈
              effectStack.pop();
          }
      }
      ​
      /**
       * 依赖收集
       * @param {*} target
       * @param {*} key
       */
      function track(target, key) {
          // 初始化依赖Map
          let depsMap = targetMap.get(target);
          if (!depsMap) {
              targetMap.set(target, (depsMap = new Map()));
          }
      ​
          // 第二层依赖使用Set存放key对应的effect
          let dep = depsMap.get(key);
          if (!dep) {
              targetMap.get(target).set(key, (dep = new Set()));
          }
      ​
          // 取当前栈中的effect存入第二层依赖中
          const activeEffect = effectStack[effectStack.length - 1];
          activeEffect && dep.add(activeEffect);
      }
      ​
      /**
       * 触发响应,执行effect
       * @param {*} target
       * @param {*} key
       */
      function trigger(target, key) {
          const depsMap = targetMap.get(target);
          if (depsMap) {
              const effects = depsMap.get(key);
              effects && effects.forEach(run => run());
          }
      }
      ​
      /**
       * 定义响应式对象,返回proxy代理对象
       * @param {*} object
       */
      function reactive(object) {
          if (reactiveMap.has(object)) return reactiveMap.get(object);
      ​
          const proxy = new Proxy(object, handlers);
      ​
          reactiveMap.set(object, proxy);
          return proxy;
      }
      ​
      /**
       * 处理器对象,定义捕获器
       */
      const handlers = {
          set(target, key) {
              Reflect.set(...arguments);
              trigger(target, key);
          },
          get(target, key) {
              track(target, key);
              return typeof target[key] === 'object'
                  ? reactive(target[key])
                  : Reflect.get(...arguments);
          },
      };
      ​
      /**
       * 计算属性
       * @param {*} fn
       */
      function computed(fn) {
          return {
              get value() {
                  return effect(fn);
              },
          };
      }
      ​
      module.exports = {
          effect,
          reactive,
          computed,
      };
      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://qingshan09.blog.csdn.net/article/details/143182866,作者:前端青山,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:JavaScript 成绩管理系统与值传递、引用传递详解

      下一篇:JavaScript DOM操作与事件处理

      相关文章

      2025-05-19 09:04:14

      复杂度的OJ练习

      复杂度的OJ练习

      2025-05-19 09:04:14
      代码 , 复杂度 , 思路 , 数组 , 算法
      2025-05-16 09:15:24

      如何将一串数字用函数的方法倒过来(C语言)

      如何将一串数字用函数的方法倒过来(C语言)

      2025-05-16 09:15:24
      函数 , 数字 , 数组
      2025-05-16 09:15:24

      jQuery遍历对象、数组、集合

      jQuery遍历对象、数组、集合

      2025-05-16 09:15:24
      jQuery , 对象 , 数组 , 遍历 , 集合
      2025-05-16 09:15:17

      递归,搜索,回溯算法(3)之穷举,暴搜,深搜,回溯,剪枝

      递归,搜索,回溯算法(3)之穷举,暴搜,深搜,回溯,剪枝

      2025-05-16 09:15:17
      回溯 , 子集 , 数组 , 算法 , 递归
      2025-05-14 10:33:31

      计算机小白的成长历程——数组(1)

      计算机小白的成长历程——数组(1)

      2025-05-14 10:33:31
      strlen , 个数 , 元素 , 内存 , 十六进制 , 地址 , 数组
      2025-05-14 10:33:31

      计算机小白的成长历程——习题演练(函数篇)

      计算机小白的成长历程——习题演练(函数篇)

      2025-05-14 10:33:31
      函数 , 字符串 , 数组 , 知识点 , 编写 , 迭代 , 递归
      2025-05-14 10:02:48

      typescript 将数组清空

      在TypeScript或JavaScript开发中,数组是用于存储和管理一组数据的基础数据结构。当需要清空一个数组时,有多种方法可以实现,而选择合适的方法不仅影响代码的可读性,还会对性能产生一定的影响。不同场景下,选择适合的清空数组的方法至关重要。

      2025-05-14 10:02:48
      length , pop , 引用 , 数组 , 方法
      2025-05-14 10:02:48

      使用JavaScript打印网页占用内存:详细指南

      在前端开发中,了解网页的内存占用情况对于优化性能和提高用户体验至关重要。

      2025-05-14 10:02:48
      JavaScript , 内存 , 占用 , 泄漏 , 浏览器 , 监听器 , 示例
      2025-05-13 09:50:28

      Java 两个小时以后

      最大正方形在一个由 '0' 和 '1' 组成的二维矩阵内,找到只包含 '1' 的最大正方形,并返回其面积。 

      2025-05-13 09:50:28
      length , matrix , nums , target , 数组
      2025-05-13 09:50:17

      java实现167. 两数之和 II - 输入有序数组

      给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列  ,请你从数组中找出满足相加之和等于目标数 target 的两个数。

      2025-05-13 09:50:17
      target , 两个 , 数组 , 整数
      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      33561

      阅读量

      5248874

      查看更多

      最新文章

      复杂度的OJ练习

      2025-05-19 09:04:14

      如何将一串数字用函数的方法倒过来(C语言)

      2025-05-16 09:15:24

      使用JavaScript打印网页占用内存:详细指南

      2025-05-14 10:02:48

      Java 两个小时以后

      2025-05-13 09:50:28

      用go语言,现有一棵无向、无根的树,树中有 n 个节点,按从 0 到 n - 1 编号 给你一个整数 n 和一个长度为 n - 1 的二维整数数组 edges

      2025-05-13 09:49:12

      JS学习(基础语法)

      2025-05-13 09:49:12

      查看更多

      热门文章

      Arrays类的使用

      2023-06-08 06:23:00

      5 个 JavaScript “罕见”原生的 API

      2024-09-25 10:15:15

      C++拷贝构造函数(深拷贝,浅拷贝)详解

      2023-03-30 09:59:46

      less中的内置函数

      2023-05-17 07:03:00

      Python打乱列表/数组原顺序,新列表/数组中元素随机分布

      2023-04-13 09:36:44

      Python数组列表过滤

      2023-04-17 09:39:09

      查看更多

      热门标签

      java Java python 编程开发 代码 开发语言 算法 线程 Python html 数组 C++ 元素 javascript c++
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      查看更多

      随机文章

      转 JavaScript 实现简单的双向数据绑定

      Java之可变参数??(Object... 数组变量名 ???)

      C++单调向量算法应用:2763所有子数组中不平衡数字之和

      C++:类与对象(2)

      JavaScript封装css方法

      Alice 和 Bob 再次设计了一款新的石子游戏。

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 旗舰店
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 天翼云旗舰店
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号