notes
  • Introduction
  • 语言
    • JS
      • JS原型到原型链
      • JS继承的实现
      • this对象
      • Promise基本概念
      • Promise实现
      • Promise实战
      • JS的EventLoop
      • JS容易出现误区的运算符
      • JS容易出现误区的操作符
      • JS深拷贝
      • JS节流与防抖
      • ES5实现原生/ES6方法
    • TS
      • 声明文件
      • 项目配置
    • CSS
      • CSS引入方式以及优先级计算
      • BFC神奇背后的原理-文摘
      • 回流reflow与重绘repaint
      • 三栏式布局
      • 垂直居中
      • 清除浮动的方法
      • 移动端适配方案
      • 纯CSS斜切角实现
      • CSS揭秘
      • 背景图片轮播
      • CSS绘制序列帧动画
      • transform实现一个多面体
    • HTML
  • ES6
  • Node.js
    • xxx
  • 前端框架
    • Vue.js
      • Vue双向数据绑定原理
      • Vue-Router原理及实现
    • React
    • AngularJS
  • 工程构建
    • Webpack
      • 01-webpack概述及背景
      • 03-webpack热更新原理
      • 04-splitChunks原理分析
      • 05-webpack工作流程
      • 07-webpack构建流程
      • 07-webpack构建流程
      • 10-webpack 如何进行性能分析
    • Gulp
    • Lint
      • ESLint
      • TSLint
    • Bable
  • 工程化
    • 模块化
    • 组件化
    • 规范化
      • 编码规范
    • 自动化
  • 运维
    • Nginx
    • GIT
    • CDN
    • VPS
    • DBA
  • 小程序
  • 跨端
  • 测试
  • 计算机技术
    • 计算机网络
      • 同源策略到前端跨域解决方案
      • TCP数据传输
      • TCP和UDP的区别
      • HTTP协议概述
      • HTTP缓存详解
      • HTTPS以及SSL建立过程
      • HTTPS的七个误解(译文)
      • cookie与Session机制区别以及Cookie SessionStorage LocalStorage异同
      • HTTP状态码Status
      • DNS原理入门
      • 网络攻击与防御
      • HTTP转发与重定向
      • 登录认证设计
    • 操作系统
      • shell脚本命令
    • Linux
      • Linux命令大全
      • vim命令
    • 浏览器
      • 浏览器内核、JS 引擎、页面呈现原理及其优化
      • 九种浏览器端缓存机制概览
      • 性能优化-网络请求方面
      • webkit解析CSS过程详解
  • 前端面试
    • 算法
Powered by GitBook
On this page
  • 实现 bind apply call 方法
  • 实现call
  • 实现apply
  • 实现bind
  • instanceOf 实现
  • Json.stringify Json.parse实现
  1. 语言
  2. JS

ES5实现原生/ES6方法

实现 bind apply call 方法

实现call

Function.prototype.myCall = function (context, ...args) {
  context = context || window;
  // 这里使用fn可能存在context已有对应属性,不严谨,可以使用Symbol对象生成唯一属性key
  context.fn = this;
  const res = context.fn(...args);
  delete context.fn;
  return res;
}

实现apply

Function.prototype.myApply = function (context, args) {
  context = context || global;
  // 这里使用fn可能存在context已有对应属性,不严谨,可以使用Symbol对象生成唯一属性key
  context.fn = this;
  const res = context.fn(...args);
  delete context.fn;
  return res;
}

实现bind

bind 返回一个原函数的拷贝,并拥有指定的this值和初始参数。

因此需要存储一下 初始参数,调用的时候,将初始参数和传入的参数合并

Function.prototype.myBind = function (context) {
  context = context || window;
  const self = this;
  let args = [...arguments].slice(1);
  console.log('args', args)
  return function () {
    return self.myApply(context, args.concat([...arguments]))
  };
}

instanceOf 实现

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

function myInstanceOf(obj, constructor) {
  let proto = Object.getPrototypeOf(obj);
  // 也可以使用__proto__
  // let proto = obj.__proto__;
  while (proto) {
    if (proto === constructor.prototype) {
      return true
    }
    proto = Object.getPrototypeOf(proto);
    // proto = proto.__proto__;
  }
  return false;
}

Json.stringify Json.parse实现

遍历对象,将对象转换为字符串,需要对 null boolean null undefined 特殊判断

function jsonStringify(obj) {
  const type = typeof obj;
  if (type !== 'object' || obj === null) {
    if (/string|undefined/.test(type)) {
      obj = `"${obj}"`
    }
    return `${obj}`;
  } else {
    const isArr = Array.isArray(obj);
    const res = [];

    for (const key in obj) {
      let v = obj[key];
      const type = typeof v;
      if (/string|undefined/.test(type)) {
        v = `"${v}"`
      } else if (type === 'object') {
        v = jsonStringify(v);
      }
      res.push(`${isArr ? '' : `"${key}":`}${String(v)}`);
    }
    return `${isArr ? '[' : '{'}${String(res)}${isArr ? ']' : '}'}`
  }
}

通过递归的方式,将字符串转换为对象,其中null boolean undefined 需要转化为对应的值

function jsonParse(jsonStr) {
  let i = 0;
  let curChar = jsonStr[i]

  // 步进器
  function next() {
    i += 1;
    curChar = jsonStr[i];
  }

  function parseValue() {
    switch (curChar) {
      case '"':
        return parseString()
      case "{":
        return parseObject();
      case '[':
        return parseArray();
      default:
        return parseOther();
    }
  }

  function parseString() {
    let str = '';
    next()
    while (jsonStr[i] !== '"') {
      str += jsonStr[i];
      i++;
    }
    next();
    return str === 'undefined' ? undefined : str;
  }

  function parseArray() {
    let arr = [];
    next();
    while (curChar !== ']') {
      arr.push(parseValue());
      if (curChar === ',') {
        // 跳过, 下一个
        next();
      }
    }
    next();
    return arr;
  }
  function parseObject() {
    let obj = {};
    next();
    while (curChar !== '}') {
      let key = parseString();
      next();
      let value = parseValue();
      obj[key] = value;
      if (curChar === ',') {
        // 跳过
        next();
      }
    }
    next();
    return obj;
  }
  function parseOther() {
    let str = '';
    while (curChar !== ',' && curChar !== ']' && curChar !== '}') {
      str += curChar;
      next();
    }
    if (!isNaN(str)) return Number(str);
    if (str === 'null') return null;
    if (str === 'true') return true;
    if (str === 'false') return false;
    return str;
  }

  return parseValue()
}
PreviousJS节流与防抖NextTS

Last updated 1 year ago

测试方法可以参考

DEMO/JS