★★★ 手写代码:实现forEach map filter reduce

★★★ 手写实现一个简易的 Vue Reactive

★★★ 手写代码,监测数组变化,并返回数组长度

★★★ 手写原生继承,并说出局限性?

★★★★ 手写一个柯里化函数

★★★ 手写一个反柯里化函数

★★★★ 手写一个Promise

★★★ 手写一个instanceOf

★★★ 手写ajax

★★★ 手写JSONP的原理和实现

★★★★ 手写深拷贝

★★★ 手写浅拷贝

★★★★ 手写 bind

★★★★ 手写 call

★★★★ 手写 apply

★★★ 手写模拟 object.create

★★★ 手写模拟 Object.is

★★★ 手写 new

★★★ 手写对象扁平化

★★★ 手写数组扁平化

★★★ 手写数组去重

★★★ 手写模拟实现 async/await

★★★★ 手写实现发布/订阅模式

★★★★ 手写防抖

★★★★ 手写节流

手写代码面试真题

★★★ 手写代码:实现forEach map filter reduce

 // 1. ------_forEach--------// Array.prototype.forEach() 方法对数组的每个元素执行一次给定的函数。//  arr.forEach(callback(currentValue [, index [, array]])[, thisArg])Array.prototype._forEach = function (fn, thisArg) {if (typeof fn !== 'function') throw '参数必须为函数'if (!Array.isArray(this)) throw '只能对数组使用此方法'let arr = thisfor (let i = 0; i < arr.length; i++) {fn.call(thisArg, arr[i], i, arr)  //用call来改变fn里面this的指向}}//test// window.value = 0// let obj = { value: 1 }// let arr = ["_", "for", "each"]// arr._forEach(//   function (ele, index, arr) {//     console.log("ele, index, arr", ele, index, arr);//     console.log("this.vaule", this.value);//   }, obj)// 2. ------_map--------// Array.prototype.map() 方法创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值。//  arr.map(callback(currentValue [, index [, array]])[, thisArg])Array.prototype._map = function (fn, thisArg) {if (typeof fn !== 'function') throw "参数必须是回调函数"if (!Array.isArray(this)) throw "只能为数组使用此方法"const arr = this      //将调用者(实例化的arr)赋值给arrconst newArr = []for (let i = 0, len = arr.length; i < len; i++) {newArr.push(fn.call(thisArg, arr[i], i, arr))//将每次调用的回调函数fn的返回值push到新数组中}return newArr  //返回新数组}//test// window.value = 0// let obj = { value: 1 }// let arr = ["_", "for", "each"]// const newArr = arr._map(//   function (ele, index) {//     return ele + "你好" + index//   }, obj)// console.log(newArr);// 3. ------_filter--------// Array.prototype.map() 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。 //  arr.filter(callback(currentValue [, index [, array]])[, thisArg])Array.prototype._filter = function (fn, thisArg) {if (typeof fn !== 'function') throw "参数必须是回调函数"if (!Array.isArray(this)) throw "只能为数组使用此方法"const arr = this      //将调用者(实例化的arr)赋值给arrconst newArr = []for (let i = 0, len = arr.length; i < len; i++) {if (fn.call(thisArg, arr[i], i, arr)) { //判断回调的返回值是否为truenewArr.push(arr[i])}}return newArr  //返回新数组}//test// window.value = 0// let obj = { value: 1 }// let arr = ["_", "for", "each"]// const newArr = arr._filter(//   function (ele, index) {//     return ele == "for"//   }, obj)// console.log(newArr);//???????传入的数组这个参数的作用是???????// 4. ------_reduce--------// Array.prototype.map() 方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。//  arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])Array.prototype._reduce = function (_reducer, initialValue) {if (typeof _reducer !== 'function') throw "参数必须是回调函数"if (!Array.isArray(this)) throw "只能为数组使用此方法"if ((!this.length && !initialValue)) throw "请传入初始值或者给非空对象使用此方法"let arr = this    //将调用者(实例化的arr)赋值给arrlet result = initialValue || arr[0]  //初始值for (let i = 0, len = arr.length; i < len; i++) {if (!initialValue && i == 0) continue // 如果提供了initialValue,则起始索引号为0,否则从索引1起始。result = _reducer(result, arr[i], i, this)}return result  //返回新数组}// //test// let arr = [1, 3, 4]// const Result = arr._reduce(function (accumulator, currentValue, index, array) {//   console.log(index);//   return accumulator + currentValue// }, 2)// console.log(Result);

