Git Product home page Git Product logo

js-challenges's Issues

Array.prototype.includes

Array.prototype.myIncludes = function (value, start = 0) {
  start = start < 0 ? this.length + start : start;
  for (let i = start; i < this.length; i++) {
    if (this[i] == value || (Number.isNaN(value) && Number.isNaN(this[i])))
      return true;
  }
  return false;
};

Array.prototype.filter

Array.prototype.myFilter = function (callback) {
  const res = [];
  for (let i = 0; i < this.length; i++) {
    callback(this[i], i, this) && res.push(this[i]);
  }
  return res;
};

JSON.stringify

function toJSON(data){

}

// test
toJSON(""); // -> ""
toJSON("abc"); // -> "abc"
toJSON(123); // -> 123
toJSON({a:1, b:2}); // -> {"a":1, "b":2}
toJSON(["1", 3, {name:"monica", age:18}]); //-> ["1", 3, {"name":"monica", "age":18}]

Array.prototype.reduce

Array.prototype.myReduce = function (callback, ...args) {
  let start = 0,
    pre;
  if (args.length) {
    //有参数的话pre等于参数第0项
    pre = args[0];
  } else {
    //没参数的话,默认从数组0项开始
    pre = this[0];
    start = 1;
  }
  for (let i = start; i < this.length; i++) {
    pre = callback(pre, this[i], i, this);
  }
  return pre;
};

7. Promise.reject

 /**
   * 得到一个被拒绝的Promise
   * @param {*} reason
   */
  Promise.reject=function(reason) {
    return new MyPromise((resolve, reject) => {
      reject(reason);
    });
  }

字符串的大小写取反

let str = "QIANDUANGOngchengshi猕猴桃Jquery很帅!哈哈 haha";
str = str.replace(/[a-zA-Z]/g, (content) => {
  return content.toUpperCase() === content
    ? content.toLowerCase()
    : content.toUpperCase();
});
console.log(str);

3. 实现Promise.allSettled

/**
   * 等待所有的Promise有结果后
   * 该方法返回的Promise完成
   * 并且按照顺序将所有结果汇总
   * @param {Iterable} proms
   */
  Promise.allSettled=function(proms) {
    const ps = [];
    for (const p of proms) {
      ps.push(
        MyPromise.resolve(p).then(
          (value) => ({
            status: FULFILLED,
            value,
          }),
          (reason) => ({
            status: REJECTED,
            reason,
          })
        )
      );
    }
    return MyPromise.all(ps);
  }

对象树遍历

const tree = {
    name: 'root',
    children: [
        {
            name: 'c1',
            children: [
                {
                    name: 'c11',
                    children: []
                },
                {
                    name: 'c12',
                    children: []
                }
            ]
        },
        {
            name: 'c2',
            children: [
                {
                    name: 'c21',
                    children: []
                },
                {
                    name: 'c22',
                    children: []
                }
            ]
        }
    ]
}

// 深度优先的方式遍历 打印 name
// ['root', 'c1','c11', 'c12', 'c2', 'c21', 'c22']
// 我写的
function solve(root) {
    const res = []
    function dfs(root) {
        for (const key in root) {
            if (key === 'name') {
                res.push(root[key])
            } else if (key === 'children') {
                root[key].forEach(ele => {
                    dfs(ele)
                });
            }
        }
    }
    dfs(root)
    return res;
}
console.log(solve(tree));

Object.create()

Object.create2 = function(proto, propertyObject = undefined) {
    function F() {}
    F.prototype = proto
    const obj = new F()
    if (propertyObject != undefined) {
        Object.defineProperties(obj, propertyObject)
    }
    if (proto === null) {
        // 创建一个没有原型对象的对象,Object.create(null)
        obj.__proto__ = null
    }
    return obj
}

Array.prototype.copy

Array.prototype.copy = function () {
    return [...this, ...this]
}
console.log([1, 2, 3, 4, 5].copy());

正则表达式模版字符串

String.prototype.render = function (data) {
    return this.replace(/{{[.\s\S]*?}}/g, match => {
        if ((match = match.substring(2, match.length - 2).trim()) == "") {
            return "";
        } else if (match.startsWith("#")) {
            return eval(match.substr(1, match.length - 1));
        } else {
            return data[match] ? data[match] : "";
        }
    })
}


