热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

综合面试题js深入版

综合面试题-js深入版数组扁平化一维数组:数组中只有一级二维数组:数组中有两级多维数组:数组中有两级及以上变成一维数组的操作——扁平化fl

综合面试题-js深入版

  1. 数组扁平化

一维数组:数组中只有一级

二维数组:数组中有两级

多维数组:数组中有两级及以上

变成一维数组的操作——扁平化

  1. flat

es6中新增的方法

ps.不知道的api找mdn

去重

  1. 对象键值对

  2. 新开一个数组 for循环 indexOf includes来判断

  3. new Set来去重

  4. ……

经典算法

  1. toString

思路:将数组变为字符串

toString是会把一个数组直接变为一个字符串字符串里绝对不会出现中括号[],而把每项用逗号, 分隔

toString会自动扁平化,以逗号连接

这里扩展一下Object.prototype.toString.call({name:'angela',age:18})

Object.prototype.toString() - Javascript | MDN

join也是一样的

ps.map改变每项的值,返回啥就改成啥

  1. JSON.stringify

stringify和toString的区别在于 stringify是有中括号的

let arr=[1,2,[3,8],[35,87,[26,9]]]
let arr1=[{name:'angela',age:18},{name:'tom',age:18}]
// 1.flat方法
console.log('1.flat方法--------------------')
console.log(arr.flat(Infinity));
// 2.toString和join
console.log('2.toString和join--------------------')
console.log(arr.toString().split(',').map(i=>Number(i)));
console.log(arr.join().split(',').map(i=>Number(i))); // join同toString是一样
console.log(arr1.flat(Infinity));
console.log(arr1.toString().split(',')); // 有局限的
console.log(arr.join('|').split(/,|\|/g)); // 有局限的
// 3.JSON.stringify
console.log('3.JSON.stringify--------------------')
console.log(JSON.stringify(arr).replace(/\[|\]/g,'').split(','))
console.log(JSON.stringify(arr1).replace(/\[|\]/g,''));

  1. concat(...array)

前言:

用函数制定一个规则,检测数组中的某一项是否符合这个规则

some做检测

ps.forEach map some find

Array.isArray手动改原型链依然判为false 检测数据类型

...arr:每次只展开一级,展开不了很深

// 4.concat(...arr)
console.log('4.concat(...arr)--------------------')
console.log([].concat(...arr))
while(arr.some(i=>Array.isArray(i))){
arr=[].concat(...arr)
}
console.log(arr);

  1. 递归处理

递归思路:

fn执行的时候又调了自己

循环当前这个数组的每一项:

  • 不是数组,创建一个新数组存起来

  • 当前是数组,再调这个方法(先不管这个),重新进来

// res在外面
let res=[]
function deep(arr){
for(let i=0;i
if(arr[i] instanceof Array){
deep(arr[i]);
continue;
}
res.push(arr[i])
}
}let arr=[1,2,[3,8],[35,87,[26,9]]]
deep(arr);
console.log(res);
// res放在里面
function myFlatter(arr){
let res=[]
arr.forEach(i=>{
if(Array.isArray(i)){
res=res.concat(myFlatter(i))
}else{
res.push(i)
}
})
return res;
}
res=myFlatter(arr);
console.log(res);
function flatter(arr){
return arr.reduce((total,i)=>{
// if(Array.isArray(i)){
// total=total.concat(flatter(i));
// }else{
// total.push(i)
// }
// return total;
return Array.isArray(i)?total.concat(flatter(i)):[...total,i]
},[])
}
res=flatter(arr);
console.log(res);

Javascript数组扁平化的五种方式_二九君的博客-CSDN博客_Javascript数组扁平化

【Javascript】实现数组扁平化_程序媛小y的博客-CSDN博客_js数组扁平化处理

  1. _new方法

作为构造函数执行的步骤:

扩展一下Object.create

+创建一个空对象

+该对象的__proto__指向你传的参数(它所属构造函数的实例)。合理下传入的应该是一个原型对象proto,那么创建出来的空对象就是proto所属构造函数(该proto的constructor指向)的实例。

这里有一点绕口令:

Fn.prototype属于哪个构造函数的原型?Fn

