前端知识体系
JavaScript
内置类型
-
内置类型有哪些?
-
类型转换
-
区分类型
- typeOf
- instanceof
- object.prototype.tostring
- constructor
基本数据类型:undefined,null,number,string,Boolean,symbol(es6新增,表示独一无二的值)
引用数据类型:
object,function,array
题外:关于栈与堆数据类型转换
转换为布尔值(调用Boolean()方法);
转换为数字(调用Number()、parseInt()和parseFloat()方法);
转换为字符串(调用.toString()或者String()方法)。【null和underfined没有.toString方法】
1)typeof ——不能判断对象具体类型
console.log(typeof 2); // number
console.log(typeof true); // boolean
console.log(typeof 'str'); // string
console.log(typeof []); // object []数组的数据类型在 typeof 中被解释为 object
console.log(typeof function(){}); // function
console.log(typeof {}); // object
console.log(typeof undefined); // undefined
console.log(typeof null); // object null 的数据类型被 typeof 解释为 object
console.log(typeof symbol); //undefined
2)instanceof ——基本数据类型不能判断,因为原理是通过判断对象的原型链中是不是能找到类型的 prototype。
console.log(2 instanceof Number); // false
console.log(true instanceof Boolean); // false
console.log('str' instanceof String); // false
console.log([] instanceof Array); // true
console.log(function(){} instanceof Function); // true
console.log({} instanceof Object); // true
// console.log(undefined instanceof Undefined); //报错
// console.log(null instanceof Null); //报错
3)constructor ——有bug,对象如果改变它的原型,判断会失误
console.log((2).constructor === Number); // true
console.log((true).constructor === Boolean); // true
console.log(('str').constructor === String); // true
console.log(([]).constructor === Array); // true
console.log((function() {}).constructor === Function); // true
console.log(({}).constructor === Object); // true
//bug
function Fn(){};
Fn.prototype=new Array();
var f=new Fn();
console.log(f.constructor===Fn); // false
console.log(f.constructor===Array); // true
4)Object.prototype.toString.call() ——用 call 方法进行狸猫换太子,借用Object的 toString 方法
var a = Object.prototype.toString;
console.log(a.call(2)); //[object Number]
console.log(a.call(true)); //[object Boolean]
console.log(a.call('str')); //[object String]
console.log(a.call([])); //[object Array]
console.log(a.call(function(){})); //[object Function]
console.log(a.call({})); //[object Object]
console.log(a.call(undefined)); //[object Undefined]
console.log(a.call(null)); //[object Null]
作用域
- 块级作用域、词法作用域
- 执行上下文
- let、const、var
let、const、var:
变量提升;
暂时性死区;
块级作用域;
重复声明;
修改声明的变量。能用const的情况尽量使用const,其他情况下大多数使用let,避免使用var
var 特点:
① var声明变量既是全局变量也是顶层变量(即window对象)
②可以变量提升
③ 可以多次声明
④ 如果在函数里面使用var声明是局部的
let特点:
① 不可声明提升(暂时性死区)
② 有作用域限制,在同一作用域里,不可以声明多次
③ 函数内声明变量名不可以和参数名一样
④
const特点:
① 声明常量,不可变
② const声明不赋值会报错
③ 如果之前用var或let声明过变量,再用const声明同样会报错
注意
:const实际上保证的并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动
面试题:
this
- 一般函数、箭头函数
- this指向:bind、apply、call
箭头函数定义的上下文是不能改的,执行的时候this就等同指向window
所以以下不能使用箭头函数的情况有:
1.定义字面量方法
2.定义原型方法
3.定义事件回调函数
4.定义构造函数
(注意:箭头函数简写虽然方便,但过于简写,能会给代码阅读和逻辑理解带来困难。)
详细内容
原型/继承
- 继承方法
- 原型/原型链
- 构造函数、new过程
ES6
事件循环
- js运行机制
- 微任务、宏任务
- 浏览器循环和node事件循环
JavaScript 执行机制?微任务和宏任务有什么区别?
浏览器与Node事件循环(Event Loop)有何区别?
满分答案
闭包
- 问题
- 应用场景
- js垃圾回收机制
看这里喔~
异步编程
-
promiss
-
方法
- all
- race
- any
- allSeleted
-
- Async await
DOM
-
事件
- 阶段:事件冒泡、目标、捕获
- 事件委托
三个阶段:事件捕获,目标,冒泡
补充:事件委托
捕获和冒泡和事件委托关系
阻止冒泡:e.stopPropagation()和e.cancelBubble=true(IE浏览器)
注意:元素被阻止冒泡就不要用事件委托监听事件,因为它的原理就是利用冒泡,如果被阻止了就无法监听
- dom操作
插入节点
数组方法
数组看这里喔
图片总结:
CSS
flex布局
重绘重排
常见布局
自适应布局:布局无论在哪里都是不会变化的
响应式布局:根据所在终端会改变对应的布局效果
- 双飞翼
- 自适应布局
- 三栏布局
学习笔记
选择符
选择符
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)可继承的样式:font-size font-family color text-indent;
不可继承的样式:border padding margin width height ;
优先级:!important > 内联 > id > class > tag
盒模型
标准盒:content
怪异盒:content + border + padding
box-sizing:border-box(怪异盒);content-box(标准盒)
盒子居中方法
BFC概念
BFC,块级格式化上下文,一个创建了新的BFC的盒子是独立布局的
解决:margin上下重叠;margin塌陷;高度塌陷
触发规则:float:left | right
overflow:hidden | scroll | auto; (不是visible)
display:inline-block | table-cell | table-caption | flex | grid ;( 非none 非inline 非block)
position: absolute | fiexed ;( 非relative)
清除浮动
less、sass
HTML
语义化标签
新增属性
1.标记方法:① DOCTYPE声明: ;② 指定字符编码:
2.语义化标签
3.新增Input类型:① email;② url; ③ number; ④ range(滑动条);
4.表单新增属性:① palceholder; ② required(布尔值,内容不能为空);更详细
5.多媒体:video;audio;
6.储存数据:sessionStorage;localStorage
VUE
双向绑定的理解
本来单向绑定是:只有model和view,我们用js更新了module,view就自动更新;
双向绑定就是:在单向绑定基础上,用户更新了view,model也会自动被更新。
总结:数据变化后更新视图,视图变化后更新数据
Vue中的双向绑定流程:
主要组成部分:
监听器(Observer):对所有数据的属性进行监听
解析器(Compiler):对每个元素节点的指令进行扫描跟解析,根据指令模板替换数据,以及绑定相应的更新函数
过程:
- new Vue()首先执行初始化,对data执行响应化处理,这个过程发生Observe中
- 同时对模板执行编译,找到其中动态绑定的数据,从data中获取并初始化视图,这个过程发生在Compile中
- 同时定义⼀个更新函数和Watcher,将来对应数据变化时Watcher会调用更新函数
- 由于data的某个key在⼀个视图中可能出现多次,所以每个key都需要⼀个管家Dep来管理多个Watcher
- 将来data中数据⼀旦发生变化,会首先找到对应的Dep,通知所有Watcher执行更新函数
组件之间通信
先看看组件之间有什么关系?
总结:父子之间常用:1.3
兄弟之间:4
祖孙与后代组件:6
复杂项目(非关系组件之间):8
v-if 和 v-show
共同点:控制页面是否显示
不同点:
v-show是障眼法,暂时让你看不到,相当于css–display:none;
v-if是把组件销毁,切换时会触发生命周期;
如果是频繁切换使用v-show,但它在初始渲染消耗比较大
关于两者原理详情请看这里
声明周期
贯穿vue整个流程,四大周期八个阶段,分别是创建——挂载——更新——卸载,还有两个阶段需要和keep-alive组件使用
适用场景:
created和mouted的区别?
① created是在组件实例一旦创建完成的时候立刻调用,这时候页面dom节点并未生成;
② mounted是在页面dom节点渲染完毕之后就立刻执行的;
③ 触发时机上created是比mounted要更早的
两者相同点:都能拿到实例对象的属性和方法
他们最大区别就是触发的时机:放在mounted请求有可能导致页面闪动(页面dom结构已经生成),但如果在页面加载前完成则不会出现此情况,所以很多时候初始化页面数据放在create生命周期当中。
$nextTick
在修改数据之后立即使用$nextTick方法,可以获取到更新后的DOM。
因为vue更新DOM是异步执行,当数据发生变化后,vue开启一个异步更新队列,视图更新需要等待所有数据都变化完成后再统一进行。
原理上解析
watch 和 computed
computed:
computed是计算属性,也就是计算值,它更多用于计算值的场景
computed具有缓存性,computed的值在getter执行后是会缓存的,只有在它依赖的属性值改变之后,下一次获取computed的值时才会重新调用对应的getter来计算 computed适用于计算比较消耗性能的计算场景
watch:
更多的是「观察」的作用,类似于某些数据的监听回调,用于观察props $emit或者本组件的值,当数据变化时来执行回调进行后续操作,当我们需要深度监听对象中的属性时,可以打开deep:true选项,这样便会对对象中的每一项进行监听。
无缓存性,页面重新渲染时值不变化也会执行
小结:
当我们要进行数值计算,而且依赖于其他数据,那么把这个数据设计为computed
如果你需要在某个数据变化时做一些事情,使用watch来观察这个数据变化
虚拟DOM 和 diff算法
template 编译过程
key 作用
v-if和v-for的优先级
v-if是决定组件内容是否渲染;
v-for是基于一个数组渲染出来,最好设置key值,并且保证每个key值是独一无二的,这便于diff算法进行优化。
当两个指令同时存在时候,v-for优先级比v-if高
但是
,永远不要把 v-if 和 v-for 同时用在同一个元素上,带来性能方面的浪费(每次渲染都会先循环再进行条件判断)
key是给每一个vnode的唯一id,也是diff的一种优化策略,可以根据key,更准确, 更快的找到对应的vnode节点
原理在这里~
vue实例挂载过程
其实就是在问:new Vue()这个过程中究竟做了些什么?(原理题)
vue-loader是什么?
如何扩展某个Vue组件
实践题,考察对vue常用api使用熟练度
答题思路:
按照逻辑扩展和内容扩展来列举,逻辑扩展有:
mixins、extends、composition api;
内容扩展有slots;
分别说出他们使用使用方法、场景差异和问题。
作为扩展,还可以说说vue3中新引入的composition api带来的变化
常见的组件扩展方法有:mixins,slots,extends等
例如:插槽主要用于vue组件中的内容分发,也可以用于组件扩展。
//子组件
<div>
<slot>父组件传递的内容</slot>
</div>
//父组件
<div>
<Child>要发给子组件的内容</Child>
</div>
vue3
- 新特性
- ref 和 reactive 区别
- watch 和 watchEffect 区别
- 性能提升
- proxy (vue3)和 defineproperty 区别
区别 - composition API (vue3) 和 options API 区别
Vue3.0 所采用的 Composition Api 与 Vue2.x 使用的 Options Api 有什么不同?
vue-cli
-
动态路由
-
路由懒加载
-
router-link 和 router-view
-
vue-router 和 router-link 跳转
声明式(标签跳转)
<router-link :to="index">
编程式( js跳转)router.push('index')
- History 和 Hash 模式区别
hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用 window.location.hash 读取。特点:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。
history模式:history采用HTML5的新特性;且提供了两个新方法:pushState(), replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更对于一般的Vue+Vue-router+Webpack+XXX形式1的Web开发场景,用history模式即可
- 嵌套路由
- vue-router 完整导航解析过程
- vuex理解
- 页面刷新后vuex数据丢失怎么处理?
- $ route和$router的区别
$ route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。
而 r o u t e r 是 “ 路 由 实 例 ” 对 象 包 括 了 路 由 的 跳 转 方 法 , 钩 子 函 数 等 , 例 如 : router是“路由实例”对象包括了路由的跳转方法,钩子函数等,例如: router是“路由实例”对象包括了路由的跳转方法,钩子函数等,例如: router.push()
项目应用
-
vue代码优化
-
SPA 、SSR 区别
-
vue渲染大量数据优化
-
权限管理
权限控制
小程序
小程序底层实现
H5 和 小程序区别
原理
浏览器
跨域
- jsonp
- CORS
- 代理
跨越原因:协议相同(protocol),主机相同(host),端口相同(port)其中一个不同就可引起跨越。
补充:
1.通过jsonp跨域
缺点:只能使用get请求
//原生实现
<script>
var script = document.creatElement('script');
script.type = 'text/javascript';
script.src = 'http://www.b.com/getdata?callback=demo';
function demo(res){
console.log(res)'
}
<script>
//jquery ajax实现
$.ajax({
url:'http://www.b.com/getdata?callback=demo',
type:'get',
dataType:'jsonp',
jsonpCallback:'demo',
data:{}
});
2.CORS-跨域资源共享
CORS是一种机制,它使用额外的HTTP头来告诉浏览器,让运行在一个origin上的web应用被允许访问来自不同源服务器上的指定资源。
目前基本所有浏览器支持CORS,IE浏览器版本不能低于10。
CORS请求分为两类:简单请求和非简单请求。
3.window.postMessage
postMessage是HTML5 XMLHttpRequest level2的API,能够解决① ifarm嵌套页面的跨域通信,
② 页面和其打开的新窗口的通信,
③ 多窗口之间消息传递
4.document.domain
这种方式只适合主域名相同,但子域名不同的ifarm跨域
5.window.name
6.Nginx代理跨域
一般在前后端分离项目中开发阶段会采用这种方式
详细讲解
7.WebSocket协议跨域
WebSocket 是基于TCP/IP协议,属于应用层且独立于HTTP协议的通信协议。(HTML5新特性之一)
WebSocket 是双向通讯,有状态,客户端一(多)个与服务端一(多)双向实时响应(客户端 ⇄ 服务端)简单来说就是:
- WebSocket可以在浏览器里使用
- 支持双向通信
优点:
① 服务器可以直接发送数据而不用等待客户端的请求;
② 只要建立起websocket连接,就可以一致保持连接状态,并不断发送信息,而且websocket的首部信息量也小 ,通信量也减少了;
③ 直接和nginx建立持久连接,减少资源消耗
从输入URL到页面显示发生什么?
页面渲染过程
cookie和localstorage
网络
http、https区别
- HTTPS原理
为什么你认为HTTPS是安全的
http缓存策略
tcp三次握手,四次握手
为什么是三次握手呢?因为建立可靠连接需要保证发送端和接收端都拥有发送能力和接收能力。
TCP 断开连接采用四次挥手的策略。
←三次握手 四次握手↓
http2.0多路复用原理
CDN
- 是什么
- 原理
CDN 的全称是 Content Delivery Network,即内容分发网络。
例如:以前你要买后车票一定要去售票大厅,后来小地方出现了代售点,那么这些代售点就是cdn,减轻了售票大厅的人流压力,又可以提高效率。
目的:让用户可就近取得所需内容,解决 Internet网络拥挤的状况,提高用户访问网站的响应速度。js 有 2 种 引入 方式:
1 下载代码文件至本地项目中,引入。
2 通过 CDN(内容分发网络) 引用它 。
DNS
我们输入URL后通过DNS解析成IP地址
别人优秀总结DNS(Domain Name System)服务是和HTTP协议一样位于应用层的协议,它提供域名到IP地址之间的解析服务。
状态码
① 1xx 100——确认信息状态码
② 2xx 200——成功请求
③ 3xx
301——永久性重定向;
302——临时重定向;
303——临时重定向,但只能用get方法;
304——上次请求完资源没修改过;
307——临时重定向,但只能用post方法;
④ 4xx
400——客户端请求错误;
401——请求未授权;
403——禁止访问;
404——找不到匹配资源
⑤ 5xx 500——服务端问题;
503——服务端无法处理请求。
安全
- xss
- csrf
- 网络传输安全
工程化
脚手架
构建工具:webpack
- 构建过程
- loader、plugin
- 优化构建速度
- 手写loader、plugin
- tree-shaking原理
- babel原理
项目部署
- 项目发布流程
- SSR项目如何发布的
开发规范
- eslint
git
性能优化
页面加快加载
-
网络优化
- http2
- CDN
-
代码大小
- 压缩
- 分割
- tree-shaking
Tree shaking是什么?
-
SSR
SSR也就是服务端渲染,也就是将Vue在客户端把标签渲染成HTML的工作放在服务端完成,然后再把html直接返回给客户端
SSR有着更好的SEO、并且首屏加载速度更快等优点。不过它也有一些缺点,比如我们的开发条件会受到限制,服务器端渲染只支持beforeCreate和created两个钩子,当我们需要一些外部扩展库时需要特殊处理,服务端渲染应用程序也需要处于Node.js的运行环境。还有就是服务器会有更大的负载需求
- 离线、缓存
客户端
- 渲染优化
- web worker
滚动和动画
- 优化大数据列表(10w+)
- js动画和css动画区别
- 分离图层动画
- 重绘重排
图片
- 压缩
- 懒加载
骨架屏+合理的loading
NodeJs
node事件循环
Node 环境的配置
内置模块
-
fs文件模块
-
path路径模块
- path.extname() 获取扩展名
- path.resolve() 生成绝对路径
- path.join() 路径拼接
- __dirname 当前执行文件完整目录
- __filename 完整目录+文件名
- process.cwd() Node命令时的目录
模块化规范CommonJS
- CommonJS 和 ESM 区别?
中间层
SSR
算法
手写
promiss
- 红绿灯交替重复
- all、race、allSeleted
this(call/apply、bind、new)
原型链
闭包
防抖节流
深浅拷贝
网络请求
- AJAX
- JSONP