const data = {
    name: "小明",
    age: 16,
    school: "第三中学",
    classroom: "教室2"
}


console.log(
    "{{ name }} 今年 {{ age }} 岁,就读于 {{ school }} 今天在 {{ classroom }} 上课,{{ name }} {{ #data.age >= 18 ? '成年了' : '未成年' }}".render(data)
);
// 小明 今年 16 岁,就读于 第三中学 今天在 教室2 上课,小明 未成年

console.log(
    `{{name}}说了句{{#
        if (data.age >= 18) {
            "我已经成年了!"
        } else {
            "我还没有成年!"
        }
    }}`.render(data)
);
// 小明说了句我还没有成年!

计算目录树的深度

const tree = {
    name: 'root',
    children: [
        { name: '叶子1-1' },
        { name: '叶子1-2' },
        {
            name: '叶子2-1',
            children: [{
                name: '叶子3-1',
                children: [{
                    name: '叶子4-1',
                    children: [{}]
                }]
            }]
        }
    ]
}

function getLevel(tree) {
    if (tree == null) return 0;
    const queue = [tree]
    let dep = 0;
    while (queue.length) {
        dep++;
        const size = queue.length
        for (let i = 0; i < size; i++) {
            const node = queue.shift()
            if (node.children) {
                for (const child of node.children) {
                    queue.push(child)
                }
            }
        }
    }
    return dep
}
console.log(getLevel(tree));

trim·

正则写就可以

return str.replace(/(^\s+)|(\s+$)/g,'')//将前空格和后空格替换为空

获取树对象属性

var tree = {
    name: '**',
    children: [
        {
            name: '北京',
            children: [
                {
                    name: '朝阳群众'
                },
                {
                    name: '海淀区'
                },
                {
                    name: '昌平区'
                }
            ]
        },
        {
            name: '浙江省',
            children: [
                {
                    name: '杭州市',
                    code: '0571',
                },
                {
                    name: '嘉兴市'
                },
                {
                    name: '绍兴市'
                },
                {
                    name: '宁波市'
                }
            ]
        }
    ]
};


function fn(tree, name) {
    //bfs
    let Queue = [[tree.name, tree.children]];
    while (Queue.length > 0) {
        //出队当前节点
        let cur = Queue.shift();
        if (cur[0] === name) return { name: name, code: cur[1] }
        //将children入队
        if (cur.length === 1) continue;

        for (let node of cur[1]) {
            let obj = [node.name];
            if (node.hasOwnProperty("children")) obj.push(node.children);
            if (node.hasOwnProperty("code")) obj.push(node.code);
            Queue.push(obj);
        }
    }
    return -1;
}
var node = fn(tree, '杭州市');
console.log(node);    // { name: '杭州市', code: 0571 }

列表转成树形结构

let arr = [
    { id: 1, name: '部门1', pid: 0 },
    { id: 2, name: '部门2', pid: 1 },
    { id: 3, name: '部门3', pid: 1 },
    { id: 4, name: '部门4', pid: 3 },
    { id: 5, name: '部门5', pid: 4 },
    { id: 6, name: '部门6', pid: 0 },
]
function getTreeList(rootList, id, list) {
    for (const item of rootList) {
        if (item.parent === id) {
            list.push(item);
        }
    }
    for (const i of list) {
        i.children = [];
        getTreeList(rootList, i.id, i.children);
        if (i.children.length === 0) {
            delete i.children;
        }
    }
    return list;
}
const res = getTreeList(rootList, null, []);
console.log("res", res);

8. 完整实现Promise A+

// 记录Promise的三种状态
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

/**
 * 运行一个微队列任务
 * 把传递的函数放到微队列中
 * @param {Function} callback
 */
function runMicroTask(callback) {
  // 判断node环境
  // 为了避免「变量未定义」的错误,这里最好加上前缀globalThis
  // globalThis是一个关键字,指代全局对象,浏览器环境为window,node环境为global
  if (globalThis.process && globalThis.process.nextTick) {
    process.nextTick(callback);
  } else if (globalThis.MutationObserver) {
    const p = document.createElement("p");
    const observer = new MutationObserver(callback);
    observer.observe(p, {
      childList: true, // 观察该元素内部的变化
    });
    p.innerHTML = "1";
  } else {
    setTimeout(callback, 0);
  }
}

