前端面试总结
把近段时间面试的题目整理归类了一下,希望对大家有所帮助!后面的答案为自行整理,如有疏漏,欢迎指正!
CSS
1. css有几种隐藏元素的方法,区别是什么?
display:none 彻底隐藏元素,不占据空间,也就不影响布局,无法点击。
overflow:hidden 用来隐藏元素溢出部分,占据空间,无法点击。
visibility:hidden 占据空间,无法点击。在读屏软件中不会被识别。
opacity:0 只是一种视觉隐藏,占据空间,可以响应点击事件。在读屏软件中会被识别。
position:absolute 相当于把元素放到可视区域外,不影响布局,可以点击。在读屏软件中会被识别
clip(clip-path):rect()/inset()/polygon() 占据空间,无法点击
z-index:-1000 不占据空间,无法点击
transform:scale(0, 0) 占据空间,无法点击
2. css设置颜色透明度有几种方法?
rgba()
R:红色值。正整数 (0~255)
G:绿色值。正整数 (0~255)
B:蓝色值。正整数(0~255)
A:透明度。取值0~1之间
opacity: value
value:指定不透明度,从0.0(完全透明)到1.0(完全不透明)
opacity:属性具有继承性,会使容器中的所有元素都具有透明度
3. css选择器有哪些?它们的优先顺序分别是什么?
1.id选择器(#myid)
2.类选择器(.myclassname)
3.标签选择器(div,h1,p)
4.相邻选择器(h1+p)
5.子选择器(ul > li)
6.后代选择器(li a)
7.通配符选择器(*)
8.属性选择器(a[rel="external"])
9.伪类选择器(a:hover, li:nth-child)
!important > 行内样式 > ID选择器 > 类选择器 > 标签选择器 > 通配符选择器 > 继承 > 浏览器默认属性
渲染机制
1.重绘和回流分别是什么? 什么时候会触发重绘,什么时候会触发回流
- 重绘是 当节点需要更改外观而不会影响布局的,比如改变 color、background-color、visibility等就叫称为重绘
- 回流是 布局或者几何属性需要改变 就称为回流。
注意: 回流必定会发生重绘,重绘不一定会引发回流。回流所需的成本比重绘高的多,改变深层次的节点很可能导致父节点的一系列回流。
会导致回流的操作:
- 页面首次渲染
- 浏览器窗口大小发生改变
- 元素尺寸或位置发生改变
- 元素内容变化(文字数量或图片大小等等)
- 元素字体大小变化
- 添加或者删除可见的DOM元素
- 激活CSS伪类(例如::hover)
- 查询某些属性或调用某些方法
JS
1. js事件捕获和事件冒泡是什么?
oakland.github.io/2016/06/14/…
2. es6数组常用方法
1. Array.from(targeObj, mapFunction, mapThis)
2. Array.of(val1, val2, val3, ....)
3. Array.copyWithin(target, start = 0, end = this.length)
4. Array.find((value, index ,arr) => {})
5. Array.findIndex
6. Array.fill(value, start, end)
7. Array.entries()
8. Array.keys()
9. Array.values()
10. Array.includes(start = 0)
11. Array.flat()
12. Array.flatMap(function)
3. es6对象新增方法
Object.is()
Object.assign()
Object.getOwnPropertyDescriptors()
__proto__属性
Object.getPrototypeOf()
Object.setPrototypeOf()
Object.keys()
Object.values()
Object.entries()
Object.fromEntries()
4. function和箭头函数有什么区别?
箭头函数是普通函数function的简写,可以更优雅的定义一个函数,和普通函数相比,有以下几点差异:
- 函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象。
- 不可以使用 arguments 对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
- 不可以使用 yield 命令,因此箭头函数不能用作 Generator 函数。
- 不可以使用 new 命令,因为:
- 没有自己的 this,无法调用 call,apply。
- 没有 prototype 属性 ,而 new 命令在执行时需要将构造函数的 prototype 赋值给新的对象的__proto__
5. 谈谈对this的理解
- this总是指向函数的直接调用者(而非间接调用者)--谁调用它,它就指向谁
- 当有new关键字时,this指向new出来的那个对象
- 在事件中,this指向触发这个事件的对象
- 特殊的是,IE中的attachEvent中的this总是指向全局对象Window
6. js的变量作用域有几种?分别是什么?
JavaScript 有两种作用域:全局和局部。
在函数定义之外声明的变量是全局变量,它的值可在整个程序中访问和修改。
在函数定义内声明的变量是局部变量。每当执行函数时,都会创建和销毁该变量,且无法通过函数之外的任何代码访问该变量。
7. let,const,var的区别是什么?
var声明变量可以重复声明,而let不可以重复声明
var是不受限于块级的,而let是受限于块级
var会与window相映射(会挂一个属性),而let不与window相映射
var可以在声明的上面访问变量,而let有暂时性死区,在声明的上面访问变量会报错
const声明之后必须赋值,否则会报错
const定义不可变的量,改变了就会报错
const和let一样不会与window相映射、支持块级作用域、在声明的上面访问变量会报错
8. es6解构赋值
数组解构
let [a, b, c] = [1, 2, 3] //a=1, b=2, c=3
let [d, [e], f] = [1, [2], 3] //嵌套数组解构 d=1, e=2, f=3
let [g, ...h] = [1, 2, 3] //数组拆分 g=1, h=[2, 3]
let [i,,j] = [1, 2, 3] //不连续解构 i=1, j=3
let [k,l] = [1, 2, 3] //不完全解构 k=1, l=2
对象解构
let {a, b} = {a: 'aaaa', b: 'bbbb'} //a='aaaa' b='bbbb'
let obj = {d: 'aaaa', e: {f: 'bbbb'}}
let {d, e:{f}} = obj //嵌套解构 d='aaaa' f='bbbb'
let g;
(g = {g: 'aaaa'}) //以声明变量解构 g='aaaa'
let [h, i, j, k] = 'nice' //字符串解构 h='n' i='i' j='c' k='e'
函数参数的定义
function personInfo({name, age, address}) {
console.log(name, age, address)
}
personInfo({ address: 'shenzhen', name: 'felix', age: 18})
函数默认参数
function saveInfo({name= 'felix', age= 18, address= 'shenzhen'} = {}) {
console.log(name, age, address)
}
saveInfo()
9. promise中有几种状态?
promise有三种状态:pending/reslove/reject
pending进行中,resolve已完成,reject已失败
10. 闭包是什么?闭包可以用来做什么?
函数A 里面包含了函数B,而 函数B 里面使用了 函数A 的变量,那么 函数B 被称为闭包。也就是说:闭包就是能够读取其他函数内部变量的函数
function A() {
var a = 1;
function B() {
console.log(a);
}
return B();
}
闭包的特征
- 函数内再嵌套函数
- 内部函数可以引用外层的参数和变量
- 参数和变量不会被垃圾回收制回收
对闭包的理解
使用闭包主要是为了设计私有的方法和变量。
闭包的优点是可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。
在js中,函数即闭包,只有函数才会产生作用域的概念
闭包 的最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量始终保持在内存中
闭包的另一个用处,是封装对象的私有属性和私有方法
闭包的好处
能够实现封装和缓存等
闭包的坏处
就是消耗内存、不正当使用会造成内存溢出的问题
使用闭包的注意点
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露
解决方法是:在退出函数之前,将不使用的局部变量全部删除
11. 如何让if(a == 5 && a == 8)为true
重写toString / valueOf
let a = {
i: 1,
toString: function () {
return a.i+3;
}
}
12.防抖和节流是什么?分别怎么实现的
防抖:任务频繁触发的情况下,只有任务触发的间隔超过指定间隔的时候,任务才会执行
function debounce(fn, waitTime) {
// 1、创建一个标记用来存放定时器的返回值
let timeout = null;
return function() {
// 2、每次当用户点击/输入的时候,把前一个定时器清除
clearTimeout(timeout);
// 3、然后创建一个新的 setTimeout,
// 这样就能保证点击按钮后的 interval 间隔内
// 如果用户还点击了的话,就不会执行 fn 函数
timeout = setTimeout(() => {
fn.call(this, arguments)
}, waitTime)
}
}
// 需要进行防抖的事件处理
function sayDebounce() {
// 需要防抖的工作,在这里执行
console.log("防抖成功!")
}
const myDebounce = document.getElementById("debounceBtn")
myDebounce.addEventListener("click", debounce(sayDebounce, 1000))
节流:指定时间间隔内只会执行一次任务
function throttle(fn, waitTime) {
// 1、通过闭包保存一个标记
let canRun = true;
return function() {
// 2、在函数开头判断标志是否为 true,不为 true 则中断函数
if(!canRun) {
return;
}
// 3、将 canRun 设置为 false,防止执行之前再被执行
canRun = false;
setTimeout( () => {
fn.call(this, arguments);
// 4、执行完事件之后,重新将这个标志设置为 true
canRun = true;
}, waitTime);
}
}
// 需要节流的事件
function sayThrottle() {
console.log("节流成功!")
}
const myThrottle = document.getElementById("throttleBtn")
myThrottle.addEventListener("click", throttle(sayThrottle, 1000))
13. 使用递归实现数组求和
function sum(arr) {
const len = arr.length
if (len === 0) {
return 0
} else if (len === 1) {
return arr[0]
} else {
return arr[0] + sum(arr.slice(1))
}
}
14. 使用冒泡排序算法将数组var a = [B,A,E,C,D];排序为var a=[A,B,C,D,E];
function mysort(list) {
const len = list.length
for (let i = 0; i < len; i++) {
for (let j = i + 1; j < len; j++) {
if (list[i] > list[j]) { // 相邻元素两两对比
let temp = list[j] // 元素交换
list[j] = list[i]
list[i] = temp
}
}
}
return list
}