2022年某呼面试题(JS部分)

1.ES6新增了哪些方法

1、includes()用于判断数组是否包含给定的值 返回一个布尔值

2、find()用于找出第一个符合条件的数组成员

3、findindex()返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1

4、set数据结构,类似于数组,但是成员的值都是唯一的,没有重复的值

5、、let声明变量、const声明常量(这里就要问你var、let、const的区别了)

6、解构赋值 ...

set 和map 的区别!!!以前被问没看过,懵逼过,所以要记住

  • Map是键值对,Set是值的集合,键和值可以是任何的值;
  • Map可以通过get方法获取值,而set不能因为它只有值,set只能用has来判断,返回一个布尔值;
  • Set的值是唯一的可以做数组去重,Map由于没有格式限制,可以做数据存储

2.promiseApi

Promise构建出来的实例存在以下方法:

  • then() 是实例状态发生改变时的回调函数,第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数
  • catch() 用于指定发生错误时的回调函数
  • finally() 用于指定不管 Promise 对象最后状态如何,都会执行的操作

Promise构造函数存在以下方法:

  • all() 用于将多个 Promise实例,包装成一个新的 Promise实例
  • race() 同样是将多个 Promise 实例,包装成一个新的 Promise 实例
  • allSettled()
  • resolve()
  • reject()
  • try()

3.Var、 let 、const 区别?

  • 变量提升
var声明的变量存在变量提升,即变量可以在声明之前调用,值为undefined
let和const不存在变量提升,即它们所声明的变量一定要在声明后使用,否则报错

js

  • 暂时性死区
var不存在暂时性死区
let和const存在暂时性死区,只有等到声明变量的那一行代码出现,才可以获取和使用该变量
  • 块级作用域
var不存在块级作用域
let和const存在块级作用域
  • 重复声明
var允许重复声明变量
let和const在同一作用域不允许重复声明变量
  • 修改声明的变量
var和let可以
const声明一个只读的常量。一旦声明,常量的值就不能改变
使用
能用const的情况尽量使用const,其他情况下大多数使用let,避免使用var

4.== 和 ===区别

相等操作符(==)会做类型转换,再进行值的比较,全等运算符(===)不会做类型转换

let result1 = ("55" === 55); // false,不相等,因为数据类型不同
let result2 = (55 === 55); // true,相等,因为数据类型相同值也相同

null 和 undefined 比较,相等操作符(==)为true,全等为false

let result1 = (null == undefined ); // true
let result2 = (null  === undefined); // false

5.数组常用方法

  • push() 接收任意数量的参数,并将它们添加到数组末尾,返回数组的最新长度
  • unshift() 开头添加
  • concat() 首先会创建一个当前数组的副本,然后再把它的参数添加到副本末尾,最后返回这个新构建的数组,不会影响原始数组

删 :

  • pop() 删除数组的最后一项,同时减少数组的length 值,返回被删除的项
  • shift() 删除数组的第一项,同时减少数组的length 值,返回被删除的项
  • splice() 传入两个参数,分别是开始位置,删除元素的数量,返回包含删除元素的数组
  • slice() 创建一个包含原有数组中一个或多个元素的新数组,不会影响原始数组

  • 常用splice
    传入三个参数,分别是开始位置,要删除元素的数量,要插入的任意多个元素,返回删除元素的数组,对原数组产生影响

  • indexOf() 返回要查找的元素在数组中的位置,如果没找到则返回 -1
  • includes() 返回要查找的元素在数组中的位置,找到返回true,否则false
  • find() 返回第一个匹配的元素

排序方法

  • reverse() 将数组元素方向反转
  • sort(首元素地址(必填), 尾元素地址的下一个地址(必填), 比较函数(非必填));
// 如果直接sort(数组名),则从小到大排序(即升序),以下为倒叙

var arr4 = [30,10,111,35,1899,50,45];
arr4.sort(function(a,b){
    return b - a;
})
console.log(arr4);//输出 [1899, 111, 50, 45, 35, 30, 10]

转换方法

  • join() 方法接收一个参数,即字符串分隔符,返回包含所有项的字符串

迭代方法

  • some() 对数组每一项都运行传入的函数,如果有一项函数返回 true ,则这个方法返回 true
  • every() 对数组每一项都运行传入的函数,如果对每一项函数都返回 true ,则这个方法返回 true
  • forEach() 对数组每一项都运行传入的函数,没有返回值
  • filter() 对数组每一项都运行传入的函数,函数返回 true 的项会组成数组之后返回
  • map() 对数组每一项都运行传入的函数,返回由每次函数调用的结果构成的数组.
    去重方法

