2019前端面试题汇总

CSS类

1. 如何清除浮动

  1. 给父容器手动加高度
    原理:手动设置高度,解决父元素获取不到高度的问题。
    优点:操作简单,易于编码。
    缺点:不灵活,只适合高度固定的布局,当子元素高度不确定时,容易出现问题。
  2. 给父元素增加样式 – overflow: hidden
    原理:通过overflow: hidden格式化上下文结构
    优点:简单、代码少、浏览器支持好
    缺点:当父元素宽度不够时,overflow: hidden会引起超出隐藏问题。
  3. 在父元素最后追加空div标签,设置clear: both
    原理:利用css - clear属性清除浮动
    缺点:需要新增空白标签,繁琐
  4. 利用伪元素方法(个人常用)
    原理:利用父元素的 ::after 伪元素,模拟空白标签div
    优点:减少重复代码(可以设置公有类)
    例:
.clearfix::after {
	/* 模拟空标签 */
	content: '';
	display: block;
	/* 不占位 */
	height: 0;
    line-height: 0;
    visibility: hidden;
	/* 清除浮动 */
    clear: both;
}

.clearfix {
	/* 兼容IE */
	zoom: 1;
}

2. 几种方式实现已知或者未知宽度的垂直水平居中

/* 思路一:父、子容器(块级)宽高都已知,可以利用 margin */
.box1 {
	width: 400px;
    height: 400px;
    background-color: rgb(129, 2, 2);
    overflow: hidden;  /* 父容器要格式化上下文,防止塌陷 */ 
}

.box1_son {
    width: 200px;
    height: 200px;
    background-color: rgb(6, 88, 6);
    margin: 100px auto;
}

/* 思路二:父容器宽高未知、子容器宽高已知,子绝父相 + margin */
.box1 {
    position: relative;
    background-color: rgb(129, 2, 2);
}

.box1_son {
    width: 200px;
    height: 200px;
    background-color: rgb(6, 88, 6);
    position: absolute;
    top: 50%;
    left: 50%;
    margin-top: -100px;
    margin-left: -100px;
}

/* 思路三:父、子容器宽高都未知,子绝父相 + 过渡 */
.box1 {
    position: relative;
    background-color: rgb(129, 2, 2);
}

.box1_son {
    background-color: rgb(6, 88, 6);
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%)
}

/* 思路四:伸缩盒子 */
.box1 {
    width: 400px;
    height: 400px;
    background-color: rgb(129, 2, 2);
    display: flex;
    justify-content: center;
    align-items: center;
}

3. 雪碧图的优缺点

原理: 将网站上需要用到的图片进行整合,放到一张图片中,从而减少HTTP请求次数。使用时通过 background-imagebackground-reportbackground-position 配合使用。
优点: 减少了HTTP请求次数,提高了网页加载速度。
原理: css样式变得复杂,需要的代码变多。

4. px,em,rem的区别

px:是指一个像素单位。
em:不是固定值,能够继承父元素的 font-size 的大小。
rem:不是固定值,永远参照 html 标签的 font-size 的大小。

JS类

1. JS基本数据类型

参考链接: https://blog.csdn.net/qq_40311523/article/details/103476125

2 实现一个函数,判断输入是不是回文字符串

  回文字符串: 是指一个字符串正序和倒序完全一致,例如:‘level’,‘12321’。
  思路一: 从字符串中抽取单个字符与对应位置上的字符比对。

const isPalindrome = (str) => {
	let isTrue = true
    // for (let i = 0; i < str.length - 1; i++) {
    //     str.charAt(i) === str.charAt(str.length - 1 - i) ? false : isTrue = false
    // }
    // 优化:减少循环次数
    for (let i = 0; i < Math.floor(str.length / 2 - 1); i++) {
        str.charAt(i) === str.charAt(str.length - 1 - i) ? false : isTrue = false
    }
    return isTrue
}

  思路二: 将字符串分解为数组,翻转后拼接并与原字符串比对。

const isPalindrome = (str) => str.split('').reverse().join('') === str

3. 编写一个数组去重的例子

  思路一: (不改变原数组)循环原数组并将每一项推入新数组,推入是判断新数组中是否有重复项

const removeDuplicate = (arr) => {
	let newArr = []
    arr.map((item) => {
    	newArr.includes(item) ? false : newArr.push(item)
    })
    return newArr
}

  思路二: (改变原数组)循环原数组每一项并判断数组中是否有重复项,有就删除

