废话不多说,直接上代码
防抖
function JLDebounce ( fn, deplay ) {
let timer = null ;
const _debounce = function ( ... args) {
if ( timer) clearInterval ( timer) ;
timer = setTimeout ( ( ) => {
fn . apply ( this , args) ;
} , deplay) ;
}
return _debounce;
}
节流
function JLThrottle ( fn, interval ) {
let lastTime = 0 ;
const _throttle = function ( ... args) {
let nowTime = new Date ( ) . getTime ( ) ;
let remainTime = interval - ( nowTime - lastTime) ;
if ( remainTime <= 0 ) {
fn . apply ( this , args) ;
lastTime = nowTime;
}
}
return _throttle;
}
柯里化
function TestCurring ( fn ) {
function curried ( ... args1) {
if ( args1. length >= fn. length) {
return fn . apply ( this , args1) ;
} else {
return function ( ... args2) {
return curried . apply ( this , args1. concat ( args2) ) ;
}
}
}
return curried;
}
深拷贝
function isObject ( value ) {
const TYValue = typeof value;
return ( value !== null ) && ( TYValue === "object" || TYValue === "function" )
}
function JLDeepClone ( originValue, map = new WeakMap ( ) ) {
if ( originValue instanceof Set ) {
return new Set ( [ ... originValue] ) ;
}
if ( originValue instanceof Map ) {
return new Map ( [ ... originValue] )
}
if ( typeof originValue === "function" ) {
return originValue;
}
if ( typeof originValue === "symbol" ) {
return Symbol ( originValue. description) ;
}
const newObj = Array. isArray ( originValue) ? [ ] : { } ;
map. set ( originValue, newObj) ;
for ( const key in originValue) {
newObj[ key] = JLDeepClone ( originValue[ key] )
}
if ( ! isObject ( originValue) ) {
return originValue
}
if ( map. has ( originValue) ) {
return map. get ( originValue)
}
const symbolKeys = Object. getOwnPropertySymbols ( originValue) ;
for ( const sKey of symbolKeys) {
newObj[ sKey] = JLDeepClone ( originValue[ sKey] , map) ;
}
return newObj;
}
数组扁平化
function JLFlat1 ( arr ) {
let res = [ ] ;
for ( let i = 0 ; i < arr. length; i++ ) {
if ( Array. isArray ( arr[ i] ) ) {
res = res. concat ( JLFlat ( arr[ i] ) ) ;
} else {
res. push ( arr[ i] ) ;
}
}
return res;
}
function JLFlat2 ( arr, depth = 1 ) {
const res = [ ] ;
arr. forEach ( item => {
if ( Array. isArray ( item) && depth > 1 ) {
res. push ( ... JLFlat2 ( item, depth - 1 ) ) ;
} else {
res. push ( item) ;
}
} ) ;
return res;
}
对象扁平化
function JLObjectFlat ( obj = '' ) {
const res = { } ;
function flat ( item , preKey = '' ) {
Object. entries ( item) . forEach ( ( [ key, value] ) => {
let newKey = key;
if ( Array. isArray ( item) ) {
newKey = preKey ? ` ${ preKey} [ ${ key} ] ` : key;
} else {
newKey = preKey ? ` ${ preKey} . ${ key} ` : key;
}
if ( value && typeof value === 'object' ) {
flat ( value , newKey)
} else {
res[ newKey] = value;
}
} )
}
flat ( obj) ;
return res;
}
map函数
Array . prototype. JLMap = function ( fn, thisValue ) {
let res = [ ] ;
thisValue = thisValue || [ ] ;
for ( let key in thisValue) {
res. push ( fn ( thisValue[ key] ) ) ;
}
return res;
}
ajax
function JLAjax ( {
url,
method = "get" ,
data = { } ,
timeout = 10000 ,
headers = { } ,
success,
failure
} = { } ) {
const xhr = new XMLHttpRequest ( )
xhr. onload = function ( ) {
if ( xhr. status >= 200 && xhr. status < 300 ) {
success && success ( xhr. response)
} else {
failure && failure ( { status : xhr. status, message : xhr. statusText } )
}
}
xhr. responseType = "json"
xhr. timeout = timeout
if ( method. toUpperCase ( ) === "GET" ) {
const queryStrings = [ ]
for ( const key in data) {
queryStrings. push ( ` ${ key} = ${ data[ key] } ` )
}
url = url + "?" + queryStrings. join ( "&" )
xhr. open ( method, url)
xhr. send ( )
} else {
xhr. open ( method, url)
xhr. setRequestHeader ( "Content-type" , "application/json" )
xhr. send ( JSON . stringify ( data) )
}
return xhr
}
ajax-promise实现
function AJAXPromise ( {
url,
method = 'get' ,
data = { } ,
timeout = 1000
} = { } ) {
const xhr = new XMLHttpRequest ( ) ;
const promise = new Promise ( ( resolve, reject ) => {
xhr. onload = function ( ) {
if ( xhr. status >= 200 && xhr. status < 300 ) {
resolve ( xhr. response) ;
} else {
reject ( { status : xhr. status, message : xhr. responseText} ) ;
}
}
xhr. timeout = timeout;
xhr. responseType = "json" ;
if ( method. toUpperCase ( ) === 'GET' ) {
const queryStrings = [ ] ;
for ( let ket in data) {
queryStrings. push ( ` ${ key} = ${ data[ key] } ` ) ;
}
url = url + "?" + queryStrings. join ( '&' ) ;
xhr. open ( method, url) ;
xhr. send ( ) ;
} else {
xhr. open ( method, url) ;
xhr. setRequestHeader ( "Content-type" , "application/json" ) ;
xhr. send ( data) ;
}
} )
promise. xhr = xhr;
return promise;
}
apply
Function . prototype. TestApply = function ( thisArg, argArr ) {
let fn = this ;
thisArg = ( thisArg !== null && thisArg !== undefined ) ? Object ( thisArg) : window;
thisArg. fn = fn;
argArr = argArr || [ ] ;
let result = thisArg. fn ( ... argArr) ;
delete thisArg. fn;
return result;
}
call
Function . prototype. TestCall = function ( thisArg, argArr ) {
let fn = this ;
thisArg = ( thisArg !== null && thisArg !== undefined ) ? Object ( thisArg) : window;
thisArg. fn = fn;
let result = thisArg. fn ( ... argArr) ;
delete thisArg. fn;
return result;
}
bind
Function . prototype. TestBind = function ( thisArg, argArr ) {
let fn = this ;
thisArg = ( thisArg !== null && thisArg !== undefined ) ? Object ( thisArg) : window;
return function ( ... args) {
let finalyArr = [ ... argArr, ... args] ;
thisArg. fn = fn;
let result = thisArg. fn ( ... finalyArr) ;
delete thisArg. fn;
return result;
}
}
new
function JLNew ( context, ... args ) {
let obj = { } ;
obj. __proto__ = context. prototype;
let res = context . apply ( obj, args) ;
return res instanceof Object ? res : obj;
}
instanceof
function JLInstanceof ( target, origin ) {
while ( target) {
if ( target. __proto__ === origin. prototype) {
return true ;
}
target = target. __proto__;
}
return false ;
}
事件总线
class JLEventBus {
constructor ( ) {
this . eventBus = { }
}
on ( eventName, eventCallback, thisArg ) {
let handlers = this . eventBus[ eventName] ;
if ( ! handlers) {
handlers = [ ] ;
this . eventBus[ eventName] = handlers;
}
handlers. push ( {
eventCallback,
thisArg
} )
}
off ( eventName, eventCallback ) {
const handlers = this . eventBus[ eventName] ;
if ( ! handlers) return
const newHandlers = [ ... handlers] ;
for ( let i = 0 ; i < newHandlers. length; i++ ) {
const handler = newHandlers[ i] ;
if ( handler. eventCallback === eventCallback) {
const index = handlers. indexOf ( handler)
handlers. splice ( index, 1 )
}
}
}
emit ( eventName, ... payload ) {
const handlers = this . eventBus[ eventName] ;
if ( ! handlers) return
handlers. forEach ( handler => {
handler. eventCallback . apply ( handler. thisArg, payload)
} )
}
}
响应式
class Depend {
constructor ( ) {
this . reactiveFns = new Set ( ) ;
}
addDepend ( fn ) {
this . reactiveFns. add ( fn) ;
}
depend ( ) {
if ( reactiveFn) {
this . reactiveFns. add ( reactiveFn) ;
}
}
notify ( ) {
this . reactiveFns. forEach ( fn => {
fn ( ) ;
} )
}
}
let reactiveFn = null ;
function watchFn ( fn ) {
reactiveFn = fn;
fn ( ) ;
reactiveFn = null ;
}
const objMap = new WeakMap ( ) ;
function getDepend ( obj, key ) {
let map = objMap. get ( obj) ;
if ( ! map) {
map = new Map ( ) ;
objMap. set ( obj, map) ;
}
let dep = map. get ( key) ;
if ( ! dep) {
dep = new Depend ( ) ;
map. set ( key, dep) ;
}
return dep;
}
function reactiveVue2 ( obj ) {
Object. key ( obj) . forEach ( key => {
let value = obj[ key] ;
Object. defineProperty ( obj, key, {
set ( newValue) {
value = newValue;
const dep = getDepend ( obj, key) ;
dep. notify ( ) ;
} ,
get ( ) {
const dep = getDepend ( obj, key) ;
dep. depend ( ) ;
return value;
}
} )
} )
return obj;
}
function reactiveVue3 ( obj ) {
return new Proxy ( obj, {
set ( target, key, newValue, receiver) {
Reflect. set ( target, key, newValue, receiver) ;
const dep = getDepend ( target, key) ;
dep. notify ( ) ;
} ,
get ( target, key, receiver) {
const dep = getDepend ( target, key) ;
dep. depend ( ) ;
return Reflect. get ( target, key, receiver) ;
}
} )
}
简易版响应式
function reactive ( obj ) {
if ( typeof obj !== 'object' && obj !== null ) {
return obj;
}
return new Proxy ( obj, {
get ( target, key, receiver) {
return Reflect. get ( target, key, receiver) ;
} ,
set ( target, key, value, receiver) {
return Reflect. set ( target, key, value, receiver) ;
} ,
deleteProperty ( target, key ) {
return Reflect. deleteProperty ( target, key) ;
}
} )
}
Promise
const PROMISE_STATUS_PENDING = 'pending' ;
const PROMISE_STATUS_FULFILLED = 'fulfilled' ;
const PROMISE_STATUS_REJECTED = 'rejected' ;
function exectorWithCatchError ( execfn, value, resolve, reject ) {
try {
const result = execfn ( value) ;
resolve ( result) ;
} catch ( err) {
reject ( err) ;
}
}
class TestPromise {
constructor ( executor ) {
this . status = PROMISE_STATUS_PENDING ;
this . value = undefined ;
this . reason = undefined ;
this . onFuifilledFns = [ ] ;
this . onRejectedFns = [ ] ;
const resolve = ( ) => {
if ( this . status === PROMISE_STATUS_PENDING ) {
queueMicrotask ( ( ) => {
if ( this . status !== PROMISE_STATUS_PENDING ) return ;
this . status = PROMISE_STATUS_FULFILLED ;
this . value = value;
this . onFuifilledFns. forEach ( fn => {
fn ( this . value) ;
} )
} )
}
}
const reject = ( ) => {
if ( this . status === PROMISE_STATUS_PENDING ) {
queueMicrotask ( ( ) => {
if ( this . sttus !== PROMISE_STATUS_PENDING ) return ;
this . reason = reason;
this . status = PROMISE_STATUS_REJECTED ;
this . onRejectedFns. forEach ( fn => {
fn ( this . reason) ;
} )
} )
}
}
try {
executor ( resolve, reject) ;
} catch ( err) {
reject ( err) ;
}
}
then ( onFulfilled, onRejected ) {
const defaultOnRejected = err => { throw err } ;
onRejected = onRejected || defaultOnRejected;
const defaultOnFulfilled = value => { return value } ;
onFulfilled = onFulfilled || defaultOnFulfilled;
return new TestPromise ( ( resolve, reject ) => {
if ( this . status === PROMISE_STATUS_FULFILLED && onFulfilled) {
exectorWithCatchError ( onFulfilled, this . value, resolve, reject) ;
}
if ( this . status === PROMISE_STATUS_REJECTED && onRejected) {
exectorWithCatchError ( onRejected, this . reason, resolve, reject) ;
}
if ( this . status === PROMISE_STATUS_PENDING ) {
if ( this . onFulfilled) this . onFuifilledFns. push ( ( ) => {
exectorWithCatchError ( onFulfilled, this . value, resolve, reject) ;
} )
if ( this . onRejected) this . onRejectedFns. push ( ( ) => {
exectorWithCatchError ( onRejected, this . reason, resolve, reject) ;
} )
}
} )
}
catch ( onRejected) {
return this . then ( undefined , reject) ;
}
finaly ( onFinaly ) {
this . then ( ( ) => {
onFinaly ( ) ;
} , ( ) => {
onFinaly ( ) ;
} )
}
static resolve ( value ) {
return new TestPromise ( ( resolve ) => resolve ( value) ) ;
}
static reject ( reason ) {
return new TestPromise ( ( resolva, reject ) => reject ( reason) ) ;
}
static all ( promises ) {
return new TestPromise ( ( resolve, reject ) => {
const values = [ ] ;
promises. forEach ( promise => {
promise. then ( res => {
values. push ( res) ;
if ( values. length === promises. length) {
resolve ( values) ;
}
} , err => {
reject ( err) ;
} )
} )
} )
}
static allSetted ( promises ) {
return new TestPromise ( ( resolve ) => {
const results = [ ] ;
promises. forEach ( promise => {
promise. then ( res => {
results. push ( { status : PROMISE_STATUS_FULFILLED , value : res } )
if ( results. length === promises. lrngth) {
resolve ( results) ;
}
} , err => {
results. push ( { status : PROMISE_STATUS_REJECTED , value : err } )
if ( results. length === promises. length) {
resolve ( results) ;
}
} )
} )
} )
}
static race ( peomises ) {
return new TestPromise ( ( resolve, reject ) => {
promises. forEach ( promise => {
promise. then ( resolve, reject)
} )
} )
}
static any ( promise ) {
const results = [ ] ;
return new TestPromise ( ( resolve, reject ) => {
promises. forEach ( promise => {
promise. then ( resolve, err => {
results. push ( err) ;
if ( results. length === promises. length) {
reject ( new AggregateError ( results) ) ;
}
} )
} )
} )
}
}
Promise.all
Promise. JLAll = function ( promiseArr ) {
return new Promise ( ( resolve, reject ) => {
const result = [ ] ;
let index = 0 ;
for ( let i = 0 ; i < promiseArr. length; i++ ) {
promiseArr[ i]
. then ( res => {
result[ i] = res;
index++ ;
if ( index === promiseArr. length) {
resolve ( result) ;
}
} )
. catch ( err => reject ( err) ) ;
}
} )
}
Promise.race
Promise. JLRace = function ( promiseArr ) {
return new Promise ( ( resolve, reject ) => {
promiseArr. forEach ( p => {
Promise. resolve ( p) . then (
res => resolve ( res) ,
err => reject ( err)
)
} )
} )
}
手写自定义类的迭代
class Person1 {
constructor ( name, age, height, friends ) {
this . name = name;
this . age = age;
this . height = height;
this . friends = friends;
}
[ Symbol. iterator] ( ) {
let index = 0 ;
const iterator = {
next : ( ) => {
if ( index < this . friends. length) {
return { done : false , value : this . friends[ index++ ] } ;
} else {
return { done : true } ;
}
}
}
return iterator;
}
}
const p1 = new Person1 ( 'JL' , 18 , 1.88 , [ "curry" , 'kobe' ] ) ;
for ( let item of p1) {
console. log ( item) ;
}
class Person2 {
constructor ( name, age, friends ) {
this . name = name;
this . age = age;
this . friends = friends;
}
* [ Symbol. iterator] ( ) {
yield * this . friends;
}
}
const p2 = new Person2 ( 'JL' , 18 , [ 'curry' , 'kobe' ] ) ;
for ( let item of p) {
console. log ( item) ;
}
插入排序
function insertSort ( arr ) {
for ( let i = 0 ; i < arr. length; i++ ) {
let j = i;
let target = arr[ j] ;
while ( j > 0 && arr[ j - 1 ] > target) {
arr[ j] = arr[ j - 1 ] ;
j-- ;
}
arr[ j] = target;
}
return arr;
}
冒泡排序
function bubblesort ( arr ) {
for ( let i = 0 ; i < arr. length; i++ ) {
for ( let j = 0 ; j < arr. length - 1 ; j++ ) {
if ( arr[ j] > arr[ j + 1 ] ) {
[ arr[ j] , arr[ j + 1 ] ] = [ arr[ j + 1 ] , arr[ j] ] ;
}
}
}
return arr;
}
选择排序
function selectSort ( arr ) {
let min;
for ( let i = 0 ; i < arr. length - 1 ; i++ ) {
min = i;
for ( let j = 0 ; j < arr. length; j++ ) {
if ( arr[ j] < arr[ min] ) {
min = j;
}
}
if ( min !== i) {
[ arr[ i] , arr[ min] ] = [ arr[ min] , arr[ i] ] ;
}
}
return arr;
}
快排
function quickSortRuan ( arr ) {
if ( arr. length === 1 ) return arr;
let pivotIndex = Math. floor ( arr. length / 2 ) ;
let pivot = arr. splice ( pivotIndex, 1 ) [ 0 ] ;
let left = [ ] ;
let right = [ ] ;
for ( let i = 0 ; i < arr. length; i++ ) {
if ( arr[ i] < pivot) {
left. push ( arr[ i] ) ;
} else {
right. push ( arr[ i] ) ;
}
}
return quickSortRuan ( left) . concat ( [ pivot] , quickSortRuan ( right) ) ;
}
function quickSort ( arr ) {
if ( arr. length <= 1 ) {
return arr;
}
let left = [ ] , right = [ ] , container = arr. splice ( 0 , 1 ) ;
for ( let i = 0 ; i < arr. length; i++ ) {
if ( arr[ i] < container) {
left. push ( arr[ i] ) ;
} else {
right. push ( arr[ i] ) ;
}
}
return quickSort ( left) . concat ( container, quickSort ( right) ) ;
}
console. log ( quickSort ( [ 8 , 2 , 5 , 1 , 4 , 9 , 3 , 7 , 6 ] ) ) ;
JSONP
const jsonp = ( { url, params, callbackName} ) => {
const getUrl = ( ) => {
let dataSrc = '' ;
for ( let key in params) {
if ( params. hasOwnProperty ( key) ) {
dataSrc += ` ${ key} = ${ params[ key] } & ` ;
}
}
dataSrc += ` callback= ${ callbackName} ` ;
return ` ${ url} ? ${ dataSrc} ` ;
}
return new Promise ( ( resolve, reject ) => {
const scriptEle = document. createElement ( 'script' ) ;
scriptEle. src = getUrl ( ) ;
document. body. appendChild ( scriptEle) ;
window[ callback] = data => {
resolve ( data) ;
document. removeChild ( scriptEle) ;
}
} )
}
继承
原型链继承
function Animal ( ) {
this . colors = [ 'black' , 'white' ] ;
}
Animal . prototype. getColor = function ( ) {
return this . colors;
}
function Dog ( ) { }
Dog . prototype = new Animal ( ) ;
let dog1 = new Dog ( ) ;
dog1. colors. push ( 'red' ) ;
console. log ( dog1) ;
let dog2 = new Dog ( ) ;
console. log ( dog2) ;
构造函数继承
function Animal ( name ) {
this . name = name;
this . getName = function ( ) {
return this . name;
}
}
function Dog ( name ) {
Animal . call ( this , name) ;
}
Dog . prototype = new Animal ( ) ;
组合继承
function Animal ( name ) {
this . name = name;
this . colors = [ 'black' , 'white' ] ;
}
Animal . prototype. getName = function ( ) {
return this . name;
}
function Dog ( name, age ) {
Animal . call ( this , name) ;
this . age = age;
}
Dog . prototype = new Animal ( ) ;
Dog . prototype. constructor = Dog;
class继承
class Animal {
constructor ( name ) {
this . name = name;
}
getName ( ) {
return this . name;
}
}
class Dog extends Animal {
constructor ( name, age ) {
super ( name) ;
this . age = age;
}
}
圣杯布局
<! DOCTYPE html >
< html lang = " en" >
< head>
< meta charset = " UTF-8" >
< meta http-equiv = " X-UA-Compatible" content = " IE=edge" >
< meta name = " viewport" content = " width=device-width, initial-scale=1.0" >
< title> 圣杯布局</ title>
< style>
* {
margin : 0;
padding : 0;
text-align : center;
}
.header,.footer {
height : 30px;
width : 100%;
background : red;
}
.center {
display : flex;
}
.left {
width : 200px;
background-color : pink;
}
.right {
width : 200px;
background-color : blue;
}
.middle {
flex : 1;
background-color : yellow;
}
</ style>
</ head>
< body>
< div class = " header" > 头部</ div>
< div class = " center" >
< div class = " left" > 左边</ div>
< div class = " middle" > 中间</ div>
< div class = " right" > 右边</ div>
</ div>
< div class = " footer" > 底部</ div>
</ body>
</ html>
双飞翼布局
<! DOCTYPE html >
< html lang = " en" >
< head>
< meta charset = " UTF-8" >
< meta http-equiv = " X-UA-Compatible" content = " IE=edge" >
< meta name = " viewport" content = " width=device-width, initial-scale=1.0" >
< title> 双飞翼布局</ title>
< style>
* {
margin : 0;
padding : 0;
}
.container {
min-width : 600px;
}
.left {
float : left;
width : 200px;
height : 400px;
background : red;
margin-left : -100%;
}
.center {
float : left;
width : 100%;
height : 500px;
background : yellow;
}
.center .inner {
margin : 0 200px;
}
.right {
float : left;
width : 200px;
height : 400px;
background : blue;
margin-left : -200px;
}
</ style>
</ head>
< body>
< div class = " container" >
< div class = " center" >
< div class = " inner" > 双飞翼布局</ div>
</ div>
< div class = " left" > </ div>
< div class = " right" > </ div>
</ div>
</ body>
</ html>
水平垂直居中
< head>
< meta charset = " UTF-8" >
< meta http-equiv = " X-UA-Compatible" content = " IE=edge" >
< meta name = " viewport" content = " width=device-width, initial-scale=1.0" >
< title> 居中1</ title>
< style>
.parent {
width : 200px;
height : 200px;
border : 1px solid red;
position : relative;
}
.children {
position : absolute;
width : 100px;
height : 100px;
background-color : yellow;
top : 50%;
left : 50%;
margin-top : -50px;
margin-left : -50px;
}
</ style>
</ head>
< body>
< div class = " parent" >
< div class = " children" > </ div>
</ div>
</ body>
< head>
< meta charset = " UTF-8" >
< meta http-equiv = " X-UA-Compatible" content = " IE=edge" >
< meta name = " viewport" content = " width=device-width, initial-scale=1.0" >
< title> 居中2</ title>
< style>
.parent {
width : 200px;
height : 200px;
border : 1px solid red;
position : relative;
}
.children {
position : absolute;
top : 0;
left : 0;
right : 0;
bottom : 0;
width : 100px;
height : 100px;
background-color : yellow;
margin : auto;
}
</ style>
</ head>
< body>
< div class = " parent" >
< div class = " children" > </ div>
</ div>
</ body>
< head>
< meta charset = " UTF-8" >
< meta http-equiv = " X-UA-Compatible" content = " IE=edge" >
< meta name = " viewport" content = " width=device-width, initial-scale=1.0" >
< title> 居中3</ title>
< style>
.parent {
width : 200px;
height : 200px;
border : 1px solid red;
position : relative;
}
.children {
position : absolute;
width : 100px;
height : 100px;
background-color : yellow;
left : 50%;
top : 50%;
transform : translate ( -50%, -50%) ;
}
</ style>
</ head>
< body>
< div class = " parent" >
< div class = " children" > </ div>
</ div>
</ body>