去重方法

  1. 利用ES6 Set去重
function unique (arr) {
  return Array.from(new Set(arr))
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
 //[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {}, {}]
  1. 利用for嵌套for,然后splice去重
function unique(arr){            
        for(var i=0; i<arr.length; i++){
            for(var j=i+1; j<arr.length; j++){
                if(arr[i]==arr[j]){         //第一个等同于第二个,splice方法删除第二个
                    arr.splice(j,1);
                    j--;
                }
            }
        }
return arr;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
    console.log(unique(arr))
    //[1, "true", 15, false, undefined, NaN, NaN, "NaN", "a", {…}, {…}]     //NaN和{}没有去重,两个null直接消失了
  1. 利用indexOf去重
function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    var array = [];
    for (var i = 0; i < arr.length; i++) {
        if (array .indexOf(arr[i]) === -1) {
            array .push(arr[i])
        }
    }
    return array;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
   // [1, "true", true, 15, false, undefined, null, NaN, NaN, "NaN", 0, "a", {…}, {…}]  //NaN、{}没有去重
  1. 利用includes
function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    var array =[];
    for(var i = 0; i < arr.length; i++) {
            if( !array.includes( arr[i]) ) {//includes 检测数组是否有某个值
                    array.push(arr[i]);
              }
    }
    return array
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
    console.log(unique(arr))
    //[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}]     //{}没有去重

6.bind、call、apply 区别

  1. call和apply会调用函数,且会改变函数内部的this指向
  2. call和apply传递的参数不一样,call传递参数aru1,aru2.形式 而apply必须是数组形式[arg]
  3. bind 不会调用函数,可以改变函数内部指向

应用场景:

  • call经常做继承
  • apply经常和数组有关系,比如借助于数学对象实现数组的max、min
  • bind不调用函数,但改变this指向,比如改变定时器内部的this指向
    apply:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.apply(A, arguments);即 A 对象应用 B 对象的方法。 call:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.call(A, args1,args2); 即 A 对象调用 B 对象的方法。 bind 除了返回是函数以外,它的参数和 call 一样。

7.本地存储的方式有哪些?区别及应用场景?

javaScript本地缓存的方法我们主要讲述以下四种:

  • cookie
  • sessionStorage
  • localStorage
  • indexedDB

区别

  • 存储大小:cookie数据大小不能超过4k,sessionStorage和localStorage虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大
  • 有效时间:localStorage存储持久数据,浏览器关闭后数据不丢失除非主动删除数据; sessionStorage数据在当前浏览器窗口关闭后自动删除;cookie设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭
  • 数据与服务器之间的交互方式,cookie的数据会自动的传递到服务器,服务器端也可以写cookie到客户端; sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存

应用场景

  • 标记用户与跟踪用户行为的情况,推荐使用cookie
  • 适合长期保存在本地的数据(令牌),推荐使用localStorage
  • 敏感账号一次性登录,推荐使用sessionStorage
  • 存储大量数据的情况、在线文档(富文本编辑器)保存编辑历史的情况,推荐使用indexedDB

8.说说你对闭包的理解?闭包使用场景

闭包就是函数中包含另一个函数,可以让你在函数外部读取到内部的变量(就是在函数内部再定义一个函数),让这些变量的值始终保持在内存中,可以达到延长变量生命周期的效果,过多使用会导致内存泄漏的问题(在创建私有变量和想延长变量的生命周期时会用到闭包)

9.深拷贝浅拷贝的区别?

浅拷贝,指的是创建新的数据,这个数据有着原始数据属性值的一份精确拷贝

如果属性是基本类型,拷贝的就是基本类型的值。如果属性是引用类型,拷贝的就是内存地址

在JavaScript中,存在浅拷贝的现象有:

  • Object.assign
  • Array.prototype.slice()
  • Array.prototype.concat()
  • 使用拓展运算符实现的复制

深拷贝开辟一个新的栈,两个对象属完成相同,但是对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性

常见的深拷贝方式有:

  • _.cloneDeep()
  • jQuery.extend()
  • JSON.stringify()
  • 手写循环递归

10.JavaScript中的数据类型?

string、number、Boolean、undefined、null、object

11.什么是防抖和节流?

防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时

节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效

电梯第一个人进来后,等待15秒。如果过程中又有人进来,15秒等待重新计时,直到15秒后开始运送,这是防抖

电梯第一个人进来后,15秒后准时运送一次,这是节流

12.如何解决数字精度丢失的问题?

  • 理论上用有限的空间来存储无限的小数是不可能保证精确的,但我们可以处理一下得到我们期望的结果

当你拿到 1.4000000000000001 这样的数据要展示时,建议使用 toPrecision 凑整并 parseFloat 转成数字后再显示,如下:

parseFloat(1.4000000000000001.toPrecision(12)) === 1.4  // True

封装成方法就是:

function strip(num, precision = 12) {
  return +parseFloat(num.toPrecision(precision));
}

最后还可以使用第三方库,如Math.js、BigDecimal.js

13.JavaScript 中内存泄漏的几种情况?

  • 使用闭包

14.原型,原型链 ? 有什么特点?

JavaScript 常被描述为一种基于原型的语言——每个对象拥有一个原型对象

当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾

原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法

14.如何实现上拉加载,下拉刷新?

开源社区有很多优秀的解决方案,如iscroll、better-scroll、pulltorefresh.js库等等

15.说说你对作用域链的理解

  • 作用域就是变量与函数的可访问范围
  • 一般情况下,变量取值到创建这个变量的函数的作用域中取值。 但是如果在当前作用域中没有查到值,就会向上级作用域去查,直到查到全局作用域,这么一个查找过程形成的链条就叫做作用域链

16.typeof 与 instanceof 区别

  • typeof与instanceof都是判断数据类型的方法,区别如下:

typeof会返回一个变量的基本类型,instanceof返回的是一个布尔值
instanceof 可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型
而typeof 也存在弊端,它虽然可以判断基础数据类型(null 除外),但是引用数据类型中,除了function 类型以外,其他的也无法判断

17.ajax、axios、jsonp的理解

  1. jsonp是一种可以解决跨域问题的方式,就是通过动态创建script标签用src引入外部文件实现跨域,script加载实际上就是一个get请求,并不能实现post请求。(其他实现跨域的方法有:iframe,window.name,postMessage,CORS…)
  2. ajax是一种技术,ajax技术包含了get和post请求的,但是它仅仅是一种获取数据的技术,不能直接实现跨域,只有后台服务器配置好Access-Control-Allow-Origin,才可以实现请求的跨域。
  3. axios是通过promise实现对ajax技术的一种封装,axios是ajax,ajax不止axios。
  • 总结:

juery的$.ajax实现get请求能跨域是因为jsonp或者因为原生ajax和服务器的配合,post请求能跨域就只能是因为原生ajax和服务器的配合。

19.ajax的请求过程

// ajax 提交 post 请求的数据
// 1. 创建核心对象
var xhr = new XMLHttpRequest();
// 2. 准备建立连接
xhr.open("POST", "register.php", true);
// 3. 发送请求
// 如果要POST提交数据,则需要设置请求头
// 有的面试官会问为什么要设置请求头? 知道请求正文是以什么格式
// Content-Type: application/x-www-form-urlencoded,请求正文是类似 get 请求 url 的请求参数
// Content-Type: application/json,请求正文是一个 json 格式的字符串
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
// 发送数据
xhr.send(querystring);
// 4. 处理响应
xhr.onreadystatechange = function () {
     if (xhr.readyState === 4) { // 请求处理完毕,响应就绪
          if (xhr.status === 200) { // 请求成功
               var data = xhr.responseText;
               console.log(data);
          }
     }
}

20.ajax请求的时候get 和post方式的区别

  • get请求不安全,post安全 ;
  • get请求数据有大小限制,post无限制 ;
  • get请求参数会在url中显示,容易被他人窃取,post在请求体中
  • post需要设置请求头。

21.什么是事件委托以及优缺点

js事件委托就是利用冒泡的原理,把本应该添加到某个元素上的事件委托给他的父级,从而减少DOM交互达到网页优化。

  • 优点:

1.可以大量节省内存占用,减少事件注册。比如ul上代理所有li的click事件就很不错。 2.可以实现当新增子对象时,无需再对其进行事件绑定,对于动态内容部分尤为合适

  • 缺点:

事件代理的常用应用应该仅限于上述需求,如果把所有事件都用事件代理,可能会出现事件误判。即本不该被触发的事件被绑定上了事件。


原文链接

文章链接:http://iwebg.cn/index.php/2023/07/20/2022%e5%b9%b4%e6%9f%90%e5%91%bc%e9%9d%a2%e8%af%95%e9%a2%98%ef%bc%88js%e9%83%a8%e5%88%86%ef%bc%89/

版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