前端面试题
1、typeof检测数据
instanceof 检测数据引用类型的区别
1、值类型
1)基本类型数据是值类型
2)保存与复制的是值本身
3)使用typeof检测数据的类型
String(字符串) number(数字) Boolean(布尔值) undefined(未定义或未赋值) null(空)**
复杂类型: Object (对象) Array(数组) Function(函数)
2、引用类型 [1,2] instanceof Array // true 返回布尔值
1)保存与复制的是指向对象的一个指针
2)使用 instanceof 检测数据类型
3)使用 new() 方法构造出的对象是引用型
2、什么是深拷贝什么是浅拷贝
答: 浅拷贝: 拷贝对象的一层属性,如果对象里面还有对象,拷贝的是地址, 两者之间修改会有影响,适用于对象里面属性的值是简单数据类型的.
深拷贝: 拷贝对象的多层属性,如果对象里面还有对象,会继续拷贝,使用递归去实现.
3、如何实现深拷贝和浅拷贝
答:
浅拷贝:
var obj = {
class: 'UI',
age: 20,
love: 'eat'
}
function getObj(obj) {
var newObj = {}
for (var k in obj) {
newObj[k] = obj[k]
}
return newObj
}
var obj2 = getObj(obj)
console.log(obj2)
深拷贝:
var obj = {
class: '前端',
age: 26,
love: {
friuts : 'apple',
meat: 'beef'
}
}
function getObj(obj) {
var newObj = {}
for (var k in obj) {
/* if (typeof obj[k] == 'object') {
newObj[k] = getObj(obj[k])
} else {
newObj[k] = obj[k]
} */
newObj[k] = typeof obj[k] == 'object' ? getObj(obj[k]) : obj[k]
}
return newObj
}
var obj2 = getObj(obj)
console.log(obj2)
4、对闭包的理解?并能举出闭包的例子
答: 闭包 函数和声明该函数的词法环境的组合(两个嵌套关系的函数,内部函数可以访问外部函数定义的变量)
闭包的优点:1、形成私有空间,避免全局变量的污染
2、持久化内存,保存数据
闭包的缺点:1、持久化内存,导致内存泄露
解决:1、尽快避免函数的嵌套,以及变量的引用
2、执行完的变量,可以赋值null,让垃圾回收机制,进行回收释放内存(当不在引用的变量,垃圾回收机制就会回收)
例: 点击li获取当前下标
<ul>
<li>111</li>
<li>222</li>
<li>333</li>
<li>444</li>
<li>555</li>
</ul>
var lis = document.querySelectorAll('li')
for (var i = 0; i < lis.length; i++) {
(function (j) {
lis[j].onclick = function () {
console.log(j)
}
})(i)
}
5、什么是原型和原型链
答: 原型: 函数都有prototype属性,这个属性的值是个对象,称之为原型
原型链: 对象都有__proto__属性,这个属性指向它的原型对象,原型对象也是对象,也有__proto__属性,指向原型对象的原型对象,这样一层一层形成的链式结构称为原型链.
6、call、apply和bind的区别
答: 1. call和apply方法都可以调用函数,方法内的第一个参数可以修改this的指向
2. call方法可以有多个参数,除了第一个参数,其他参数作为实参传递给函数
apply方法最多有2个参数,第二个参数是个数组或伪数组,数组里面的每一项作为实参传递给函数
3. bind方法不能调用函数,它会创建一个副本函数,并且绑定新函数的this指向bind返回的新的函数
7、es6-es10新增常用方法
答:
es6:
1、let、const
2、解构赋值 let { a, b } = { a: 1, b: 2 }
3、箭头函数 ()=>{}
4、模板字符串 ``
5、扩展运算符 ...arr
6、数组方法:map、filter、some 等等
7、类:class关键字
8、promise 主要用于异步计算
9、函数参数默认值 fn(a = 1) {}
10、对象属性简写 let a = 1; let obj = {a}
11、模块化:import--引入、exprot default--导出
es7:
1、 includes()方法,用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回true,否则返回false。
es8:
1、async/await
es9:
1、Promise.finally() 允许你指定最终的逻辑
es10:
1、数组Array的flat()和 flatmap()
flat:方法最基本的作用就是数组降维
var arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]
var arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);
// [1, 2, 3, 4, 5, 6]
//使用 Infinity 作为深度,展开任意深度的嵌套数组
arr3.flat(Infinity);
// [1, 2, 3, 4, 5, 6]
flatmap:方法首先使用映射函数映射(遍历)每个元素,然后将结果压缩成一个新数组
8、let、const和var的区别
1、var声明变量存在提升(提升当前作用域最顶端),let和const是不存在变量提升的情况
2、var没有块级作用,let和const存在块级作用域
3、var允许重复声明,let和const在同一作用域不允许重复声明
4、var和let声明变量可以修改,const是常量不能改变
9、怎么理解函数的防抖和节流
答:
1、定义:
防抖: 就是指触发事件后在n秒内函数只能执行一次,如果在n秒内又触发了事件,则会重新计算函数执行时间。
例如:设定1000毫秒执行,当你触发事件了,他会1000毫秒后执行,但是在还剩500毫秒的时候你又触发了事件,那就会重新开始1000毫秒之后再执行
节流: 就是指连续触发事件但是在设定的一段时间内中只执行一次函数。
例如:设定1000毫秒执行,那你在1000毫秒触发在多次,也只在1000毫秒后执行一次
2、防抖和节流的实现:
<body>
<input type="text" class="ipt" />
<script>
var timerId = null
document.querySelector('.ipt').onkeyup = function () {
// 防抖
if (timerId !== null) {
clearTimeout(timerId)
}
timerId = setTimeout(() => {
console.log('我是防抖')
}, 1000)
}
document.querySelector('.ipt').onkeyup = function () {
// 节流
console.log(2)
if (timerId !== null) {
return
}
timerId = setTimeout(() => {
console.log('我是节流')
timerId = null
}, 1000)
}
</script>
</body>
10、js的运行机制是什么
答:js是单线程执行的,页面加载时,会自上而下执行主线程上的同步任务,当主线程代码执行完毕时,才开始执行在任务队列中的异步任务。具体如下
1.所有同步任务都在主线程上执行,形成一个执行栈。
2.主线程之外,还存在一个"任务队列(eventloop队列或者消息队列)"。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
3.一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。哪些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
4.主线程不断重复上面的第三步。
11、怎么理解面向对象
答:1、面向对象是一种软件开发的思想和面向过程是相对应的,就是把程序看作一个对象,将属性和方法封装其中,以提高代码的灵活性、复用性、可扩展性。
2、面向对象有三大特性:封装、继承、多态。
封装:把相关的信息(无论数据或方法)存储在对象中的能力
继承:由另一个类(或多个类)得来类的属性和方法的能力
多态:编写能以多种方法运行的函数或方法的能力
3、基本思想是使用对象,类,继承,封装等基本概念来进行程序设计
易维护
易扩展
开发工作的重用性、继承性高,降低重复工作量。
缩短了开发周期
12、数组如何进行降维(扁平化)
1、利用Array.some方法判断数组中是否还存在数组,es6展开运算符连接数组
let arr = [1,2,[3,4]]
while (arr.some(item => Array.isArray(item))) {
arr = [].concat(...arr);
}
2、使用数组的concat方法
let arr = [1,2,[3,4]]
let result = []
result = Array.prototype.concat.apply([], arr)
3、 使用数组的concat方法和扩展运算符
var arr = [1,2,[3,4]]
var result = []
result = [].concat(...arr)
4、es6中的flat函数也可以实现数组的扁平化
let arr = [1,2,['a','b',['中','文',[1,2,3,[11,21,31]]]],3];
let result = arr.flat( Infinity )
注意:flat方法的infinity属性,可以实现多层数组的降维
14、斐波那契数列
// 斐波那契数列
function fiB(n) {
if (n == 1 || n == 2) {
return 1
}
return fn(n - 1) + fn(n - 2)
}
console.log(fiB(10))