图片懒加载
<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);
};
}
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);
}
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);
}
});
}
});
};
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);
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;
}
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"));