code

类型

isType

function isType(type){
return function (o){
return Object.prototype.toString.call(o)===`[object ${type}]`
}
}

深拷贝

1.
JSON.parse(JSON.stringfy(obj));
2.
//WeakMap解决对象循环引用问题
function deepClone(obj, weakMap = new WeakMap()) {
if (!(obj instanceof Object)) return obj
var isArray = obj instanceof Array
var res = isArray ? [] : {}
if (!isArray) {
if (weakMap.get(obj)) return {}
weakMap.set(obj, {}.toString.call(obj))
}
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
res[key] = deepClone(obj[key], weakMap)
}
}
return res
}
// 浅拷贝
function clone(obj) {
if (!(obj instanceof Object)) return obj
var res = obj instanceof Array ? [] : {}
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
res[key] = obj[key]
}
}
return res
}

防抖

function debounce(fn, delay) {
let timer;
return function (...args) {
const context = this;
clearTimeout(timer);
timer = setTimeout(fn.bind(context, ...args), delay);
};
}

节流

function throttle(fn, time) {
let canCall = true;
return function (...args) {
if (!canCall) return;
canCall = false;
fn(...args);
setTimeout(() => {
canCall = true;
}, time);
};
}

实现 new

function newObject() {
var obj = Object.create(null);
//去除参数里的构造函数
const Constructor = [].shift.call(arguments);
obj.__proto__ = Constructor.prototype;
Constructor.apply(obj, arguments);
return obj;
}
function factory(name, age) {
this.name = name;
this.age = age;
}
var obj = newObject(factory, "xjq", 23);

实现 call

Function.prototype.call2 = function (context) {
// 首先要获取调用call的函数,用this可以获取
context.fn = this;
const obj = [].shift.call(arguments);
obj.fn(...arguments);
delete obj.fn;
};

实现bind

Function.prototype.bind2 = function (o) {
const context = this
return function () {
const symbol = Symbol()
o[symbol] = context
o[symbol](...arguments)
delete o[symbol]
}
}

实现 instanceof

function _instanceof(l, r) {
const f = r.prototype
while (true) {
if (l === f) {
return true
}
if (!l) {
return false
}
l = l.__proto__
}
}

实现 Promise

function Promise(fn) {
this.state = 'pending'
this.value = null
this.callbacks = []
fn(this._resolve.bind(this), this._reject.bind(this))
}
Promise.prototype._resolve = function (value) {
if (this.state === 'pending') {
this.state = 'fullfilled'
this.value = value
this.callbacks.forEach((fn) => this._handle(fn))
}
}
Promise.prototype._reject = function (value) {
if (this.state === 'pending') {
this.state = 'rejected'
this.value = value
this.callbacks.forEach((fn) => this._handle(fn))
}
}
Promise.prototype._handle = function (callback) {
if (this.state === 'pending') {
this.callbacks.push(callback)
return
}
let cb = this.state === 'fullfilled' ? callback.onFullfilled : callback.onRejected
if (!cb) {
cb = this.state === 'fullfilled' ? callback.resolve : callback.reject
cb(this.value)
return
}
let ret
try {
ret = cb(this.value)
cb = this.state === 'fullfilled' ? callback.resolve : callback.reject
} catch (error) {
ret = error
cb = callback.reject
} finally {
cb(ret)
}
}
Promise.prototype.then = function (onFullfilled, onRejected) {
return new Promise((resolve, reject) => {
this._handle({
onFullfilled: onFullfilled || null,
onRejected: onRejected || null,
resolve,
reject,
})
})
}
Promise.prototype.catch = function (onError) {
return this.then(null, onError)
}
Promise.prototype.finally = function (onFinally) {
if (typeof onFinally !== 'function') return this.then()
let promise = this.constructor
return this.then(
(value) => promise.resolve(onFinally()).then(() => value),
(reason) =>
promise.resolve(onFinally()).then(() => {
throw reason
})
)
}
Promise.resolve = function (value) {
if (value && value instanceof Promise) {
return value
} else if (value && value instanceof Object && value.then instanceof Function) {
const then = value.then
return new Promise((resolve) => then(resolve))
} else {
return new Promise((resolve) => resolve(value))
}
}
Promise.reject = function (value) {
if (value && value instanceof Object && value.then instanceof Function) {
const then = value.then
return new Promise((resolve, reject) => then(reject))
} else {
return new Promise((resolve, reject) => reject(value))
}
}
Promise.all = function (promiseList) {
return new Promise((resolve, reject) => {
const resList = []
promiseList.forEach((p, index) => {
p.then(
(res) => {
resList[index] = res
if (resList.length === arr.length) {
resolve(resList)
}
},
(err) => reject(err)
)
})
})
}
Promise.race = function (promiseList) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promiseList.length; i++) {
Promise.resolve(promiseList[i]).then(
(res) => {
resolve(res)
},
(err) => {
reject(err)
}
)
}
})
}

