總結(jié)一下前端常見javascript基礎(chǔ)面試題:

1.var ,let 和const的區(qū)別:

let和const是es6新增的語法, let和var都可以定義變量,但是二者作用域不同,let有塊級作用域,var沒有。所以在var變量值會存在變量提升現(xiàn)在,而let不會;const是定義常量。

2.typeof返回類型:

區(qū)分值類型和引用類型;

值類型: Number,String,Boolean,Undefined,Symbol

引用類型:Object,function,null(typeof null === 'object')

所以typeof的返回值為?Number,String,Boolean,Undefined,Symbol Object,function。常見的強制類型轉(zhuǎn)換parseInt,parseFloat,toString。常見的隱式類型轉(zhuǎn)換:拼接字符串, == ,等等;

3.數(shù)組slice和splice區(qū)別:

slice: slice(startIndex, endIndex),如果傳入一個參數(shù),默認從startIndex剪切到endIndex = (arr.lenght-1);

splice: splice(startIndex, number, string),和slice類似,但是只限于類似。第一個參數(shù)是起始位置,第二個參數(shù)是需要剪切的數(shù)量,第三個參數(shù)是你需要插入數(shù)組中的內(nèi)容。也可以設(shè)置第二個參數(shù)為0,不剪切數(shù)據(jù),直接插入數(shù)據(jù),和數(shù)組的常用方法(push, pop,unshift,shift)聯(lián)系起來。

兩者最大的區(qū)別就是slice是純函數(shù),splice是非純函數(shù);

4.[10, 20, 30].map(parseInt)輸出內(nèi)容是什么?

[10, 20, 30].map(parseInt) 等價于[10, 20, 30].map( (item, index) => { return parseInt(item, index)});所以問題等價于返回的數(shù)組中的值是什么?parseInt(10, 0) = 10; parseInt(20, 1) = NaN; parseInt(30, 2) = NaN;

5.get請求和post請求之間的區(qū)別?

1.get一般請求url地址查詢,post一般提交表單操作;

2.get參數(shù)拼接在url上,受url長度限制;post請求放在請求體內(nèi),所以post請求數(shù)據(jù)體積可以較大;

3.安全性: post易于防止CSRF攻擊(cross-site request forgery跨站偽請求,偽造你的信息,向服務(wù)器發(fā)送請求,竊取賬號密碼);

6.call, apply, bind的區(qū)別?

三者都是改變函數(shù)this的指向,call和apply只是參數(shù)傳遞有區(qū)別:call(this, a1, a2, a3, ...), apply(this, argument) argument是數(shù)組或者偽數(shù)組(或者說是集合);call和bind的區(qū)別:bind返回一個函數(shù)對象;

7.事件的委托(代理):

事件的委托(代理)是通過事件的冒泡實現(xiàn)的,事件的冒泡可以理解為由下向上觸發(fā)父級元素事件的一個過程(氣泡會受到浮力,從下往上運動)。給父級元素綁定事件,可以通過子元素來觸發(fā),這就是事件委托(代理)。

8.函數(shù)閉包和閉包的特性,有何負面影響?

