实现new
- 创建一个空对象
- 将这个对象的原型指向构造函数的prototype属性
- 将构造函数的this赋值给这个空对象(因此this指向了这个对象)
- 执行构造函数内部的代码(为这个新对象添加属性)
function _new(Fn, ...args) {
let obj = Object.create(Fn.prototype)
const result = Fn.call(obj, ...args)
return result instanceof Object ? result : obj;
}
// function A(){}
// _new(A)
instanceof
function _instanceof(leftValue, rightValue) {
var proto = rightValue.prototype
var left = leftValue.__proto__
while(true) {
if(left === null) {
return false
}
if(left === proto) {
return true
}
left = left.__proto__
}
}
// function A(){}
// var a = new A()
// _instanceof(a, A)
实现bind
Function.prototype._bind = function(context, ...args) {
const fn = this;
return function(...rest) {
return fn.call(context, ...args, ...rest)
}
}
// function test(){}
// test._bind(null, 1,2,3)(4,5,6);
柯里化
function curry (fn, ...args) {
if(args.length >= fn.length) {
return fn(...args)
} else {
return function(...args2) {
return curry(fn, ...args, ...args2)
}
}
}
// function add2(x, y, z) {
// return x + y + z
// }
// const add = curry(add2)
// console.log(add(1, 2, 3));
// console.log(add(1)(2)(3));
防抖
事件触发n秒后执行函数,如果n秒内又触发了事件,重新计时
function debounce(fn, delay) {
let timer
return function(){
if(timer) clearTimeout(timer)
timer = setTimeout(function() {
fn()
},delay)
}
}
// function print() {console.log(1)}
// let dfn = debounce(print,1000)
// document.onmousemove = function() {
// dfn()
// }
节流
每隔n秒执行一次函数
// 节流-定时器
function throttle(fn,delay) {
var timer
return function() {
if(timer) {
return
}
timer = setTimeout(function() {
fn();
timer = null;
}, delay)
}
}
// 节流-时间戳
function throttle2(fn, delay) {
let previous = 0;
return function() {
const now = new Date();
if(now - previous > delay) {
fn()
previous = now;
}
}
}
// function print() {console.log(1)}
// let tfn = throttle(print, 1000)
// document.onmousemove = function() {
// tfn()
// }
生成随机字符串
Math.random().toString(32).substring(2)
//'3nalkn8332g'
UUID
let uuid = self.crypto.randomUUID();
console.log(uuid); // for example "36b8f84d-df4e-4d49-b662-bcde71a8764f"
生成随机颜色
`#${Math.floor(Math.random()*0xffffff).toString(16).padEnd(6,'0')}`
// '#a2e0f4'
isPhone
function isPhone(phone) {
return /^1[3456789]\d{9}$/.test(phone);
}
发布订阅
class MyEventEmit {
eventMap = {}
on(type, handler) {
(this.eventMap[type] || (this.eventMap[type] = [])).push(handler);
}
emit(type) {
this.eventMap[type].forEach(handler => handler())
}
}
var myEmit = new MyEventEmit();
myEmit.on('click', function(){
console.log('emit...')
})
isNaN() vs Number.isNaN()
- NaN的类型为number
- isNaN函数会先用Number把参数转换为数值
- Number.isNaN不会把参数转换为数值,只有参数为NaN时才返回true
RGB to Hex
const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0');
// RGBToHex(255,165,1)
// 'ffa501'
Get a Cookie Value
const cookie = name => `; ${document.cookie}`.split(`; ${name}=`).pop().split(';').shift();
// cookie('_ga')
// 'GA1.2.30664543.1648188756'
React useDebounce
function useDebounce(value, delay) {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(handler);
};
}, [value, delay]);
return debouncedValue;
}
// 使用
const debouncedSearchTerm = useDebounce(varible, 1000);
useEffect(() => {
// TODO
}, [debouncedSearchTerm]);
交换两个变量的值
var a = 1, b = 3;
// 1
a=[b, b=a][0]
// 2
var tem = a
a = b
b = tem
// 3
[b, a] = [a, b]
// 4
cosnt K = a => b => a
a = K(b)(b = a)
// 5
a = a + b
b = a - b
a = a - b
Rating
const rating = (star) => '★★★★★☆☆☆☆☆'.slice(5 - star, 10 - star)
// rating(1) '★☆☆☆☆'
getTop
function getTop(e) {
let offset = e.offsetTop;
if (e.offsetParent != null) offset += getTop(e.offsetParent);
return offset;
}
统计一个页面标签的数量
Object.entries([...document.querySelectorAll("*")].map(item => item.tagName).reduce((acc, curr) => ((acc[curr] = ++acc[curr] || 1),acc),{})).sort((a, b) => b[1] - a[1]).slice(0,3).map(item => item[0])