- 基础知识与素养
- JS基本功训练与思考
- 程序设计的渗透与应用
- 业务技巧的积累与训练
- 生产力转换
- 项目的组织架构
- 转换专业人才的全面生产力
什么样的技术水平决定了你应该学习什么样的知识与技术,什么样的知识与技术水平决定了你到什么样的公司,到什么样的公司决定了你在什么样社会层次,什么样的社会层次决定了你的眼界与发展的高度。
试题来源
一 面试题:
0、*浮动的影响
① 浮动元素不占位,脱离文档流,可以达到文字环绕的排版效果,也会引起标准流div被浮动元素遮挡
② 父元素高度塌陷
1、*BFC:解决因为浮动引起的问题 BFC
1)触发BFC的条件
① body元素
② float非none的
③ 绝对定位的(position:fixed/absolute)
④ display: flex/inline-block/table-cells
⑤ overflow非visible
2)BFC的特性
同一BFC内margin折叠
3)BFC的作用
① 清除浮动(解决父元素高度塌陷)
② 解决元素被浮动元素覆盖(可用于做左右两列布局,左宽度固定,右自适应)
2、*完整的web请求(返回了html)浏览器访问地址
3、*页面渲染HTML过程
4、*get、post请求的区别,解释get请求可以被缓存(浏览器决策)、不想缓存如何做:
1)在ajax发送请求前加上xmlHttpRequest.setRequestheader(‘Cache-Control’,“no-cache”) 或者请求头(“if-Modified-Since”:“0”)
2)在服务端加 header("cache-Control:no-cache,must-revalidate)
3)增加一个唯一值的参数:一般是使用timestamp = new Date().getTime() (推荐)
(场景:请求服务器资源,如下载文件,文件更新时)
5、下载文件,window.open、download属性依然不下载(必须同源)
6、反向代理是什么、作用
1)反向代理
反向代理(Reverse Proxy)方式是指:代理服务器来接受 Internet 上的连接请求,然后将请求转发给内部网络上的服务器,并将从内部网络上服务器得到的结果返回给 Internet 上请求连接的客户端。此时代理服务器对外就表现为一个服务器,反向代理服务器对于客户端而言它就像是原始服务器,并且客户端不需要进行任何特别的设置。
反向代理的作用:
保证内网的安全,可以使用反向代理提供 WAF 功能,阻止 web 攻击。
负载均衡,通过反向代理服务器来优化网站的负载。
7、**vue项目性能优化(小野森森)
- vue-for为什么要加key(更快定位数据与diff)
- 模块化、组件化(封装高度复用性的模块:http、拆分高度复用性的组件、组件可配置性强)
- 路由懒加载/动态加载组件 :首屏加快渲染
- productionSourceMap设置false:否则,生产map文件,打包后体积变大,且能定位源码(泄漏源码逻辑)【在bulid/config/index文件下】
- productionGzip设置true:gzip压缩、打包体积更小
- keep-alive:缓存组件,用keep-alive包裹router-view
- 插件CDN:vue-router、axios可以用link方式引入到html中,并在configureWebpack里注册,减少打包(也可以将这些js、css文件下载,放在自己的CDN、以防官方服务器挂了)
- 图片CDN、图片懒加载(vue-lazyLoad插件,v-lazy指令)、使用CSS图标(在main.js里全局引入iconfont字体图标)
- 组件按需导入: import { Button, Input } from ‘element-ui’
8、**webpack打包工具 (小野森森)【考配置流程、loader的作用】
1、作用①:压缩代码,混淆js代码;
2、作用②:浏览器不支持ES5以上的语法,webpack可以安装一系列依赖包将之翻译成ES5
3、作用③:将less、sass编译成css
4、所需依赖:
- 【三大件】webpack、webpack-cli(脚手架)、webpack-dev-server(开发者服务器插件)
- 【六件套】处理ES6 ES7… 装饰器:
. babel-loader@7、babel-core、babel-preset-env
. babel-plugin-transform-runtime
. babel-plugin-transform-decorators、 babel-plugin-transform-decorators-legacy- 【四大件】处理样式sass:
. sass-loader、node-sass、css-loader、style-loader ( postcss-loader autoprefixer )- 处理模板:ejs-loader
- 处理HTML: html-webpack-plugin
5、安装指令:
- –save-dev 简写 -D (安装在开发环境下的,线上不跑)
- –save 简写 -S (安装在生成环境下的)
6、配置安装包 webpack.config文件
特*:所有plugin结尾的依赖,一般要require导入、babel则不用
plugins: [ new HtmlWebpackPlugin( { } ) ]
7、 用命令跑配置文件webpack.config,在package.json的script里(跑脚本)
9、***Promise(小野森森)
引子:一个高阶函数(参数里有函数),返回一个fn,在fn里有条件的执行回调方法(闭包)
const doSth = (t) => {return () => {if (--t === 0) {print1(() => {print2(() => {print3()})})}}
}
const print1 = (cb) => {console.log('第一次打印')// 打印出这句话后执行cbcb()
}
const print2 = (cb) => {console.log('第二次打印')cb()
}
const print3 = () => {console.log('第三次打印')
}
const fn = doSth(3, print1)
fn()
fn()
fn()
1. 基本
目的:需要处理异步请求的嵌套,比如,先根据接口判断是否重复,拿到res后再进行下一次请求
① Promise是解决异步流程化的手段,Promise不是异步
② Promise是构造函数,需要new
③ Promise的唯一参数,executor函数,有参数resolve、reject
④ executor在new Promise的时候调用
⑤ executor是同步执行的,而then是异步调用的
⑥ 每个返回的Promise都有一个then方法,方法有2个回调函数cb,第一个cb的参数需由resolve执行时传入,resolve时执行第一个cb,reject时执行第二个cb
⑦ 没有第二个callback的时候可以通过.catch,优先走then里的第二个cb,且无论是第几个then,总是优先于catch
⑧ reject能做的,throw new Error也可以
⑨ 每个then可以再继续.then下去 (在第一个Promise里返回Promise)
⑤ ↓
let promise = new Promise((resolve, reject) => {console.log(1)reject(3)
})
promise.then((res) => {console.log('打印', res)
}, (err) => {console.log(err)
})
console.log(2)
// 打印 1 2 3
⑥ ↓
let promise = new Promise((resolve, reject) => {resolve('结果')
})
promise.then((err) => {console.log('打印', err)
})
// 打印 结果
let promise = new Promise((resolve, reject) => {reject('服务异常')
})
promise.then((res) => {console.log('打印', res)
}, (err) => {console.log(err)
})
// 服务异常
⑦ ↓
let promise = new Promise((resolve, reject) => {reject('服务异常')
})
promise.then().catch((err) => {console.log(err)
})
// 服务异常
let promise = new Promise((resolve, reject) => {reject('服务异常')
})
promise.then(() => { }, (err) => {console.log('优先then', err)
}).catch((res) => {console.log(res)
})
// 优先then 服务异常
let promise = new Promise((resolve, reject) => {reject('服务异常')
})
promise.then(() => { }).then().then(() => { }, (err) => {console.log('无论第几个then,总是优先', err)
}).catch((res) => {console.log(res)
})
// 无论第几个then,总是优先 服务异常
⑧ ↓
let promise = new Promise((resolve, reject) => {throw new Error('抛出错误')
})
promise.then(() => { }).then().then(() => { }, (err) => {console.log('无论第几个then,总是优先', err)
}).catch((err) => {console.log(err)
})
let promise = new Promise((resolve, reject) => {throw new Error('抛出错误')
})
promise.then(() => { }).catch((err) => {console.log(err)
})
⑨ ↓
let promise = new Promise((resolve, reject) => {resolve('结果1')
})
promise.then((res) => {console.log('打印', res)return new Promise((resolve, reject) => {resolve('结果2')})
}).then((res) => {console.log('打印', res)
})
// 打印 结果1
// 打印 结果2
2. 语法糖Promise.resolve Promise.reject
相当于是 new Promise(…)
let promise = new Promise((resolve, reject) => {resolve('结果1')
})
promise.then((res) => {console.log('打印', res)return Promise.resolve('成功啦')
}).then((res) => {console.log(res)
})
// 打印 结果1
// 成功啦
3. Promise.all(通常用于等待多个异步任务完成)
① Promise.all接收iterable类型数据(如Array、Set、Map),数据的每一项可以是Promise也可以不是
② 返回值是Promise,因此可以.then。 如果resolve,则将iterable的每个Promise resolve的data依次放入数组
③ 若参数为空数组,返回空数组
④ 只要其中一个Promise的状态rejected了,整个Promise.all的状态便rejected,失败的原因是第一个失败的Promise的结果
⑤ 使用场景:一个页面初始化需要请求多个接口,只要任何一个接口失败,便认为初始化是失败的,需要重新请求
4. Promise.race
① 谁先完成,就只返回那个Promise的结果,且无论成功或失败,都会返回
② 若参数为空数组,Promise.race的结果永远处于pending状态,看起来是什么都没返回
③ 可以比较资源或接口的响应速度
5. async、await
① await是一个操作符,她等待一个Promise对象产出结果,如果这个结果是rejected,就会抛出异常
② async函数返回一个pending状态,这本身并没有什么意义
10、***函数防抖与节流小野森森
1、函数防抖
1)含义:
① 延迟执行(时间被触发n秒后再执行的回调)
② 如果在n秒内再次触发,则重新开始计时
2)场景:
① ajax请求数据(比如下拉刷新、首次延迟)
② ajax提交数据(提交、支付等按钮重复点击、首次不延迟)
③ 表单校验(input输入时,延迟验证,首次也延迟)否则可能无法得到校验通过的结果
3)实现:
① clearTimeOut的返回值是计时器id,此时t还有值 只有t = null,t才会变成null
② 这里不要乱用箭头函数
③ 不要debugger调试
④ 思路:考虑首次不延迟的情况→没有定时器则为首次,因此time后要t = null
(time内频繁触发,计时器会频繁重新开始计时)
domObj.onclick = debounce(myFn)
const myClick = () => {console.log('tag', Date.now())
}
var debounce = function (fn, time, triggleNow) {var t = null // 只有第一次点击会走这里var debounced = function () {var _self = this,args = arguments;if (t) {console.log('t0', t)clearTimeout(t)// 清除定时器后,t的值还在 // 除非赋值null,否则随着点击次数而增加}console.log('t1', t)if (triggleNow) {var exec = !tconsole.log('t2', t)t = setTimeout(function () {t = null}, time)// 到这里 t必有idconsole.log('t3', t)if (exec) {fn.apply(_self, args)}} else {console.log('t4', t)t = setTimeout(function () {fn.apply(_self, args)}, time)}}debounced.remove = function () {clearTimeout(t)t = null}return debounced}
const box = document.getElementsByClassName('box')[0]
box.onclick = debounce(myClick, 1000, true)
表单输入
const oInput = document.getElementById('input')
const myCheck = function () {var val = this.valueif (val.length < 6) {console.log('校验失败')} else {console.log('校验成功')}
}
oInput.onkeyup = debounce(myCheck, 1000, true)
// 只会打印校验失败,之后即使长度满足了,由于在time内频繁键入,也不会再触发了
若函数有返回值
var debounce = function (fn, time, triggleNow) {var t = null,res// console.log('t', t)// time内多次点击,只有初次会走这里var debounced = function () {var _self = this,args = arguments;if (t) {console.log('t0', t)clearTimeout(t)// 清除定时器后,t的值还在 // 除非赋值null,否则随着点击次数而增加}console.log('t1', t)if (triggleNow) {var exec = !tconsole.log('t2', t)t = setTimeout(function () {t = null}, time)// 到这里 t必有idconsole.log('t3', t)if (exec) {res = fn.apply(_self, args)}} else {console.log('t4', t)t = setTimeout(function () {res = fn.apply(_self, args)}, time)}return res // 假若函数有返回值}debounced.remove = function () {clearTimeout(t)t = null}return debounced}
2、 函数节流
1)含义场景:
事件被触发、n秒内只且必执行一次事件处理函数 ,可用于输入验证、ajax提交
2) 实现:
function throttle(fn, delay) {// 闭包var t = null,begin = new Date().getTime()return function () {var _self = this,args = arguments,cur = new Date().getTime()clearTimeout(t)if (cur - begin >= delay) {console.log(1)// 隔了很久后再在原来基础上输入,会先走1,再走2fn.apply(_self, args)begin = cur} else {console.log(2)t = setTimeout(function () {fn.apply(_self, args)}, delay)}}
}
对比:
n秒内频繁触发,永远不让执行,用函数防抖
n秒内频繁触发,有且执行一次,用函数节流
11、 事件循环 文
① 消息队列/任务队列/事件队列是一样的,即异步任务相关的队列(先进先出/排队)
② 异步任务有:(队列中的消息对应着事件,因此叫事件循环,循环读取消息队列)
- 普通事件:click、resize → DOM操作对应DOM事件
- 资源加载:load、error → 资源加载操作对应加载事件
- 定时器:setInterval、setTimeout
③ 详细步骤:
- 所有同步任务都在主线程上执行,形成一个执行栈
- 主线程之外,还存在一个"消息队列"。只要异步操作执行完成,就到消息队列中排队
- 一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取消息队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行
- 主线程不断重复上面的第三步
从代码执行顺序的角度来看,程序最开始是按代码顺序执行代码的,遇到同步任务,立刻执行;遇到异步任务,则只是调用异步函数发起异步请求。此时,异步任务开始执行异步操作,执行完成后到消息队列中排队。程序按照代码顺序执行完毕后,查询消息队列中是否有等待的消息。如果有,则按照次序从消息队列中把消息放到执行栈中执行。执行完毕后,再从消息队列中获取消息,再执行,不断重复。
12、宏任务、微任务 文
① 微任务早于宏任务
② 多个定时器(内含同步、微任务),按定时器顺序完整执行完
13、this指向 文
1:this永远指向一个对象;
2:this的指向完全取决于函数调用的位置;
针对以上的第一点特别好理解,不管在什么地方使用this,它必然会指向某个对象;确定了第一点后,也引出了一个问题,就是this使用的地方到底在哪里,而第二点就解释了这个问题,但关键是在JavaScript语言之中,一切皆对象,运行环境也是对象,所以函数都是在某个对象下运行,而this就是函数运行时所在的对象(环境)。
11、****设计模式
1)单例模式
12、***原型链
13、***闭包
14、****事件循环
15、**vue路由模式、前端单页面路由跳转实现的原理是什么
1、Vue模板编译(小野森森)
11、Vue2、3的区别(小野森森)
- vue2.0:options API (低内聚)
- vue3.0:可以将方法提出来
12、**call、bind、apply
- 改变this指向(第一个参数)
- 只有applay的参数是数组
- 只有bind返回的是函数
案例
const doSth = (t, cb) => {return () => {if (--t === 0) {cb()}}
}
const print1 = (cb) => {console.log('第一次打印')// 打印出这句话后执行cbcb()
}
const fn = doSth(3, print1)
fn()
fn()
fn()
const doSth = (t, cb) => {return () => {if (--t === 0) {cb()}}
}
const print1 = (cb) => {console.log('第一次打印')// 打印出这句话后执行cbcb()
}
const print2 = (cb) => {console.log('第二次打印')cb()
}
const fn = doSth(3, print1.bind(null, print2))
fn()
fn()
fn()
13、401:没有提供认证信息。请求的时候没有带上 Token 等
- 预编译、作用域、闭包
- 内容字数位置,宽度高度不定,只展示2行,多余内容…
- 中断ajax请求(超时、手动中断)后端响应超时:吉行无忧
- 事件代理的使用场景
- vue核心功能
微信网页版:Http 请求报文头部信息,其中 Connection: keep-alive 意味着这次请求结束后不会关闭 TCP 连接
待续…
es6程序设计
websocket
面试题
vue3.0+ts
响应式布局
vue3.0星座项目
使用开发者工具