1、冒泡排序
function bubbleSortFn ( arr ) {
for ( let i = arr. length - 1 ; i >= 1 ; i-- ) {
for ( let j = 0 ; j < i; j++ ) {
if ( arr[ j] > arr[ j + 1 ] ) {
let temp = arr[ j] ;
arr[ j] = arr[ j + 1 ] ;
arr[ j + 1 ] = temp;
}
}
}
return arr;
}
console. log ( 'bubbleSortFn:' , bubbleSortFn ( [ 12 , 33 , 1 , 3 , 49 , - 1 , 88 ] ) )
2、选择排序
function selectSortFn ( arr ) {
for ( let i = 0 ; i < arr. length; i++ ) {
let min = i;
for ( let j = i + 1 ; j < arr. length; j++ ) {
if ( arr[ j] < arr[ min] ) {
min = j;
}
} ;
let temp = arr[ i] ;
arr[ i] = arr[ min] ;
arr[ min] = temp;
}
return arr;
}
console. log ( 'selectSortFn:' , selectSortFn ( [ 12 , 33 , 1 , 3 , 2 , 49 , - 1 , 88 ] ) )
3、插入排序
function insertSortFn ( arr ) {
for ( let i = 1 ; i < arr. length; i++ ) {
let temp = arr[ i] ;
let j = i;
while ( arr[ j - 1 ] > temp && j > 0 ) {
arr[ j] = arr[ j - 1 ] ;
j-- ;
}
arr[ j] = temp;
}
return arr;
}
console. log ( 'insertSortFn:' , insertSortFn ( [ 12 , 33 , 1 , 3 , 2 , 49 , - 1 , 88 ] ) )
4、二分法查找
function twoFindFn ( arr, target ) {
arr. sort ( ( a, b ) => a - b) ;
let left = 0 ;
let right = arr. length - 1 ;
while ( left <= right) {
let middle = Math. floor ( ( left + right) / 2 ) ;
if ( target < arr[ middle] ) {
right = middle - 1 ;
} else if ( target > arr[ middle] ) {
left = middle + 1 ;
} else {
return middle;
}
}
return - 1 ;
}
console. log ( 'twoFindFn:' , twoFindFn ( [ 12 , 33 , 1 , 3 , 2 , 49 , - 1 , 88 ] , 1 ) )
5、实现一个计数器
function sendCountFn ( n ) {
return function ( ) {
return n++ ;
}
}
let afterCountFn = sendCountFn ( 3 ) ;
console. log ( afterCountFn ( ) )
console. log ( afterCountFn ( ) )
6、获取 URL 参数
function getSearchParams ( ) {
let paramsObj = { } ;
let search = new URLSearchParams ( location. search) ;
for ( let [ key, value] of search. entries ( ) ) {
paramsObj[ key] = value;
} ;
return paramsObj;
}
function getSearchParams2 ( ) {
let resObj = { } ;
let searchStr = location. search. substring ( 1 ) ;
let searchStrArr = searchStr. split ( '&' ) ;
searchStrArr. forEach ( item => {
const [ key, value] = item. split ( '=' ) ;
resObj[ key] = value;
} ) ;
return resObj;
}
7、手写 new 的执行过程
function myNew ( Constructor, ... args ) {
let obj = { } ;
obj. __proto__ = Constructor . prototype;
obj . apply ( Constructor, args) ;
return obj;
}
8、手写实现 Object.create()
function myCreate ( prototype ) {
if ( Object . prototype. toString . call ( prototype) != '[object Object]' ) {
throw 'prototype is not a Object' ;
}
function F ( ) { } ;
F . prototype = prototype;
return new F ( ) ;
}
9、instanceof实现
function myInstanceof ( instance, constructor ) {
while ( instance) {
if ( instance. __proto__ == constructor. prototype) return true ;
instance = instance. __proto__;
}
return false ;
}
console. log ( 'myInstanceof:' , myInstanceof ( 'wsw' , Array) )
10、实现红黄绿循环打印
const task = ( color, time ) => {
return new Promise ( ( resolve, reject ) => {
setTimeout ( ( ) => {
resolve ( ) ;
console. log ( color)
} , time) ;
} )
}
async function taskRunner ( ) {
await task ( 'red' , 1000 ) ;
await task ( 'green' , 2000 ) ;
await task ( 'yellow' , 3000 ) ;
taskRunner ( ) ;
}
11、用 promise 如何实现异步加载图片
function importImageFn ( src ) {
return new Promise ( ( resolve, reject ) => {
let imgObj = new Image ( ) ;
imgObj. src = src;
imgObj. onload = function ( ) {
resolve ( ) ;
} ;
imgObj. onerror = function ( ) {
reject ( ) ;
}
} )
}
13、实现数组的 push、filter、map 方法
Array . prototype. mypush = function ( ... args) {
let arr = this ;
let length = arr. length;
for ( let i = 0 ; i < args. length; i++ ) {
arr[ length + i] = args[ i] ;
}
return arr;
}
let myarr = [ ] ;
myarr. mypush ( '1' , '2' , '3' ) ;
console. log ( 'myPush:' , myarr) ;
Array . prototype. myfilter = function ( callback ) {
let arr = this ;
let length = this . length;
let newArr = [ ] ;
for ( let i = 0 ; i < length; i++ ) {
if ( callback && callback ( arr[ i] , i , arr) ) {
newArr. push ( arr[ i] )
}
}
return newArr;
}
console. log ( 'myfilter:' , [ 1 , 2 , 3 , 4 ] . myfilter ( item => item >= 3 ) ) ;
Array . prototype. mymap = function ( callback ) {
let arr = this ;
let length = this . length;
let newArr = [ ] ;
for ( let i = 0 ; i < length; i++ ) {
newArr. push ( callback ( arr[ i] , i , arr) ) ;
}
return newArr;
}
console. log ( 'mymap:' , [ 1 , 2 , 3 , 4 ] . mymap ( item => item + 3 ) ) ;
14、使用 setTimeout 实现 setInterval
function mysetInterval ( callback, time ) {
let timer = null ;
let isStop = false ;
const repeat = ( ) => {
if ( isStop) return ;
callback ( ) ;
timer = setTimeout ( repeat, time)
}
repeat ( ) ;
return {
stop : function ( ) {
clearTimeout ( timer) ;
timer = null ;
isStop = true ;
}
}
}
let count = 0 ;
let stopRes;
stopRes = mysetInterval ( ( ) => {
count++ ;
console. log ( 'mysetInterval....' , count)
if ( count === 5 ) {
stopRes. stop ( ) ;
}
} , 3000 ) ;
15、手写 bind
Function . prototype. mybind = function ( obj, ... args ) {
let self = this ;
return function ( ... arguments) {
self . apply ( obj, [ ... args, ... arguments] ) ;
}
}
16、实现 jsonp
function myJsonp ( api, callbackName, success, fail ) {
let scriptEle = document. createElement ( 'script' ) ;
scriptEle. src = ` ${ api} ?callbackName= ${ callbackName} ` ;
document. body. appendChild ( scriptEle) ;
window[ callbackName] = function ( response ) {
success && success ( response) ;
document. body. removeChild ( scriptEle) ;
}
}
17、手写一个深度比较 isEqual
function isEqual ( obj1, obj2 ) {
if ( typeof obj1 != 'object' || typeof obj2 != 'object' ) {
return obj1 === obj2;
} ;
if ( obj1 === obj2) return true ;
let keys1 = Object. keys ( obj1) ;
let keys2 = Object. keys ( obj2) ;
if ( keys1. length !== keys2. length) return false ;
for ( const iterator of keys1) {
let res = isEqual ( obj1[ iterator] , obj2[ iterator] ) ;
if ( ! res) return false ;
} ;
return true ;
}
console. log ( 'isEqual:' , isEqual ( { name : { age : 10 } } , { name : { age : 10 } } ) )
18、手写深拷贝
function deepClone ( obj ) {
if ( typeof obj != 'object' || obj == null ) return ;
let target = Array. isArray ( obj) ? [ ] : { } ;
for ( key in obj) {
if ( Object. hasOwnProperty . call ( obj, key) ) {
if ( typeof obj[ key] == 'object' ) {
deepClone ( obj[ key] )
} else {
target[ key] = obj[ key] ;
}
}
}
return target;
} ;
19、手写数组去除重复
function removeRep ( arr ) {
return [ ... new Set ( arr) ] ;
}
function removeRep2 ( arr ) {
let resArr = [ ] ;
arr. forEach ( item => {
if ( ! resArr. includes ( item) ) {
resArr. push ( item) ;
}
} ) ;
return resArr;
}
20、大数相加
function bigNumAdd ( num1, num2 ) {
let sum = '' ;
let addNum = '' ;
let f = 0 ;
let maxLen = Math. max ( num1. length, num2. length) ;
num1 = num1. padStart ( maxLen, '0' ) ;
num2 = num2. padStart ( maxLen, '0' ) ;
for ( let i = maxLen - 1 ; i >= 0 ; i-- ) {
addNum = parseInt ( num1[ i] ) + parseInt ( num2[ i] ) + f;
f = Math. floor ( addNum / 10 ) ;
sum = addNum % 10 + sum;
} ;
if ( f == 1 ) {
sum = '1' + sum;
}
return sum;
}
21、节流函数
function throttle ( fn, delay ) {
let content = this ;
let timer = null ;
let isFirst = true ;
return ( ... arguments) => {
if ( isFirst) {
fn . apply ( content, arguments) ;
isFirst = false ;
return ;
}
if ( timer) return ;
timer = setTimeout ( ( ) => {
fn . apply ( content, arguments) ;
timer = null ;
} , delay) ;
}
}
22、防抖函数
function debund ( fn, delay ) {
const content = this ;
let timer = null ;
let isFirst = true ;
return ( ... args) => {
if ( isFirst) {
fn . apply ( content, args) ;
isFirst = false ;
return ;
}
if ( timer) clearTimeout ( timer) ;
timer = setTimeout ( ( ) => {
fn . apply ( content, args) ;
timer = null ;
} , delay) ;
}
}
23、设计一个图片懒加载 SDK
const throttle = ( fn, delay ) => {
let timer = null
return function ( ... args) {
if ( ! timer) {
setTimeout ( ( ) => {
fn . apply ( this , args)
timer = null
} , delay)
}
}
}
const lazyLoadImages = ( ) => {
const images = document. querySelectorAll ( 'img[data-src]' )
images. forEach ( ( img ) => {
const rect = img. getBoundingClientRect ( )
if ( rect. top < window. innerHeight) {
img. src = img. dataSet. src
img. removeAttribute ( 'data-src' )
}
} )
}
const throttledLazyLoad = throttle ( lazyLoadImages, 100 )
window. addEventListener ( 'scroll' , throttledLazyLoad)
24、用正则实现trim() 清除字符串两端空格
String . prototype. mytrim = function ( ) {
let str = this ;
return str. replace ( / (^\s)|(\s$) / g , '' ) ;
}
console. log ( ' xsxsxsxs ' . mytrim ( ) )
25、简单写一个webpack配置文件
module. exports = {
mode : 'development' ,
entry : './src/index.js' ,
output : {
filename : 'build.js' ,
path : resolve ( '../dist/' )
} ,
modules : {
rules : [
{
test : / \.css$ / ,
use : [ 'style-loader' , 'css-loader' ]
} ,
{
test : / \.html$ / ,
use : [ 'html-loader' ]
}
]
} ,
plugins : [
new HtmlWebpackPlugin ( {
template : './index.html'
} ) ,
] ,
devServer : {
port : 3000 ,
...
}
}
26、react自定义 Hook useCountdown
/**
* 请通过 React Hooks API 实现一个具有倒计时功能的自定义 Hook useCountdown,
* 要求可以使组件每秒自动更新倒计时。
* 当超过倒计时截止时间 targetDate 时,变成正计时(返回的 expired 为 false)
*
* @param {Date} targetDate 倒计时截止时间
*/
// function useCountdown(targetDate) {
// // 你的代码实现...
// // 返回的数据结构示例
// return {
// expired: false, // 是否已超期
// days: 0, // 剩余或已超过天数(整数),无上限
// hours: 0, // 剩余或已超过小时(整数),0~23
// minutes: 0, // 剩余或已超过分钟数(整数),0~59
// seconds: 0, // 剩余或已超过秒数(整数),0~59
// };
// }
function useCountdown ( targetDate ) {
const [ countdown, setCountdown] = useState ( {
expired : false ,
days : 0 ,
hours : 0 ,
minutes : 0 ,
seconds : 0 ,
} ) ;
useEffect ( ( ) => {
const intervalId = setInterval ( ( ) => {
const now = new Date ( ) ;
const distance = targetDate - now;
if ( distance <= 0 ) {
const expiredDistance = now - targetDate;
const expiredDays = Math. ceil ( expiredDistance / ( 1000 * 60 * 60 * 24 ) ) ;
const expiredHours = Math. ceil ( ( expiredDistance % ( 1000 * 60 * 60 * 24 ) ) / ( 1000 * 60 * 60 ) ) ;
const expiredMinutes = Math. ceil ( ( expiredDistance % ( 1000 * 60 * 60 ) ) / ( 1000 * 60 ) ) ;
const expiredSeconds = Math. ceil ( ( expiredDistance % ( 1000 * 60 ) ) / 1000 ) ;
setCountdown ( {
expired : true ,
days : expiredDays,
hours : expiredHours,
minutes : expiredMinutes,
seconds : expiredSeconds,
} ) ;
} else {
const days = Math. ceil ( distance / ( 1000 * 60 * 60 * 24 ) ) ;
const hours = Math. ceil ( ( distance % ( 1000 * 60 * 60 * 24 ) ) / ( 1000 * 60 * 60 ) ) ;
const minutes = Math. ceil ( ( distance % ( 1000 * 60 * 60 ) ) / ( 1000 * 60 ) ) ;
const seconds = Math. ceil ( ( distance % ( 1000 * 60 ) ) / 1000 ) ;
setCountdown ( {
expired : false ,
days,
hours,
minutes,
seconds,
} ) ;
}
} , 1000 ) ;
} , [ targetDate] ) ;
return countdown;
}
27、实现一下call和apply方法
Function . prototype. myCall = function ( context, ... args ) {
if ( typeof this !== 'function' ) {
throw Error ( 'this is not Fcnction' ) ;
} ;
let contentObj = context || window;
context. fn = this ;
let result = context. fn ( ... args) ;
delete context. fn;
return result;
} ;
Function . prototype. myApply = function ( content, ... agrs ) {
if ( typeof this != 'function' ) {
throw Error ( 'this is not function' ) ;
} ;
let execObj = content || window;
execObj. fn = this ;
let result = execObj. fn ( agrs) ;
delete execObj. fn;
return result;
}
28、 写一个前端图片压缩的工具方法
function compressImg ( url, qulidy = 0.7 , name = '' ) {
let imgType = url. split ( '.' ) . pop ( ) || 'jpeg' ;
let imgObj = new Image ( ) ;
imgObj. src = url;
imgObj. onload = function ( ) {
console. dir ( imgObj) ;
let canvasEle = document. createElement ( 'canvas' ) ;
canvasEle. width = imgObj. width;
canvasEle. height = imgObj. height;
let canvasCont = canvasEle. getContext ( '2d' ) ;
canvasCont. drawImage ( imgObj, 0 , 0 , imgObj. width, imgObj. height) ;
let canvasDataUrl = canvasEle. toDataURL ( ` image/ ${ imgType} ` , qulidy) ;
console. log ( canvasDataUrl)
let aEle = document. createElement ( 'a' ) ;
aEle. href = canvasDataUrl;
aEle. download = ( name || 'test' ) + '.' + imgType ;
document. body. appendChild ( aEle) ;
aEle. click ( ) ;
document. body. remove ( aEle) ;
}
}
compressImg ( 'http://127.0.0.1:8080/123.jpeg' , 0.1 , 'testimg12' )