前端高频面试题

1.var和let const的区别

  • var是 ES5语法,let const是ES6语法;var有变量提升
  • var和let是变量,可修改;const是常量,不可修改;
  • let const有块级作用域,var没有

2.typeof 返回哪些类型

  • 值类型:undefined string number boolean symbol
  • 引用类型:object(注意,typeof null === ‘object’’)
  • 函数:function

3.列举强制类型转换和隐式类型转换

  • 强制:parseInt parseFloat toString 等
  • 隐式:if、逻辑运算、==、+拼接字符串

4.手写深度比较,模拟lodash.isEqual

在这里插入图片描述

// 判断是否是对象或数组
function isObject(obj) {
    return typeof obj === 'object' && obj !== null
}
// 全相等(深度)
function isEqual(obj1, obj2) {
    if (!isObject(obj1) || !isObject(obj2)) {
        // 值类型(注意,参与 equal 的一般不会是函数)
        return obj1 === obj2
    }
    if (obj1 === obj2) {
        return true
    }
    // 两个都是对象或数组,而且不相等
    // 1. 先取出 obj1 和 obj2 的 keys ,比较个数
    const obj1Keys = Object.keys(obj1)
    const obj2Keys = Object.keys(obj2)
    if (obj1Keys.length !== obj2Keys.length) {
        return false
    }
    // 2. 以 obj1 为基准,和 obj2 一次递归比较
    for (let key in obj1) {
        // 比较当前 key 的 val —— 递归!!!
        const res = isEqual(obj1[key], obj2[key])
        if (!res) {
            return false
        }
    }
    // 3. 全相等
    return true
}

// 测试
const obj1 = {
    a: 100,
    b: {
        x: 100,
        y: 200
    }
}
const obj2 = {
    a: 100,
    b: {
        x: 100,
        y: 200
    }
}

console.log( isEqual(obj1, obj2) )

const arr1 = [1, 2, 3]
const arr2 = [1, 2, 3, 4]

5.split()和join()的区别

在这里插入图片描述
在这里插入图片描述

6.数组的pop push unshift shift 分别是什么

在这里插入图片描述

7.【扩展】数组的API,有哪些是纯函数?

纯函数概念:1. 不改变原数组(没有副作用);2. 返回一个数组
纯函数:concat、map、filter、slice
非纯函数:push、pop、 shift、 unshift、 forEach、some、every、reduce、splice

8.数组slice和splice的区别

slice -切片,splice-剪接
在这里插入图片描述
splice():用于删除原数组的一部分,并且可以在删除的位置添加新的数组成员,返回值是被删除的数组元素。

splice(t, v, s)
t:被删除元素的起始位置;v:被删除元素个数;s:s以及后面的元素为被插入的新元素。
v=0 时,则为在原数组上插入新元素

9.[10, 20,30].map(parseInt)返回结果是什么?

  • map的参数和返回值
  • parseInt参数和返回值

parseInt(string, radix)
string:需要被解析的字符串;radix表示要解析的进制(可选)
parseInt函数将其第一个参数转换为一个字符串,对该字符串进行解析,然后返回一个整数或 NaN

在这里插入图片描述

const res = [10, 20, 30].map(parseInt)
console.log(res) // [10,NaN,NaN]

// 拆解
[10, 20, 30].map((num, index) => {
    return parseInt(num, index)
})

结果:[10,NaN,NaN]

10.ajax请求get和post的区别?

  • get 一般用于查询操作,post 一般用户提交操作
  • get 参数拼接在url 上 , post放在请求体内(数据体积可更大)
  • 安全性:post易于防止 CSRF

11.函数call和apply的区别

在这里插入图片描述

12.事件代理(委托)是什么?

定义:把原本需要绑定在子元素的响应事件(click、keydown…)委托给父元素,让父元素担当事件监听的职务。
原理:DOM元素的事件冒泡。
在这里插入图片描述

13.闭包是什么,有什么特性?有什么负面影响?

  • 是什么
    函数a的内部函数b,被函数a外部的一个变量引用的时候,就创建了一个闭包。

  • 应用场景
    作为参数被传入,作为返回值被返回

  • 闭包的特性
    ①封闭性:外界无法访问闭包内部的数据,如果在闭包内声明变量,外界是无法访问的,除非闭包主动向外 界提供访问接口;(隐藏变量,避免全局污染; 可以读取其它函数内部的变量)
    ②持久性:一般的函数,调用完毕之后,系统自动注销函数,而对于闭包来说,在外部函数被调 用之后,闭包结构依然保存在;

  • 负面影响:
    使用闭包会占有内存资源,过多的使用闭包会导致内存溢出等。

14.如何阻止事件冒泡和默认行为?

event.stopPropagation()
event.preventDefault()

15.查找、添加、删除、移动DOM节点的方法?

// 新建节点
const newP = document.createElement('p')
newP.innerHTML = 'this is newP'

// 插入节点
div1.appendChild(newP)

// 移动节点
const p1 = document.getElementById('p1')
div2.appendChild(p1)

// 移除节点 
div1.removeChild(node)

// 获取父元素
console.log(p1.parentNode)

16.如何减少DOM操作?

  • 缓存DOM查询结果
  • 多次DOM操作,合并到一次插入

17.解释jsonp 的原理,为何它不是真正的ajax ?

①jsonp的原理:就是利用浏览器可以动态地插入一段js并执行的特点完成的。

