复习--代码

225 阅读5分钟

图片懒加载

<ul>
  <li><img src="./imgs/default.png" data="./imgs/1.png" alt=""></li>
  <li><img src="./imgs/default.png" data="./imgs/2.png" alt=""></li>
  <li><img src="./imgs/default.png" data="./imgs/3.png" alt=""></li>
  <li><img src="./imgs/default.png" data="./imgs/4.png" alt=""></li>
  <li><img src="./imgs/default.png" data="./imgs/5.png" alt=""></li>
  <li><img src="./imgs/default.png" data="./imgs/6.png" alt=""></li>
  <li><img src="./imgs/default.png" data="./imgs/7.png" alt=""></li>
  <li><img src="./imgs/default.png" data="./imgs/8.png" alt=""></li>
  <li><img src="./imgs/default.png" data="./imgs/9.png" alt=""></li>
  <li><img src="./imgs/default.png" data="./imgs/10.png" alt=""></li>
</ul>

// 链接:https://juejin.cn/post/6844903891591495693
let imgs =  document.querySelectorAll('img')
// 可视区高度
let clientHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
function lazyLoad () {
  // 滚动卷去的高度
  let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
  for (let i = 0; i < imgs.length; i ++) {
    // 图片在可视区冒出的高度
    let x = clientHeight + scrollTop - imgs[i].offsetTop
    // 图片在可视区内
    if (x > 0 && x < clientHeight+imgs[i].height) {
      imgs[i].src = imgs[i].getAttribute('data')
    } 
  }      
}
// addEventListener('scroll', lazyLoad) or setInterval(lazyLoad, 1000)

使用setTimeout模拟setInterval

var i = 0;
function time() {
  console.log(i++);
  setTimeout(time, 1000);
}
time();

防抖

function debounce(fn) {
  let timeout = null;
  return () => {
    clearTimeOut(timeout);
    timeout = setTimeout(() => {
      fn.apply(this, args);
    }, 100);
  };
}

节流

function throttle(fn) {
  let flag = true;
  return () => {
    if (!flag) {
      return;
    }
    flag = false;
    setTimeout(() => {
      fn.apply(this, args);
      flag = true;
    }, 100);
  };
}
# api 要执行的函数 执行间隔 第一次是否立即执行
function throttle(fn, time, immeFlag) {
  var flag = true;
  var immeFlag = immeFlag;
  return function() {
    if (!flag) {
      return;
    }
    flag = false;
    if (immeFlag) {
      fn();
      immeFlag = !immeFlag;
    } else {
      setTimeout(() => {
        fn();
        flag = true;
      }, time);
    }
  };
}

Promise.all()

Promise.all = promises => {
  const result = [];
  let j = 0;
  const process = (i, data, resolve) => {
    result[i] = data;
    j++;
    if (j === promises.length) {
      resolve(result);
    }
  };
  return new Promise((resolve, reject) => {
    for (let i = 0; i < promises.length; i++) {
      promises[i].then(data => {
        process(i, data, resolve);
      }, reject);
    }
  });
};

二叉树 新增节点+ 前中后序遍历 + 查找最小值 + 查找指定值 + 删除某节点

// 二叉树 inset方法 + 前中后序遍历
function Node(val) {
  // 节点
  this.val = val;
  this.left = null;
  this.right = null;
}
function BinarySearchTree(root) {
  this.root = null;
  // 插入节点
  this.insert = function(val) {
    var newNode = new Node(val);
    if (this.root === null) {
      this.root = newNode;
    } else {
      insertNode(this.root, newNode);
    }
  };
  // 中序遍历(先序遍历 后序遍历也类似)
  this.inOrderTraversal = function() {
    inOrderTraversal(this.root);
  };
  // 查找二叉树最小值(查找最大值类似)
  this.findMin = function() {
    return findMin(this.root);
  };
  // 查找指定值
  this.searchNode = function(val) {
    return searchNode(this.root, val);
  };
  // 删除指定节点
  this.remove = function(val) {
    removeNode(this.root, val);
  };
}
function insertNode(node, newNode) {
  if (newNode.val < node.val) {
    if (node.left === null) {
      node.left = newNode;
    } else {
      insertNode(node.left, newNode);
    }
  } else {
    if (node.right === null) {
      node.right = newNode;
    } else {
      insetNode(node.right, newNode);
    }
  }
}
function inOrderTraversal(node) {
  inOrderTraversal(node.left);
  console.log(node.val);
  inOrderTraversal(node.right);
}
function findMin(node) {
  if (!node) {
    return null;
  }
  while (node.left !== null) {
    node = node.left;
  }
  return node.val;
}
function searchNode(node, val) {
  if (node === null) {
    return null;
  }
  if (val === node.val) {
    return node;
  } else if (val < node.left) {
    return searchNode(node.left, val);
  } else {
    return searchNode(node.right, val);
  }
}