const removeDuplicate = (arr) => {
	let len = arr.length
    for (let i = 0; i < len; i++) {
        let index = arr.lastIndexOf(arr[i])
        if (index != i) {
            arr.splice(index, 1)
	        i--
	        len--
        }
    }
}

4. 编写一个统计字符出现最多的字符,及最多的次数

  思路: 将字符串转为对象,key为字符串,value为出现次数,并按照value大小排序

// 获取统计对象
const toObject = (str) => {
	let obj = {}
    str.split('').map((item) => {
		obj[item] ? obj[item]++ : obj[item] = 1
	})
	return obj
}
// 获取最大值对象
const getMax = (obj) => {
	let maxKey = ''
    let maxVal = 0
    for (const key in obj) {
		if (obj.hasOwnProperty(key) && obj[key] > maxVal) {
			maxKey = key
			maxVal = obj[key]
        }
    }
    return {maxKey, maxVal}
}

  使用: console.log(getMax(toObject(str)))

5. 怎么给一个DOM元素绑定多个同类型事件?

利用 addEventListener 属性绑定多个同类型事件。
扩展: 利用 removeEventListener 进行事件监听移除,移除事件时,必须传入要移除的事件函数名
注意: addEventListenerremoveEventListener 中,事件名不加 on
例如:

let btnObj = document.getElementById('btn')
let fn1 = () => {
    console.log('Hello World')
}
let fn2 = () => {
    console.log('Hi World')
}
btnObj.addEventListener('click', fn1)
btnObj.addEventListener('click', fn2)
// btnObj.removeEventListener('click', fn1)

6. cookies sessionStorage 和 localStorage 的异同点

相同点: 都是将数据存储在浏览器端
不同点:

  1. 存储大小:
       cookie存储的数据大小不能超过4KB,否则会被截掉;
       sessionStoragelocalStorage 可以达到5M或更多。
  2. 功能:
       cookie主要是用来存储需要和服务器发生交互的数据,即:cookie中的数据每次请求时都会在发送到服务器端
       sessionStoragelocalStorage 中存储的数据仅是在客户端使用,不会主动参与交互
  3. 存储时间:
       localStorage 中的数据会长久储存,关闭浏览器也会保留,除非手动删除
       sessionStorage 中的数据在窗口关闭时会被删除
       cookie 中的数据可以设置有效期,有效期内不会被删除;未设置有效期,会在窗口关闭时删除

7. 闭包

  • 什么是闭包?
    • MDN: 函数与对其状态即词法环境的引用共同构成闭包(closure)。
    • 个人理解: 闭包就是能够读取其他函数内部变量的函数。

例:

const fn = () => {
    let name = '张三'
    return () => name
}

console.log(name)   // 空

const fn1 = fn()
console.log(fn1())  // 张三
  • 闭包的作用?
    • 闭包可以储存变量,一般在函数体内声明的变量,在使用完后会被释放,但闭包的外部函数中的变量一直是引用状态,不会被释放。
    • 闭包可以用来操作私有变量。

8. 继承

父类(构造函数):

function Animal(name) {
    this.name = name
}
Animal.prototype.eat = function () {
    console.log('吃肉..')
}
  1. 原型链继承
function Dog() {}
Dog.prototype = new Animal()
let dog = new Dog()
console.log(dog.name)   // undefined
dog.eat()               // 吃肉..

  重点: 让子构造函数的原型指向父构造函数的实例
  优点: 可以继承父构造函数原型中的属性和方法
  缺点: 新实例无法向父类构造函数传参,无法继承构造函数实例中的属性和方法

  1. 构造函数继承
function Cat() {
    Animal.call(this, '猫')
}
let cat = new Cat()
console.log(cat.name)   // 猫
cat.eat()               // cat.eat is not a function

  重点: 子构造函数中调用父构造函数并改变 this 指向
  优点: 可以继承父构造函数中的属性和方法
  缺点: 无法继承构造函数原型中的属性和方法

  1. 组合继承(常用)
function Cat(name) {
    Animal.call(this, name)
}
Cat.prototype = new Animal()
let cat = new Cat('猫')
console.log(cat.name)
cat.eat()

  重点: 结合构造函数继承和原型链继承的特点
  优点: 可以继承父构造函数及其原型中的属性和方法
  缺点: 代码复杂

  1. class 关键字继承
    父类:
class Animal {
    constructor(name) {
        this.name = name
    }

    eat() {
        console.log(this.name + '吃吃吃')
    }
}

子类:

class Cat extends Animal {
    constructor(name) {
        super(name)
    }
}
let cat = new Cat('猫')
console.log(cat.name)     // 猫
cat.eat()                 // 猫吃吃吃

  重点: 子类的 constructor 方法中要调用 super 方法,表示调用父类的 constructor 方法
  优点: 可以继承父类中的属性和方法,代码简单