实现 reduce

function _reduce(fn, initialValue) {
const arr = this
let i = 0
if (initialValue === undefined) {
initialValue = arr[0]
i++
}
for (; i < arr.length; i++) {
initialValue = fn(initialValue, arr[i], i)
}
return initialValue
}

for of

function forOf(fn) {
const it = this[Symbol.iterator]()
while (true) {
const { value, done } = it.next()
if (done) break
fn(value)
}
}
const arr = [1, 2, 3, 4]
forOf.call(arr, (e) => {
console.log(e)
})

jsonp

function jsonp({ url, callback }) {
const script = document.createElement('script')
script.src = url + '?cb=' + callback.name
document.body.appendChild(script)
}
function fn(data) {
console.log('data', data)
}
jsonp({
url: 'http://127.0.0.1:3000',
callback: fn,
})
// 后端返回的是javascript代码
// fn({a:1})

柯里化函数

const add = (args) => args.reduce((a, b) => a + b, 0)
function currying(func) {
const args = []
return function result(...rest) {
if (rest.length) {
args.push(...rest)
return result
} else {
return func(args)
}
}
}

响应式原理

Proxy

const app = document.querySelector('#app')
var data = {
t1: 't1',
t2: 't2',
t3: [1, 2],
t4: { a: 1, arr: [1, 2] },
}
function proxy(target, handler) {
Object.keys(target).forEach((key) => {
if (target[key] instanceof Array || target[key] instanceof Object) {
target[key] = proxy(target[key], handler)
}
})
return new Proxy(target, {
get: function (obj, key) {
return obj[key]
},
set: function (obj, key, newValue) {
obj[key] = newValue
handler()
return true
},
})
}
var dataProxy = proxy(data, update)
function update() {
const { t1, t2, t3, t4 } = dataProxy
document.getElementById('app').textContent = `t1:${t1},t2:${t2},t3:${t3.map((o) => o)},t4:${t4.arr.map((v) => v)}`
}
update()

Object.defineProperty

const app = document.querySelector('#app')
var data = {
t1: 't1',
t2: 't2',
t4: { a: 1 },
}
function reactive(target, handler) {
Object.keys(target).forEach((key) => {
if (target[key] instanceof Object) {
reactive(target[key], handler)
} else {
let tar = target[key]
console.log(key, tar)
Object.defineProperty(target, key, {
get: function () {
return tar
},
set: function (newValue) {
if (tar !== newValue) {
tar = newValue
handler()
}
},
})
}
})
}
reactive(data, update)
function update() {
const { t1, t2, t4 } = data
document.getElementById('app').textContent = `t1:${t1},t2:${t2},t4:${t4.a}`
}
update()

数组监听

function MyArray() {}
function clone(prototype) {
function F() {}
F.prototype = prototype
return new F()
}
function inherit(p, o) {
let prototype = clone(o.prototype)
prototype.constructor = o
p.prototype = prototype
}
inherit(MyArray, Array)
const _methodKey = ['push', 'pop', 'shift']
const _method = _methodKey.reduce((acc, cur) => {
acc[cur] = MyArray.prototype[cur]
return acc
}, {})
MyArray.prototype.push = function (params) {
this.update('push')
_method['push'].call(this, params)
}
MyArray.prototype.pop = function (params) {
this.update('pop')
_method['pop'].call(this, params)
}
MyArray.prototype.update = function (type) {
console.log(type)
}
const arr = new MyArray()
arr.push(3)
arr.pop()
arr.push(3)
console.log(arr)

Event类实现