★★★ 手写实现一个简易的 Vue Reactive

★★★ 手写代码,监测数组变化,并返回数组长度

//手写代码,监测数组变化,并返回数组长度
// 获取Array的原型,并创建一个新的对象指向这个原型// const arrayMethods = Object.create(Array.prototype)// 创建一个新的原型,这就是改造之后的数组原型const ArrayProto = []// 重新构建Array原型里面的虽有方法Object.getOwnPropertyNames(Array.prototype).forEach(method => {if (typeof Array.prototype[method] === "function") {ArrayProto[method] = function () {console.log("我已经监听到数组触发了" + method + "事件")let len = this.lengthlet result = Array.prototype[method].apply(this, arguments)console.log(len, this.length);if (len !== this.length) return this.lengthreturn result}}})let list = [1, 2, 3]// 将数组的原型链指向新构造的原型list.__proto__ = ArrayProto// 执行push事件console.log(list.push(2), list.pop(2), list.slice(2), list.unshift(2));

★★★ 手写原生继承,并说出局限性?

★★★★ 手写一个柯里化函数

//柯里化:固定部分参数,返回一个接受剩余参数的函数,也称为部分计算函数,目的是为了缩小适用范围,创建一个针对性更强的函数。核心思想是把多参数传入的函数拆成单参数(或部分)函数,内部再返回调用下一个单参数(或部分)函数,依次处理剩余的参数。
//好处: 入口单一,易于测试和复用
//缺点:  函数嵌套多、占内存function Curry(fn,...args){return (..._args)=>{return fn(...args,..._args))}
}function V(l,w,h){return l*w*h
}const hcy =Curry(V,10)
hcy(5,8)   //400
hcy(6,7)   //420

★★★ 手写一个反柯里化函数

//反柯里化,从字面讲,意义和用法跟函数柯里化相比正好相反,扩大适用范围,创建一个应用范围更广的函数。使本来只有特定对象才适用的方法,扩展到更多的对象。
Function.prototype.unCurrying = function() {const self = thisreturn function(...rest) {return Function.prototype.call.apply(self, rest)}
}

★★★★ 手写一个Promise

