1. 程式人生 > 實用技巧 >前端面試題集錦-2021年前端面試題收集題庫3

前端面試題集錦-2021年前端面試題收集題庫3

常見的javascript 語句基本規範

1.變數和函式的命名規則

  • 命名規則-駝峰命名法
  • 建構函式首字母大寫

2.空格,縮排,註釋的使用規範

  • 一般使用2空格代替tab
  • 註釋多行用 /** */
  • 單行註釋直接 //

3.其他使用規範

  • 判斷變數是否相等時使用===強等型別判斷一起
  • switch語句必須有default分支
  • 使用字面量建立陣列和物件代替new Array()
  • 不要在同一行宣告多個變數
  • 不要使用全域性函式
  • 函式不應該有時有返回值,有時沒有返回值

eval函式的功能是什麼

定義和用法

用來計算某個字串,並且執行其中的JavaScript程式碼

語法

eval(string)

需要注意的點

  • 如果傳入 eval() 的引數不是字串,則會直接返回該引數
  • 非嚴格模式下直接呼叫 eval() 時,裡面使用 var 宣告的變數和使用 function 宣告的函式會修改當前詞法作用域,裡面使用 let 和 const 宣告的變數不會修改當前詞法作用域,但是會在當前建立新的詞法作用域。
  • 非嚴格模式下間接引用 eval() 時,會直接執行在全域性環境中,裡面使用 var 宣告的變數和使用 function 宣告的函式會修改全域性詞法作用域,裡面使用 let 和 const 宣告的變數不會修改全域性詞法作用域,但是會在全域性環境建立新的詞法作用域
  • 使用 window.eval() 等同於間接引用 eval()
  • eval() 中執行的程式碼只能呼叫 JS 直譯器(Interpreter)來解釋執行,無法被即時編譯器(JIT Compiler)優化, eval() 中的執行的程式碼可能會導致 JS 引擎在已經生成的機器程式碼中進行變數查詢和賦值,帶來效能問題。
  • eval() 使用不當可能會導致裡面執行的字串容易遭受惡意修改,帶來安全問題(比如 XSS 攻擊)。
  • 使用 eval() 會干擾程式碼壓縮工具的行為。程式碼壓縮工具一般會將區域性變數名重新命名為更短的變數名(如 a 和 b 等),以便減小程式碼體積。當使用了 eval() 時,由於外部的區域性變數可能會被 eval() 訪問到,程式碼壓縮工具便不會對可能會被 eval() 訪問到的區域性變數名進行壓縮,會降低程式碼壓縮率。

執行一下程式碼結果是什麼["1","2","3"].map(parseInt)

  • 上面程式碼主要考察高階函式 mapparseInt 函式
    ['1','2','3'].map(parseInt(item,index))
    => parseInt('1',0)
    => parseInt('2',1)
    => parseInt('3',2)
    // parseInt 第一個引數為 需要被轉換的字串
    // parseInt 第二個引數為 被轉換字串的進位制
    // parseInt('2',1) 表示將 1進位制的 字串‘2’轉換為10進位制,不存在1進位制的字串'2',所以返回值為NaN
  • 所以最後的返回值為[1,NaN,NaN]

說說對this物件的理解

  • this執行上下文
  • 表示函式執行時的上下文
  • 預設指向函式執行的上下文 全域性執行則是window,引用物件呼叫則是引用物件
var name = 'jeskson';
function person() {
 return this.name;
}

console.log(this.name); // jeskson
console.log(window.name); // jeskson
console.log(person()); // jeskson
  • 使用call和apply可以指定上下文

function person() {
 return this.name;
}

var obj = {
 name: 'jeskson'
}

console.log(person.call(obj)); // jeskson
console.log(person.apply(obj)); // jeskson
  • 建構函式中this指向構造出來的新物件
function Person(name) {
 this.name = name;
 return name;
}
console.log(new Person('jeskson').name); // jeskson

  • 複雜的this指向問題,需要考慮函式執行上下文的出棧和壓棧問題判斷

JavaScript中存在哪些偽陣列,如何將偽陣列轉化為陣列

  • 常見的偽陣列:arguments document.getElementsByTagName獲取的元素標籤集合
  • 區別和相似:
    • 相似: 都具有 length 屬性,都是有序的引用組合,可以下標獲取元素,偽陣列也是可迭代物件,可以呼叫 for of
    • 區別:Array.isArray,偽陣列為false,並且陣列的類方法不能使用,例如遍歷的forEach等
  • 如何轉換:
    • Array.from (偽陣列) 可以將偽陣列轉化為正常的標準陣列
    • Array.prototype.slice.call(偽陣列) 實際上是呼叫陣列的 slice 方法
    • 利用偽陣列的可迭代特性,for of 手動 push 到空的標準陣列