class Event {
constructor() {
this.event = {}
this.maxListener = 5
this.listenerCount = 0
}
on(type, fn) {
if (this.listenerCount >= this.maxListener) {
throw new Error('事件数量超限')
}
let hasEvent = !!this.event[type]
if (typeof fn === 'function') {
if (hasEvent) {
this.event[type].push(fn)
} else {
this.event[type] = [fn]
}
}
if (!hasEvent) this.listenerCount++
}
once(type, fn) {
const _this = this
function newFn() {
fn(...arguments)
_this.removeListener(type, newFn)
}
this.on(type, newFn)
}
emit(type, params) {
if (this.event[type]) {
this.event[type].forEach((fn) => fn(params))
}
}
setMaxListeners(count) {
this.maxListener = count
}
listeners(type) {
return this.event[type] || []
}
removeAllListener(type) {
this.event[type] = null
}
removeListener(type, listener) {
if (this.event[type]) {
this.event[type] = this.event[type].filter((fn) => listener !== fn)
}
}
addListener(type, fn) {
this.on(type, fn)
}
}
const e = new Event()
function a1() {
console.log('a1')
}
function a2() {
console.log('a2')
}
e.once('a', a1)
e.on('a', a2)
e.emit('a')
e.emit('a')

并发限制的异步调度器

class Scheduler {
constructor() {
this.runQueue = []
this.queue = []
this.count = 2
}
addTask(task) {
this.queue.push(task)
return this.run()
}
run() {
if (this.runQueue.length < this.count && this.queue.length) {
const task = this.queue.shift()
const promise = task().then(() => {
this.runQueue.splice(this.runQueue.indexOf(promise), 1)
})
this.runQueue.push(promise)
return promise
} else {
return Promise.race(this.runQueue).then(() => this.run())
}
}
}
const timeout = (time) =>
new Promise((resolve) => {
setTimeout(resolve, time)
})
const scheduler = new Scheduler()
const addTask = (time, order) => {
scheduler
.addTask(() => timeout(time))
.then(() => {
console.log(order)
})
}
addTask(10000, '1')
addTask(5000, '2')
addTask(3000, '3')
addTask(4000, '4')

实现 redux

实现

export function createStore(reducer, enhancer) {
let state = {}
let isDispatching = false
let listeners = []
if (typeof enhancer === "function") {
return enhancer(createStore)(reducer)
}
function getState() {
return state
}
function dispatch(action) {
if (typeof action.type === undefined) {
throw new Error("action has not type")
}
if (isDispatching) {
throw new Error("is dispatching")
}
try {
isDispatching = true
state = reducer(state, action)
console.log(state)
listeners.forEach((fn) => fn())
} catch (error) {
console.log(error)
isDispatching = false
}
}
function subscribe(listener) {
listeners.push(listener)
return listeners.filter((fn) => listener !== fn)
}
return {
getState,
dispatch,
subscribe,
}
}
export function dispatchBook(payload) {
return { type: "BOOK", payload }
}
export function reducerBook(state = {}, action) {
switch (action.type) {
case "BOOK":
return { ...state, name: action.payload }
}
}
export function bindActionCreators(actionCreators, dispatch) {
return Object.keys(actionCreators).reduce((acc, cur) => {
acc[cur] = function (...args) {
dispatch(actionCreators[cur](...args))
}
return acc
}, {})
}
export function combineReducers(reducers) {
return (state, action) => {
return Object.keys(reducers).reduce((acc, cur) => {
acc[cur] = reducers[cur](state[cur], action)
return acc
}, {})
}
}
export function applyMiddleware(middleWares) {
return (createStore) => (reducer) => {
let store = createStore(reducer)
let newDispatch = compose(middleWares.map((middleware) => middleware(store)))(store.dispatch)
return { ...store, dispatch: newDispatch }
}
}
export function compose(args) {
return args.reduce(
(acc, cur) =>
(...args) =>
acc(cur(...args))
)
}

test

import { combineReducers, createStore, applyMiddleware, bindActionCreators } from "./index"
function reduxLogger(store) {
return (dispatch) => (action) => {
console.log(store.getState())
dispatch(action)
console.log(store.getState())
}
}
function reduxCustom(store) {
return (dispatch) => (action) => {
dispatch(action)
console.log("c", store.getState())
}
}
const mergeReducers = combineReducers({ book: reducerBook })
const store = createStore(mergeReducers, applyMiddleware([reduxCustom, reduxLogger]))
const actions = bindActionCreators({ dispatchBook }, store.dispatch)
store.subscribe(() => {
// console.log(11)
})
actions.dispatchBook("xxx")

实现 react-redux