/**
 * 判断一个数据是否是Promise对象
 * @param {any} obj
 * @returns
 */
function isPromise(obj) {
  return !!(obj && typeof obj === "object" && typeof obj.then === "function");
}

class MyPromise {
  /**
   * 创建一个Promise
   * @param {Function} executor 任务执行器,立即执行
   */
  constructor(executor) {
    this._state = PENDING; // 状态
    this._value = undefined; // 数据
    this._handlers = []; // 处理函数形成的队列
    try {
      executor(this._resolve.bind(this), this._reject.bind(this));
    } catch (error) {
      this._reject(error);
      console.error(error);
    }
  }

  /**
   * 向处理队列中添加一个函数
   * @param {Function} executor 添加的函数
   * @param {String} state 该函数什么状态下执行
   * @param {Function} resolve 让then函数返回的Promise成功
   * @param {Function} reject 让then函数返回的Promise失败
   */
  _pushHandler(executor, state, resolve, reject) {
    this._handlers.push({
      executor,
      state,
      resolve,
      reject,
    });
  }

  /**
   * 根据实际情况,执行队列
   */
  _runHandlers() {
    if (this._state === PENDING) {
      // 目前任务仍在挂起
      return;
    }
    while (this._handlers[0]) {
      const handler = this._handlers[0];
      this._runOneHandler(handler);
      this._handlers.shift();
    }
  }

  /**
   * 处理一个handler
   * @param {Object} handler
   */
  _runOneHandler({ executor, state, resolve, reject }) {
    runMicroTask(() => {
      if (this._state !== state) {
        // 状态不一致,不处理
        return;
      }

      if (typeof executor !== "function") {
        // 传递后续处理并非一个函数
        this._state === FULFILLED ? resolve(this._value) : reject(this._value);
        return;
      }
      try {
        const result = executor(this._value);
        if (isPromise(result)) {
          result.then(resolve, reject);
        } else {
          resolve(result);
        }
      } catch (error) {
        reject(error);
        console.error(error);
      }
    });
  }

  /**
   * Promise A+规范的then
   * @param {Function} onFulfilled
   * @param {Function} onRejected
   */
  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      this._pushHandler(onFulfilled, FULFILLED, resolve, reject);
      this._pushHandler(onRejected, REJECTED, resolve, reject);
      this._runHandlers(); // 执行队列
    });
  }

  /**
   * 仅处理失败的场景
   * @param {Function} onRejected
   */
  catch(onRejected) {
    return this.then(null, onRejected);
  }

  /**
   * 无论成功还是失败都会执行回调
   * @param {Function} onSettled
   */
  finally(onSettled) {
    return this.then(
      (data) => {
        onSettled();
        return data;
      },
      (reason) => {
        onSettled();
        throw reason;
      }
    );
  }

  /**
   * 更改任务状态
   * @param {String} newState 新状态
   * @param {any} value 相关数据
   */
  _changeState(newState, value) {
    if (this._state !== PENDING) {
      // 目前状态已经更改
      return;
    }
    this._state = newState;
    this._value = value;
    this._runHandlers(); // 状态变化,执行队列
  }

  /**
   * 标记当前任务完成
   * @param {any} data 任务完成的相关数据
   */
  _resolve(data) {
    this._changeState(FULFILLED, data);
  }

  /**
   * 标记当前任务失败
   * @param {any} reason 任务失败的相关数据
   */
  _reject(reason) {
    this._changeState(REJECTED, reason);
  }

}

正则判断手机号,qq,颜色,邮箱

// 手机号
let reg1 = /^1[44578]\d{9}$/g;
let str1 = '15928229999'
console.log(reg1.test(str1));
// qq号
let reg2 = /^[1-9][0-9]{4,9}$/g;
let str2 = '159222'
console.log(reg2.test(str2));

// 颜色
let reg3 = /#?([0-9a-fA-F]{6}|[0-9a-fA-F]{3})/g;
let str3 = '#abc'
console.log(reg3.test(str3));
// 邮箱
let reg4 = /^([A-za-z0-9_\-\.]+)+@([A-za-z0-9_\-\.]+)\.([A-Za-z]{2, 6})$/g;//+一到多
var reg = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/;
let str4 = '[email protected]'
console.log(reg4.test(str4));