②为什么不是真正的 ajax?
ajax的核心是 : 通过XmlHttpRequest获取非本页内容,
jsonp的核心 : 动态添加<script>标签来调用服务器提供的js脚本。

具体可参考jasonp和ajax

18.document load 和ready的区别

在这里插入图片描述

19.== 和 ===的不同

== 会尝试类型转换
=== 严格相等

20.函数声明和函数表达式的区别

  • 函数声明function fn) {…}
  • 函数表达式const fn = function() {…}
  • 函数声明会在代码执行前预加载,而函数表达式不会

21.new Object()和Object.create()的区别

  • 等同于new Object) ,原型Object.prototype
  • Object.create(null)没有原型
  • Object.create(i…})可指定原型

22.关于this的场景题

在这里插入图片描述
this的值在执行的时候才知道,第一个this指向user本身,第二个this指向window
答案:1 undefined

23.关于作用域和自由变量的场景题-1

在这里插入图片描述
答案:4 4 4

24.判断字符串以字母开头,后面字母数字下划线,长度6-30

const reg =/ [a-zA-Z]\w{5,29}$/

\w表示字母、数字或下划线

正则拓展
// 邮政编码
/\d{6}/

// 小写英文字母
/^[a-z]+$/

// 英文字母
/^[a-zA-Z]+$/

// 日期格式 2019.12.1
/^\d{4}-\d{1,2}-\d{1,2}$/

// 用户名
/^[a-zA-Z]\w{5, 17}$/

// 简单的 IP 地址匹配
/\d+\.\d+\.\d+\.\d+/

25.关于作用域和自由变量的场景题-2

在这里插入图片描述
答案:100 10 10

26.手写字符串trim方法,保证浏览器兼容性

在这里插入图片描述

27.如何获取多个数字中的最大值

方法一 手写function函数在这里插入图片描述
方法二 利用API
在这里插入图片描述

28.如何用JS实现继承?

  • class继承
  • prototype继承(不推荐)

29.如何捕获JS程序中的异常?

手动捕获(高风险地方)
在这里插入图片描述
自动捕获(其它地方)
在这里插入图片描述

30.什么是JSON ?

  • json是一种数据格式,本质是一段字符串。
  • json格式和JS对象结构一致,对JS语言更友好(全面替代了xml)
  • window.JSON是一个全局对象
    JSON.stringify(对象->字符串) JSON.parse(字符串->对象)
    在这里插入图片描述

31.获取当前页面url参数

  • 传统方式,查找location.search
  • 新API,URLSearchParams
function query(name) {
    const search = location.search
    const p = new URLSearchParams(search)
    return p.get(name)
}
console.log( query('b') )

32.将url参数解析为JS对象

在这里插入图片描述
在这里插入图片描述

33.手写数组flatern ,考虑多层级

在这里插入图片描述
方法一:使用遍历

function flat(arr) {
    // 验证 arr 中,还有没有深层数组 [1, 2, [3, 4]]
    const isDeep = arr.some(item => item instanceof Array)
    if (!isDeep) {
        return arr // 已经是 flatern [1, 2, 3, 4]
    }

    const res = Array.prototype.concat.apply([], arr)
    return flat(res) // 递归
}

const res = flat([1, 2, [3, 4, [10, 20, [100, 200]]], 5])

方法二:使用 ES6 API flat()

//使用 Infinity,可展开任意深度的嵌套数组
var arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
arr4.flat(Infinity);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

34.数组去重

方法1.传统方式,遍历元素挨个比较、去重

// 传统方式
function unique(arr) {
    const res = []
    arr.forEach(item => {
        if (res.indexOf(item) < 0) {
            res.push(item)
        }
    })
    return res
}

const res = unique([30, 10, 20, 30, 40, 10])
console.log(res)

方法2.使用Set (效率更高)

// 使用 Set (无序,不能重复)
function unique(arr) {
    const set = new Set(arr) // Set(4) {30, 10, 20, 40}
    return [...set] //  [30, 10, 20, 40]
}

const res = unique([30, 10, 20, 30, 40, 10])
console.log(res)

35.手写深拷贝

在这里插入图片描述
注意,Object.assign 不是深拷贝!

36.介绍一下RAF requestAnimationFrame

  • 要想动画流畅,更新频率要60帧/s ,即16.67ms 更新一次视图
  • setTimeout要手动控制频率,而用RAF浏览器会自动控制
  • 后台标签或隐藏iframe中,RAF 会暂停,而setTimeout依然执行
// 3s 把宽度从 100px 变为 640px ,即增加 540px
// 60帧/s ,3s 180 帧 ,每次变化 3px

const $div1 = $('#div1')
let curWidth = 100
const maxWidth = 640

// setTimeout
function animate() {
    curWidth = curWidth + 3
    $div1.css('width', curWidth)
    if (curWidth < maxWidth) {
        setTimeout(animate, 16.7) // 自己控制时间
    }
}
animate()

// RAF
function animate() {
    curWidth = curWidth + 3
    $div1.css('width', curWidth)
    if (curWidth < maxWidth) {
        window.requestAnimationFrame(animate) // 时间不用自己控制
    }
}
animate()

37.前端性能如何优化?一般从哪几个方面考虑?

原则:多使用内存、缓存,减少计算、减少网路请求
方向︰加载页面,页面渲染,页面操作流畅度

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值