自用记录,不保证都对
手写applyMiddlewares
- 题目要求
function rawMethod(a){
return a+1
}
function middleware1(next){
return function(a){
console.log('middleware1======')
return next(a)+1
}
}
function middleware2(next){
return function(a){
console.log('middleware2======')
return next(a)+1
}
}
function middleware3(next){
return function(a){
console.log('middleware3======')
return next(a)+1
}
}
var newMethod = applyMiddleWare(rawMethod,middleware3,middleware2)
var x = newMethod(1) // 要求输出 middleware2=>middleware3=>rawMethod
console.log(x) // 3
var newMethod = applyMiddleWare(newMethod,middleware1)
var y = newMethod(10) // 要求输出 middleware1=>middleware2=>middleware3=>rawMethod
console.log(y)// 13
- 代码实现
function applyMiddleWare(){
const _fn = arguments[0]
const _middles = Array.prototype.slice.call(arguments,1)
let _temp = _fn
for(let i = 0; i<_middles.length;i++ ){
_temp = _middles[i](_temp)
}
function _outputFn1(n){
return _temp(n)-1
}
_outputFn1.__apply = true
function _outputFn2(n){
return _temp(n)
}
_outputFn2.__apply = true
if(_fn.__apply){
return _outputFn2
}else {
return _outputFn1
}
}
手写call
Function.prototype.myCall = function(ctx,...args){
var context = ctx==null?globalThis: Object(ctx)
var key = Symbol('temp')
Object.defineProperty(context,key,{
enumerable: false,
value: this
})
var result = context[key](...args)
delete context[key]
return result
}
手写bind
Function.prototype.mybind = function(ctx){
let args = Array.prototype.slice.call(arguments,1)
let fn = this
return function A(){
let restArgs = Array.prototype.slice.call(arguments)
let allArgs = args.concat(restArgs)
if(Object.getPrototypeOf(this)===A.prototype){
return new fn(...allArgs)
}else{
fn.apply(ctx,allArgs)
}
}
}
new 做了什么
function create(fn,...args){
var obj = {}
Object.setPrototypeOf(obj,fn.prototype)
var result = fn.apply(obj,args)
return result instanceof Object?result: obj
}
深度优先遍历(dfs)
- 题目
const data = {
name: 'A',
children: [
{
name: 'B',
children: [
{
name: 'D'
},
{
name: 'E'
}
]
},
{
name: 'C',
children: [
{
name: 'F'
},
{
name: 'G'
}
]
}
]
}
- 代码实现
function DFS(data){
if(!data){
return
}
console.log(data?.name)
if(data.children && data.children.length>0){
data.children.forEach(item=>{
DFS(item)
})
}
}
// 查找子节点
console.log(findItem(data, 'G'))
function findItem(root, target){
if(!root){
return
}
if(root.name === target){
return root
}
if(root.children&& root.children.length>0){
for(let i = 0; i< root.children.length; i++){
const res = findItem(root.children[i],target)
if(res){
return res
}
}
}
}
广度优先遍历 (bfs)
function BFS(data){
const stack = [data]
while(stack.length){
const node = stack.shift()
console.log(node.name)
if(node.children && Array.isArray(node.children)){
node.children.forEach(item=>{
stack.push(item)
})
}
}
}
vue2的响应式方法
- 对象
const person = {
name: 'lily',
age: 18,
hobbits: ['dance','sing'],
}
function reactive(obj){
for(let key in obj) {
Object.defineProperty(obj,key,{
get: function(){
console.log('get====',key)
},
set: function(value){
console.log('set======',key,value)
}
})
}
}
reactive(person)
console.log(person.age)
console.log(person.age=5,person.age)
- 数组
const newArrProto = Object.create(Array)
['push','pop','slice','splice','sort','shift','unshift'].forEach(element => {
// newArrProto.prototype[element] = function(){
// console.log('element=========', element)
// Array.prototype[element].call(this,arguments)
// }
})
const a = []
a.push('kkk')
console.log(a)
vue3的响应式方法
function reactive(obj){
if(typeof obj !=='object'){
return
}
return new Proxy(obj,{
get(target,key,receiver){
console.log('get====',target,key)
return Reflect.get(...arguments)
},
set(target,key,value,receiver){
console.log('set===',target,key,value)
return Reflect.set(...arguments)
},
deleteProperty(target,key){
console.log('deleteProperty=======',target,key)
return Reflect.deleteProperty(...arguments)
}
})
}
let arr = ['1','2','3','4','5']
const arrProxy = reactive(arr)
console.log('arrProxy=======',arrProxy)
arrProxy.push('6')
arrProxy.pop()
arrProxy[6] = '9999'
柯里化函数
- 题目
function add(a, b, c) {
return a + b + c
}
const sum = curring(add,1);
console.log(sum(2,3));
console.log(sum(2)(3));
- 代码
function curring(fn){
let args = Array.prototype.slice.call(arguments,1)
return function(){
let restArgs = Array.prototype.slice.call(arguments)
let allArgs = args.concat(restArgs)
if(fn.length<=allArgs.length){
return fn.apply(this, allArgs)
}else {
return curring(fn, ...allArgs)
}
}
}
compose函数
function add1(str) {
return 1 + str;
}
function add2(str) {
return 2 + str;
}
function sum(a, b) {
return a + b;
}
// add1(add2(sum(a,b)))
function compose(...funcs){
if(funcs.length === 0){
return args=>args
}
if(funcs.length === 1){
return funcs[0]
}
return funcs.reduce((a,b)=>{
return (...args)=>a(b(...args))
})
}
instanceOf
function instanceofFn(left,right){
if(typeof A !== 'object' || A === null || typeof B !=='function'){
return false
}
while(true){
if(left === null){
return false
}
if(left.__proto__ === right.prototype){
return true
}
left = left.__proto__
}
}
lazyman
- 题目
// 实现一个 LazyMan 方法
// LazyMan("Hank")
// 输出:
// Hi! This is Hank!
// LazyMan("Hank").sleep(10).eat("dinner")
// 输出
// Hi! This is Hank!
// //等待10秒..
// Wake up after 10
// Eat dinner
// LazyMan("Hank").eat("dinner").eat("supper")
// 输出
// Hi! This is Hank!
// Eat dinner
// Eat supper
// LazyMan(“Hank”).sleepFirst(5).eat(“supper”)输出
// //等待5秒
// Wake up after 5
// Hi! This is Hank!
// Eat supper
- 代码
class lazyMan {
constructor(name){
this.name = name
this.promiseQueue=[]
this.callName()
this.walk()
}
callName = function(){
let fn = ()=>{
console.log('Hi! This is' + this.name)
return Promise.resolve();
}
this.promiseQueue.push(fn)
return this
}
walk = function(){
let promiseResolve = Promise.resolve()
setTimeout(()=>{
this.promiseQueue.forEach((item)=>{
promiseResolve = promiseResolve.then(item)
})
},0)
}
sleep = (time)=>{
let fn = ()=>{
return new Promise((resolve)=>{
setTimeout(()=>{
console.log('Wake up after '+ time)
resolve()
},time*1000)
})
}
this.promiseQueue.push(fn)
return this
}
eat = (value)=>{
var fn = function(){
console.log("Eat " + value)
return Promise.resolve()
}
this.promiseQueue.push(fn)
return this
}
sleepFirst = (time)=>{
var fn = function(){
return new Promise(function(resolve){
setTimeout(function(){
console.log('Wake up after'+ time)
resolve()
}, time * 1000)
})
}
this.promiseQueue.unshift(fn)
return this
}
}
function LazyMan(name){
return new lazyMan(name)
}
LazyMan("Hank").sleep(5).eat('supper')
// LazyMan("Hank").sleepFirst(5).eat('supper')
深拷贝
- 拷贝目标
/*
实现深拷贝
1。 判断循环引用
2. 判断正则对象
3. 判断日期对象
4. 属性对象直接进行递归拷贝
5. 考虑拷贝时不能丢失原本对象的原型继承关系
6. 考虑拷贝时的属性修饰符
*/
- 代码实现
function deepCopy(value) {
var weakMap = new WeakMap()
function _deepCopy(value){
// 如果value是普通类型 直接返回
if( value instanceof Date) {
return new Date(value.valueOf())
}
if( value instanceof RegExp) {
return new RegExp(value.valueOf())
}
if (typeof value !== 'object' || value === null) {
return value
}
if(weakMap.has(value)){
return weakMap.get(value)
}
// // 考虑对象的原型 获得原本对象的原型 创建一个新的对象继承这个对象的原型
const prototype = Object.getPrototypeOf(value)
// 考虑拷贝时不能 丢失对原有对象的属性描述符
const description = Object.getOwnPropertyDescriptors(value)
// 创建新的空对象 同时继承原有对象原型 同时拥有对应的描述符
let result = Object.create(prototype, description)
// 遍历对象的属性 进行拷贝 Reflect.ownKeys 遍历获取自身的不可枚举以及key为Symbol的属性
result = Array.isArray(value) ? []: {}
weakMap.set(value, result)
for(var key in value) {
if(value.hasOwnProperty(key)) {
result[key] = _deepCopy(value[key])
}
}
return result
}
return _deepCopy(value)
}
// const newObj = deepCopy(obj1)
// console.log(newObj)
// console.log(newObj !== obj1)
// console.log(newObj.loop !== obj1.loop)
// console.log(newObj.customArr[3] !== obj1)
// console.log(newObj.customArr[3] === newObj)
promise拦截器
- 完全串形执行,按顺序输出
- 并行执行,按顺序输出
let i = 0
const createPromise = (num) => new Promise((resolve, reject) => setTimeout(function(){
resolve(i++)
}, num*1000))
// 完全串形执行,按顺序输出
function runOneByOne(promises) {
if(!Array.isArray(promises) || promises.length === 0){
return Promise.resolve([])
}
return new Promise((resolve,reject)=>{
let arr = []
const runTask = function(){
console.log('promises===', promises)
if(promises.length === 0 ) {
return resolve(arr)
}
const task = promises.shift()
task().then((res)=>{
console.log('res===', res)
arr.push(res)
runTask()
}).catch(err=>{
runTask()
})
}
runTask()
})
}
// 并行执行,串形按顺序输出
function runOneByOne2(promises) {
if(!Array.isArray(promises) || promises.length === 0){
return Promise.resolve([])
}
return new Promise((resolve,reject)=>{
let i = 0
let result = []
function handleResult(index,res){
if(index === i){
i++
while(result[i] !=null){
i++
}
}else{
result[index] = res
}
if(i ===promises.length ){
console.log('i', i)
resolve()
}
}
for(let i = 0; i<promises.length; i++){
promises[i](4-i).then((res)=>{
handleResult(i,res)
}).catch(err=>{
console.log('err')
})
}
})
}
const promises = [createPromise, createPromise, createPromise, createPromise]
console.time('run')
runOneByOne2(promises)
.then(res => {
console.timeEnd('run')
console.log('全部执行结束', res)
})
对象转a.b.c.dd格式
// 输入
const entry={
a: {
b: {
c: {
dd: "abcdd"
}
},
d: {
x: "adxx"
}
}
}
const output = {
"a.b.c.dd": "abcdd",
"a.d.xx": "adxx",
};
// 输出
function transferObj(obj){
let result = {}
const parse = (data,parentKey)=>{
if(typeof data === 'string'){
result[parentKey] = data
}
if(typeof data === 'object'){
for(let key in data){
parse(data[key],(parentKey?parentKey+'.':parentKey)+key)
}
}
}
parse(obj,'')
return result
}
console.log(transferObj(entry))
a.b.c.dd格式转对象
// 输入
const input = {
"a.b.c.dd": "abcdd",
"a.d.xx": "adxx",
};
// 输出
const output={
a: {
b: {
c: {
dd: "abcdd"
}
},
d: {
x: "adxx"
}
}
}
function transferObj(obj){
if(typeof obj !== 'object'){
return
}
let result = {}
for(let key in obj){
let keyArr = key.split('.')
let temp = result
for(let i = 0; i< keyArr.length; i++){
if(i === keyArr.length - 1){
temp[keyArr[i]] = obj[key]
}else{
temp[keyArr[i]] = temp[keyArr[i]] || {}
temp = temp[keyArr[i]]
}
}
}
return result
}
环形杀人
环形100个人,0-99每隔3个人杀一个人,从第0开始(比如下标为0和为4的人会被杀掉)问最终剩下哪3个人。对应人的位置或者写出代码均可。
function loopKill(){
let arr = []
for(let i = 0; i< 100; i++){
arr[i] = i
}
const deepKill = (arr,index)=>{
while(index<arr.length && arr.length>3){
let num = arr.splice(index,1)
index+=3
}
if(arr.length>3){
deepKill(arr,index-arr.length)
}else if(arr.length===3){
return arr
}
}
deepKill(arr,0)
}
loopKill()
proxy代理输出路径
- 题目
// 题目:实现一个 proxyObj 方法,输出符合预期
const a = {
b: 1,
c: {
d: 2,
}
};
function proxyObj(obj) {
// code here
}
const proxyA = proxyObj(a);
console.log(proxyA.b);
// 输出 ‘b’
console.log(proxyA.c.d);
// 输出 ’c.d‘
- 代码实现
function proxyObj(obj,parentkey) {
return new Proxy(obj,{
get(target,prop){
let currentKey = parentkey?`${parentkey}.${prop}`:prop
if(typeof target[prop] === 'object'){
return proxyObj(target[prop],currentKey)
}else{
return currentKey
}
}
})
}
proxy 链式调用
- 题目
function increase(a){
return a + 1
}
function decrease(a){
return a - 1
}
function double(a){
return 2 * a
}
console.log(chain(3).increase.double.end) // 输出8
console.log(chain(2).decrease.double.end) // 输出2
- 代码实现
// 写法一
function chain(value){
const proxy = new Proxy({value},{
get(obj, prop){
if(typeof window[prop] === 'function'){
obj.value = window[prop](obj.value)
return proxy
}else if(prop === 'end'){
return obj.value
}
}
})
return proxy
}
// 写法二
const chain = (function(){
return function(value){
let fnArr = []
const proxy = new Proxy({value},{
get(obj, prop){
if(prop === 'end'){
console.log(fnArr)
return fnArr.reduce((prev,curr)=>{
return curr(prev)
},value)
}
fnArr.push(window[prop])
return proxy
}
})
return proxy
}
})()
打印二维数组成三角形格式
- 题目
二位数组,对角线依次打印所有元素。
[
[1,2,3,4],
[2,3,4,5],
[3,4,5,6],
[4,5,6,7]
]
输出,从左上角开始,到右下角
1
2 2
3 3 3
4 4 4 4
5 5 5
6 6
7
- 代码实现
let arr = [[1,2,3,4],[2,3,4,5],[3,4,5,6],[4,5,6,7]]
function log(arr){
if(!Array.isArray(arr) || arr.length ===0){
return ''
}
let str = ''
let ln = arr.length-1
let max = ln*2+1
let count = 0
while(count<max){
let row = count> ln ? ln : count
let col = count> ln ? count - ln : 0
while(row>=0&&col<=ln){
str+=arr[row][col]
row--
col++
}
str+='\n'
count++
}
return str
}
console.log(log(arr))
手动实现Array.prototype.map方法
Array.prototype.myMap = function(fn){
if(typeof fn !== 'function'){
throw new Error('first params must be a function')
}
if(!Array.isArray(this)){
throw new Error('array error')
}
let arr = this
let result = []
for(let i = 0; i< arr.length; i++){
let value = fn(arr[i],i,arr)
result.push(value)
}
return result
}
手动实现Array.prototype.filter方法
if(typeof fn !== 'function'){
throw new Error('first params must be a function')
}
if(!Array.isArray(this)){
throw new Error('array error')
}
let arr = this
let result = []
for(let i = 0; i< arr.length; i++){
let value = fn(arr[i],i,arr)
if(value){
result.push(arr[i])
}
}
return result
手动实现Array.prototype.reduce方法
Array.prototype.myReduce = function(fn,initial){
if(typeof fn !== 'function'){
throw new Error('first params must be a function')
}
if(!Array.isArray(this)){
throw new Error('array error')
}
let arr = this
let prev = initial !== undefined ? initial : arr[0]
let min = initial !== undefined ? 0 : 1
for(let i = min; i< arr.length; i++){
prev = fn(prev,arr[i],i,arr)
}
return prev
}