判断有无符合路径和 -> 打印所有路径

const data3 = [
    {
        id: 1,
        name: '前端',
        children: [
            {
                id: 2,
                name: 'html',
                children: [
                    { id: 5, name: 'vue', children: [] },
                    { id: 6, name: 're', children: [] },
                ]
            },
            {
                id: 3,
                name: 'html',
                children: [
                    { id: 7, name: 'vue', children: [] },
                    { id: 8, name: 're', children: [] },
                ]
            }
        ]
    }
]

2. 实现Promise.finally

/**
   * 无论成功还是失败都会执行回调
   * @param {Function} onSettled
   */
 Promise.prototype.finally = function (onSettled) {
    return this.then(
      (data) => {
        onSettled(); // 实现了收不到参数了
        return data;
      },
      (reason) => {
        onSettled();
        throw reason;
      }
    );
    // finally函数 返回结果应该是无效的
  }
  
/******test finally*******/
// 无论什么结果,都会运行
const pro = new Promise((resolve, reject) => {
  resolve(1);
});
const pro2 = pro.finally((d) => {
  console.log("finally", d); // 收不到d参数
  // 本身不改变状态,但是抛出一个错误,数据就会变成它的错误
  // throw 123;
  return 123; //不起作用
});
setTimeout(() => {
  console.log(pro2);
});

String.prototype.repeat

 String.prototype.repeat= function (n) {
    let str = this;
    let res = ''
    while (n) {
        res += str;
        n--
    }
    return res
}
console.log('abc'.repeat(3));

4. 实现Primise.race

/**
   * 返回的Promise与第一个有结果的一致
   * @param {iterator} proms
   */
  Promise.race=function(proms) {
    return new MyPromise((resolve, reject) => {
      for (const p of proms) {
        MyPromise.resolve(p).then(resolve, reject);
      }
    });
  }

Array.prototype.flat

const arr = [1, [2, 3, [4, 5]], 1, 2, [6, 7]]
Array.prototype.flat = function (deep = 1) {
    let res = []
    deep--
    for (const p of this) {
        if (Array.isArray(p) && deep >= 0) {
            res = res.concat(p.flat(deep))
        } else {
            res.push(p)
        }
    }
    return res
}
console.log(arr.flat(1))

树形结构获取路径名

const treeData = [
    {
        name: "root",
        children: [
            { name: "src", children: [{ name: "index.html" }] },
            { name: "public", children: [] },
        ],
    },
];
const RecursiveTree = (data) => {
    const res = []
    const dfs = (data) => {
        data.forEach(ele => {
            res.push(ele.name)
            ele.children && dfs(ele.children)
        });
    }
    dfs(data)
    return res;
}
console.log(RecursiveTree(treeData));

Array.prototype.fill

Array.prototype.myFill = function (initValue, start = 0, end) {
  end = end < 0 ? this.length + end : end;
  for (let i = start; i < end; i++) {
    this[i] = initValue;
  }
  return this;
};
let arr = [3, 3, 21, 3, 14, 12, 4, 1, 2];
console.log(arr.fill(1, 3, 5));

Array.prototype.push

Array.prototype.myPush = function (...arg) {
  for (let i = 0; i < arg.length; i++) {
    this[this.length] = arg[i];
  }        
  return this.length;
};

实现es6的set集合

class MySet {
  constructor(iterator = []) {//不传默认空数组
    if (typeof iterator[Symbol.iterator] !== "function") {
      throw new TypeError(`你提供的${iterator}不是一个可迭代的对象`)
    }
    this._datas = [];
    for (const item of iterator) {
      this.add(item);
    }
  }

  get size() {
    return this._datas.length;
  }

  add(data) {
    if (!this.has(data)) {// 不包含data,才加入
      this._datas.push(data);
    }
  }

  has(data) {// 是否有data
    for (const item of this._datas) {
      if (this.isEqual(data, item)) {// isEqual判断两个数据是否相等
        return true;
      }
    }
    return false;
  }
  delete(data) {
    for (let i = 0; i < this._datas.length; i++) {
      const element = this._datas[i];
      if (this.isEqual(element, data)) {
        //删除
        this._datas.splice(i, 1);
        return true;
      }
    }
    return false;
  }