function Dog(name){
this.name=name;
}
Dog.prototype.bark=function(){
console.log('wang wang')
}
Dog.prototype.sayName=function(){
console.log('my name is' + this.name);
}let sanmao=new Dog('sanmao');
console.dir(sanmao);// function _new(Dog,name){
// const obj={};
// obj.name=name;
// obj.__proto__=Dog.prototype;
// return obj;
// }
function _new(Fn,...args){
// let obj={}
// obj.__proto__=Fn.prototype;
let obj=Object.create(Fn.prototype);
Fn.call(obj,...args);
return obj;
}
sanmao=_new(Dog,'liumao')
console.dir(sanmao);

  1. 数组合并?题意本身不是很明确

数组合并concat

(function(){
let arr1=['A1','A2','B1','B2','C1','C2','D1','D2']
let arr2=['A','B','C','D'] let arr=[]
for(let i=0;i
if(arr1[i][0]
let alpha=arr2.find(item=>item===arr1[i][0])
alpha?arr.push(arr2.shift()):null;
continue;
}
arr.push(arr1[i]) } if(arr2.length){
// 如果原来数组是乱序的这里还得改一下
arr=arr.concat(arr2);
} console.log(arr);
console.log(arr1);
console.log(arr2);
})()function method2(){
let arr1=['A1','A2','B1','B2','C1','C2','D1','D2']
let arr2=['A','B','C','D'] let arr=[]
arr2.forEach((alpha)=>{
let index=arr1.findLastIndex(i=>i[0]===alpha)
arr1.splice(index+1,0,alpha);
})
console.log(arr);
console.log(arr1);
console.log(arr2);
}
method2();

  1. 闭包

let形成块级作用域

let形成块级作用域。当前i的值存在当前块级作用域里,定时器回调触发的时候找的i是当前块级作用域中的i

大闭包

  1. 循环体里面整个是一个大函数,保存变量i

for(var i=0;i<10;i++){
(function(i){
// i为参数
setTimeout(()=>{
console.log(i)
},1000)
})(i)}

把回调处理成闭包*

  1. 另一种思路是在setTimeout的回调做文章,这里也是一个函数

for(var i=0;i<10;i++){
// setTimeout((function(i){
// return ()=>console.log(i)
// })(i),1000)
// return一个function是在这里做文章
setTimeout(((i)=>()=>console.log(i))(i),1000)}
function timer(){
return i=>{
setTimeout(()=>console.log(i),1000)
}
}

  • 思路一样,使用bind

for(var i=0;i<10;i++){
var fn=function(i){
console.log(i)
}
setTimeout(fn.bind(null,i),1000)}

  1. 匿名函数

匿名函数如果设置了函数名

  1. 外面反而不能用,里面是能用的

  2. 里面AAA就相当于是一个const变量,

  • 你改这个值是没有效果的,但是它不会报错(非strict)

  • 但是你前面加了var,本身这个函数名就失效了

设置了名字带来的问题:

外面不能用,里面用了还不能改

当一个变量前没有var let const,沿着上级作用域链查找

  1. a==1 & a==2 & a==3

    1. toString类型转换

两个等号叫比较

三个等号叫绝对比较

(一个等号叫赋值)

==:若数据类型不一样,先转换成一样的再进行比较

===:类型一样值也一样

var a={
i:0,
valueOf:function(){
this.i++;
console.log(this.i);
return this.i;
},
[Symbol.toPrimitive]:function(){
return ++this.i;
}
}
console.log(a==1)

这道题思路:

number类型不可能,bool也不行,字符串……

Array.prototype.toString 以逗号连接数组中的每一项

Object.prototype.toString 用来检测数据类型的

所属类原型上的方法

  1. Object.defineProperty

对某个属性的描述,设置某个属性的相关特征

参数:对象 键 描述符

获取这个属性的时候,就会走get函数