class Promise{constructor(executor){this.state = 'pending';this.value = undefined;this.reason = undefined;this.onResolvedCallbacks = [];this.onRejectedCallbacks = [];try{  // 如果executor执行报错,直接执行rejectexecutor(this.resolve, this.reject);} catch (err) {reject(err);}}//成功resolv(value){// state改变,resolve调用就会失败if (this.state === 'pending') {// resolve调用后,state转化为成功态this.state = 'fulfilled';// 储存成功的值this.value = value;}};//失败reject(reason) {// state改变,reject调用就会失败if (this.state === 'pending') {// reject调用后,state转化为失败态this.state = 'rejected';// 储存失败的原因this.reason = reason;}};//then方法then(onFulfilled,onRejected) {// 声明返回的promise2let promise2 = new Promise((resolve, reject)=>{if (this.state === 'fulfilled') {let x = onFulfilled(this.value);// resolvePromise函数,处理自己return的promise和默认的promise2的关系resolvePromise(promise2, x, resolve, reject);};if (this.state === 'rejected') {let x = onRejected(this.reason);resolvePromise(promise2, x, resolve, reject);};if (this.state === 'pending') {this.onResolvedCallbacks.push(()=>{let x = onFulfilled(this.value);resolvePromise(promise2, x, resolve, reject);})this.onRejectedCallbacks.push(()=>{let x = onRejected(this.reason);resolvePromise(promise2, x, resolve, reject);})}});// 返回promise,完成链式return promise2;}
}

★★★ 手写一个instanceOf

function instanceOf(left,right){let proto = left.__proto__let prototype = right.prototypewhile(true){if(proto === null) return falseif(proto === prototype) return true proto = proto.__proto__;}
}

★★★ 手写ajax

//1.创建对象
let  xhq = new XMLHttpRequest()
//2.初始话http请求参数
xhq.open(methode, url, true)
//3.发送请求
xhq.send({username:'wzx'
})
//4.监听请求状态,执行对应的回调函数
xhq.onreadystatechange = function () {if ( xhq.readystate == 4 && xhq.status == 200 ) {// success 回调success(xhq.responseText)}  else if (xhq.readyState == 4 && xhq.status !== 200) {// error 回调error()}
}//-----------完整实现-----------
function sendAjax(obj) {function splicStr(data) {// get方式传入时,将内容进行data内容进行拼接var str = ''for (var i in data) {str = i + '=' + data[i]}return str}// 原生ajax实现 步骤分析
// 一、声明XMLHttpRequest, 为了兼容IE5、6需要使用ActiveXObject()let xhq = new XMLHttpRequest() // 创建对象
// 二、初始化HTTP请求参数, 只初始化并不会发送if (obj.method.toUpperCase() === 'GET') { // get方法xhq.open(obj.method, obj.url + '?' + splicStr(obj.data),  typeof obj.async === 'boolean'? obj.async : true) // 路径拼接xhq.send()// 三、发送此次请求}else if (obj.method.toUpperCase() === 'POST') { // post方法xhq.open(obj.method, obj.url, typeof obj.async === 'boolean'? obj.async : true)xhq.setRequestHeader("content-type","application/x-www-form-urlencoded") // 以表单提交xhq.send(obj.data)// 三、发送此次请求}
//四、监听发送xhq.onreadystatechange = function () {if ( xhq.readyState == 4 && xhq.status == 200 ) {// success 回调success(xhq.responseText)} else if (xhq.readyState == 4 && xhq.status !== 200) {// error 回调error()}}
}sendAjax({url: 'your url',method: 'post',async: true,data: {username: 'xiong',pwd: '123'},success: function (data) {console.log(data)},error: function () {console.log('发生了错误')}
})

★★★ 手写JSONP的原理和实现

function jsonp(url,data,callback){var funcName = 'jsonp_'+Date.now()+Math.random().toString().substr(2, 5)//如果有其他参数需要拼接if(typeof data==='object'){var tmpArr = []for (let key in data){let value =data[key]tmpArr.push(key+'='+value)}data = tmpArr.join('&')}let script = document.createElement('script')script.src = url + '?' + data + '&callback= ' + funcNamedocument.body.appendChild(script)window[funcName]= function (data){callback(data)//清除标签delete Window[funcName]document.body.removeChild(script)}
}

★★★★ 手写深拷贝

//乞丐版
function deepCopy(obj){return obj.JSON.Parse(JSON.Stringify(obj))
}//面试够用版
function deepCopy(obj){if(typeof obj)if(typeof obj =='object'){//判断是否为复杂数据源类型var result = obj.constructor == Array?[]:{}  //数组还是对象for(let i in obj){result[i]= typeof obj[i] =='object'? deepCopy(obj[i]):obj[i]}}else{//简单数据类型 var result = obj;}return result
}

★★★ 手写浅拷贝

function clone(target) {if(target === null ) {return target}// 克隆 数组 和 对象let cloneTarget = Array.isArray(target) ? [] : {}for (const key in target) {if (target.hasOwnProperty(key)) {//判断是否是本身的属性cloneTarget[key] = target[key]}}return cloneTarget
}

★★★★ 手写 bind

Function.prototype.myBind = function(context) {if (typeof this !== 'function') {throw new TypeError('Error')}//返回一个绑定this的函数,这里我们需要保存thisconst _this = thisconst args = [...arguments].slice(1)//返回一个函数return function F() {//因为返回一个函数,我们可以new F()需要判断能当做构造函数吗if (this instanceof F) { //实例是F这个构造函数造出来的return new _this(...args, ...arguments)  }return _this.apply(context, args.concat(...arguments))}
}

★★★★ 手写 call

Function.prototype.myCall = function(context) {context=context||window //传入参数的话,就指定context为this指向,否则指定windowcontext.fn = thisconst args = [...arguments].slice(1) //入参删除contextconst result = context.fn(...args)delete context.fnreturn result
}

★★★★ 手写 apply

Function.prototype.myApply = function(context) {context = context || windowcontext.fn = this   //给传入的上下文对象添加一个fn方法,这个fn方法即为myApply调用者let result if(arguments[1]){result = context.fn(...arguments[1])}else{result = context.fn()}delete context.fnreturn result
}

★★★ 手写模拟 object.create

function _create (obj){function F(){}  //创建一个构造函数F.prototype = obj  //将构造函数的原型对象赋值return new F()
}

★★★ 手写模拟 Object.is

function _is(x, y) {if (x === y) {//运行到1/x === 1/y的时候x和y都为0,但是1/+0 = +Infinity, 1/-0 = -Infinity, 是不一样的return x !== 0 || y !== 0 || 1 / x === 1 / y} else {//NaN===NaN是false,这是不对的,我们在这里做一个拦截,x !== x,那么一定是 NaN, y 同理//两个都是NaN的时候返回truereturn x !== x && y !== y}
}console.log(is(+0, -0))
console.log(is(NaN, NaN))

★★★ 手写 new

//new的实现过程(实际上就是调用这个构造函数,同时将构造函数的prototype上的属性方法挂上去。)
//1. 新建一个对象
//2. 对象 继承 构造函数的 原型链
//3. 将构造函数的this指向这个对象
//4. 根据构造函数的返回值的返回结构
function myNew(fn){ let obj = {} //定义空对象objobj = Object.create(fn.prototype) //将传入的构造函数的prototype属性方法复制到obj里面let args = Array.prototype.slice.call(arguments,1)// 获取除去fn之外的参数//或者  [...arguments].slice(1)let result = fn.call(obj,...args)  // 调用传入的构造函数,矫正this为obj,并传入argsreturn typeof result === 'object'||result instanceof Function? result : obj;//如果构造函数返回引用类型,直接返回,否则返回obj
}class Foo{constructor(){this.name = 'ciel'this.arg = arguments[0]}callname(){console.log(this.name)}
}// 测试
let test = myNew(Foo, 'hhh', '123', 'saf')
test.callName()
console.log(test.arg)

★★★ 手写对象扁平化

export function jsonFlatten(data) {var result = {}function recurse(cur, prop) {if (Object(cur) !== cur) {result[prop] = cur} else if (Array.isArray(cur)) {for (var i = 0, l = cur.length; i < l; i++) { recurse(cur[i], prop + '[' + i + ']') }if (l === 0) { result[prop] = [] }} else {var isEmpty = truefor (var p in cur) {isEmpty = falserecurse(cur[p], prop ? prop + '.' + p : p)}if (isEmpty && prop) { result[prop] = {} }}}recurse(data, '')return result
}

★★★ 手写数组扁平化

//第一种 正则表达式
function flatten(arr){let str = JSON.stringify(arr);return str.replace(/(\[\]))/g,'').split(',')
}
//第二种 递归
function flatten(arr, result = []) {if (!Array.isArray(arr)) {result.push(arr)return result}for (let value of arr) {flatten(value, result)}return result
}
//第三种 数组字符串方法
function flatten(arr) {return arr.toString().split(',').map(ele => parseInt(ele))
}//第四种
function flatten(arr){while(arr.some(item => Array.isArray(item))){arr = [].concat(...arr);}return arr;
}

★★★ 手写数组去重

//1.ES6的Setfunction unique(arr){ruturn Array.from(new Set(arr))   }
//2. 双层for循环function unique(arr) {let result = []for (let i = 0, len = arr.length; i < len; i++) { //第一层遍历let flag = false  //进行标记for (let k = i + 1, len = arr.length; k < len; k++) {if (arr[i] === arr[k]) {  //如果后面有重复的就跳过flag = truek = arr.length}}if (!flag) result.push(arr[i]) //没有重复的,添加到数组中}return result}
//3. 利用数组的indexOf方法 function unique(arr) {let result = []for (let i = 0, len = arr.length; i < len; i++) {if (result.indexOf(arr[i]) === -1) result.push(arr[i])}return result}
//4. 利用类似桶排序的方法function unique(arr) {let result = []   let bucket = [];  //创建一个桶for (let i = 0, len = arr.length; i < len; i++) {bucket[arr[i]] = 1   //将有些桶标记}for (key in bucket) { //取出有标记的桶的下标console.log(key);result.push(Number(key))}return result}
//5. 利用filter方法function unique(arr) {return arr.filter((ele, index) => (arr.indexOf(ele) === index)) //过滤}//6. 利用map方法function unique(arr) {return arr.map((ele, index) => {if (arr.indexOf(ele) === index) return ele})}
//7.排序后进行数组function unique(arr) {arr.sort()let result = []arr.forEach((ele, index) => {if (ele !== arr[index + 1]) result.push(ele)})return result}

★★★ 手写模拟实现 async/await

★★★★ 手写实现发布/订阅模式

class Subject { //定义被观察者constructor() {this.observers = []}addObserver(observer) { //订阅this.observers.push(observer)}removerObserver(observer) {//取消订阅let index = this.observers.indexOf(observer)if (index !== -1) {this.observers.splice(index, 1)}}notify() {  //通知this.observers.forEach(observer => {observer.update()})}
}class Observer { // 定义观察者update() {console.log('subject更新了');}subscribeTo(subject) {subject.addObserver(this)}
}let subject = new Subject() //被观察者
let observer1 = new Observer()  //观察者
observer1.subscribeTo(subject) //观察者进行订阅
let observer2 = new Observer()  //观察者
observer2.subscribeTo(subject) //观察者进行订阅
subject.notify()

★★★★ 手写防抖

funtion debounce(fn,delay){let timer = nullreturn ()=>{clearTimeout(timer)timer =  setTimeout(()=>(fn()),delay)}
}let a = debounce(()=>(console.log('防抖处理')),500)function 点击事件(){a()
}

★★★★ 手写节流

function throttle(fn, delay = 500) {let lastTime, timereturn function(){let context = this;let args = [].slice.call(arguments);time = Date.now()if (!lastTime || time - lastTime > delay) {fn.apply(context)lastTime = time}}
}function fn(){console.log('节流')
}let a =  throttle(fn, 1000)function 点击事件(){a()
}

手写代码(笔试面试真题)相关推荐

  1. 汇总5大Python常用笔试面试真题,知己知彼方能百战不殆

    俗话说的好,打仗之前知晓敌方的军情越多,获胜的把握也会越大,知己知彼方能百战不殆嘛!换个角度来说,如今的面试不正是和古代打战一样嘛,知晓的越多,成功几率也就越大,小编今天就为大家汇总了5大Python ...

  2. 武汉大学计算机学院自主招生考试内容,武汉大学自主招生笔试面试真题

    武汉大学自主招生笔试面试真题2018-10-20 14:16:33文/叶丹 自主招生考试中,笔试和面试是考生和家长最为关注的,而每年都有关于自主招生脑洞大开的题目,大家很好奇自主招生考试都考什么?下面 ...

  3. 银行java面试题手写代码_面试系列——手写代码实现(一)

    前言 本文是面试系列篇的实现篇.笔者整理了面试过程中可能会遇到的手写实现,以及它的原理.这可以帮助面试者在笔试环节获得良好的加分. 其他文章系列,欢迎关注我文末的公众号 正文 apply和call a ...

  4. 福利篇2——嵌入式岗位笔试面试资料汇总(含大厂笔试面试真题)

    前言 汇总嵌入式软件岗位笔试面试资料,供参考. 文章目录 前言 一.公司嵌入式面经 1.小米 1)面试时长 2)面试问题 2.科大讯飞 1)面试时长 2)面试题目 3.其余公司面经 二.嵌入式笔试面试 ...