  clear() {
    this._datas.length = 0;
  }
  *[Symbol.iterator]() {// 遍历效果
    for (const item of this._datas) {
      yield item;
    }
  }
  forEach(callback) {
    for (const item of this._datas) {
      callback(item, item, this);
    }
  }
  /**
     * 判断两个数据是否相等
     * @param {*} data1 
     * @param {*} data2 
     */
  isEqual(data1, data2) {
    if (data1 === 0 && data2 === 0) {
      return true;
    }
    return Object.is(data1, data2);
  }
}

promisify

手动实现一个promisify函数的意思是:我们把一个异步请求的函数,封装成一个可以具有 then方法的函数,并且在then方法中返回异步方法执行结果的这么一个函数

  1. 具有 then 方法
  2. then 方法里返回异步接口执行结果
// 首先定一个需要进行 promisify 的函数
function asyncFn(a, b, callback) {
        // 异步操作,使用 setTimeout 模拟
        console.log('异步请求参数', a, b)
        setTimeout(function() {
                callback('异步请求结果')
        }, 3000)
}

// 我们希望调用的方式是
const proxy = promisify(asyncFn)
proxy(11,22).then(res => {
        // 此处输出异步函数执行结果
        console.log(res)
})

// 定义一个方法, 需要针对异步方法做封装,所以需要一个入参,既需要promisify的原异步方法
function promisify(func) {
  return function(...args) {
    return new Promise((resolve, reject) => {
      const callback = (err, data) => {
        if (err) {
          reject(err);
        } else {
          resolve(data)
        }
      };
      func.call(this, ...args, callback);
    });
  }
}

6. Promise.resolve

Promise.resolve = function (data) {
    if (data instanceof MyPromise) {
      return data;
    }
    return new MyPromise((resolve, reject) => {
      if (isPromise(data)) {
        data.then(resolve, reject);
      } else {
        resolve(data);
      }
    });
  }

Array.prototype.getLevel

Array.prototype.getLevel = function () {
    let max = 1
    for (const a of this) {
        if (a instanceof Array) {
            const depth = a.getLevel() + 1
            if (max < depth) max = depth
        }
    }
    return max
};
const a1 = [1, 2, [1], [1, [2, [3]]]];
console.log(a1.getLevel()); //4

DOM2JSON

{
  tag: 'DIV',
  children: [
    {
      tag: 'SPAN',
      children: [
        { tag: 'A', children: [] }
      ]
    },
    {
      tag: 'SPAN',
      children: [
        { tag: 'A', children: [] },
        { tag: 'A', children: [] }
      ]
    }
  ]
}

function dom2Json(domtree) {
  let obj = {};
  obj.name = domtree.tagName;
  obj.children = [];
  domtree.childNodes.forEach((child) => obj.children.push(dom2Json(child)));
  return obj;
}

5. 实现 Promise.prototype.catch

 /**
   * 本质就是then,只是少传了一个onFulfilled
   * 所以仅处理失败的场景
   * @param {*} onRejected
   */
Promise.prototype.catch = function(onRejected) {
    return this.then(null, onRejected);
}

获取树结构中的name:getName

let data = [
      {
          "name": "1-1",
          "kind": "oo",
          "children": [
              {
                  "name": "2-2",
                  "kind": "ii",

              },
              {
                  "name": "3-3",
                  "children": [
                      {
                          "name": "4-4",
                          "children": [
                              {
                                  "name": '707'
                              }
                          ]
                      }
                  ]
              }
          ]
      },
      {
          "name": "5-5",
      },
      {
          "name": "6-6"
      }
  ]
  function getName(data, key = "name") {
      let result = [];
      if (Array.isArray(data)) {
          for (let item of data) {
              if (item[key]) {
                  result.push(item[key]);
              }
              if (item.children) {
                  result = result.concat(getName(item.children));
              }
          }
          return result;
      } else {
          return result;
      }
  }

  console.log(getName(data))

Array.prototype.unshift

