JavaScript高频副本面试题,看看你都会吗
发布时间:2025年09月19日 12:17
instanceof 用于监测构造变数的prototype确实在模板的的设计双链上,必须注意的是instanceof只能用来监测摘录图表叔父类,对于大体图表监测更亦会调回false
数学模型通过反转监测模板的_proto_特性确实与构造变数的prototype特性相等
字符串借助/** * instanceof 用于监测构造变数的prototype确实在模板的的设计双链上 */function myInstanceof(left, right) { // 必先排除大体图表叔父类 if(typeof left !== 'object' || left === null) return false let proto = left._proto_ while(proto) { if(proto === right.prototype) return true proto = proto._proto_ } return false}function Person() {}let person = new Person()console.log(myInstanceof(person,Person)) // true三维Function.prototype.apply()apply() 方法有codice_一个具给定this系数的变数,以及以一偶双链表(或类双链表具体来说)的形结构设计包括的模板。
Function.prototype.myApply = function(context) { var context = context || window // 受益必须绑定的this context.fn = this // 受益必须转变this的变数 const arg = arguments[1] // 受益传递给变数的模板 if(!(arg instanceof Array)) { throw Error('模板必须是一偶双链表') } const res = context.fn(...arg) // 督导变数 delete context.fn // 封禁该方法有 return res // 调回变数调回系数}function say(a,b,c) { console.log(this.name,a,b,c)}say.myApply({name:'nanjiu'},[1,2,3]) //nanjiu 1 2 3say.apply({name:'nanjiu'},[1,2,3]) //nanjiu 1 2 3三维Function.prototype.call()call() 方法有用于一个均须的 this 系数和分开注意到的一个或多个模板来codice_一个变数。
Function.prototype.myCall = function(context) { var context = context || window // 受益必须转变的this context.fn = this // 受益必须转变this的变数 const args = [...arguments].slice(1) // 受益模板列表 const res = context.fn(...args) // 将模板教给变数并督导 delete context.fn // 封禁该方法有 return res // 调回变数调回系数}function say(a,b,c) { console.log(this.name,a,b,c)}say.myCall({name:'nanjiu'},1,2,3) //nanjiu 1 2 3say.call({name:'nanjiu'},1,2,3) //nanjiu 1 2 3三维Function.prototype.bind()bind() 方法有成立一个一新的变数,在 bind() 被codice_时,这个一新变数的 this 被均须为 bind() 的第一个模板,而其余模板将作为一新变数的模板,专供codice_时用于。
Function.prototype.myBind = function(context) { var context = context || window //受益必须转变的this context.fn = this // 受益必须转变this的变数 //受益变数模板 const args = [...arguments].slice(1) // 与apply,call各不相同的是这里必须调回一个变数 return () => { return context.fn.apply(context,[...args]) }}function say(a,b,c) { console.log(this.name,a,b,c)}say.bind({name: 'nanjiu'},1,2,3)() //nanjiu 1 2 3say.myBind({name: 'nanjiu'},1,2,3)() //nanjiu 1 2 3三维Array.prototype.forEach()forEach() 方法有对双链表的每个类型督导一次给定的变数,无调回系数。
语法arr.forEach(callback(currentValue [, index [, array]])[, thisArg])模板callback为双链表中亦会每个类型督导的变数,该变数交还一至三个模板:currentValue双链表中亦会打算管控的理论上类型。index 预设双链表中亦会打算管控的理论上类型的图表库。array 预设forEach() 方法有打算转换的双链表。thisArg 预设预设模板。当督导程序在变数 callback 时,主要用途 this 的系数。字符串借助Array.prototype.myForEach = function(callback, context) { const arr = this // 受益codice_的双链表 const len = arr.length || 0 let index = 0 // 双链表下标 while(index < len) { callback.call(context ,arr[index], index) index++ }}let arr = [1,2,3]arr.forEach((item,index) => { console.log(MLT-key: ${index} - item: ${item}MLT-)})console.log('----------')arr.myForEach((item,index) => { console.log(MLT-key: ${index} - item: ${item}MLT-)})/** * key: 0 - item: 1key: 1 - item: 2key: 2 - item: 3----------key: 0 - item: 1key: 1 - item: 2key: 2 - item: 3 */三维Array.prototype.map()map() 方法有成立一个一新双链表,其结果是该双链表中亦会的每个类型是codice_一次包括的变数后的调回系数。
语法var new_array = arr.map(function callback(currentValue[, index[, array]]) { // Return element for new_array }[, thisArg])模板callback
转立体化并成一新双链表类型的变数,用于三个模板:
currentValue双链表中亦会打算管控的理论上类型。index预设双链表中亦会打算管控的理论上类型的图表库。array预设map 方法有codice_的双链表。thisArg预设
督导 callback 变数时系数被主要用途this。
字符串借助/** * map() 方法有成立一个一新双链表,其结果是该双链表中亦会的每个类型是codice_一次包括的变数后的调回系数。 */Array.prototype.myMap = function(callback, context) { const arr = this,res = [] const len = arr.length || 0 let index = 0 while(index < len) { res.push(callback.call(context, arr[index], index)) index ++ } return res // 与forEach各不相同的是map有调回系数}const arr = [1,2,3]let res1 = arr.map((item,index) => { return MLT-k:${index}-v:${item}MLT-})let res2 = arr.myMap((item,index) => { return MLT-k:${index}-v:${item}MLT-})console.log(res1) // [ 'k:0-v:1', 'k:1-v:2', 'k:2-v:3' ]console.log(res2) // [ 'k:0-v:1', 'k:1-v:2', 'k:2-v:3' ]三维Array.prototype.Filter()filter() 方法有成立一个一新双链表, 其相关联通过所包括变数借助的试验的所有类型。
语法var newArray = arr.filter(callback(element[, index[, array]])[, thisArg])模板callback
用来试验双链表的每个类型的变数。调回 true 坚称该类型通过试验,沿用该类型,false 则不沿用。它接受都有三个模板:
element双链表中亦会理论上打算管控的类型。index预设打算管控的类型在双链表中亦会的图表库。array预设codice_了 filter 的双链表本身。thisArg预设
督导 callback 时,用于 this 的系数。
字符串借助/** * MLT-filter()MLT- 方法有成立一个一新双链表, 其相关联通过所包括变数借助的试验的所有类型。 */Array.prototype.myFilter = function(callback, context) { const arr = this,res = [] const len = arr.length let index = 0 while(index < len) { if(callback.call(context,arr[index],index)) { res.push(arr[index]) } index ++ } return res}const arr = [1,2,3]let res1 = arr.filter((item,index) => { return item<3})let res2 = arr.myFilter((item,index) => { return item<3})console.log(res1) // [ 1, 2 ]console.log(res2) // [ 1, 2 ]变数柯里立体化柯里立体化,英语:Currying(果然是满满的英译中亦会的既视感),是把接受多个模板的变数变换并成接受一个单一模板(最初变数的第一个模板)的变数,并且调回接受余下的模板而且调回结果的一新变数的核心技术。
必先来思考一下什么是变数柯里立体化,上面文绉绉的内容不太可能不是那么较易思考,我们还是这样一来上字符串来思考吧
// 假如有这样一个变数function add (a,b,c) { console.log(a+b+c)}add(1,2,3) //6/** * 我们希望可以通过add(1,2)(3)或add(1)(2)(3)或add(1)(2,3)这样codice_也必须得倒正确的计算结果 这就是变数柯里立体化的简单应用 */字符串借助function curry(fn, curArgs) { const len = fn.length // 必须柯里立体化变数的模板偶数 curArgs = curArgs || [] return function() { let args = [].slice.call(arguments) // 受益模板 args = curArgs.concat(args) //裁剪模板 // 大体思维就是当裁剪完毕的模板偶数与原变数模板偶数相等才督导这个变数,否则就语句裁剪模板 if(args.length < len) { return curry(fn, args) }else{ return fn.apply(this, args) } }}let fn = curry(function(a,b,c){ console.log([a,b,c])})fn(1,2,3) // [ 1, 2, 3 ]fn(1,2)(3) // [ 1, 2, 3 ]fn(1)(2,3) // [ 1, 2, 3 ]fn(1)(2)(3) // [ 1, 2, 3 ]类双链表转双链表类双链表是具length特性,但不具双链表的设计上的方法有。常见的类双链表有arguments、DOM转换方法有调回的结果。
function translateArray() { //方法有一:Array.from const res1 = Array.from(arguments) console.log(res1 instanceof Array, res1) // true [ 1, 2, 3 ] // 方法有二:Array.prototype.slice.call const res2 = Array.prototype.slice.call(arguments) console.log(res2 instanceof Array, res2) // true [ 1, 2, 3 ] // 方法有三:concate const res3 = [].concat.apply([],arguments) console.log(res3 instanceof Array, res3) // true [ 1, 2, 3 ] // 方法有四:扩展语句 const res4 = [...arguments] console.log(res4 instanceof Array, res4) // true [ 1, 2, 3 ]}translateArray(1,2,3)借助更深批量在批量的时候判断一下特性系数的叔父类,如果是具体来说,语句codice_更深批量变数
/** * 在批量的时候判断一下特性系数的叔父类,如果是具体来说,语句codice_更深批量变数 */function deepClone(obj, cache=new Map()) { // 大体图表叔父类这样一来调回 if(typeof obj !== 'object' || obj === null) return obj // 防止反转摘录 const cacheTarget = cache.get(obj) // 已经存有就这样一来调回 if(cacheTarget) return cacheTarget let newObj = obj instanceof Array ? [] : {} // 扩建一个具体来说 cache.set(obj, newObj) // 遍历原具体来说 for(let key in obj) { if(obj.hasOwnProperty(key)) { newObj[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key] } } return newObj}const obj = { name: '张三'}const obj1 = objconst obj2 = deepClone(obj)console.log(obj1===obj) //trueconsole.log(obj2===obj) //false教给的借助的设计双链教给的设计双链教给借助的数学模型就是将构造变数的的设计所设为另一个构造变数的模板具体来说,这样就可以教给另一个的设计具体来说的所有特性和方法有,可以继续往上,终于形并成的设计双链。
function Parent1(name, age) { this.name = name, this.age = age}Parent1.prototype.say = function() { console.log(this.name)}function Child1(name) { this.name = name}Child1.prototype = new Parent1()Child1.prototype.constructor = Child1let child1 = new Child1('负责任',18)console.log(child1) //Child1 {name: '负责任'}child1.say() // 负责任弱点:
当借助教给后,另一个的设计的模板特性,转立体化并成了今日这个的设计的的设计特性,然后该的设计的摘录叔父类特性亦会被所有的模板框架,这样教给的设计摘录叔父类特性的模板中间便具自己的独特性了。在成立叔父叔父类的模板时,很难办法在不影响所有具体来说模板的情况给时是叔父类的构造变数中亦会传递模板。构造变数教给为了补救的设计中亦会相关联摘录叔父类系数的难题,开始用于另加构造变数,也叫仅仅只是造具体来说或经典教给
构造变数教给借助的数学模型就是在叔父类中亦会codice_父类构造变数来借助教给
function Parent2(age) { this.age = age this.say = function() { console.log(this.name) }}function Child2(name,age,gender) { this.name = name Parent2.call(this, age) this.gender = gender}let child2 = new Child2('张三', 18, 'boy')console.log(child2) //Child2 {name: '张三', age: 18, gender: 'boy'}child2.say() // 张三优点: 可以传递模板以及消除了摘录叔父类的特性被所有模板框架
弱点: 所有方法有都在构造变数内,每次成立具体来说更亦会成立几乎一致的方法有,大幅浪费存储器
第一组教给*也叫仅仅只是经典教给,将的设计双链和另加构造变数的核心技术第一组到一块。用于的设计双链借助对的设计特性和方法有的教给,而通过构造变数来借助对模板特性的教给。
function Parent3(age) { this.age = age}Parent3.prototype.say = function() { console.log(this.name)}function Child3(name,age,gender) { this.name = name Parent3.call(this, age) this.gender = gender}Child3.prototype = new Parent3Child3.prototype.constructor = Child3let child3 = new Child3('张三', 18, 'boy')console.log(child3) //Child3 {name: '张三', age: 18, gender: 'boy'}child2.say() // 张三将Child3的的设计均须为Parent3的一个模板,大致方结构设计中和的设计双链教给完全相同,只是多了在Child3中亦会借调Parent3的现实生活。模板特性表述在构造变数中亦会,而方法有则表述在构造变数的一新的设计中亦会,同时将一新的设计的constructor指向构造变数。可以通过instanceof和isPrototypeOf()来识别基于第一组教给成立的具体来说。消除了的设计双链和另加构造变数的不足之处,融合了它们的优点,并成为JS中亦会最常用的教给方结构设计。的设计结构设计教给借助的设计可以基于已有的具体来说成立一新具体来说,同时还不必因此成立自表述叔父类。
function object(obj) { function F(){} F.prototype = obj return new F()}let parent4 = { age: 18, name: '张三', say() { console.log(this.name) }}let child4 = object(parent4)console.log(child4) /**{[[Prototype]]: Object age: 18 name: "张三" say: ƒ say() [[Prototype]]: Object }*/child4.say() // 张三在 object()变数之外,必先成立了一个临时性的构造变数,然后将兴起的具体来说作为这个构造变数的的设计,最后调回了这个临时叔父类的一个一新模板。从本质上说是,object()对兴起其中亦会的具体来说督导了一次青绿色复制
这种的设计结构设计教给,要求必须要有一个具体来说可以作为另一个具体来说的基础用这种方结构设计成立的具体来说相当于是兴起模板具体来说的手写它说是就是ES5 Object.create的三维借助,将兴起的具体来说作为成立具体来说的的设计
在只想让一个具体来说与另一个具体来说保持完全相同的情况,的设计教给是完毕全可以长处的。的设计方结构设计下的弱点:摘录叔父类特性的框架难题。
雌雄同体教给雌雄同体结构设计教给与的设计结构设计教给紧密相关,与雌雄同体构造变数和工厂方结构设计完全相同,即成立一个极少用于晶圆教给现实生活的变数,该变数在之外以某种方结构设计来增强具体来说,最后便调回具体来说。
function createAnother(original) { var clone = object(original) //通过codice_变数成立一个一新具体来说 clone.say = function(){ // 以某种方结构设计来增强这个具体来说 console.log('nanjiu') }; return clone // 调回这个具体来说}弱点: 跟另加构造变数方结构设计一样,每次成立具体来说更亦会成立一遍方法有。
雌雄同体的单教给*第一组教给是 JavaScript 最常用的教给方结构设计;不过,它也有自己的不足。第一组教给最大的难题就是无论什么情况,更亦会codice_两次时是叔父类构造变数:一次是在成立叔父叔父类的设计的时候,另一次是在叔父叔父类构造变数之外。没错,叔父叔父类终于亦会相关联时是叔父类具体来说的全部模板特性,但我们不得不在codice_叔父叔父类构造变数时编写这些特性。
function object(o) { function F() {} F.prototype = o; return new F();}function prototype(child, parent) { var prototype = object(parent.prototype); prototype.constructor = child; child.prototype = prototype;}function Parent6(age) { this.age = age}Parent6.prototype.say = function() { console.log(this.name)}function Child6(name, gender) { this.name = name this.gender = gender}// 用于prototype(Child6, Parent6);let child6 = new Child6('nanjiu', 'boy')console.log(child6) // Child6 {name: 'nanjiu', gender: 'boy'}child6.say() // nanjiu总结JavaScript 主要通过的设计双链借助教给。的设计双链的框架是通过将一个叔父类的模板赋系数给另一个构造变数的的设计借助的。这样,叔父叔父类就必须访问时是叔父类的所有特性和方法有,这一点与基于类的教给很相近。
的设计双链的难题是具体来说模板框架所有教给的特性和方法有,因此不适宜分开用于。补救这个难题的核心技术是另加构造变数,即在叔父叔父类构造变数的之外codice_时是叔父类构造变数。这样就可以明白每个模板都具自己的特性,同时还能往时是叔父类构造变数中亦会传递模板,但是很难变数相依。用于最多的教给方结构设计是第一组教给,这种方结构设计用于的设计双链教给框架的特性和方法有,而通过另加构造变数教给模板特性。此外,还存有下列可专供择一择的教给方结构设计。的设计结构设计教给,可以在不必预必先表述构造变数的情况借助教给,其本质是督导对给定具体来说的青绿色复制。而复制获取的手写还可以获取进一步改造。雌雄同体结构设计教给,与的设计结构设计教给非常相近,也是基于某个具体来说或某些反馈成立一个具体来说,然后增强具体来说,最后调回具体来说。为了补救第一组教给方结构设计由于多次codice_时是叔父类构造变数而致使的低效率难题,可以将这个方结构设计与第一组教给一起用于。雌雄同体的单教给,集雌雄同体结构设计教给和第一组教给的优点与一身,是借助基于叔父类教给的最有效方结构设计。借助AJAX方结构设计中:
成立XMLHttpRequest具体来说锁上双镜像 (均须允诺叔父类,必须允诺图表在代理服务器的地址,确实异步i允诺)向代理服务器发送到允诺(get叔父类这样一来发送到允诺,post叔父类必须所设允诺头)交还代理服务器的声势浩大图表(需根据XMLHttpRequest的readyState特性断定codice_哪个程序在变数)function ajax(url, method, data=null) { const xhr = XMLHttpRequest() // 咱们这里就不管IE低版本了 // open()方法有,它接受3个模板:要发送到的允诺的叔父类,允诺的url和确实异步发送到允诺的布尔系数。 xhr.open(method, url ,false) // 敞开一个允诺,理论上还未能发送到 xhr.onreadyStatechange = function() { if(xhr.readyState == 4) { if ((xhr.status>= 200 && xhr.status < 300) || xhr.status == 304){ alert(xhr.responseText); } else { console.log("Request was unsuccessful: " + xhr.status); } } } if(method === 'post') { xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); } xhr.send(data) // get允诺,data应为null,模板裁剪在URL上}多维双链表扁平立体化function flat(arr) { const res = [] // 语句借助 const stack = [...arr] // 复制一份 while(stack.length) { //取出复制栈内第一个类型 const val = stack.shift() if(Array.isArray(val)) { // 如果是双链表,就展开推入栈的最后 stack.push(...val) }else{ // 否则就推入res调回系数 res.push(val) } } return res}const arr = [1,[2],[3,4,[5,6,[7,[8]]]]]console.log(flat(arr)) //[1, 2, 3, 4, 5, 6, 7, 8]当然你也可以用双链表内嵌的方法有flat,将展开层数均须为Infinity无穷大,看看面试官搭车不搭车理你
const arr = [1,[2],[3,4,[5,6,[7,[8]]]]]console.log(arr.flat(Infinity)) //[1, 2, 3, 4, 5, 6, 7, 8]setTimeout 三维 setInterval出发点就是语句codice_setTimeout
function mySetInterval(callback, delay) { let timer = null let interval = () => { timer = setTimeout(()=>{ callback() interval() // 语句 }, delay) } interval() // 必先督导一次 return { id: timer, clear: () => { clearTimeout(timer) } }}let time = mySetInterval(()=>{ console.log(1)},1000)setTimeout(()=>{ time.clear()},2000)setInterval 三维 setTimeout出发点就是setInterval督导一次后将setInterval清除即可
function mySetTimeout(callback, delay) { let timer = null timer = setInterval(()=>{ callback() clearInterval(timer) },delay)}mySetTimeout(()=>{ console.log(1)},1000)sleep借助一个变数,n秒后督导均须变数
function sleep(func, delay) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(func()) }, delay) })}function say(name) { console.log(name)}async function go() { await sleep(()=>say('nanjiu'),1000) //过一秒列印nanjiu await sleep(()=>say('前端张三'),2000) // 便过两秒列印前端张三}go()双链表去重的多种借助方结构设计用于Setlet arr = [1,2,3,2,4,5,3,6,2]function arrayToHeavy1(arr) { return [...new Set(arr)]}console.log(arrayToHeavy1(arr)) //[ 1, 2, 3, 4, 5, 6 ]用于indexOffunction arrayToHeavy2(arr) { let newArr = [] for(let i=0; iF(n) = F(n - 1) + F(n - 2),其中亦会 n> 1
暴力语句版本function fib(n) { if(n == 0) return 0 if(n == 1 || n == 2) return 1 return fib(n-1) + fib(n-2)}// console.log(fib(4)) //F(4)=F(3)+F(2)=F(2)+F(1)+F(2)=1+1+1=3let t = +new Date()console.log(fib(40)) //102334155console.log(+new Date()-t) //783ms优立体化版本function fib2(n) { if(fib2[n] !== undefined) return fib2[n] if(n == 0) return 0 if(n == 1 || n == 2) return 1 const res = fib2(n-1) + fib2(n-2) fib2[n] = res return res}let t1 = +new Date()console.log(fib2(40)) //102334155console.log(+new Date()-t1) //5ms发布一新闻电子书用过Vue的eventBus的同学必要很熟悉,$on电子书重大事件,$emit发布一新闻重大事件
class EventEmitter { constructor() { this.events = {} } // 电子书重大事件 on(event, callback) { if(!this.events[event]) { this.events[event] = [] } // 将重大事件几乎一致的程序在装入该重大事件的重大事件队列中亦会 this.events[event].push(callback) return this } //发布一新闻重大事件 emit(event, args) { const callbackList = this.events[event] if(callbackList.length) { callbackList.forEach(cb => cb.apply(this, args)) } return this } // 封禁电子书 off(event, callback) { // event没传,则封禁所有电子书的重大事件 if (typeof event === 'undefined') { delete this.events } else if (typeof event === 'string') { // 封禁均须重大事件的程序在 if (typeof callback === 'function') { this.events[ event ] = this.events[ event ].filter((cb) => cb !== callback) } else { // 封禁整个重大事件 delete this.events[ event ] } } return this } // 只进行一次的重大事件电子书 once (event, callback, context) { const proxyCallback = (...args) => { callback.apply(context, args) // 程序在变数督导完毕并成之后就封禁重大事件电子书 this.off(event, proxyCallback) } this.on(event, proxyCallback, context) }}// 完了毕测一把const bus = new EventEmitter()// 必先电子书一个重大事件bus.on('add', () => { console.log('nanjiu')})// 发布一新闻重大事件。眼睛结膜炎是什么原因引起的吗孩子消化不良吃什么好
角膜炎是什么原因引起的
先诺欣
积食
精彩回顾
瘦身丰胸
幼儿口臭
- 老婆称孩子不是亲生的,宝爸做了2次认定后,全家都乱了
- 考研难度分等级?这样择校提高上岸几率!
- 孩子超级爱咬指甲的习惯怎么也改不掉,精神科:这可能是病,得治
- 女儿3种“讨人厌”的行为,恰恰说明大脑发育好,智商超过同龄人
- 体制内朋友聚会,我发现混得好的人,大多有这四个特性
- 重要通知!3年底1日开始
- 知识界英文 | 留学西班牙热门的大学有哪些院校
- 多子女家庭,受益多的孩子会为孩子养老多付出吗?未必
- 江苏美女学霸被北京大学录取,父母配朋友圈庆贺,却等来心寒回复
- 笑喷,“超懒”小学生作业走红,老师哭笑不得又只得给分
- 美国本科顶级夏校你发觉几个?千万别错过这些藤校入场券!
- 为什么总有家长希望调整所中学入学年龄
- 苏翊鸣问考清华难吗?清华大学做出回应,北京师范大学却坐不住了
- 上海:粪菌移植治疗百余自闭症儿童 “星星的女儿” 变化喜人