2022年前端js面試題

還有部分沒更新完...

var、let、const區(qū)別

1. var存在變量提升,而let、const沒有
2. let、const有塊級作用域,而var沒有
3. var 在同一塊作用域可以重復聲明多個相同的變量,后者覆蓋前者,let、const重
復聲明會報錯
4.let、var聲明變量后可以進行改變值,const聲明不能修改([對象、數組]的屬性和方法可以改變

合并對象的方法可以寫幾種

const obj1 = {a:'a',b:'b',c:'c'};
const obj2 = {c:'c',d:'d',e:'e'};
方式一:使用ES6的拓展運算符
{...obj1,...obj2}
方式二:Object.assign(obj1,obj2);
方式三:手寫遍歷
function assign(obj1,obj2){
    for(let key in obj2){
        obj1[key] = obj2[key];
    }
   return obj1;
}
assign(obj1,obj2);

find和filter的區(qū)別

1. find 條件符合就找到第一個符合的元素返回,否則返回 undefined
2. filter 如果條件符合  就返回一個新的數組(多個元素),否則返回空數組[]

some和every的區(qū)別

1. every()是對數組中每一項運行給定函數,如果該函數對每一項返回true,則返回true。 有點&&的意思
2. some()是對數組中每一項運行給定函數,如果該函數對任一項返回true,則返回true。有點||的意思

深拷貝和淺拷貝

箭頭函數和普通函數有什么區(qū)別

1. 箭頭函數不能用于構造函數,如果使用會報錯
2. 箭頭函數沒有 arguments對象、prototype 原型對象
3. 箭頭函數的this在定義時就已經指定,而普通函數是調用時才指定,如果普通函數用于構造函數this的指向就是當前實例

Promise有幾種狀態(tài)

1. pending(初始狀態(tài))
   pending的意思是“待定的,發(fā)生的”,相當于是一個初始狀態(tài)。創(chuàng)建[Promise]對象時,且沒有調用resolve或者是reject方法,相當于時初始狀態(tài)。這個初始狀態(tài)會隨著你調用resolve,或者是reject函數而切換到另一種狀態(tài)。

2 . resolved(成功態(tài))
    resolved表示成功了。當[Promise]實例對象中異步任務順利完成且返回結果值時,就調用了resolved這個參數

3. rejected(失敗狀態(tài))
   rejected 失敗,當[Promise]實例對象中異步任務執(zhí)行失敗時,就調用了resolved這個參數

localstorage、sessionstorage、cookie的區(qū)別

一、存儲的時間有效期不同
1、cookie的有效期是可以設置的,默認的情況下是關閉瀏覽器后失效
2、sessionStorage的有效期是僅保持在當前頁面,關閉當前會話頁或者瀏覽器后就會失效
3、localStorage的有效期是在不進行手動刪除的情況下是一直有效的

二、存儲的大小不同
1、cookie的存儲是4kb左右,存儲量較小,一般頁面最多存儲20條左右信息
2、localStorage和sessionStorage的存儲容量是5Mb(官方介紹,可能和瀏覽器有部分差異性)

三、與服務端的通信
1、cookie會參與到與服務端的通信中,一般會攜帶在http請求的頭部中,例如一些關鍵密匙驗證等。
2、localStorage和sessionStorage是單純的前端存儲,不參與與服務端的通信

JS數據類型有哪些

基本類型:String、Number、Boolean、Undefined、Null、Symbol、Bigint
引用類型:Object(Array、Function、Date、RegExp)
注意:typeof null 返回的是 'object' 
      NaN是一個Number類型,但是不是一個具體的數字
      typeof NaN 返回的是 'number'

null和undefined的區(qū)別

1. 作者在設計js的都是先設計的null(為什么設計了null:最初設計js的時候借鑒了java的語言)
2. null會被隱式轉換成0,很不容易發(fā)現錯誤。
3. 先有null后有undefined,出來undefined是為了填補之前的坑。
具體區(qū)別:JavaScript的最初版本是這樣區(qū)分的:null是一個表示"無"的對象(空對象指針),轉為數值時為0;undefined是一個表示"無"的原始值,轉為數值時為NaN。

==和===有什么不同

==  :  比較的是值
        
        string == number || boolean || number ....都會隱式轉換
        通過valueOf轉換(valueOf() 方法通常由 JavaScript 在后臺自動調用,并不顯式地出現在代碼中。)

=== : 除了比較值,還比較類型

JS微任務和宏任務

1. js是單線程的語言。
2. js代碼執(zhí)行流程:同步執(zhí)行完==>事件循環(huán)
    同步的任務都執(zhí)行完了,才會執(zhí)行事件循環(huán)的內容
    進入事件循環(huán):請求、定時器、事件....
3. 事件循環(huán)中包含:【微任務、宏任務】
微任務:promise.then
宏任務:setTimeout..

要執(zhí)行宏任務的前提是清空了所有的微任務

流程:同步 > 事件循環(huán)【微任務和宏任務】> 微任務 > 宏任務 > 微任務...

JS作用域

1. 除了函數外,js是沒有塊級作用域。
2. 作用域鏈:內部可以訪問外部的變量,但是外部不能訪問內部的變量。
     注意:如果內部有,優(yōu)先查找到內部,如果內部沒有就查找外部的。
3. 注意聲明變量是用var還是沒有寫(window.)
4. 注意:js有變量提升的機制【變量懸掛聲明】
5. 優(yōu)先級:聲明變量 > 聲明普通函數 > 參數 > 變量提升

JS判斷變量是不是數組,你能寫出哪些方法

1. isArray
2. Array.prototype.isPrototypeOf([])
3. Object.prototype.toString.call([]).indexOf('Array') > -1
4. [].constructor.toString().indexOf('Array') > -1

slice是干嘛的、splice是否會改變原數組

1. slice是來截取的
    參數可以寫slice(3)、slice(1,3)、slice(-3)
    返回的是一個新的數組
2. splice 功能有:插入、刪除、替換
    返回:刪除的元素
    該方法會改變原數組

JS數組去重

方式一:new set

const arr= [1,2,3,2,4,1];
function unique(arr){
    return [...new Set(arr)]
}

方式二:Object的key是唯一
function unique(arr) {
  const param = {};
  arr.forEach(key => {
    param[key] = key;
  });
  return Object.keys(param);
};

方式三:indexOf

function unique( arr ){
    var brr = [];
    for( var i=0;i<arr.length;i++){
        if(  brr.indexOf(arr[i]) == -1 ){
            brr.push( arr[i] );
        }
    }
    return brr;
}

方式四:sort

function unique( arr ){
    arr = arr.sort();
    var brr = [];
    for(var i=0;i<arr.length;i++){
        if( arr[i] !== arr[i-1]){
            brr.push( arr[i] );
        }
    }
    return brr;
}

找出多維數組最大值

function fnArr(arr){
    var newArr = [];
    arr.forEach((item,index)=>{
        newArr.push( Math.max(...item)  )
    })
    return newArr;
}
console.log(fnArr([
    [4,5,1,3],
    [13,27,18,26],
    [32,35,37,39],
    [1000,1001,857,1]
]));

給字符串新增方法實現功能

給字符串對象定義一個addPrefix函數,當傳入一個字符串str時,它會返回新的帶有指定前綴的字符串,例如: console.log( 'world'.addPrefix('hello') ) 控制臺會輸出helloworld

String.prototype.addPrefix = function(str){
    return str  + this;
}
console.log( 'world'.addPrefix('hello') )

找出字符串出現最多次數的字符以及次數

var str = 'aaabbbbbccddddddddddx';
var obj = {};
for(var i=0;i<str.length;i++){
    var char = str.charAt(i);
    if( obj[char] ){
        obj[char]++;
    }else{
        obj[char] = 1;
    }
}
console.log( obj );
//統(tǒng)計出來最大值
var max = 0;
for( var key in obj ){
    if( max < obj[key] ){
        max = obj[key];
    }
}
//拿最大值去對比
for( var key in obj ){
    if( obj[key] == max ){
        console.log('最多的字符是'+key);
        console.log('出現的次數是'+max);
    }
}

new操作符具體做了什么

1. 創(chuàng)建了一個空的對象
2. 將空對象的原型,指向于構造函數的原型
3. 將空對象作為構造函數的上下文(改變this指向)
4. 對構造函數有返回值的處理判斷

實現代碼如下 :
function Fun( age,name ){
    this.age = age;
    this.name = name;
}
function create( fn , ...args ){
    var obj = {};
    Object.setPrototypeOf(obj,fn.prototype);
    var result = fn.apply(obj,args);
    return result instanceof Object ? result : obj;
}
console.log( create(Fun,18,'張三')   )

說一下call、apply、bind區(qū)別

1. 共同點:功能一致,都是可以改變this指向
2. 語法: 函數.call()、函數.apply()、函數.bind()
3. 區(qū)別一:參數不同,apply第二個參數是數組,call和bind有多個參數需要挨個寫
   區(qū)別二:call、apply都是立即執(zhí)行 bind不會立即執(zhí)行,因為bind返回的是一個函數需要加入()執(zhí)行

場景:

1. 用apply的情況
var arr1 = [1,2,4,5,7,3,321];
console.log( Math.max.apply(null,arr1) )

2. 用bind的情況
var btn = document.getElementById('btn');
var h1s = document.getElementById('h1s');
btn.onclick = function(){
    console.log( this.id );
}.bind(h1s)

閉包

1. 閉包是什么
    閉包是一個函數加上到創(chuàng)建函數的作用域的連接,閉包“關閉”了函數的自由變量。
2. 閉包可以解決什么問題【閉包的優(yōu)點】
    2.1 內部函數可以訪問到外部函數的局部變量
    2.2 閉包可以解決的問題
            var lis = document.getElementsByTagName('li');
      for(var i=0;i<lis.length;i++){
        (function(i){
          lis[i].onclick = function(){
            alert(i);
          }
        })(i)
      }
3. 閉包的缺點
    3.1 變量會駐留在內存中,造成內存損耗問題。
                解決:把閉包的函數設置為null
  3.2 內存泄漏【ie】 ==> 可說可不說,如果說一定要提到ie

原型鏈


1. 原型可以解決什么問題:解決了對象的共享屬性、方法
2. 誰有原型:函數擁有prototype、對象擁有__proto__
3. 對象查找屬性或者方法的順序
    先在對象本身查找 > 構造函數中查找 > 對象的原型 > 構造函數的原型中 > 當前原型的原型中查找
4. 原型鏈的最頂端是null

JS繼承有哪些方式

1. ES6 class 的extends
2. 原型鏈繼承
3. 借用構造函數繼承
4. 組合式繼承(原型鏈繼承和借用構造函數繼承)

方式一:ES6
class Parent{
    constructor(){
        this.age = 18;
    }
}

class Child extends Parent{
    constructor(){
        super();
        this.name = '張三';
    }
}
let o1 = new Child();
console.log( o1,o1.name,o1.age );


方式二:原型鏈繼承

function Parent(){
    this.age = 20;
}
function Child(){
    this.name = '張三'
}
Child.prototype = new Parent();
let o2 = new Child();
console.log( o2,o2.name,o2.age );


方式三:借用構造函數繼承

function Parent(){
    this.age = 22;
}
function Child(){
    this.name = '張三'
    Parent.call(this);
}
let o3 = new Child();
console.log( o3,o3.name,o3.age );

方式四:組合式繼承

function Parent(){
    this.age = 100;
}
function Child(){
    Parent.call(this);
    this.name = '張三'
}
Child.prototype = new Parent();
let o4 = new Child();
console.log( o4,o4.name,o4.age );

延遲加載JS有哪些方式

1. defer 是等html全部解析完成,才會執(zhí)行js代碼,順次執(zhí)行js腳本。
2. async 是和html解析同步的(并行的),不是順次執(zhí)行js腳本(誰先加載完誰先執(zhí)行)
3. 使用js動態(tài)創(chuàng)建<script type="text/javascript" src="xxx">標簽
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容