Array.prototype.myUnshift = function (...items) {
    this.reverse().push(...items.reverse())
    this.reverse()
    return this.length
}

JSON.parse

// eval 实现
var json = '{"a":"1", "b":2}';
var obj = eval("(" + json + ")");  // obj 就是 json 反序列化之后得到的对象
// New Function
var json = '{"name":"小姐姐", "age":20}';
var obj = (new Function('return ' + json))();

实现new

(1)首先创建了一个新的空对象
(2)设置原型,将对象的原型设置为函数的 prototype 对象。
(3)让函数的 this 指向这个对象,执行构造函数的代码(为这个新对象添加属性)
(4)判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象。

function myNew(constructorFn, ...args) {
    let newObj = {}
    newObj.__proto__ = constructorFn.prototype;
    // newObj = Object.create(constructor.prototype);
    let result = constructorFn.apply(newObj, args)
    return result instanceof Object ? result : newObj
}
function Animal(name) {
    this.name = name;
}
let animal = myNew(Animal, 'dog')
console.log(animal);

JSON2DOM = react的render函数

{
  tag: 'DIV',
  attrs:{
  id:'app'
  },
  children: [
    {
      tag: 'SPAN',
      children: [
        { tag: 'A', children: [] }
      ]
    },
    {
      tag: 'SPAN',
      children: [
        { tag: 'A', children: [] },
        { tag: 'A', children: [] }
      ]
    }
  ]
}
把上诉虚拟Dom转化成下方真实Dom
<div id="app">
  <span>
    <a></a>
  </span>
  <span>
    <a></a>
    <a></a>
  </span>
</div>

Object.assign

Object.assign2 = function(target, ...source) {
  let ret = Object(target) 
  source.forEach(function(obj) {
    if (obj) {
      for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
          ret[key] = obj[key]
        }
      }
    }
  })
  return ret
}
const obj1 = {a: 1}
const obj2 = {b: 2}
const res = Object.assign2(obj1, obj2)
console.log(obj1);

Object.is

Object.is = function (x, y) {
  if (x === y) {
    // 当前情况下,只有一种情况是特殊的,即 +0 -0
    // 如果 x !== 0,则返回true
    // 如果 x === 0,则需要判断+0和-0,则可以直接使用 1/+0 === Infinity 和 1/-0 === -Infinity来进行判断
    return x !== 0 || 1 / x === 1 / y;
  }
  // x !== y 的情况下,只需要判断是否为NaN,如果x!==x,则说明x是NaN,同理y也一样
  // x和y同时为NaN时,返回true
  return x !== x && y !== y;
};

实现es6的map集合

class MyMap {
  constructor(iterable = []) {
    //验证是否是可迭代的对象
    if (typeof iterable[Symbol.iterator] !== "function") {
      throw new TypeError(`你提供的${iterable}不是一个可迭代的对象`)
    }
    this._datas = [];
    for (const item of iterable) {
      // item 也得是一个可迭代对象
      if (typeof item[Symbol.iterator] !== "function") {
        throw new TypeError(`你提供的${item}不是一个可迭代的对象`);
      }
      const iterator = item[Symbol.iterator]();
      //不一定是数组,所以用这种方式
      const key = iterator.next().value;
      const value = iterator.next().value;
      this.set(key, value);
    }

  }

  set(key, value) {
    const obj = this._getObj(key);
    if (obj) {//已经有了就是要修改
      //修改
      obj.value = value;
    }
    else {//没有的话添加
      this._datas.push({
        key,
        value
      })
    }
  }

  get(key) {
    const item = this._getObj(key);
    if (item) {
      return item.value;
    }
    return undefined;// 找不到
  }

  get size() {
    return this._datas.length;
  }

  delete(key) {
    for (let i = 0; i < this._datas.length; i++) {
      const element = this._datas[i];
      if (this.isEqual(element.key, key)) {
        this._datas.splice(i, 1);
        return true;
      }
    }
    return false;
  }

  clear() {
    this._datas.length = 0;
  }

  /**
     * 根据key值从内部数组中,找到对应的数组项
     * @param {*} key 
     */
  _getObj(key) {
    for (const item of this._datas) {
      if (this.isEqual(item.key, key)) {
        return item;
      }
    }
  }

  has(key) {
    return this._getObj(key) !== undefined;
  }

