Javascipt面试题
# 1.js数据类型有哪些?如何检测数据类型?他们有啥区别?
# 数据类型
# 检测类型
typeOf
- typeOf检测null为object(浏览器bug)
- typeOf检测复杂数据类型array、object都为object
intanceOf (检测某一个实例为这个类)
- 可以正确判断对象类型的数据,不能判断简单数据类型,机制是通过原型链上能否找到这个原型
constructor
- 实例和类的关系,从而检测数据类型,引用原来构造的函数
- 除了undefind和null其他能够检测正确
Object.prototype.toString.call() (检测数据类型)
- 任何数据类型都可以检测
# 区别
# 2.深拷贝和浅拷贝有啥区别?
- 浅拷贝:复制的是内存地址,原地址发生改变,拷贝出来的对象也会改变
- 深拷贝:在内存中会开辟一个新的地址,用于存放复制的对象
# 用递归实现深拷贝
function fun(obj,capyObj) {
for(k in capyObj) {
if(obj[k] instanceof Array) { // 判断属性值类型
capyObj[k] = []
fun(obj[k],capyObj[k])
} else if(capyObj[k] instanceof Object) {
obj[k] = {}
fun(obj[k],capyObj[k])
} else {
obj[k] = capyObj[k]
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 3.什么是高阶函数?
# 函数为参数
<script>
function fun(fn) {
fn && fn()
}
fun(function (){
console.log('函数作为参数')
})
</script>
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 函数为返回值
<script>
function fun(fn) {
return function() {
console.log('函数作为返回值')
}
}
fun()
</script>
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 4.什么是闭包,闭包会带来什么,应用场景?
# 概述
函数内部有权访问函数外部的变量
1
# 带来问题
- 问题:内存泄漏
- 解决:标记清除法
# 作用
延伸变量作用范围
# 应用场景
防抖、节流、react中
# 5.什么是递归,应用场景?
函数内部自己调用自己,容易发生栈溢出,一定要加个退出循环条件return
let num = 1
function fun() {
console.log('我要10个水果')
if(num == 10) {
return
}
num ++
fun()
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 1-3的阶乘
function sum(n) {
if(n==1) return 1
return n * sum(n-1)
}
sum(3)
// 详细思路
// return 3 * sum(2)
// return 3 * (2 * sum(1))
// return 3 * 2 * 1
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 1到3的和
function sum(n) {
if(n==1) return 1
return n + sum(n - 1)
}
sum(3)
1
2
3
4
5
2
3
4
5
# 斐波那契数列
function fb(n) {
if(n === 1 || n === 2) return 1
return fb(n-1) + fb(n-2)
}
fb(8)
1
2
3
4
5
2
3
4
5
总结:递归函数就是函数内部自己调用自己,这个函数就称为递归函数,递归函数跟循环是一样的,重复执行某一段代码,此时它只是重复的调用我们的函数而已。所以我们使用递归函数必须加个退出条件,不然不断的开辟作用域,不断的创建内存就会栈溢出。
# 6.函数防抖和节流?
防抖:重复执行的函数在规定时间内只执行最后一次
function debounce(fn,delay) {
let timer = null
return function () {
if(timet) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.apply(this)
},delay)
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
节流:一个函数执行一次后,大于设定的周期才会执行第二次
// 第一种
function throttle(fn,delay = 200) {
let flag = true
return () => {
if(flag) {
flag = false
fn.apply(this)
}
setTimeout( () => {
flag = true
}, delay)
}
}
// 第二种
function throttle(fn,delay = 200) {
let start = 0
let nowDate = new Date()
return () => {
if(nowDate - start > delay) {
fn.apply(this)
}
setTimeout(() => {
start = nowDate
})
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
节流思路和实现
- 事件函数执行,先判断是否有定时器,则直接return
- 把逻辑代码放到定时器中
- 定时器执行完成后置空定时器
- 事件函数执行完以后再创建定时器
# Demo演示过渡
可用F12开发者工具查看元素及样式,可打开codepen在线编辑代码。
# 7.localStorage、sessionStorage和cookie有啥区别?
# 相同点
都是存储在客户端
# 不同点
存储时间不同
- localStorage 数据是永久存在的,除非自己手动删除
- sessionStorage 浏览器关闭数据就会删除
- cookie 则有个过期时间,一旦超过存储时间数据就会删除
存储大小不同
- localStorage 和 sessionStorage存储大小为5M左右
- sessionStorage存储大小为4KB
- 当然不同的浏览器存储大小是不同的
数据与服务之间的交互不同
- localStorage和sessionStorage不会自动把数据发给服务器端,仅本地保存
- cookie可以在客户端和服务器端来回传递
应用场景不同
- localStorage 用于长期进行本地登录,适用长期保存本地数据
- sessionStorage 敏感账号一次性登录,单页面应用比较多
- cookie 判断用户是否登录过网站,以便下次自动登录或记住密码
# 请你谈谈promise
它是一个异步编程,用于解决回调地狱的问题。我们通过new Promise()来创建promise对象,里面传两个参数,分别表示执行成功和失败后的回调函数,然后promise初始化状态(peeding)变为成功(fulfilled)或着失败(rejected)状态。然后我们可以用.then去获取回调函数执行的结果。
# 请你说说async、await
是另外一种异步编程解决方案,本质: 是 Generator 的语法糖。
- sync 的返回值是 Promise 实例对象。
- await 可以得到异步结果。
上次更新: 2023/03/05, 15:03:00