函數(shù)和對其周圍狀態(tài)(lexical environment,詞法環(huán)境)的引用捆綁在一起構(gòu)成閉包closure)。也就是說,閉包可以讓你從內(nèi)部函數(shù)訪問外部函數(shù)作用域。在 JavaScript 中,每當函數(shù)被創(chuàng)建,就會在函數(shù)生成時生成閉包。(MDN官方介紹?https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures

閉包的特性:函數(shù)作為參數(shù)或者返回值。閉包會占用內(nèi)存,得不到釋放。(自由變量的查找是在函數(shù)定義的地方,而不是函數(shù)使用的地方)。

9.阻止事件冒泡和默認行為的方法?

阻止冒泡:event.stoppropagation;阻止默認行為:event.preventdefault;

10.如何減少DOM操作?

1.緩存DOM的查詢結(jié)果

2.多次DOM操作合并到一次(Fragment)

11.函數(shù)聲明和函數(shù)表達式的區(qū)別?

函數(shù)表達式:const fn = function () { };函數(shù)聲明:function fn () { };兩者的區(qū)別就是函數(shù)表達式會預(yù)解析(頁面加載時會提前解析函數(shù)聲明,函數(shù)聲明寫在邏輯后面,也會執(zhí)行生效),而函數(shù)表達式不會。

12.new Object( )和Object.creat( )區(qū)別?

new Object( ) === { };我們習慣于 const obj = { }這中寫法,其實這種寫法等于 const obj = new Object ( )。new Object ( )的原型指向于Object.prototype,即obj.__proto__ === Object.prototype。Object.creat(null)是沒有原型的(Object.prototype.__proto__? === null),但是Object.creat({ })可以指定原型。

例如:const obj1 = { }; const obj2 = Object.creat(obj1);??obj2.__proto__ === obj1

13.關(guān)于this:

this指向其實就是作用域和調(diào)用對象的問題。

14.手寫字符串trim方法:

trim是去除字符串開頭或結(jié)尾處的空格的方法。例如 const? str = '? hello? '; console.log(str.trim()) = 'hello';

為了保證兼容性,我們可以使用正則表達式的方式改寫trim方法:

String.prototype.trim_ =function(str) {

????return str.replace(/^\s+/, '').replace(/\s+$/, '');

}

(^表示開頭,\s表示空格,+表示一個或多個,$表示結(jié)尾)

15.求數(shù)組中的最大值

方法有多種:

1.簡單暴力:直接調(diào)用Api。Math.max()

2.利用數(shù)組的sort()方法,然后去最后一位數(shù)。(sort()方法是用來排序的,按從小到大的順序),arr.sort([...])[arr.length - 1]

3.利用forEach循環(huán),(map也行,但是map返回值是默認是數(shù)組,所以如return的值要修改)

const arr = [];

let max =arr[0];

arr.forEach( item => max = max < item ? max = item :max)

4.利用for循環(huán):

const arr = [];

let max =arr[0];

for (let i =0; i < arr.length; i ++) {

max < arr[i] ? max = arr[i] : max

}

5.冒泡算法

16.如何實現(xiàn)繼承?

ES6中新增的class方法,extends和super關(guān)鍵字就可以實現(xiàn)繼承。ES5可以通過prototype實現(xiàn)繼承。

17.如何捕獲js程序中的異常?

1.手動捕獲異常:try{ },catch{ },finally{ }方法。一般會在異步調(diào)用的時候用到。(promise函數(shù)。promise函數(shù)是同步,then方法才是異步)

2.自動捕獲異常:通過window.onerror = function(message,source,lineNum,colNum,error) { } (對于跨域的js,如cdn,沒有詳細的報錯原因;對于壓縮的js,還要配合sourcemap反查到未壓縮的行、列)。

18.獲取當前頁面url參數(shù)

有兩種方式:

1.這里需要用到bom中l(wèi)ocation的一個api:location.search(BOM: location, navigator, screen,history)。通過location.search我們可以拿到url的參數(shù)(包括問號,所以需要用substr方法進行修改)。

function getUrl() {

const str =location.search.substring(1);//拿到問號后面的字符串。例如:?id=666&&name=zhangsan => //id=666&&name=zhangsan

? ? const value = str.split('&&').map( item => {/*map是純函數(shù)方法,返回一個數(shù)組,如果用forEach會顯示undefined,因為forEach沒有返回值 */

????????????const arr = item.split('=');//把=切割,返回一個數(shù)組,包含兩個元素

? ? ????????? ? const key = arr[0];//把數(shù)組的第一項復(fù)制給key

? ? ? ????????? const value = arr[1];//把數(shù)組的第二項賦值給value

? ? ? ? ????return { key, value }

????????})

}

2.第二種是直接使用URLSearchParams

function getUrl(url) {

const str =location.search;

? ? const paras =new URLSearchParams(str);//URLSearchParams是一個class構(gòu)造函數(shù)

? ? paras.get(url)

}

3.使用正則表達式

19.數(shù)組排平(flatten)比如:[1, 2, 5, [1, 2, 5], 7] 變成[1, 2, 5, 1, 2, 5, 7],[1, [2, 3, 4], [1, [ 2, 3, [ 4, 5] ] ], 6] = [ 1, 2, 4, 5, 1, 2, 3, 4, 5, 6]

首先這個問題肯定涉及到數(shù)組合并的問題,concat()方法是肯定需要使用的。Array.prototype.concat.apply([ ], arr)這句代碼的意思就是合并arr數(shù)組里面的數(shù)組,但是只會合并兩層(例如:Array.prototype.concat.apply([ ], [1, [2, 3])? === [1, 2, 3])Array.prototype.concat.apply([ ], arr)其實可以寫成 [ ].concat(arr)

const arr = [1, 2, 4, [2, 4, 5, [1, 2, [4]]]];

function flatten(arr) {

????let res =Array.prototype.concat.apply([], arr)

????const flag = arr.some(item => iteminstanceof Array)//some( ) 返回一個Boolean值

????if (flag) {

????????return flatten(res)//如果i數(shù)組中還嵌套數(shù)組,遞歸

}

????return arr;

}

console.log(flatten(arr));// [1, 2, 4, 2, 4, 5, 1, 2, 4]

20.數(shù)組去重

1.使用Set( )函數(shù):

function unique1(arr) {

????const set =new Set(arr);

? ? return [...set]//ES6結(jié)構(gòu)賦值

}

2.遍歷數(shù)組(性能上有所欠缺,需要多次遍歷,indexOf本質(zhì)也是遍歷)

function unique2(arr) {

????const res = [];

? ? arr.forEach( item => {

????????if (res.indexOf(item) <0) {

????????res.push(item)

????????}

????})

????????return res;

}

21.數(shù)組排序(升序,降序)

1.使用Array.prototype.sort( )方法。sort()排序規(guī)則是按照UTF-16編碼排序。sort( )中可以傳入函數(shù)作為參數(shù)。

? ?升序:arr.sort((a, b) => a - b);降序:arr.sort((a, b) => b - a);

2.冒泡算法。冒泡算法就是將數(shù)組元素中相鄰的兩個元素的值大小做比較,交換順序。

????for (let i =0; i < arr.length; i ++ ) {

????????for (let j =0; j < arr.length - 1 - i; i ++) {

????????????if (arr1[j] >arr1[j +1]) {

????????????????let temp =arr1[j];

? ? ? ? ? ? ????arr1[j] =arr1[j +1];

? ? ? ? ? ? ? ? arr1[j +1] = temp;

? ? ?????????? }

????????}

????}

22.手寫深拷貝

涉及到多層次的對象和數(shù)組就需要遞歸

function deepClone(obj) {

????let res;

? ? if (typeof obj ==="object" || obj ==null) { //判斷傳入?yún)?shù)的類型

????????return obj;

? ? }

????if (obj instanceof Array) { //是數(shù)組則賦值為數(shù)組

????res = [];

? ? }????else {

????????res = { } //否則賦值為對象

????}

????for (let keyin obj) {

????????if (obj.hasOwnProperty(key)) {//這個是為了代碼嚴謹。obj上可能會有原型的key。不寫不太影響結(jié)果

????????????res[key] =deepClone(obj[key]);//遞歸

????????}

}

????return res;

}

22.函數(shù)節(jié)流防抖

1.函數(shù)防抖:

function debounce(fn, delay) {

????let timer;

? ? return function () {

????????if (timer) {

????????????clearTimeout(timer);

? ? ? ? }

????timer =setTimeout(function () {

????????fn.apply(this, arguments)

????????})

????????timer =null;

? ? }

}

2.函數(shù)節(jié)流:

function throttle(fn, delay) {

? ? ?let timer =null;

? ? return function () {

????????if (timer) {

????????return;

? ? ? ? }

????timer =setTimeout(function () {

????????fn.apply(this, arguments)

????????}, delay);

? ? ? ? timer =null;

? ? }

}

23.Promise函數(shù)和異步

Promise是ES6中新增的函數(shù)。主要是解決callback hell(回調(diào)地獄)。Promise((resolve,rejecte)=> {})三種狀態(tài):pending(將要進行)、fulfilled(完成)、rejecte(失?。?。同時還衍生了generator函數(shù),async await(解決then()回調(diào)問題)。Promise函數(shù)體是同步,then()方法是異步。then( () => { } )接受成功的回調(diào)函數(shù),catch(() => { })接受失敗后的回調(diào)。?

24.Cookie、session、Localstorage、Sessionstorage的區(qū)別和作用

Cookie中的數(shù)據(jù)存儲在客戶端,session中的數(shù)據(jù)存儲在服務(wù)器端。所以從安全性上考慮,用戶的登陸信息需要存儲在session當中。cookie中僅保存一些非安全性的信息,比如用戶登陸狀態(tài)過期的時間,如果不設(shè)置用戶登陸狀態(tài)過期時間,默認頁面關(guān)閉,登陸狀態(tài)也就消失。

Localstorage是把數(shù)據(jù)存儲在瀏覽器本地的一種存儲方式。如果用戶不手動清除數(shù)據(jù)信息,則數(shù)據(jù)不會消失。Sessionstorage則是僅保存當前頁面的數(shù)據(jù)信息。當前頁面關(guān)閉,則數(shù)據(jù)信息自動清除。

在存儲大小方面。cookie的存儲容量為4kb左右,session為4mb。

25.地址欄輸url會發(fā)生什么?

1.第一步是查看本地緩存

2.第二步是域名DNS解析

3.第三部是建立TCP鏈接

4.第四步是發(fā)起HTTP請求

5.瀏覽器接收到服務(wù)器返回的文件,渲染

26.TCP/IP模型

TCP/IP是一系列網(wǎng)絡(luò)協(xié)議的總稱。這些協(xié)議的目的是使得計算機之間可以進行信息交換。

TCP/IP模型四層架構(gòu)從上到下分別是鏈路層、網(wǎng)絡(luò)層、傳輸層、應(yīng)用層

1.鏈路層的作用是負責建立電路連接,是整個網(wǎng)絡(luò)的物理基礎(chǔ),典型的協(xié)議包括以太網(wǎng)、ADSL等。

2.網(wǎng)絡(luò)層負責分配地址和傳送二進制數(shù)據(jù),主要要協(xié)議是IP協(xié)議

3.傳輸層負責傳送文本數(shù)據(jù),主要協(xié)議是TCP

4.應(yīng)用層負責傳送各種最終形態(tài)的數(shù)據(jù),是直接與用戶信息打交道的層,主要寫是HTTP、ftp等

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容