// 简单版
let n=0;
Object.defineProperty(window,&#39;a&#39;,{
get(){
return ++n;
}
})
if(a==1 && a==2 & a==3){
console.log(&#39;OK&#39;)
}


Object.defineProperty(window,&#39;a&#39;,{
get(){
// 这时的this代表这个属性
this.value?this.value++:this.value=1;
return this.value;
}
})
if(a==1 && a==2 & a==3){
console.log(&#39;OK&#39;)
}

  1. Array.prototype.push原理

  1. 数组经典排序算法

  1. 冒泡排序

冒泡:越大的气泡越在上。

当前项和后一项进行比较,最大的排在后面

动图效果:

1662627592813.mp4

引申一下:交换

外层循环控制比较的轮数,n个数我只需要比较n-1次,因为我只需要把n-1个数依次放到末尾;

内层循环控制每轮要比较的次数,

整体思路:

外循环控制多少轮,里层循环控制比较次数,不用跟自己比,做多length-1,然后减掉末尾的数;

  1. 插入排序

将抓入的牌依次和手里的牌进行比较;

从后往前看,手上的牌小了,就往前挪;大了就插过去

let arr=[9,16,28,18,98,63,3];
for(let i=1;i
// arr[i]:要插入的元素
let insert=arr[i]
let j=i-1;
for(;j>=0;j--){
// 插入的数大于(等于)比较的元素 j+1
if(insert>=arr[j]){
// j+1 -> i-1 往后挪
for(let p=i-1;p>=j+1;p--){
arr[p+1]=arr[p];
}
arr[j+1]=insert;
break;
}
}
// 出循环没插入
if(j<0){
// 0 -> i-1 往后挪
for(let p=i-1;p>=0;p--){
arr[p+1]=arr[p];
}
arr[0]=insert;
}
}
console.log(arr);

let arr=[9,16,28,18,98,63,3];
for(let i=1;i
// arr[i]:要插入的元素
let insert=arr[i]
let j=i-1;
for(;j>=0;j--){
// 插入的数大于(等于)比较的元素 j+1
if(insert>=arr[j]){
// 用splice一定要先删除再插入// 这里删除的位置一定大于插入的位置,所以不会产生数组塌陷
arr.splice(i,1);
arr.splice(j+1,0,insert)
break;
}
}
// 出循环没插入
if(j<0){
// 用splice一定要先删除再插入
arr.splice(i,1);
arr.splice(0,0,insert)
}
}
console.log(arr);

或者就像视频中新开一个数组,视频中的方法是新开一个数组

https://www.jianshu.com/p/bd0ed19bc158

Javascript插入排序 - 帕图纳克斯 - 博客园

js 实现排序算法 -- 插入排序(Insertion Sort)

网上很多是这样:

let arr=[9,16,28,18,98,63,3];
for(let i=1;i
// arr[i]:要插入的元素
let insert=arr[i]
let j=i-1;
while(j>=0 && insert
arr[j+1]=arr[j];
j--;
}
arr[j+1]=insert; }
console.log(arr);

自己总结:

插入排序其实就是抓牌,将新的牌与手中已有的牌进行比较,从后往前比,当新的牌大于(等于)当前比较的元素时,这个时候插入进去。

所以代码上是:

首先取0号位置作为已排序数组,所以外层循环从1号位置开始循环,i=1;i

从后往前扫描,j=i-1;并且用一个变量temp保存这张新牌即arr[i],从后往前扫描的同时元素依次往后挪,边比较边往后挪,内层循环的条件是 while j>=0 && temp

  1. 快速排序

思路:

let arr=[18,24,56,90,3,7,65]
function quick(arr){
let i=Math.floor(arr.length/2);
let middle=arr[i];
arr.splice(i,0);
let left=[],right=[];
arr.forEach(item=>{
if(item
if(item>=middle) right.push(item)
}) if(left.length>=1) left=quick(left);
if(right.length>=1) right=quick(right)
return left.concat(middle).concat(right)}console.log(quick(arr));

Javascript 实现快速排序 - 知乎

快速排序(Quicksort)的Javascript实现 - 阮一峰的网络日志

diff算法 阮一峰_Javascript实现十大排序算法_短腿胖胖小笨猪的博客-CSDN博客

自己总结:

首先在数组中选一个元素作为基准点,比如一般选中间值,比这个值小的都放到左边,比这个值大的都放到右边,然后分别对左边和右边依次递归,最后返回的是左中右的拼接。

    1. 递归

一门语言:

语法本身,设计模式,底层原理,框架,服务器部署,数据库;

这3个排序是入门级别的,二叉树&三叉树,

  1. 数组填充

let obj={
1:22,
2:333,
12:878,
}let arr=new Array(12).fill(null);
arr.forEach((i,index)=>{
obj[index+1]?arr[index]=obj[index+1]:null;
})
// 这里用map会更好
arr=new Array(12).fill(null).map((_,index)=>{
return obj[index+1] || null;
})
console.log(arr);

map改变之前的值

let obj={
1:22,
2:333,
12:878,
}obj.length=13;
arr=Array.from(obj).slice(1).map(i => i || null)
console.log(arr);

  1. 求交集

注意一下重复元素的情况

let arr1=[1,2,2,76,39,22];
let arr2=[2,39,67,36];
let arr=arr1.reduce((total,item)=>{let index=arr2.indexOf(item)if(index>-1){
arr2.splice(index,1)
total.push(item);}return total;
},[])
console.log(arr);

思考题:交差并补

  1. 旋转数组(其实就是将数组平移k个位置)

k写几就是把最后几位放前面

方法一:slice支持负数作为索引

方法二:splice返回删除的数组

方法三:pop unshift

数组切割再拼接

let arr=[1,2,3,4,5,6,7,8]
function rotate(arr,k){
let length=arr.length;
k=k%length;
arr=arr.map((value,index)=>{
return {
value,
index:(index+k)%length
}
})
arr.sort((a,b)=>{
return a.index-b.index;
})
arr=arr.map(i=>(i.value))
return arr;}arr=rotate(arr,3);
console.log(arr);

  1. 函数柯理化

比较简单的做法,这样也行

function add(n1,n2,n3){return n1+n2+n3;
}
function currying(...args){if(args.length>=3){return add(...args)}return (...arg)=>{return currying(...args,...arg);}
}
console.log(currying(1,2)(3))
console.log(currying(1)(2,3))
console.log(currying(1)(2)(3))
console.log(currying(1,2,3))

call & apply & bind 与柯理化



推荐阅读
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • STL迭代器的种类及其功能介绍
    本文介绍了标准模板库(STL)定义的五种迭代器的种类和功能。通过图表展示了这几种迭代器之间的关系,并详细描述了各个迭代器的功能和使用方法。其中,输入迭代器用于从容器中读取元素,输出迭代器用于向容器中写入元素,正向迭代器是输入迭代器和输出迭代器的组合。本文的目的是帮助读者更好地理解STL迭代器的使用方法和特点。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • WebSocket与Socket.io的理解
    WebSocketprotocol是HTML5一种新的协议。它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送 ... [详细]
  • Redis底层数据结构之压缩列表的介绍及实现原理
    本文介绍了Redis底层数据结构之压缩列表的概念、实现原理以及使用场景。压缩列表是Redis为了节约内存而开发的一种顺序数据结构,由特殊编码的连续内存块组成。文章详细解释了压缩列表的构成和各个属性的含义,以及如何通过指针来计算表尾节点的地址。压缩列表适用于列表键和哈希键中只包含少量小整数值和短字符串的情况。通过使用压缩列表,可以有效减少内存占用,提升Redis的性能。 ... [详细]
  • 集合的遍历方式及其局限性
    本文介绍了Java中集合的遍历方式,重点介绍了for-each语句的用法和优势。同时指出了for-each语句无法引用数组或集合的索引的局限性。通过示例代码展示了for-each语句的使用方法,并提供了改写为for语句版本的方法。 ... [详细]
  • 本文介绍了一种在PHP中对二维数组根据某个字段进行排序的方法,以年龄字段为例,按照倒序的方式进行排序,并给出了具体的代码实现。 ... [详细]
  • 本文介绍了如何使用OpenXML按页码访问文档内容,以及在处理分页符和XML元素时的一些挑战。同时,还讨论了基于页面的引用框架的局限性和超越基于页面的引用框架的方法。最后,给出了一个使用C#的示例代码来按页码访问OpenXML内容的方法。 ... [详细]
author-avatar
少爷自控_592
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有