9. documen.write和 innerHTML的区别

documen.write 只能是整个页面进行重绘;
innerHTML 可以只重绘页面中的一部分。

10. .call() 、 .apply() 和 .bind() 的区别和作用?

  • 作用:
    .call().apply().bind() 的作用都是改变一个函数的this指向。

  • 区别:
    .call() :直接调用目标函数并改变this指向,第一个参数是 this 指向,之后依次传入目标函数的原有参数。
    .apply() :直接调用目标函数并改变this指向,第一个参数是 this 指向,之后以数组形式传入目标函数的原有参数。
    .bind() :改变this指向并返回一个新函数,第一个参数是 this 指向,之后依次传入目标函数的原有参数。

优化类

1. 浏览器渲染页面的流程

一、渲染流程

  1. 首先浏览器会根据 URL地址DNS服务器 上请求网页文档,期间经过三次握手、四次挥手

  2. 当浏览器拿到服务器响应过来的文档后,会加载 DOM树CSSOM树,会根据文档将字节转为字符,生成标签,再确定节点,构成节点树。DOM树CSSOM树 会并行加载,所以一般把 link 标签放到 head 标签中,通过延长并行时间来缩短整体加载时间。

    例:DOM树加载图例
    DOM树加载图例

  3. 加载 JS 文件,加载 JS 文件时会停止生成 DOM树CSSOM树,所以一般把 script 标签放到 body 标签的最后,减少渲染时间。

  4. 根据 DOM树CSSOM树 合成 渲染树(Render Tree),其实渲染树和 DOM树CSSOM树 都是并行的,解析一部分 DOM树CSSOM树,就合成一部分渲染树,浏览器就渲染一部分,所以经常会看到浏览器一边解析,一边渲染的情况。

二、个人理解:

  浏览器渲染页面就相当于盖一幢大楼,硬装和软装同时生产,生产出来一个房间就先装修好一个房间

2. 重绘和重排

一、概念

  1. 重绘(repaint): 页面一部分要重新绘制。当 CSSOM 树 中的节点发生变化,但不影响该节点的空间大小,此时会引起浏览器重绘。例如:改变某一节点颜色
  2. 重排(reflow): 也称为回流,当 CSSOM 树 中的节点发生变化,影响了该节点的所占大小(实际宽高变化),此时会引起浏览器重排。例如:display: none

二、个人理解:

  重绘就是一个房子重新软装、粉刷,重排就是一个房子的结构要发生变化

3. CSS和JS的位置会影响页面的效率,为什么?

  • 加载css文件时会生产 CSSOM树,与 DOM树 是并行的,所以越早加载css文件越好,会延长并行时间,缩短整体时间;

  • 加载js文件时与生成 DOM树CSSOM树 是单线程的,并且会优先加载js文件,会影响页面渲染,所以越晚引入越好。

4. 如何优化网页加载速度

减少http请求:图片地图,CSS Sprites(精灵图)。
使用CDN:使用外部的 JS 和 CSS。
样式引入放头部,脚本引入放底部。
避免CSS表达式。
减少DNS查找。
精简 javaScript。
避免重定向。
删除重复脚本。

5. 优雅降级和渐进增强

优雅降级和渐进增强是用来处理兼容性的两种方式。
优雅降级是指,一开始就考虑高级浏览器开发好完整功能,在逐步根据低版本浏览器的需求进行兼容。
渐进增强和优雅降级刚好相反,一开始只根据低级浏览器开发基本功能,再针对高级浏览器开发效果,交互,提升用户体验。

交互类

1. get和post的区别

传参方式: get 传参会拼接到URL地址后,形式是 ? 后面以 & 分割,post 传参是将参数放到请求体里
数据大小: get 传参有数据大小的限制,一般参照浏览器地址栏支持的最大字节长度,post 传参没有参数数据大小要求
安全性: post 的安全性相对较高。
使用: getpost 都可以用来获取或更新数据,只是一般用 get 来获取数据,post 来存储数据

2. 跨域问题的产生和解决

同源策略: 协议名、域名、端口号都相同的两个URL地址叫做同源,非同源的地址间交互会产生跨域。
解决跨域:

  1. 通过 JSONP 解决跨域
  2. 通过 CORS 解决跨域(跨域资源共享)
  3. node.js 中间件代理跨域
  4. WebSocket协议跨域

详细情况:https://segmentfault.com/a/1190000011145364



(文档会持续更新)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值