js用递归遍历多维数组_js面试题更新之40
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次undefinedfor?(let?i?=?0;?i????setTimeout(function(){??????????? console.log(arr[i])?????????})?????? } //輸出 1 2 3 4 5 55、前端有哪幾種本地存儲方式,簡述各自的特點(請描述一下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、 setTimeout10、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。這里強調是上一層的作用域,是因為對象是不能形成獨立作用域的。)
?33、es5和es6的區別,說一下你所知道的es6
?ES6新增的一些特性:
?01、聲明變量的關鍵字:let、const-------兩個都有塊級作用域且var?有變量提升。
?02、箭頭函數
03、模板字符串------模板字符串是增強版的字符串,用反引號(`)標識,可以當作普通字符串使用,也可以用來定義多行字符串
?04、 解構賦值--------ES6 允許按照一定模式,從數組和對象中提取值,對變量進行賦值
?05、for of循環--------for...of循環可以遍歷數組、Set和Map結構、某些類似數組的對象、對象,以及字符串
?06、import、export導入導出----在es6中文件可以默認為一個模塊,模塊通過export向外暴露接口。通過import導入一個模塊,注意import和export只能出現在模塊的最外層結構中能夠,否則報錯。
?07、Set數據結構----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用递归遍历多维数组_js面试题更新之40的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: docker 安装nginx_使用 Do
- 下一篇: laravel redis_如何将red