const { Component } = require("react");
const { bindActionCreators } = require("redux");
class Provider extends Component{
getChildContent(){
return {store:this.props.store}
}
render(){
return this.props.children
}
}
function connect(mapStateToProps,mapDispatchToProps){
return function(WrapperComponent){
class ProxyComponent extends Component{
constructor(props,context){
super(props,context)
this.store=context.store
this.state=mapStateToProps(this.store.getState())
}
render(){
let actions
if(typeof mapDispatchToProps==='function'){
actions=mapDispatchToProps(this.store.dispatch)
}else if(typeof mapDispatchToProps==='object'){
actions=bindActionCreators(mapDispatchToProps,this.store.dispatch)
}
return <WrapperComponent {...this.state} {...actions}/>
}
}
return ProxyComponent
}
}

数组

乱序

扁平化

function flatten(arr) {
let res = []
arr.forEach((item) => {
if (Array.isArray(item)) {
res = [...res, flatten(item)]
} else {
res.push(item)
}
})
return res
}

去重

1. Set
[...new Set[arr]]
2. 对象属性去重
function unique(arr) {
let len = arr.length
let res = []
let obj = {}
for (let i = 0; i < len; i++) {
if (!obj.hasOwnProperty(arr[i])) {
obj[arr[i]] = arr[i]
}
}
return Object.values(arr)
}
3. indexOf
function unique(arr) {
let res = []
for (let i = 0; i < arr.length; i++) {
if (res.indexOf(arr[i]) === -1) {
res.push(arr[i])
}
}
return res
}

Ajax

function request({ method, url, data = null, config: { headers = {}, timeout = 60 * 1000, async = true } }) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open(method, url, async)
Object.entries(headers).forEach((headerArr) => {
xhr.setRequestHeader(headerArr[0], headerArr[1])
})
xhr.send(data)
xhr.timeout = timeout
xhr.ontimeout = () => {
reject()
}
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
const status = xhr.status
if ((status >= 200 && status < 300) || status === 304) {
resolve(xhr.responseText)
} else {
reject()
}
}
}
})
}
request({ method: 'POST', url: 'http://127.0.0.1:3000', config: { timeout: 10 * 1000 } })
.then((res) => {
console.log(res)
})
.catch((err) => {
console.log(err)
})

排序

稳定性:待排序的记录中,存在多个具有相同关键字的记录,经过排序后,这些记录的相对序列保持不变,则称算法是稳定的,否则是不稳定的

冒泡排序

function bubbleSort(arr) {
let len = arr.length
for (let i = 0; i < len - 1; i++) {
for (let j = 0; j < len - i; j++) {
if (arr[j] > arr[j + 1]) {
let temp = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = temp
}
}
}
return arr
}

快排

function quickSort(arr) {
_quickSort(arr, 0, arr.length - 1)
}
function _quickSort(arr, l, r) {
if (l > r) return
let left = l,
right = r
let base = arr[left]
let temp
while (l != r) {
while (arr[r] >= base && l < r) {
r--
}
while (arr[l] <= base && l < r) {
l++
}
if (l < r) {
temp = arr[l]
arr[l] = arr[r]
arr[r] = temp
}
}
arr[left] = arr[l]
arr[l] = base
_quickSort(arr, left, l - 1)
_quickSort(arr, l + 1, right)
}

归并排序

function mergeSort(arr) {
_mergeSort(arr, 0, arr.length - 1)
}
function _mergeSort(arr, l, r) {
if (l < r) {
const mid = l + parseInt((r - l) / 2)
_mergeSort(arr, l, mid)
_mergeSort(arr, mid + 1, r)
_merge(arr, l, mid, r)
}
}
function _merge(arr, l, mid, r) {
let i = l,
j = mid + 1
let k = 0,
temp = []
while (i <= mid && j <= r) {
if (arr[i] > arr[j]) {
temp[k++] = arr[j++]
} else {
temp[k++] = arr[i++]
}
}
while (i <= mid) {
temp[k++] = arr[i++]
}
while (j <= r) {
temp[k++] = arr[j++]
}
for (let i = 0; i < k; i++) {
arr[l + i] = temp[i]
}
}

选择排序

function selectSort(arr) {
let len = arr.length
let temp, minIdx
for (let i = 0; i < len - 1; i++) {
minIdx = i
for (let j = i + 1; j < len; j++) {
if (arr[minIdx] > arr[j]) {
minIdx = j
}
}
temp = arr[minIdx]
arr[minIdx] = arr[i]
arr[i] = temp
}
return arr
}

插入排序

function insert(arr) {
let len = arr.length
for (let i = 0; i < len - 1; i++) {
let preIdx = i
let current = arr[i + 1]
while (preIdx >= 0 && current < arr[preIdx]) {
arr[preIdx + 1] = arr[preIdx]
preIdx--
}
arr[preIdx + 1] = current
}
return arr
}