CSS面试题
如果理解HTML语义化
- 让人更容易读懂(增加代码可读性)
- 让搜索引擎更容易读懂 (SEO )
CSS布局
盒子模型的宽度如何计算?
补充:如果让 offsetWidth 等于 100px,该如何做 ?
设置box-sizing: border-box;
margin
纵向重叠问题
margin
负值的问题
BFC
的理解和应用
常见应用:清除浮动 overflow: hidden;
Block format context,块级格式化上下文
一块独立渲染区域,内部元素的渲染不会影响边界以外的元素
浮动
- 脱标且不保留原来的位置
- 想要块级元素一行内显示,用浮动它们之间不会有缝隙,但是设置为行内块就会有缝隙
如何实现圣杯布局和双飞翼布局
三栏布局,中间一栏最先加载和渲染(内容最重要)
两侧内容固定,中间内容随着宽度自适应
一般用于PC网页
技术总结
- 使用
float
布局 - 两侧使用
margin
负值,以便和中间内容横向重叠 - 防止中间内容被两侧覆盖,一个用
padding
一个用margin
圣杯布局 用padding留白
记得加padding
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>圣杯布局</title>
<style>
html *{
margin: 0;
padding: 0;
}
#header{
height: 100px;
width: 100%;
background-color: pink;
}
#container{
/* container设置padding */
padding-left: 200px;
padding-right: 200px;
}
/* container每一列都设置浮动 */
#center{
float: left;
width: 100%;
background-color: orange;
}
#left{
float: left;
width: 200px;
background-color: green;
margin-left: -100%;
/* 相对于原来位置左移自身宽度 */
position: relative;
right: 200px;
}
#right{
float: left;
width:200px;
background-color: green;
margin-right: -200px;
}
#footer{
height: 100px;
width: 100%;
background-color: pink;
overflow: hidden;
}
</style>
</head>
<body>
<header id="header">头部</header>
<section id="container">
<div id="center">中间</div>
<div id="left">左边</div>
<div id="right">右边</div>
</section>
<footer id="footer">尾部</footer>
</body>
</html>
双飞翼布局 用margin留白
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>双飞翼布局</title>
<style>
html * {
margin: 0;
padding: 0;
}
.col{
float: left;
}
#container{
width: 100%;
height: 100px;
}
#center{
margin: 0 200px 0 200px;
height: 100px;
background-color: red;
}
#left{
width: 200px;
height: 100px;
background-color: green;
margin-left: -100%;
}
#right{
width:200px;
height: 100px;
background-color: green;
margin-left: -200px;
}
</style>
</head>
<body>
<div id="container" class="col">
<div id="center"中间></div>
</div>
<div id="left" class="col">左</div>
<div id="right" class="col">右</div>
</body>
</html>
clearfix
CSDN介绍
display:table
可以解决父子外边距重叠的问题。clearfix
这样写既可以解决子元素浮动撑不开父元素的问题,又可以解决父子外边距重叠的问题。【下面那个zoom没什么必要】
flex
实现一个三点的色子
align-self
属性定义flex子项
单独在侧轴(纵轴)方向上的对齐方式。
auto|stretch|center|flex-start|flex-end|baseline|initial|inherit;
居中对齐有哪些实现方式?
最后一个方法兼容性最好,第三个方法的transform
兼容性不好
CSS图文样式
line-height
的继承问题
CSS响应式
rem
是什么?
rem单位的使用是相对于根元素的字体大小,配合媒体查询等技术实现响应式布局。
如何实现响应式
CSS3
关于CSS3动画【不是面试重点】
JS高级进阶
eventloop
promise
async await
宏任务和微任务
什么是宏任务和微任务,两者区别
为什么有这种先后区别
场景题
手写Promise
5-17 5-20
怎么同时执行两个async函数
const [result1, result2] = await Promise.all([func1(), func2()]);
第2章 JS基础-变量类型和计算
题目:
typeof
能判断哪些类型- 何时使用
===
何时使用==
- 值类型和引用类型的区别(做个题写出运行结果)
- 手写深拷贝
1. typeof运算符
- 识别所有值类型
- 识别函数
- 判断是否是引用类型
'object'
(但区分不出来)
手写深拷贝
不需要深拷贝的直接返回
- 根据深拷贝对象类型,给
result
设定用数组
装还是对象
装 obj.hasOwnProperty(key)
的属性才拷贝- 拷贝要用
递归
/**
* 深拷贝
* @param {Object} obj 要拷贝的对象
*/
function deepClone(obj = {}) {
if (typeof obj !== 'object' || obj == null) {
// obj 是 null ,或者不是对象和数组,直接返回
return obj
}
// 初始化返回结果
let result
if (obj instanceof Array) {
result = []
} else {
result = {}
}
for (let key in obj) {
// 保证 key 不是原型的属性
if (obj.hasOwnProperty(key)) {
// 递归调用!!!
result[key] = deepClone(obj[key])
}
}
// 返回结果
return result
}
2. 变量计算 - 类型转换
(1). 字符串拼接
(2). ==
它会隐式地给你做类型转换然后让它们尝试相等
(3). if
语句和逻辑运算
truly 变量:!!a === true的变量
falsely 变量:!!a === false的变量
其实 if 语句判断不是 true or false ,而是 truly 和 falsely 变量
第3章 JS基础-原型和原型链【三座大山之一,必考!!!】
题目:
- 如何准确判断一个变量是不是数组?
a instanceof Array
结合原型链理解 class
的原型本质,怎么理解?
原型和原型链的图示,属性和方法的执行规则- 手写一个简易的
jQuery
,考虑插件和扩展性【可以更好地理解class和继承】
class jQuery {
constructor(selector) {
const result = document.querySelectorAll(selector)
const length = result.length
for (let i = 0; i < length; i++) {
this[i] = result[i]
}
this.length = length
this.selector = selector
}
get(index) {
return this[index]
}
each(fn) {
for (let i = 0; i < this.length; i++) {
const elem = this[i]
fn(elem)
}
}
on(type, fn) {
return this.each(elem => {
elem.addEventListener(type, fn, false)
})
}
// 扩展很多 DOM API
}
// 插件
jQuery.prototype.dialog = function (info) {
alert(info)
}
// “造轮子”
class myJQuery extends jQuery {
constructor(selector) {
super(selector)
}
// 扩展自己的方法
addClass(className) {
}
style(data) {
}
}
// const $p = new jQuery('p')
// $p.get(1)
// $p.each((elem) => console.log(elem.nodeName))
// $p.on('click', () => alert('clicked'))
1. 原型和原型链
2. 类型判断 instanceof
比如你让 xialuo instanceof Array
,结果是等于 false 的
因为数组的原型
不在 xialuo 的这个体系内(xialuo顺着隐式原型往上找找不到数组的显式原型
)
第4章 JS基础-作用域和闭包【三座大山之二,不会闭包,基本不会通过】
题目:
this
的不同应用场景,如何取值?- 当作普通函数被调用【直接返回
window
】 - 使用
call
apply
bind
【传入什么就绑定什么】 - 作为对象方法调用【返回对象本身】
- 在class的方法中调用【返回实例对象本身】
- 箭头函数【找的是它上级作用域的this】
- 当作普通函数被调用【直接返回
- 手写
bind
函数
你这里的self是指fn1,类比想象一下xialuo.say()的this其实是指向xialuo
Array.prototype.slice.call(arguments)
能将具有length属性
的对象(且key值为数字
)转成数组
- 实际开发中闭包的应用场景,举例说明
- 隐藏数据,只对外界提供API
- 如做一个简单的cache工具
- 创建10个
<a>
标签,点击的时候弹出来对应的序号【考作用域】
错:输出的i永远是10,当你点击的时候早就循环完 i 变成10了,你这个自由变量 i 往上找这个全局作用域的 i ,次次都是10
对:这样for循环里每次都产生一个新的块作用域,每次都是在这个块作用域找 i
1. 作用域
- 全局作用域
- 函数作用域
- 块级作用域(ES6新增)
自由作用域:
- 一个变量在当前作用域没有定义,但被使用了
- 向上级作用域,一层一层依次寻找,直到找到为止
- 如果到全局作用于都没找到,则报错 xx is not defined
2. 闭包
作用域应用的特殊情况。有两种表现:
- 函数作为
参数
被传递 - 函数作为
返回值
被返回
所有的自由变量的查找,是在函数定义的地方向上级作用域查找
,不是在执行的地方!
以下两个代码都是输出 100
3. this
this取什么值,是在函数执行
的时候确认的
{width=61%}
箭头函数的 this 取的是它上级作用域的 this
第5章 JS基础-异步【三座大山之三,必考!!!】
题目:
- 同步和异步的区别
- 异步是基于
JS
是单线程语言
- 异步
不会阻塞
后面代码的执行 - 同步
会阻塞
代码执行(比如alert
之后你不点击确认,后面的console
就执行不了)
- 异步是基于
- 前端使用异步的场景有哪些
- 网络请求,如
ajax
图片加载 - 定时任务,如
setTimeout
- 网络请求,如
- 场景题【打印:13542】
{width=43%} - 手写用Promise加载一张图片 4.27 Promise Fetch axios
function loadImg(src) {
const p = new Promise(
(resolve, reject) => {
const img = document.createElement('img')
img.onload = () => {
resolve(img)
}
img.onerror = () => {
const err = new Error(`图片加载失败 ${src}`)
reject(err)
}
img.src = src
}
)
return p
}
// const url = 'https://img.mukewang.com/5a9fc8070001a82402060220-140-140.jpg'
// loadImg(url).then(img => {
// console.log(img.width)
// return img
// }).then(img => {
// console.log(img.height)
// }).catch(ex => console.error(ex))
const url1 = 'https://img.mukewang.com/5a9fc8070001a82402060220-140-140.jpg'
const url2 = 'https://img3.mukewang.com/5a9fc8070001a82402060220-100-100.jpg'
loadImg(url1).then(img1 => {
console.log(img1.width)
return img1 // 普通对象
}).then(img1 => {
console.log(img1.height)
return loadImg(url2) // promise 实例
}).then(img2 => {
console.log(img2.width)
return img2
}).then(img2 => {
console.log(img2.height)
}).catch(ex => console.error(ex))
第6章 JS-Web-API-DOM【学会DOM,才能具备网页开发的基础】
题目
- DOM是哪种数据结构【树、DOM树】
- DOM操作的常用
API
- DOM节点操作
- DOM结构操作
attribute
和property
attr
和property
的区别【推荐property
】property
:修改对象属性,不会体现到html
结构中attribute
:修改html
属性,会改变html
结构- 两者都有可能引起
DOM
重新渲染
- 一次性插入多个DOM节点,考虑性能
DOM的本质:DOM是从HTML文件解析出来的一棵树
DOM节点操作:
- 获取
DOM
节点
attribute
修改的是标签的属性
property
修改的是JS的属性
DOM结构操作
- 新增/插入节点
- 获取子元素列表 & 获取父元素
- 删除节点
DOM性能
- DOM操作非常“昂贵”,避免频繁的DOM操作
- 对DOM查询做缓存
- 将频繁操作改为一次性操作
第7章 JS-Web-API-BOM【内容虽然不多,但是你不能不会】
题目:
- 如何识别浏览器的类型
- 分析拆解
url
各个部分
第8章 JS-Web-API-事件【事件不会,基本等于半残废,必考!必考!】
题目:
- 描述事件冒泡的流程
- 基于
DOM
树形结构 事件会顺着触发元素往上冒泡
- 应用场景:
代理
- 基于
- 无限下拉的图片列表,如何监听每个图片的点击?
- 事件代理
- 用
e.target
获取触发元素 - 用
matches
来判断是否是触发元素
- 编写一个通用的事件监听函数【支持普通和代理绑定】
element.mathces(seletor);
判断当前DOM节点
是否能完全匹配对应的CSS选择器
,如果匹配成功,返回true
,反之则返回false
function bindEvent(elem, type, selector, fn) {
if (fn == null) {
fn = selector
selector = null
}
elem.addEventListener(type, event => {
const target = event.target
if (selector) {
// 代理绑定
if (target.matches(selector)) {
fn.call(target, event)
//当点击的是selector匹配的这个元素时才调用
}
} else {
// 普通绑定
fn.call(target, event)
}
})
}
// 普通绑定【fn里的this指向绑定元素】
const btn1 = document.getElementById('btn1')
bindEvent(btn1, 'click', function (event) {
// console.log(event.target) // 获取触发的元素
event.preventDefault() // 阻止默认行为
alert(this.innerHTML)
})
// 代理绑定【fn里的this指向触发元素】
const div3 = document.getElementById('div3')
bindEvent(div3, 'click', 'a', function (event) {
event.preventDefault()
alert(this.innerHTML)
})
第9章 JS-Web-API-Ajax【每个工程师必须熟练掌握的技能】
题目:
-
手写一个简易的
ajax
-
跨域的常用实现方式
JSONP
CORS
1. XMLHttpRequest
2. 同源策略(仅限浏览器,爬虫那种不同)
{width=81%}
{width=81%}
3. 跨域
4. JSONP【面试一般是问原理】
5. CORS-服务器设置 http header 【知晓即可】
6. ajax
的常用插件
jQuery
fetch
axios
第10章 JS-Web-API-存储【内容虽然不多,但不可不会】
题目:
- 描述
cookie localStorage sessionStorge
区别
{width=61%}
Http面试题
常见Request Headers
常见Response Headers
自定义headers
axios文档说明
缓存headers
http
缓存
第二点常考
为什么需要缓存
- 相对于cpu计算,资源请求是很慢的,优化可以从这方面开始
- 网络不稳定性(就导致页面加载不稳定)
- 可以缓存的是静态资源(
js css img
),业务数据就不行(因为后端随时会修改)
强制缓存
协商缓存(对比缓存)
三种刷新操作
https
第11章 开发环境【不会这些,你就会被认定是菜鸟小白,没做过项目】
1. Git常用命令
- 创建远程仓库
- 创建ssh公钥、私钥文件,打开pub文件到远程仓库里配置公钥,本地配置用户名、邮箱
把远程仓库的内容克隆到本地
git status
查看状态
git branch
查看现有分支
git commit
提交到仓库
git log(git show id)
查看修改记录
git checkout .
恢复修改
git push origin master
推送到远程仓库
git pull origin master
从远程仓库拉取到本地
git checkout -b xin
开发新功能就建立新分支 - 协同开发完后,你作为项目负责人,把分支pull下来,然后merge到main上,再把main分支push回git主分支上(后同)
- 如果合并分支有冲突,打开vscode解决完冲突后,
git add. ,git commit -m " "
再git merge等等 - 如果一不小心在master上修改了,但是你修改了蛮多又不想重来,可以在master运行
git stash
把修改先暂存,让main干净起来,再切换分支,运行git stash pop
把暂存的修改释放出来,接着就可以git add,git commit
了,再合并分支等等
2.chrome 调试工具
Application
主要是看storage
、cookies
3. 抓包
移动端h5页面,查看网络请求需要用工具抓包
windows
一般用fiddler
MacOS
一般用charles
抓包(演示charles)
- 手机和电脑连同一个局域网
- 将手机代理到电脑上(手机上选“代理”->“手动”,填电脑网络的那个IP),端口号可以在Proxy-Proxy Settings里看(默认是8888)
- 手机浏览网页既可抓包
- 查看网络请求
- 网址代理
- https
webpack和babel
- ES6模块化,浏览器暂不支持
- ES6语法,浏览器并不完全支持
- 压缩代码,整合代码,可以让网页加载更快
webpack搭建环境步骤
- 初始化webpack环境
npm init -y
,运行后会创建一个package.json
的文件 - 安装webpack
cnpm install webpack webpack-cli -D
- 建立
webpack.config.js
文件,webpack默认配置文件名字
package.json
文件scripts
下新增"build":"webpack"
- 然后
npm run build
就可以打包完成了,这时就有dist文件了 - 下载一个
解析html
的插件npm install html-webpack-plugin -D
- 下载一个
能启动本地服务
的插件npm install webpack-dev-server -D
- 再到
package.json
文件中新增"dev":"webpack-dev-server"
- 然后
npm run dev
运行一下
babel
因为你写的ES6语法webpack打包后还是显示ES6,我们希望变成ES5代码,这时就需要babel了
npm install @babel/core @babel/preset-env babel-loader -D
- 新建
.babelrc
文件,配置如下
webpack.config.js
新增
- 再次运行
npm run dev
webpack-ES6-Module
- 导出用
export default
的话到时候导入必须是import XX from './xx'
- 导出用
export
的话到时候可以用解构赋值import {xx,xx} from './xx'
webpack配置生产环境
- 新建
webpack.prod.js
文件,把以前的webpack.config.js
的内容拷过来。【一个配置文件做开发环境下的,一个做生产环境的】 webpack.prod.js
里修改"mode":"production"
,然后devServer不要了
- 运行
npm run build
命令
Linux命令
- 本地登录到线上机器
ssh 线上机器用户名@线上机器ip地址
,然后输入密码 ls
查看目录,ls -a
可查看隐藏文件(linux
中以.
开头的都是隐藏文件)ll
看列表型目录,clear
清屏,mkdir abc
创建文件夹rm -rf abc
删除文件夹,加-rf
会把文件夹内容清空,不加可能会出问题mv index.html index1.html
修改文件名,mv
还可以移动文件位置cp a.js b.js
拷贝a成b文件touch d.js
新建文件vi d.js
没有的话新建文件并打开(有则直接打开),之后点一下i
就可以输入了,点击键盘上Esc
,接着输入:w
然后回车代表保存写入,再点回车+:q
退出。不想保存强制退出:q!
cat a.js
查看文件把文件内容全部显示出来head a.js
打印前面几行tail a.js
打印后面几行grep "babel" a.js
在a.js
文件中查找babel
关键字
第12章 运行环境【这些会了,你就可以飞了】
题目:
- 从输入
url
到渲染出页面的整个过程
{width=81%} window.onload
和DOMContentLoaded
的区别
1. 页面加载和渲染
{width=60%}
{width=63%}
{width=68%}
{width=81%}
- 建议把
css
放head里 js
放body
最后
2. 性能优化
{width=81%}
{width=81%}
{width=81%}
{width=81%}
3. 防抖debounce
4. 节流throttle
5. 安全
- 常见的
web
前端攻击方式有哪些?XSS
跨站请求攻击
XSRF
跨站请求伪造
{width=81%}
第13章 课程总结【很有必要带你避免面试犯低级错误】
略
第14章 真题模拟【我是来告诉你答案是什么】
题目:
var
和let const
的区别
typeof
返回哪些类型
{width=81%}- 列举强制类型转换和隐式类型转换
- 手写深度比较,模拟
loadash.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( obj1 === obj2 )
console.log( isEqual(obj1, obj2) )
const arr1 = [1, 2, 3]
const arr2 = [1, 2, 3, 4]
split()
和join()
的区别split()
方法用于把一个字符串分割成字符串数组
。join()
方法将数组作为字符串返回
。元素将由指定的分隔符分隔。默认分隔符是逗号,
-
数组的
pop push unshift shift
分别做什么- 功能是什么?
- 返回值是什么?
- 是否会对原数组造成影响?
{width=81%}
-
数组
slice
和splice
的区别- 功能区别(
slice -切片 splice -剪接
) - 参数和返回值
- 是否纯函数?
{width=76%}
- 功能区别(
[10,20,30].map(parseInt)
返回结果是什么?【其实就是”//拆解”里的那个意思】
ajax
请求get
和post
的区别?
- 函数
call
和apply
的区别【传参形式不同】
{width=54%} - 闭包是什么,有什么特性?有什么负面影响?
{width=81%}
{width=60%}{width=40%} - 解释
jsonp
的原理,为何它不是真正的ajax?
- 函数声明和函数表达式的区别
{width=81%}
new Object()
和Object.create()
的区别
- 关于
this
的场景题【this指向谁要看调用的时候】
{width=81%} - 作用域和自由变量的场景题1
所有的自由变量的查找,是在函数定义的地方向上级作用域查找
- 正则表达式【菜鸟教程 】 【正则表达式30分钟入门教程】
\w
匹配字母、数字、下划线
,等价于[A-Za-z0-9_]
- 手写字符串
trim
方法,保证浏览器兼容性
- 如何获取多个数字中的最大值【两种方法】
- 如何用JS实现继承?
class
继承【更推荐】prototype
继承
- 如何捕获
JS
程序中的异常?
- 什么是
JSON
?
- 获取当前页面
url
参数
- 将
url
参数解析为JS对象【两种方法】
- 手写数组
flatern
,考虑多层级
- 数组去重
- 传统方式,遍历元素挨个比较、去重
- 使用
Set
- 考虑计算效率
{width=61%}
- 手写深拷贝【注意
Object.assign
不是深拷贝】
{width=81%} - 介绍一下
RAF requestAnimateFrame
- 前端性能如何优化?一般从哪几个方面考虑?