JavaScript 2022 最新面试题 前端面试题

Posted 慕遥慕遥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript 2022 最新面试题 前端面试题相关的知识,希望对你有一定的参考价值。

文章目录

1.面试题: 请描述一下 location.go(-1) 和 history.go(-1) 有什么区别

首先熟悉 location 地址信息

  • href 属性:用于控制浏览器地址栏,一般用于代码中完成网页跳转或者刷新页面
  •     <script>
             // location对象
             // 实现页面的点击跳转,类似超链接功能,比超链接功能强大(可以在跳转页面时 编写逻辑代码实现一些功能)
             var _baidu = document.getElementById("baidu")
             _baidu.onclick = function()
                // 跳转网页
                location.href = "http://www.baidu.com/s?wd=明日战记"
             
              // 实现当前网页刷新
              var _refresh = document.getElementById("refresh")
              _refresh.onclick = function() 
                location.href = "#"  // 一般这里写的都是当前网页网址
              
        </script>
    

    and history 历史访问记录:

  • back() / forward()
  • go()
  •     <script>
            // history对象
            var _b = document.getElementById("b")
            var _f = document.getElementById("f")
            var _back = document.getElementById("back")
    
            _b.onclick = function() 
                // 访问上一条记录
                history.back()
            
    
            _f.onclick = function() 
                // 访问下一条记录
               history.foeward()
            
    
            _back.onclick = function() 
                // 访问上一条记录
                history.go(-1)
            
    
        </script>
    

    面试题: 请描述一下 location.go(-1) 和 history.go(-1) 有什么区别?

    • 两个函数都可以用于页面回到上一页, location.go() 需要插件支持*
    • location.go(-1)回到上一页并且刷新页面
    • history.go(-1) ,回到上一页

    2.面试题:什么是 cookie? 如何回答!

    cookie 是网站应用开发中,服务器给浏览器客户端记录文本数据的一个对象;记录数据的时候有如下特点:

    • 数据格式: key=value ,保存的数据只能是文本数据
    • 有过期时间: expires=xxxx        
    • 不设置过期时间,称为临时 cookie ,会话结束数据删除
    • 设置过期时间,称为永久 cookie ,过期时间一到立即删除
    • 可以包含路径,给不同的路径保存不同的 cookie
    • 一个网站,大部分浏览器限制最多保存50个 key=value 键值对
    • 一个网站,大部分浏览器限制最多保存 4K 数据
    • 缺点 存储量太小,只有4KB
    • 缺点 每次HTTP请求都会发送到服务端,影响获取资源的效率
    • 缺点 需要自己封装获取、设置、删除cookie的方法
    • 缺点 当超过单个域名限制之后,再设置cookie,浏览器就会清除以前设置的cookie。IE和Opera 会清理近期最少使用的cookie,FF会随机清理cookie

    回答:

    1. cookie是以小的文本文件形式(即纯文本),完全存在于客户端;cookie保存了登录的凭证,有了它,只需要在下次请求时带着cookie发送,就不必再重新输入用户名、密码等重新登录了。

    2. 是设计用来在 **服务端** 和 **客户端 **进行 **信息传递** 的;

    3.面试题: 描述一下 cookie / sessionStorage / localStraoge 区别?

    cookie / sessionStorage / localStorage 都属于浏览器缓存数据的操作对象

    cookie 是服务器存储在浏览器客户端的一段 key=value 格式的文本内容,包含过期时间、每个网站最多存储 4k 数据或者 50 个键值对数据;操作时如果需要删除数据可以选择清除浏览器缓存或者设置过期时间

    sessionStorage 属于 H5 提供的会话缓存数据,在用户访问网站网页时建
    立会话就可以存储数据,存储的数据在本次会话中可以访问,一旦会话结束存
    储的数据就立即销毁;一般用于存储会话状态数据,如用户登录状态

    localStorage 属于 H5 提供的本地缓存数据,可以在任意访问情况下进行
    数据存储,不受到会话限制,除非用户主动删除否则永久保存在用户本地;一
    般用于存储一些提高用户体验的、没有保密性的数据,如用户视频播放进度等

    sessionStorage localStorage 也受到浏览器的限制,最多存储 5M 的数据

    4.面试题: 面向对象 call apply bind 辅助函数 三个的区别?

    回答思路:先说联系/共同点,然后说区别,最后说项目中的应用场景

    call / apply / bind 都是辅助函数,可以用来修改正在执行的函数内部 this 指向

    call 修改 this 指向,通过 数据序列 传递给函数实际参数,如tom.eat.call(jerry, ‘数据a’, ‘数据b’)

    apply 修改 this 指向,通过 数组方式 传递个函数实际参数,如tom.eat.apply(jerry, [‘数据a’, ‘数据b’])

    bind 修改 this 指向,通过 数据序列方式 传递给函数实际参数,同时返回函数的声明,让开发人员可以延迟或者立即调用,扩展了使用范围,如:tom.eat.bind(jerry, ‘数据a’, ‘数据b’)()

    项目开发中这三个函数作用一致,根据实际传递数据的情况确定使用哪种方式,

    • 如项目中传递给函数的数据都是零散数据,就可以使用 call 进行函数的调用;
    • 如果传递给函数的数据包含在一个数组中,就可以使用 apply 完成函数的调用;
    • 如果将参数数据交给函数之后,需要做一些其他工作才能执行目标函数,可以使用 bind 交付参数,并且延迟执行函数

    5.面试题: 请简要描述原生 JavaScript 中有几种实现继承的方式?分别有什么优缺点? 重点 难点

    原生 JavaScript 中通过函数的方式模拟面向对象语法,主要的继承的实现方式有4种,分别是 原型继承、 冒充继承组合继承寄生组合继承

    原型继承,基于原型对象的继承,子类和父类在原型链上就存在继承关系;存在的问题是子类在创建对象时无法直接修改父类的属性数据,必须在创建的对象上通过访问属性的方式进行修改,让编码变得复杂;开发中一般很少独立使用

     <script>
          function Person() 
          function Student() 
          //原型继承
          Student.prototype = new Person()
      </script>
    ``
    

    冒充继承,基于 call() 辅助函数修改 this 指向的功能,在子类中通过调用父类构造函数的 call() 方法,完成子类可以使用父类构造函数内部属性和方法的使用;存在的问题是首先在原型链上没有真实继承关系,所以子类无法继承父类在原型对象上的数据和函数

     <script>
           function Person(name) 
          function Student(name, age) 
               // 冒充继承,可以直接修改父类属性
               Person.call(this, name)
               this.age = age
          
      </script>
    

    组合继承,结合了原型继承和冒充继承,通过原型继承让子类可以使用父类原型对象上的属性和函数,通过冒充继承可以让子类直接访问父类属性,优化操作语法;存在的问题是两种继承方式都访问了父类的构造函数,继承过程中造成父类构造函数的多次调用存在一定的性能问题;如果性能没有太高要求的情况下,可以通过组合继承的方式进行实现

       <script>
          function Person(name) 
           function Student(name, age) 
              //冒充继承
              Person.call(this, name)
              this.age = age
         
        //原型继承
         Student.prototype = new Person('')
       </script>
    

    寄生组合继承,对组合继承的一种升级,将父类原型对象进行了复制得到一个空对象,子类在冒充继承的继承上,实现原型继承时继承这个空对象,就不需要让父类的构造函数再次调用,这个空对象的创建和调用性能消耗较低,对性能上有一定的优化提升;项目中如果出现了对继承关系的频繁使用,建议可以将寄生组合继承进行封装使用,优化项目性能

    <script>
            function Person(name) 
            function Student(name, age) 
               // 冒充继承
               Person.call(this, name)
               this.age = age
             
            // 寄生函数
           function inherit(Parent, Child)
              //寄生构造函数|空函数
            var Temp = function() 
            // 复制 原型对象
            Temp.prototype = Parent.prototype
               // 原型继承(空构造函数,性能 优化)
              Child.prototype = new Temp()
               // 指定自己构造函数
              Child.prototype.constructor = Child
           
           // 寄生继承:让Student继承自Parent类型
           inherit(Person, Student)
      </script>
    

    ``

    6. 面试题: 字符串内存分析: 请简单描述,下面的代码在内存中 创建了几个对象 | 分配了几个空间?

    问题:

    var str = new String("hello")
    
    • new 创建的对象,都是需要在堆内存中创建的
    • 字符串作为一个项目中最常用的数据类型,编程语言为了提高字符串使用效率会将字符串存储到常量区,创建字符串对象时检查常量区中是否存在这个字符串(存在的话直接复制对象到堆内存;如果不存在的话创建对象并复制到堆内存)

    答: 最终在内存中创建了3个对象 | 分配了3个空间

    图解:

    7.面试题:关于事件面试题:简单描述一下 JavaScript 中事件绑定时如何处理兼容性问题?

    分析:这个问题归结于历史原因!

    软件行业发展过程中,有一家公司 微软 开发了自己特立独行的浏览器:探险家/ IE ,内核中使用了大量和其他浏览器不同的程序,所以导致后续开发的很多应用都需要兼容 IE

    JavaScript 中绑定事件的标准语法,为了兼容 IE6~IE11 ,事件绑定语法:

  • 非 IE 浏览器:绑定事件 addEventListener(事件名称, 处理函数)
  • IE 浏览器:绑定事件 attachEvent(事件名称,处理函数)
  • 引申   事件可以绑定,那么事件可以取消吗?

  • 绑定到标签上的事件,是可以取消的!
  • 1.对象属性绑定的事件,取消

        <script>
            // 绑定事件
            _btn.onclick = function() 
            // 取消事件
            _btn.onclick = null
        </script>
    

    2.标准语法绑定事件,取消

      <script>
            function handler()
                // 事件处理函数
            
            // 绑定事件
            _btn.addEventListener("click", handler)
            // 取消指定事件
            _btn.removeEventListener("click", handler)
        </script>
    

    8.面试题:简述 GET 请求和 POST 请求区别?

    总- GET 请求和 POST 请求都是 HTTP 规范中定义的请求方式,描述了客户端向服务器发送请求完成后续操作的过程

    分- GET 请求在规范中主要用于向服务器请求获取数据,也可以附带字符串参数,参数会拼接在 url 地址的后面,参数的长度收到服务器限制;请求效率非常高,浏览器地址栏、超链接、 Ajax 都可以发送 GET 请求

    分- POST 请求在规范中主要用于向服务器新增数据,但是项目开发中我们一般对于给服务器提交比较敏感的数据时,会使用 POST 请求将参数包装在请求中进行传递,既可以传送字符串数据,也可以传送二进制数据,如实现文件上传等操作;传递参数的大小受到服务器的限制;请求效率相对 GET 没有那么优秀,但是数据安全性得到了一定的保障;一般网页中我们通过表单Ajax 发 送 POST 请求

    总- 网页中实现页面跳转、请求一些不敏感的数据如搜索,这些都可以通过效率较高的 GET 完成数据的请求操作;网页中一些包含敏感数据的操作如登录、注册、转账等建议使用 POST 请求完成数据操作

    详解 上一篇文章   get/post 详解

    9.面试题:请完成数组的深浅拷贝

    什么是拷贝?

    拷贝:就是复制的意思,将数据再复制一份

    什么是深浅拷贝?

    深拷贝:将对象以及对象中包含的所有属性,全部独立的复制一份;两个对象之
    间完全没有任何关系,都是独立的数据

    浅拷贝:将对象以及对象的属性赋值一份,但是对象的属性中如果包含内存地址
    ~只赋值地址数据,不复制内存地址中具体的数据

    备注:关于数据的复用,引用赋值、浅拷贝、深拷贝

    图解:

    3.如何实现

    代码操作如下:

      <script>
            // 声明一个原数组
            let arr = ['tom', 'jerry']
            // 浅拷贝:属性独立的两个数组,两个数组的属性中保存的地址相同
            // 直接修改属性数据,互相没有影响
            // 修改属性/地址数据,互相产生影响
            let arr2 = [...arr]
    
            // 深拷贝:完全独立的两个数组
    
            // 直接修改属性数据,互相没有影响
            // 修改属性/地址数据,互相没有影响
            let arr3 = JSON.parse(JSON.stringify(arr))
        </script>
    

    .
    .

    10.面试题. (笔试)   数组中的重复数据剔重

    数组中的重复数据剔重

      var arr = [1,2,2,2,3,4,5,5,5,6,7,8,8]
    

    请将数组中的重复数据删除,所有的数据都保留唯一的一份?

    代码如下 (笔试):

        <script>
          // 数组
          var arr = [1, 2, 2, 2, 3, 4, 5, 5, 5, 6, 7, 8, 8];
          // 1、原始编码
          var newArr = [];
          for (var i = 0; i < arr.length; i++) 
            // 每次循环的数据
            var item = arr[i];
            if (!newArr.includes(item)) 
              // 如果没有包含,将数据添加进来
              newArr.push(item);
            
          
    
          console.log(newArr, "新数组");
    
          // 2、Set集合,完成数组剔重
          // 将数组转换成集合类型:集合中不能存放重复数据
          var s = new Set(arr);
          // 将集合转换回数组:数组的剔重,最终得到数组类型的数据
          var arr2 = Array.from(s);
          console.log(arr2);
        </script>
    

    11.面试题. (笔试)  观察下面的字符串,统计每个字符出现的次数

    考察ES6进阶   Map

    MapES6中提供的一种映射、字典类型,可以包含多个key:value键值对数据,其中key可以是任意类型的、不能重复的数据;是对原生JSON对象的扩展

    观察下面的字符串,统计每个字符出现的次数

    <script>
       var str = "sadasdsawffdsafsdfgp[d[]sds./dfskdfjsdasdajsfhuhkic/;x/c;ljfioqadpfsaodckljspdsadpiogvkjdsifepofasklxifep9opieio90"
      </script>
    

    分析:

    • 既然统计每个字符出现的次数,统计时的字符不能重复,可以作为 key 值
    • 统计字符出现的次数,是一个整数数据,出现多次时数据累加,可以作 为 value 值

    代码实现: 需手写

       <script>
          // 原始数据
          var str =
            "sadasdsawffdsafsdfgp[d[]sds./dfskdfjsdasdajsfhuhkic/;x/c;ljfioqadpfsaodckljspdsadpiogvkjdsifepofasklxifep9opieio90";
          // 统计数据
          // 记录每个字符出现次数的统计数据
          const map = new Map();
          for (var i = 0; i < str.length; i++) 
            // 获取当前字符
            const _c = str.charAt(i);
            // 判断map中是否包含这个key
            if (map.has(_c)) 
              // 如果包含
              let cnt = map.get(_c);
              map.set(_c, ++cnt);
             else 
              // 如果没有包含,包含进来 _c: 1
              map.set(_c, 1);
            
          
          console.log(map, "字符统计");
        </script>
    

    11.面试题.选择题 set 和 map 正确语法

    观察下面创建 Set 的代码,正确的是?( AB )
    A: new Set()

    B: new Set([])

    C: new set()

    D: newset([])

    观察下面创建 Map 的代码,正确的是?( A )
    A: new Map()
    B: new Map()
    C: new map()
    D: newmap()

    12.面试题. 简单说明箭头函数和普通函数的区别?

    回答思路:

    总:箭头函数和普通函数,都是封装了多行代码实现了一定功能的代码
    块,都可以提高代码的复用性

    分:和普通函数相比较,箭头函数内部的 this 指向 window 或者指向外
    部函数的 this ,所以函数内部如果要使用 this 的情况下不建议使用箭头函
    数替代普通函数,如对象内部的方法、事件处理函数等;另外箭头函数不能和普通函数一样作为构造函数使用

    总:箭头函数本质上就是 ES6 提供的在语法上和语义上对功能简单的普通
    函数的优化方案,针对功能性函数进行编码效率和代码可读性提升,如数组的函数 filter(fn)/map(fn)/… 回调函数都可以使用箭头函数进行优化

    
     <script>
        const a = [1, 2, 3, 4, 5];
        const a2 = a.map(function (item) 
         return item * item;
       );
       // a2: [1,4,9,16,25]
       const a3 = a.map((item) => item * item);
       // a3: [1,4,9,16,25]
      </script>
    

    注意:关于箭头函数内的 this ,某些资料会提到箭头函数没有 this
    向(如果真的没有 this 指向,内部无法访问 this 引用);但是如果箭头函
    数包含在其他有 this 指向的函数内部,箭头函数内的 this 就是外部函数的
    this

    小小练习题:

    
        <script>
          function fn() 
            console.log(this); //window
          
    
          const fn = function () 
            console.log(this); //当前函数
          ;
    
          const tom = 
            name: "tom",
            fn() 
              console.log(); //当前对象tom
            ,
          ;
    
          _btn.onclick = function () 
            console.log(this); //当前对象_btn
          ;
    
          _btn.onclick = () => 
            console.log(this); //window
          ;
    
          _btn.onclick = function () 
            //this:_btn
            const fx = () => 
              // 箭头函数内部有this引用,和函数所在上下文环境this相同
              console.log(this); //_btn
            ;
    
            fx();
          ;
        </script>
    

    13.Javascript基本数据类型

    1.String 字符串类型
    2.Number 数值类型
    3.Boolean 布尔类型
    4.Null 空值类型
    5.Undefined 未定义类型
    6.Object 对象类型

    14.var关键字 和 let关键字有什么区别?

    -var关键字存在变量的预解析,可以重复声明变量,存在全局作用域和局部作用域
    -let关键字不存在变量的预解析,不可以重复声明变量,只存在块级作用域

    15.什么是变量预解析

    在原生JavaScript中,用var声明的变量,再解释执行时,解释器会将变量的声明提升到代码的最前面,.赋值在原来的位置,保障了代码在运行的过程中程序不会出现错误导致程序崩溃退出的问题,解释器执行变量提升的过程就是变量的预解析

    16.说几个数组中的操作函数

    创建的操作函数
    push() 末尾追加一个
    pop() 末尾删除一个
    ushift() 开头添加一个
    shift()开头删除一个
    forEach() 遍历数组
    filter() 遍历条件过滤
    map() 遍历数据转换
    every() 遍历全部判断
    some() 遍历部分判断
    reduce() 遍历迭代输出

    17.正则表达式中 ()和 【】 和 分别有什么意义

    小括号:分组,包含的字符数据会被当成一个整体进行匹配
    如:(abc)表示匹配整个abc一串整体数据
    中括号:或者关系,包含的字符数据呈现或者条件;也可以包含范围内容
    如:[abc]表示匹配一个a或者b或者c;[a-z]表示小写字母
    大括号:量词,表示匹配前面的字符出现的次数
    如:xm,n表示前面的x出现至少m次最多n次的匹配情况

    18.什么是构造函数

    构造函数指通过new函数名来实例化对象的函数叫构造函数,首字母一般大写

    19.原生JS中几种继承方式

    原生JS中有四种继承方式,分别为:原型继承,冒充继承,组合继承,寄生组合继承

    20.GET请求和POST请求区别;超链接标签实现网页跳转发送了什么请求。

    -Get请求中的参数可见,通过拼接的方式拼接在url地址中.安全性较弱
    -Post请求参数不可见,参数通过请求体传输,安全性较高

    21.JavaScript类型转换方式?两种转换方式的区别?

    JavaScript中类型转换分为显式类型转换和隐式类型转换
    -显式类型转换:指的是在编程过程中,开发人员通过指定的语法如parseInt(),parseFloat(),boolean()等将目标数据转换为指定类型的方式称为显示类型转换
    -隐式类型转换:指的是在程序运行过程中,解释器自动匹配数据对应的数据类型,如乘除减法运算,toFixed()函数调用

    22.隐式类型转换的场景,至少说三个

    *-某些算数运算符,如-, , /
    -If()选择结构
    -toFiex()函数

    23.字符串操作的常见函数

    indexOf()
    lastIndexOf()
    includes()
    trim()
    trimLeft()
    trimStart()
    trimRight()
    trimEnd()
    toLowe

    以上是关于JavaScript 2022 最新面试题 前端面试题的主要内容,如果未能解决你的问题,请参考以下文章

    2022最全最新前端面试题(附加解答)

    一周热文和最新 JS 进阶面试题 #3

    2022最新版 Redis大厂面试题总结(附答案)

    2022年最新前端面试题

    2022最新前端vue面试题

    2022最新前端vue面试题