js用递归遍历多维数组_js面试题更新之40

js用递归遍历多维数组_js面试题更新之40_第1张图片

1、数组方法pop() push() unshift() shift()

push     后面添加元素,个数不限,返回新数组的长度

pop     从后面删除一个元素,返回那个元素

unshift   从前面添加元素,个数不限,返回新数组的长度

shift     从前面删除一个元素,返回那个元素

2、javascript的typeof返回哪些数据类型

Object  number  function  Boolean  underfind

(注意这里没有null,null是一个空对象,是Object的类型。undefined隐形转换数字为NaN,不是任何值,不等于NaN本身。null隐形转换数字文0。强制转化都为NaN。)

3、split() join() 的区别

split() 字符串的方法,把字符串分割成数组   split(“,”)

join()  数组的方法,把数组连接成字符串   join(“--”)

4、输出的值是什么:

   var arr = [1, 2, 3, 4, 5, 5]        for (var i = 0; i        setTimeout(function(){                 console.log(i)         })      //输出6次6。setTimeout()是异步操作。var定义变量是存在变量提升,//当i=6时循环停止,才开始执行6次console.log(i) }      
for (let i = 0; i    setTimeout(function(){            console.log(i)         })       }  //输出0 1 2 3 4 5 。let不存在变量提升,可以形成块级作用域
for (var i = 0; i    setTimeout(function(){            console.log(arr[i])         })       }  //输出6次undefined
for (let i = 0; i    setTimeout(function(){            console.log(arr[i])         })       }  //输出 1 2 3 4 5 5

5、前端有哪几种本地存储方式,简述各自的特点(请描述一下cookies,sessionStorage和localStorage的区别?)

前端有三种本地存储的方式:cookie、localStorage 、 sessionStorage

  • cookie---最大数据量为4kb左右,存储量小,可以设置有效期,默认为会话级别。是基于http的。

  • localStorage---有效期永久,存多了,不主动删除,会造成浏览器很卡。同源可以修 改localStorage的数据。

  • sessionStorage:有效期顶层窗口关闭钱,数据在页面会话结束的时候会被清除,属   于临时保存同一窗口的数据。最大容量有5M左右。

6、简述常见的http状态码

200 请求成功

304 服务器已经执行了请求,当文件没有变化 ,简单讲有缓存了。 

404 Not Found

500 服务端错误

7、从输入URL到页面加载发生了什么?      

  1、DNS解析 (把域名解析为相应的ip地址)

          2、TCP连接 (三次握手的过程)

          3、发送HTTP请求

          4、服务器处理请求并返回HTTP报文

          5、浏览器解析渲染页面

          6、连接结束 (断开连接过程是四次挥手的过程)

8、Promise构造函数是同步执行还是异步执行,那么 then 方法呢?

Promise构造函数是同步执行的,then方法是异步执行的

9、setTimeout、Promise、async/await 的区别?

      事件循环(Event Loop)中分为宏任务队列和微任务队列

       setTimeout的回调函数放到宏任务队列里,等到执行栈清空以后执行

 promise.then里的回调函数会放到相应宏任务的微任务队列里,等宏任务里面的同步代码执行完再执行

async函数表示函数里面可能会有异步方法,await后面跟一个表达式。async方法执行时,遇到await会立即执行表达式,然后把表达式后面的代码放到微任务队列里,让出执行栈让同步代码先执行

补充:promise 是es6新增一种异步编程的方案

      async/await是es7中新增的异步编程的方案。

经典案例:今日头条的面试题,执行的顺序

async function async1 () {  console.log('async1 start') // 2  await async2();  console.log('async1 end')    //7}async function async2 () {  console.log('async2')      //3}console.log('script start')       // 1setTimeout(function () {  console.log('setTimeout')   //8}, 0)async1();new Promise (function (resolve) {  console.log('promise1')   //4   resolve();}).then (function () {  console.log('promise2')  //6})console.log('script end')       //5运行结果:1、 script start2、 async1 start3、 async24、 promise15、 script end6、 promise27、 async1 end8、 setTimeout

10、forEach、for in、for of三者区别

       forEach:用来遍历数组,对数组中的每个元素执行一次提供的函数,不改变原数组,无返回值,undefined。

for in 一般常用来遍历对象或json。

for of数组对象都可以遍历。其中遍历对象使用Object.keys()

例:arr.forEach(function(value,index,arr){代码段})

例:let obj={a:1,b:2}   for(let o in obj){ console.log(o)   //a b }

例:let arr=[‘China’,’korea’]   let obj={a:1,b:2}

for(let o of arr){console.log(o)  // China Korea}

for(let o of Object.keys(obj)){     //直接写for(let o of obj)报错

console.log(o)  } // a b  对象中的键

11、手写一个 Promise(中高级必考)什么是promise?promise是用来干啥的?解决了什么问题?

Promise是异步编程的一个解决方案,主要用来解决两个问题:1、解决异步的问题,2、解决回调地狱的,就是第一个函数的输出是第二个函数的输入的这种现象。

let  promise=new Promise((resolve,reject)=>{If(异步操作成功){resolve(value);}else{reject(error); //操作失败}})promise.then(function(value){ //success },function(error){ //failure })  //promise.then()两个参数,第二个参数可选

Promise 对象的三种状态:pending(正在进行)、fulfilled(成功)、rejected(失败)。

状态只能pending到fulfilled或者pending到rejected,状态一旦改变不能再变。

12、对象、数组的深拷贝浅拷贝

浅拷贝:就是流于表面的拷贝方式,浅拷贝只拷贝的对象的地址,也就是说两个对象指向的是同一地址,修改其中的一个对象的属性,另一个对象的属性也会修改。

深拷贝:完全拷贝,拷贝之后新旧数据完全分离,不再共用对象类型的属性值,不会相互影响。

13、手写一个js深拷贝  (先理解什么是深拷贝)

乞丐版

01、var newObj=JSON.parse(JSON.stringify(obj))无法复制函数,丢失原型链,对于多维数组也有效02、var newArr=arr.slice() 或者arr.concat() 只能实现一维数组的深拷贝03、var […newArr]=arres6扩展运算法实现数组的深拷贝(当然数组中没有属性值没有对象的时候)04、var {…obj2}=obj05、对象只有一层的话可以使用Object.assign()函数var newobj=Object.assign({},obj)

面试够用版(判断是数组还是对象,新建一个数组或者对象,通过for in循环数组对象,完成深拷贝) 递归拷贝

function deepCopy(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;}

14、数组去重手写

利用es6中Set去重

var arr = [1,2,2,23,23,undefined,undefined];     var newarr = Array.from(new Set(arr))  console.log(newarr) //  [1, 2, 23, undefined]补充:ES6提供了一个新的数据结构Set,本身是一个构造函数,用来生成Set的数据结构。类似于数组,但是成员的属性都是唯一的,没有重复的值。

双重for循环+splice()方法

function single(arr){  for(var i=0;i    for(var j=i+1;j      if(arr[i]==arr[j]){      arr.splice(j,1);      j--;  //arr的长度变了    }  }} return  arr;}var arr = [1,2,2,23,23,undefined,undefined];     console.log(single(arr)) //  [1, 2, 23, undefined]

利用indexOf去重

var arr = [1,2,2,23,23,undefined,undefined];  var newapp=[];for(var i=0;iif(newapp.indexOf(arr[i])===-1){newapp.push(arr[i])}}   console.log(newapp)  //  [1, 2, 23, undefined]

新建一个空数组,for循环判断新数组中是否存在原数组中元素,如果有相同的值则跳过,不相同push到新数组。

15、冒泡排序和选择排序

冒泡排序:相邻两个元素比较

相邻两个元素进行比较,将一个数组中数字使用循环进行升序或排序的

 arr = [1, 2, 3, 4]        for (var j = 0; j < arr.length; j++) {            for (var i = 0; i < arr.length; i++) {                if (arr[i] < arr[i + 1]) {                    var a = arr[i]                    arr[i] = arr[i + 1]                    arr[i + 1] = a;                }            }        }

选择排序:先找值

这种排序方式先找最大的,排在最左侧,然后找第二个往左靠。。。。

arr = [1, 2, 3, 4]        for (var i = 0; i < arr.length - 1; i++) {            for (var j = i + 1; j < arr.length; j++) {                if (arr[i] < arr[j]) {                    tmp = arr[i];                    arr[i] = arr[j];                    arr[j] = tmp;                }            }        }

冒泡排序和顺序排序(划重点)。

(1)冒泡排序是比较相邻位置的两个数,而选择排序是按顺序比较,找最大值或者最小值;

(2)冒泡排序每一轮比较后,位置不对都需要换位置,选择排序每一轮比较都只需要换一次位置;

(3)冒泡排序是通过数去找位置,选择排序是给定位置去找数;

总结:一般选择排序优于冒泡排序。因为每次排序只需要交换一位置。冒泡排序比较耗性能。

16、 浅谈async/await

    1、async声明一个异步async function fun(){….}

自动将常规的函数转换成Promise ,返回值也是一个Promise对象。

只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数。

  异步函数内部可以使用await

  2、await 等待异步功能执行 var result=await new Promise()

 放置在Promise调用之前,await强制其他代码等待,直到Promise完成并返回结果

只能与Promise一起使用,不适于回调。

只能在async函数内部使用。

17、事件循环

function printing() {      console.log(1);       setTimeout(function() { console.log(2); }, 1000);      setTimeout(function() { console.log(3); }, 0);      console.log(4); }  // 1 4 3 2

  理解:javascritpt是一门单线程的语言。

js分为同步任务和异步任务。事件循环分为宏任务和微任务。

同步任务在主线程上执行,形成一个执行栈,主线程之外,事件触发线程管理着一个任务队列,只要异步任务有了运行结果,就在任务队列中放置一个事件。

一旦执行栈中的所有同步任务执行完毕,系统就会读取任务队列,将可执行的异步任务添加到执行栈中,开始执行。

执行顺序:执行栈中的任务----事件循环中宏任务------事件循环中的微任务

同步任务交给主线程,主线程之外事件触发线程管理一个任务队列,为异步任务

18、ajax请求的时候get 和post方式的区别

1、get请求会将参数跟在url后面进行参数传递,而post请求则是作为http消息的实体内容发送给web服务器。

2、get提交的数据大小有限制,这个限制是url的整体长度而不是参数的长度。post提交没有这个限制。

3、get请求的数据会被浏览器缓存起来,带来严重的安全问题,而post相对来说可以避免这些问题。

4、一般情况下。Get请求用来请求数据,post请求用来提交数据。

19、Javascript垃圾(GC)回收机制

Javascript垃圾回收机制原理:为了防止内存泄漏,垃圾回收机制会定期的清理哪些不再用到内存变量,然后释放其内存。

现在各大浏览器的通常采用的垃圾回收机制的两种方法:标记清除、引用计数 

Js最常用的垃圾回收方式是标记清除,当变量进入环境时,将这个变量标记为“进入环境”,当这个变量离开环境时标记“离开环境”。标记为‘离开环境’的就回收内存。

20、闭包是什么,有什么特性,对页面有什么影响

闭包是指有权访问另—个函数作用域中变量的函数。创建闭包的最常见的方式就是在—个函数内创建另—个函数,通过另—个函数访问这个函数的局部变量,利用闭包可以突破作用链域,将函数内部的变量和方法传递到外部。

闭包的特性:

1.函数内再嵌套函数

2.内部函数可以引用外层的参数和变量

3.参数和变量不会被垃圾回收机制回收,使变量私有化,容易造成内存的泄漏。

21、”==”和“===”的不同

前者会自动转换类型,再判断是否相等,后者不会自动类型转换,直接去比较

22、函数声明与函数表达式的区别

定义函数的三种方式1、函数声明 2、函数表达式3、new Function构造函数。

在Javscript中,解析器在向执行环境中加载数据时,对函数声明和函数表达式并非是一视同仁的,解析器会率先读取函数声明(函数提升),并使其在执行任何代码之前可用(可以访问),至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解析执行。

hello()

function hello(){

console.log(“函数的声明”)

}

fun()   //这里会报错!

var fun=function(){

console.log(“函数表达式”)

}

23、null和undefined的区别?

null是一个表示"无"的对象,转为数值时为0;undefined是一个表示"无"的原始值,转为数值时为NaN。当声明的变量还未被初始化时,变量的默认值为undefined。null用来表示尚未存在的对象

undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。典型用法是:

(1)变量被声明了,但没有赋值时,就等于undefined。

(2)调用函数时,应该提供的参数没有提供,该参数等于undefined。

(3)对象没有赋值的属性,该属性的值为undefined。

(4)函数没有返回值时,默认返回undefined。

null表示"没有对象",即该处不应该有值。典型用法是:

(1) 作为函数的参数,表示该函数的参数不是对象。

(2) 作为对象原型链的终点。

24、new操作符具体干了什么呢?(面对对象)

1、创建一个空对象

2、将构造函数中的this指向这个对象

3、将属性和方法绑定到这个对象上

4、隐式返回这个对象

25、如何获取javascript三个数中的最大值和最小值?

Math.max(a,b,c);//最大值

Math.min(a,b,c)//最小值

Math.max(…arr) //arr是一个数组[2,5,66,7] 返回66  扩展符

26、 闭包的优点:(32特点)

(1)希望一个变量长期驻扎在内存当中(不被垃圾回收机制回收)

(2)避免全局变量的污染

(3)私有成员的存在

27、如何优化网页加载速度?

1压缩 css和 Js 代码 ,减少css和js的文件大小

2、合并js、css文件,减少http请求

3、将css样式放在顶部,将js脚本放在底部

4、减少DOM操作,尽可能的用变量代替不必要的dom操作。

5、使用外部的js和css。

28、你如何优化自己的代码

1、代码重用:

2、避免全局变量(命名空间,封闭空间,模块化mvc..)

3、拆分函数避免函数过于臃肿

4、适当的注释

5、变量命名规范

6、内存管理,尤其是闭包中的变量的释放。

29、重绘和回流(重排)

回流(重排):

1、当render tree 中的一部分(或全部)因为元素的规模尺寸,布局、隐藏等改变而需要重新构建,这就称为回流

2、当页面布局和几何属性改变时就需要回流

什么是重绘?

1、当render tree 中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如background-color。则就称为重绘。

回流必将引起重绘,而重绘不一定会引起回流

30、栈和堆的区别?

栈(stack):由编译器自动分配释放,存放函数的参数值,局部变量等;

堆(heap):一般由程序员分配释放,若程序员不释放,程序结束时可能由操作系统释放

31、Javascript作用链域

作用域链的原理和原型链很类似,如果这个变量在自己的作用域中没有,那么它会寻找父级的,直到最顶层。

注意:JS没有块级作用域,若要形成块级作用域,可通过(function(){})();立即执行的形式实现

32、 谈谈this的理解-------(this永远指向最后调用它的对象,也就是执行的时候谁调用的)

01、普通函数中的this代表window。

02、事件中的this代表的事件源(特殊IE浏览器attchEvent中的this总指向去全局对象window)

03、定时器中函数代表的window

04、自调用的函数中额this指向window

05、对象中的方法中this的代表的是当前对象

06、箭头函数中this指向定义时的上一层作用域中this

(补充:箭头函数本身没有this和arguments的,在箭头函数中引用this实际上是调用定义时的上一层作用域的this。这里强调是上一层的作用域,是因为对象是不能形成独立作用域的。)

 33es5和es6的区别,说一下你所知道的es6

 ES6新增的一些特性:

 01、声明变量的关键字:let、const-------两个都有块级作用域且var 有变量提升。

 02箭头函数

03模板字符串------模板字符串是增强版的字符串,用反引号(`)标识,可以当作普通字符串使用,也可以用来定义多行字符串

 04解构赋值--------ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值

 05for of循环--------for...of循环可以遍历数组、Set和Map结构、某些类似数组的对象、对象,以及字符串

 06、import、export导入导出----在es6中文件可以默认为一个模块,模块通过export向外暴露接口。通过import导入一个模块,注意import和export只能出现在模块的最外层结构中能够,否则报错。

 07Set数据结构----Set数据结构类似数组,所有的数据都是唯一的,没有一个重复值,它本身是一个构造函数。

 08、展开运算符---- …

 09、class类的继承--- ES6中不再像ES5一样使用原型链实现继承,而是引入class这个概念

10、Promise------es6提供的一个异步编程的方案。

11、Proxy代理------使用代理监听对象的操作

12、修饰器------ decorator 是一个函数,用于修改类似与方法的行为

13、Symbol----- 新的原始数据类型。Symbol 通过调用symbol函数产生,它接收一个可选的名字参数,该函数返回的symbol是唯一的

34、var、let、const之间的区别

 var声明变量可以重复声明,而let不可以重复声明

var是不受限于块级的,而let是受限于块级

var会与window相映射(会挂一个属性),而let不与window相映射

var可以在声明的上面访问变量,而let有暂存死区,在声明的上面访问变量会报错

const声明之后必须赋值,否则会报错

const定义不可变的量,改变了就会报错

const和let一样不会与window相映射、支持块级作用域、在声明的上面访问变量会报错

35、使用箭头函数应注意什么?

(1)箭头函数中的this,不是指向window,而是父级。

(2)不能使用arguments对象(箭头函数中没有this和arguments对象)

(3)不能用作构造函数,就是不能使用new命令,否则会跑出错误。

(4)不可以使用yeild命令。因此箭头函数不能用作Generator函数

(补充:Generator函数作为一个用来操作异步的状态机,遇到yeild停止,通过调用next()来继续操作,一:function关键字与函数名之间有一个星号,函数体使用yeild(类似return)产出不同的状态。)

36、ECMAScript 6 怎么写 class ,为何会出现 class?

ES6的class可以看作是一个语法糖,它的绝大部分功能ES5都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法

class Person{constructor(name){         this.name=name  //this关键字代表实例对象     }     say(){         console.log(123)    }}var person =new Person(‘张三’);person.say()

37、说一下es6的导入导出模块

导入通过import关键字

import {sum} from "./example.js"  导入一个模块中一个成员

import {sum,multiply,time} from "./exportExample.js"  //导入多个

import * as example from "./exportExample.js"    //导入一整个模块

导出通过export关键字

export var name = 'Michael';

export {firstName, lastName, year};

使用export default时,对应的import语句不需要使用大括号

let bosh = function crs(){ }

export default bosh; //导出

import crc from 'crc'; //导入

不使用export default时,对应的import语句需要使用大括号

let bosh = function crs(){ }

export bosh; //导出

import {crc} from 'crc'; //导入

在es6中文件可以默认为一个模块,模块通过export向外暴露接口。通过import导入一个模块,注意import和export只能出现在模块的最外层结构中能够,否则报错。

Export default向外暴露成员只允许一次

38、http和https 区别;

HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。简单来说,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。

HTTPS和HTTP的区别主要如下:

1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。

2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。

3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、

身份认证的网络协议,比http协议安全。

39、简述readyonly与disabled的区别:

1、readonly 只针对input(type为text和password)和textarea有效。而disabled对于所有的表单元素都有效。

2、当表单元素使用了disabled后,当我们将表单以PSOT和get方式提交的话,这个元素的值不会被传递出去,而readonly将会把值传递出去。

40、同步和异步的区别:同步异步主要是事情做完以后,如何进行处理、或者说关注的是一种消息通信机制。

            同步:同步相当于当客户端发送请求给服务端。在等待服务端的响应请求时,客户端不做其他事情。

当服务端做完了才返回给客户端,这样的话客户端一直等待,用户使用起来不友好。

异步:当客户端发送给服务器请求时,在等待服务器响应的时候吗,客户端可以做其他的事情,不用等待服务端的响应,

你可能感兴趣的:(js用递归遍历多维数组)