JavaScript中的callee和caller的作用是什麼

  • caller 是JavaScript中函式型別的自由屬性,用來標識函式的呼叫的函式,如果是父函式中引用呼叫子函式,則子函式的caller是父函式,如果函式直接在頂層JavaScript環境中呼叫,那麼caller則是 null
  • callee 則是函式呼叫時 偽陣列 arguments 的屬性,此屬性返回的是當前函式執行本體,例如
    function test(){
        console.log(arguments.callee)
    }
    test()
    // 返回值是test函式本身,返回值可以直接呼叫類似 arguments.callee()
  • 作用:
    • caller 用來朔源,標識函式的呼叫鏈,用來除錯和觀察
    • callee 用來函式本身對自身的回撥,例如 遞迴呼叫,可以脫離函式名,通過這個屬性直接呼叫自身

統計字串中字母的個數或統計最多的字母

function countStr(str) {=
    let dic = str.split('').reduce((prev,current)=>{
        if(prev[current] && prev[current].value === current) ++prev[current].count
        else prev[current] = {
            value:current,
            count:0
        }
        return prev
    },{})
    for(let index = 0;index< Object.keys(dic).length;index++){
        let k = Object.keys(dic)[index]
        console.log(dic[k].value + ' : '+ dic[k].count)
    }
}

寫一個函式清除字串前後的空格

  • 考察正則
function trim(str) {
    if (str && typeof str === "string") {
        return str.replace(/(^\s*)|(\s*)$/g,""); //去除前後空白符
    }
}

  • 另一種方式
function quickTrim(str) {
    let temp = str.split('')
    let resultArry = temp.reduce((count,ele)=>{
        if(ele !== ' ') count.push(ele)
        return count
    },[])
    return resultArry.join('')
}

寫一個函式實現一個數組合並的方法

  • 遍歷
 b.forEach(ele=>{
     a.push(a)
 })
  • Array自帶的concat方法
    a.concat(b)
  • 巧用apply和push
    • push可以接受多個引數,全部push到數組裡面
    • apply會把陣列當作引數組合傳入
    a.push.apply(a,b)

工作中,常用的邏輯運算子有哪些

  • &&
  • ||
  • !

什麼是事件代理(事件委託)

  • 原理
    • 事件冒泡:js在處理事件時,如果當前 dom 沒有對事件進行接收和捕獲,事件會順著 dom樹的結構自下往上傳遞,最終在根節點dom
  • 實現
    • 在 父dom結構上進行事件捕獲和事件處理,通過 Event target 物件判斷具體觸發物件
    • 子元素例如 li 元素不監聽事件,將事件委託給 ul 元素處理和捕獲
  • 優點
    • 減少dom樹的遍歷和dom事件的繫結,效能優化
    • 子元素修改或者新增時不需要重新進行事件繫結

未宣告和未定義的變數有什麼區別

  • 未宣告
    • 記憶體空間沒有開闢
    • 沒有這個東西存在
    • 不存在 但是直接呼叫
    • 或報錯,提示未宣告
  • 未定義
    • 已開闢記憶體空間
    • 但是記憶體空間並沒有東西
    • 用來形容這種狀態的 js 資料型別叫做 undefined

什麼是全域性變數,這些變數如何宣告,使用全域性變數有哪些問題

  • 作用域
    • js 中只有函式可以包裹作用域
  • 全域性作用域
    • 沒有包裹在函式內部,最外層的作用域
  • 怎麼宣告
    • 直接在最外層宣告
    • 用window物件 宣告
    • 不用var 關鍵字,直接寫變數名也會提升到全域性
  • 會有什麼問題
    • 容易出現變數名衝突,影響全域性
    • 不利於回收,出現記憶體效能問題
    • 變數和程式碼混亂

常用的定時器工作說明,使用定時器的缺點

  • 常用的定時器
    • setTimeOut
      • 定時一段時間之後執行
    • setTimeInterval
      • 間隔一段時間重複執行
  • 清除定時器
    • clearTimeInterval
      • 只有知道具體的定時器名稱才可以關閉
      • 如果不關閉定時器,會一直執行,直到頁面退出,記憶體釋放

說說ViewState和SessionState有什麼區別

  • ViewState 是.net 提出的一種客戶端資料儲存的方式,通過一個隱藏的dom節點,儲存一些可序列化的資料結構
  • SessionState 是儲存於服務端的一種資料結構,同主機域名下的所有tab頁面可以共享
  • 這個都沒接觸過了

什麼是 === 運算子

  • 強等運算子
  • 比較過程中不進行強制型別轉換
  • 並且在比較之前優先進行型別判斷,如果資料型別不一樣,直接返回 false