  /**
     * 判断两个数据是否相等
     * @param {*} data1 
     * @param {*} data2 
     */
  isEqual(data1, data2) {
    if (data1 === 0 && data2 === 0) {
      return true;
    }
    return Object.is(data1, data2);
  }

  *[Symbol.iterator]() {//迭代器创建函数本身就是生成器函数  *
    for (const item of this._datas) {
      yield [item.key, item.value];
    }
  }

  forEach(callback) {
    for (const item of this._datas) {
      callback(item.value, item.key, this);
    }
  }
}

Array.prototype.forEach

// 无返回值,调用callback
Array.prototype.myForEach = function (callback) {
  if (typeof callback !== "function") {
    throw new TypeError(callback + " is not a function");
  }
  for (let i = 0; i < this.length; i++) {
    callback(this[i], i, this);
  }
};

lodash.get

const obj = {
    a: {
        b: 123
    },
    arr: [
        {
            demo: 'demo'
        }
    ]
}
function getKey(obj, str) {
   
}
console.log(getKey(obj, 'a.b'));
console.log(getKey(obj, 'arr[0].demo'));

树形结构转成列表

const data = [
    {
        id: 1,
        text: '节点1',
        parentId: 0,
        children: [
            {
                id: 2,
                text: '节点1_1',
                parentId: 1
            }
        ]
    }
]
function treeToList(data) {
    let res = [];
    const dfs = (tree) => {
        tree.forEach((item) => {
            if (item.children) {
                dfs(item.children);
                delete item.children;
            }
            res.push(item);
        });
    };
    dfs(data);
    return res;
}

instanceof

function myInstanceof(left, right) {
  let proto = Object.getPrototypeOf(left), // 获取对象的原型
      prototype = right.prototype; // 获取构造函数的 prototype 对象

  // 判断构造函数的 prototype 对象是否在对象的原型链上
  while (true) {
    if (!proto) return false;
    if (proto === prototype) return true;
    proto = Object.getPrototypeOf(proto);
  }
}
function Person() { };
var p = new Person();
console.log(myInstanceof(p, Object));
// console.log(p instanceof Person);//true

String.prototype.zpadStart

String.prototype.zpadStart = function (targetLength, padString) {
    let string = this
    while (string.length < targetLength) {
        string = padString + string
    }
    return string
}
const res = 'abc'.padStart(8, "0");

Array.prototype.map

const arr = [1, 2, 3]
Array.prototype.map = function (callback) {
    const res = [];
    for (let i = 0; i < this.length; i++) {
        res.push(callback(this[i], i, this))
    }
    return res;
}
const res = arr.map((ele, index, arr) => {
    return ele * 2
})
console.log(res)

查找json中的children路径

现有如下json(简化为对象),已知每个节点id唯一,编写findNode(id),返回路径,如findNode(5 输出 1->4->5

json = {
    id: 1,
    children: [
        { id: 2, children: [{ id: 3, children: [] }] },
        {
            id: 4,
            children: [
                { id: 5, children: [] },
                { id: 6, children: [] },
            ],
        },
        { id: 7, children: [] },
    ],
};
function findNode(obj) {
    const res = []
    function dfs(obj, currPath, target) {
        if (!obj) return;
        if (obj.id === target) {
            currPath += obj.id
            res.push(currPath)
            return
        }
        currPath += obj.id + '->'
        obj.children && obj.children.forEach(ele => {
            dfs(ele, currPath, target)
        });
    }
    dfs(obj, '', 5)
    return res;
}

call apply bind

Function.prototype.call2 = function(context, ...args) {
  context = (context === undefined || context === null) ? window : context
  context.__fn = this
  let result = context.__fn(...args)
  delete context.__fn
  return result
}
Function.prototype.apply2 = function(context, args) {
  context = (context === undefined || context === null) ? window : context
  context.__fn = this
  let result = context.__fn(...args)
  delete context.__fn
  return result
}
Function.prototype.bind2 = function(context, ...args1) {
  context = (context === undefined || context === null) ? window : context
  let _this = this
  return function(...args2) {
    context.__fn = _this
    let result = context.__fn(...[...args1, ...args2])
    delete context.__fn
    return result
  }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.