function removeNode(node, val) {
  if (val < node.val) {
    node.left = removeNode(node, val);
  } else if (val > node.val) {
    node.right = removeNode(node, val);
  } else {
    if (node.left === null && node.right === null) {
      node = null;
      return node;
    } else if (node.left === null) {
      node = node.left;
      return node;
    } else if (node.right === null) {
      node = node.right;
      return node;
    } else {
      var minNode = this.findMin(node.right); // 如果被删除的节点有左右子节点 需要找到右子树的最小节点 然后把该节点的值赋给当前node 然后删掉右子树最小节点
      node.val = minNode.val; // 相当于把node.right的最小节点赋给要删除的node了
      this.removeNode(node.right, node.val);
      return node;
    }
  }
}

树的深度优先遍历

function deepTraversal(node, nodesList) {
  if (node) {
    nodesList.push(node);
    let children = node.children;
    for (let i = 0; i < children.length; i++) {
      deepTraversal(children[i], nodesList);
    }
  }
  return nodesList;
}

树的深度优先遍历(非递归)

// 树深度优先遍历----非递归
function deepTraversal(node) {
  var nodeList = [];
  if (node) {
    var stack = [];
    stack.push(node);
    while (stack.length) {
      var currentNode = stack.pop();
      nodeList.push(currentNode);
      var children = currentNode.children;
      for (var i = children.length - 1; i >= 0; i--) {
        stack.push(children[i]);
      }
    }
  }
}

树的广度优先遍历

function widthTraversal(node) {
  let nodes = [];
  let queue = [];
  if (node) {
    queue.push(node);
    while (queue.length) {
      let item = queue.shift();
      nodes.push(item);
      let children = item.children;
      for (let i = 0; i < children.length; i++) {
        queue.push(children[i]);
      }
    }
  }
  return nodes;
}

实现myPromise

function myPromise(executor) {
  let self = this;
  self.status = "pending";
  self.value = undefined;
  self.reason = undefined;
  self.onResolvedCallbacks = [];
  self.onRejectedCallbacks = [];
  function resolve(value) {
    if (self.status === "pending") {
      self.status = "resolved";
      self.value = value;
      self.onResolvedCallbacks.forEach(fn => {
        fn();
      });
    }
  }
  function reject(reason) {
    if (self.status === "pending") {
      self.status = "rejected";
      self.reason = reason;
      self.onRejectedCallbacks.forEach(fn => {
        fn();
      });
    }
  }
  executor(resolve, reject); // new Promise()会立即执行的函数
}
myPromise.prototype.then = (onFulfilled, onRejected) => {
  let self = this;
  return new myPromise((resolve, reject) => {
    if (self.status === "resolved") {
      try {
        let x = onFulfilled(self.value);
        resolve(x);
      } catch (e) {
        reject(e);
      }
    }
    if (self.status === "rejeted") {
      try {
        let x = onRejected(self.reason);
        resolve(x);
      } catch (e) {
        reject(e);
      }
    }
    if (self.status === "pending") {
      self.onResolvedCallbacks.push(() => {
        try {
          let x = onFulfilled(self.value);
          resolve(x);
        } catch (e) {
          reject(e);
        }
      });
      self.onRejectedCallbacks.push(() => {
        try {
          let x = onReject(self.reason);
          resolve(x);
        } catch (e) {
          reject(e);
        }
      });
    }
  });
  // if (self.status === "pending") {
  //   self.onResolvedCallbacks.push(() => {
  //     onFulfilled(self.value);
  //   });
  //   self.onRejectedCallbacks.push(() => {
  //     onRejected(self.reason);
  //   });
  // }
  // if (self.status === "resolved") {
  //   onFulfilled(self.value);
  // }
  // if (self.status === "rejected") {
  //   onRejected(self.reason);
  // }
};

Object.create()

function create(obj) {
  function F() {}
  F.prototype = obj;
  return new F();
}

new

function myNew(fn, ...args) {
  var obj = {};
  obj.__proto__ = fn.prototype;
  var res = fn.call(obj, ...args);
  return typeof res === "object" ? res : obj;
}

bind()

Function.prototype.bind = function(obj, ...args1) {
  var ob = obj || window;
  var that = this;
  var bound = function(...args2) {
    var args = args1.concat(args2);
    var res = that.call(ob, ...args);
    return res;
  };
  function F() {}
  F.prototype = that.prototype;
  bound.prototype = new F();
  return bound;
};
var obj = {
  a: 1
};
function fn(args1, args2) {
  console.log(this.a + args1 + args2);
}
var myFn = fn.bind(obj, 1);
myFn(3); // 5


call()---es5

Function.prototype.myCall = function(obj) {
  obj = obj || window;
  obj.__fn__ = this;
  let args = [];
  for (let i = 1; i < arguments.length; i++) {
    args.push("arguments[" + i + "i");
  }
  let res = eval("obj.__fn__(" + args + ")");
  delete obj.__fn__;
  return res;
};

call()--es6

Function.prototype.myCall = function(obj, ...args) {
  obj = obj || window;
  obj.__fn__ = this;
  let res = obj.__fn__(...args);
  delete obj.__fn__;
  return res;
};

apply()

Function.prototype.myApply = function(obj) {
  obj = obj || window;
  obj.__fn__ = this;
  let args = [];
  for (let i = 1; i < arguments.length; i++) {
    args.push("arguments[" + i + "]");
  }
  let res = eval("obj.__fn__(" + args + ")");
  delete obj.__fn__;
  return res;
};