  5. python面试情景题_50道python笔试面试真题大集合

    Python爬虫人工智能100GB web 爬虫  数据分析  人工智能视频免费领 题目后面有50道题答案领取方式哦 1.一行代码实现1--100之和 利用sum()函数求和 2.如何在一个函数内部修 ...

  6. 2020今日头条面试真题及答案整理最新最全持续更新中~~~~

    大家好,我是好好学习天天编程的天天 一个整天在互联网上爬虫的程序员,每天给大家分享学习干货的攻城狮 2020今日头条面试真题及答案整理&最新最全&持续更新中~~~~ 2020今日头条面 ...

  7. 2020年前端面试之JS手写代码题合集

    2020年前端面试之JS手写代码题合集 预计会有上千道题,后续慢慢补! 1.  写一个把字符串大小写切换的方法 function caseConvert(str){return str.replace ...

  8. 前端面试高频手写代码题

    前端面试高频手写代码题 一.实现一个解析URL参数的方法 方法一:String和Array的相关API 方法二: Web API 提供的 URL 方法三:正则表达式+string.replace方法 ...

  9. python在哪里写代码比较适合-程序员面试被要求手写代码,你与顶级程序员的差别在哪?...

    原标题:程序员面试被要求手写代码,你与顶级程序员的差别在哪? 前言: Python现在非常火,语法简单而且功能强大,很多同学都想学Python! 所以小的给各位看官们准备了收藏已久的视频教程分享给大家 ...

最新文章

  1. UNICODE字符集表
  2. java服务限流_SpringCloud微服务:Sentinel哨兵组件,管理服务限流和降级
  3. 互联网公司败局汇总,这些公司都是怎么死的?(上篇)
  4. 《App后台开发运维与架构实践》第4章 Linux系统
  5. Nature公开1300多篇论文工厂论文的期刊分布,这个杂志高居榜首
  6. java验证cron表达式_cron表达式
  7. [设计模式-创建型]单态(Singleton)
  8. Java反射修改返回值_java反射调用时如果返回值是整型数组怎么处理?
  9. Shell脚本编程之(三)执行方式差异(source, sh script, ./script)
  10. 生物信息学 | GEO介绍与安装
  11. 自动驾驶相关的期刊和会议
  12. 一个程序员是如何蜕变为投资人的?
  13. 自动售货机每个月用多少M的物联卡?
  14. 【鸿蒙】HiSpark Wifi IOT开发板资料汇总
  15. 捡了西瓜丢芝麻——注意编程细节
  16. 《启示录:打造用户喜爱的产品》 -读后感
  17. 多机房UPS及环境集中监控方案丨UPS环境综合监控主机
  18. 元宇宙:未来or骗局?
  19. 《Long-term Recurrent Convolutional Networks for Visual Recognition and Description》论文翻译
  20. 2018年电赛A题(电流检测设备)的复刻

热门文章

  1. 【Matlab】在Matlab中输入希腊字母
  2. JPL-DE430星历调用(使用Fortran)
  3. 做avi播放器的反思
  4. 长三角城市数字经济发展水平评估白皮书
  5. app线上推广的四种主流方法
  6. 尚学堂Java学习第四章课后编程题作业参考答案
  7. 面向对象的三大特征(封装、继承、多态)
  8. 代数,几何及微积分之间的关系
  9. CISCN2023 badkey1badkey2
  10. 【文件格式-TIFF】TIFF图像格式结构