当前位置:首页>IT那点事>前端常见面试题

前端常见面试题

闭包

1. 闭包是什么
函数嵌套函数,内部函数被外部函数返回并保存下来时,就会产生闭包

2. 闭包可以解决什么问题【闭包的优点】
    2.1 可以重复利用变量,并且这个变量不会污染全局的一种机制,这个变量是一只保存在内存中,不会被垃圾回收机制回收
    2.2 闭包可以解决的问题
        比如我的页面上有4个li,我点他的时候,因为我要循环后座点击事件,根据js执行流程来说,首先执行同步在执行异步的,这个时候onclick是最后执行,i已经执行完了,所以点击li的时候结果都是最后的结果值,加入闭包情况下,让i注入在内存中,就可以解决这样的问题,关闭了函数的自由变量
        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

4. 使用场景
    防抖、节流、函数嵌套函数避免全局污染的时候。

数组去重

1.new Set()
let arr = [[1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10];
let newArr = Array.from(new Set(arr.flat(Infinity).sort((a,b)=>{return a-b}))) 
//打印结果:[1,2,3,4,5,6,7,8,9,10,11,12,13,14]

2.indexOf
let arr = [[1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10];
let newArr = arr.flat(Infinity).sort((a,b)=>{return a-b})
function unique(arr){
    let brr = [];
    for( var i=0; i<arr.length; i++ ){
        if(brr.indexOf(arr[i]) === -1){
            brr.push(arr[i)
        }
    }
    return brr;
}
console.log(unique(newArr))
//打印结果:[1,2,3,4,5,6,7,8,9,10,11,12,13,14]

数据类型

基本类型:string,number,boolern,undefined,null,symbol
引用类型:object

考题:

1. console.log(true + 1) // 打印结果2     bool值默认false = 0,true = 1
2. console.log('name' + true) // 打印结果:nametrue    字符串和其他类型相加,变成连接的形式
3. console.log(undefined + 1) // 打印结果:NaN   数值类型和其他类型相加都会转换为数值类型,除了string类型
4. console.log()

延迟加载JS有哪些

1. async
async是和html解析同步的,不是顺次执行js脚本,谁先加载完谁先执行
2. defer
等html全部解析完成,才会执行js代码,顺次执行js脚本

JS微任务和宏任务

1. js是单线程的语言。
2. js代码执行流程:同步执行完==》事件循环
    同步的任务都执行完了,才会执行事件循环的内容
    进入事件循环:请求、定时器、事件....
3. 事件循环中包含:【微任务、宏任务】
微任务:promise.then
宏任务:setTimeout..

要执行宏任务的前提是清空了所有的微任务

流程:同步==》事件循环【微任务和宏任务】==》微任务==》宏任务=》微任务...

判断是否为数组

1. Array.isArray()
    var arr = [1,2,2,3]
    console.log(Array.isArray(arr))  // true
2. 原型prototype
    var arr = [1,2,2,3]
    var isArr = prototype.toString.call( arr ).indexOf('Array') > -1
    console.log(isArr)  // true,如果不等于-1,那他就是数组
3. isPrototypeOf()
    var arr = [1,2,2,3]
    var isArr = Array.prototype.isPrototypeOf(arr)
    console.log(isArr) // true
4. constructor
    var arr = [1,2,2,3]
    var isArr = arr.contrustor.toString().indexOf('Array') > -1;
    console.log(isArr) // true

slice是干嘛的、splice是否会改变原数组

1. slice是来截取的
    参数可以写1个、2个或者是负数
    返回的是一个新数组
2.splice 功能有:插入、替换、删除
    返回:删除的元素
    该方法 会改变原数组

找出多维数组中的最大值,并组成新的数组

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

判断一个字符串中出现次数最多的字符,并统计次数

var str = 'aaaassssssssssssxxxxxxeeeeebbbbbbbbbbbbbbbbbbbbbasaaqqqwe';
var obj = {};
for (var i = 0; i < str.length; i++) {
    var char = str.charAt(i);
    if (obj[char]) {
        obj[char]++
    } else {
        obj[char] = 1
    };
}
// 统计最大值
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. 创建了一个空的对象
2. 将空对象的原型,指向于构造函数的原型
3. 将空对象作为构造函数的上下文(改变this指向)
4. 对构造函数有返回值的处理判断

原型链

说到原型链,我先说下原型,作者设计原型,是用来解决对象共享属性和共享方法的,那么函数拥有prototype,对象拥有__proto__,对象查找某个属性或者摸个方法时,他会先去对象本身查找 ---> 构造函数中查找 --> 对象的原型 --> 构造函数的原型中 --> 当前原型的原型中找,这样的话会形成一个原型链,原型链的最定端的话是一个null,找不到

Vue2和Vue3的区别

1. Vue2 和 Vue3 双向绑定方法不同
    Vue2 : Object.defineProperty
    Vue3 : new Proxy()

说出 ===== 的区别

- == (普通相等)
  - 在类型不相同的情况下, 会将运算元先转成Number的值, 再进行比较(隐式转换)
  - null比较特殊: null在进行比较的时候, 应该是会被当成一个对象和原生类型进行比较的
- === (严格相等)
  - 在类型不同的情况下,直接返回false

对防抖、节流的理解,以及它们的区别和应用场景

防抖

将多次执行函数变成最后⼀次执行 等待固定时间还没有事件触发时执行的函数

  • 应用场景
    • 按钮的点击
    • 屏幕滚动时的复杂计算
    • 输入框输入时进行搜索
    • 用户缩放浏览器的resize事件
  • 简单的防抖函数实现
function myDebounce(execFn, delay) {
  let timer = 0
  function _debounce(...args) {
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => {
      execFn.apply(this, args)
      timer = null
    }, delay)
  }
  return _debounce
}

节流

按照固定的时间频率(间隔)来执行对应的函数

  • 应用场景:
    • 监听页面的滚动事件 通过节流来降低事件调用的频率
    • 鼠标标移动
    • 用户频繁点击按钮的操作
  • 简单实现
function myThrottle(execFn, interval) {
  let initTime = 0
  function throttle(...args) {
    let nowTime = Date.now()
    const waitTime = interval - (nowTime - initTime)
    if (waitTime <= 0) {
      execFn.apply(this, args)
      initTime = nowTime
    }
  }
  return throttle
}

Local Storage和Session Storage的区别

  • Local Storage提供⼀种永久性存储的方法 在网页关闭打开时 依然保留
  • Session Storage: 会话存储 再关闭该网页时 存储的内容被清除
  • 区别:
    • local Storage永久性存储 Session Storage在关闭当前页面时存储的内容就会失效
    • Session Storage只能被同⼀个窗口的同源页面共享 local Storage除⾮手动删除 否则⼀直存在
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

给TA打赏
共{{data.count}}人
人已打赏
6 条回复 A文章作者 M管理员
  1. 可爱爱大侠

    就服你

  2. 朽木白哉

    测试一下

  3. 辉夜姬

    就服你

  4. 翅膀酷炫

    支持一下

  5. 绯村剑心

    哈哈哈哈哈

个人中心
搜索

本站承接WordPress建站仿站、二次开发、主题插件定制等PHP开发服务!