遍历DOM(非递归)

function traversal(node) {
  const stack = [];
  stack.push(node);
  while (stack.length > 0) {
    const item = stack.pop();
    if (item && item.nodeType === 1) {
      console.log(item.tagName);
      const children = node.children;
      for (let i = 0; i < children.length; i++) {
        stack.push(children[i]);
      }
    }
  }
}

遍历DOM(递归)

function traversal(node) {
  if (node.nodeType === 1) {
    console.log(node.tagName);
  }
  let children = node.children;
  for (let i = 0; i < children.length; i++) {
    if (children[i].nodeType === 1) {
      traversal(children[i]);
    }
  }
}

Promise封装ajax----get

function myAjax() {
  let xhr = new XMLHttpRequest();
  return new Promise((resolve, reject) => {
    xhr.onreadystatechange = function() {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          resolve(xhr.responseText);
        } else {
          reject("error");
        }
      }
    };
    xhr.send();
  });
}

Promise封装ajax---post

function myAjax(url, methods, data = null) {
  let xhr = new XMLHttpRequest();
  return new Promsie((resolve, reject) => {
    xhr.open(url, methods, true);
    xhr.onreadystatechange = function() {
      if (XMLHttpRequestEventTarget.readyState === 4) {
        if (xhr.status === 200) {
          resolve(shr.responseText);
        } else {
          reject("error");
        }
      }
    };
    methods === "get" ? shr.send() : xhr.send(data);
  });
}

获取点击元素的下标

var lis = document.getElementsByTagment("li");
for (let i = 0; i < lis.length; i++) {
  lis[i].index = i; // 给每一个li元素设置index属性
}
document.getElementsByTagName("ul")[0].addEventListener(
  "click",
  function(e) {
    if (e.target.tagName === "LI") {
      console.log(e.target.index);
    }
  },
  false
);

深拷贝--考虑日期对象以及正则表达式 JSON.parse(JSON.stringify()局限性---无法拷贝函数 日起对象 正则)

function isObj(obj) {
  return (
    (tyoeof(obj) === obj || typeof obj === "function") && typeof obj !== null
  );
}
function deepClone(obj, hash = new weakMap()) {
  let Constructor = obj.constructor; // 对象的构造函数
  let cloneObj;
  switch (Constructor) {
    case RegExp:
      cloneObj = new Constructor(obj);
      break;
    case Date:
      cloneObj = new Constructor(obj.getTime());
      break;
    default:
      if (hash.get(obj)) return hash.get(obj);
      cloneObj = new Constructor();
      hash.set(obj.cloneObj);
  }
  for (let key in obj) {
    cloneObj[key] = isObj(obj[key]) ? deepClone(obj[key], hash) : obj[key];
  }
  return cloneObj;
}

数组中出现次数最多的item 以及对应的次数

function getMaxItemAndNum(arr) {
  let maxItem,
    maxNum = 0;
  let res = arr.reduce(function(res, currentItem) {
    currentItem in res ? (res[currentItem] += 1) : (res[currentItem] = 1);
    if (res[currentItem] > maxNum) {
      maxItem = currentItem;
      maxNum = res[currentItem];
    }
    return res;
  }, {});
  return `出现次数最多的为${maxItem}次数为${maxNum}`;
}

最长无重复子串长度(滑动窗口)

function lengthOfMaxSubString(s) {
  if (s.length === 0) {
    return 0;
  }
  if (s.length === 1) {
    return 1;
  }
  let max_len = 0; // 最长子串的长度
  let cur_arr = []; // 保存当前窗口的子串
  let i = 0; // 当前窗口的左侧
  let j = 0; // 当前窗口的右侧,用来扩大窗口长度的指针
  for (; j < s.length; j++) {
    let val = s[j];
    if (cur_arr.indexOf(val) > -1) {
      i = cur_arr.indexOf(val);
      cur_arr = cur_arr.slice(i + 1);
    }
    cur_arr.push(val);
    if (max_len < cur_arr.length) {
      max_len = cur_arr.length;
    }
  }
  return max_len;
}

最长无重复字串

function lengthOfMaxSubString(s) {
  if (s.length === 0) {
    return 0;
  }
  if (s.length === 1) {
    return 1;
  }
  let max_len = 0; // 最长子串的长度
  let cur_arr = []; // 保存当前窗口的子串
  let i = 0; // 当前窗口的左侧
  let j = 0; // 当前窗口的右侧,用来扩大窗口长度的指针
  let begin = 0;
  for (; j < s.length; j++) {
    let val = s[j];
    if (cur_arr.indexOf(val) > -1) {
      i = cur_arr.indexOf(val);
      cur_arr = cur_arr.slice(i + 1);
    }
    cur_arr.push(val);
    if (max_len < cur_arr.length) {
      max_len = cur_arr.length;
      begin = j - cur_arr.length + 1;
    }
  }
  return s.substr(begin, max_len);
}
console.log(lengthOfMaxSubString("abcddcgadb"));