1、原型
JavaScript中每个函数都有prototype(原型)属性,这个prototype(原型)属性是一个指针,指向一个对象,
这个对象的用途是包含特定类型的所有实例共享的属性和方法每个实例对象的_proto_都指向这个构造函数/类的prototype(原型)属性
构造函数
构造函数是一种特殊的方法,用来在创建对象时初始化对象,每个构造函数都有propety(原型)属性(注意:箭头函数和function.prototype.bind()函数是没有prototype(原型),
这个prototype(原型)属性是一个指针,指向一个对象,这个对象的用途是包含特定类型的所有实例共享的属性和方法,
即这个对象是用来给对象共享属性和方法的。
每个实例对象的_proto_都指向这个构造函数/类的prototype(原型)属性
面向对象的三大特性
继承、多态、封装
1、new执行的函数,函数内部默认生成了一个对象
2、函数内部的this默认指向了这个new生成的对象
3、new生成的对象是函数的默认返回值
// =============es5
function Person(obj){
this.name = obj.name
this.age = obj.age
}
// 原型方法
Person.prototype.say = function(){
console.log('你好',this.name)
}
// p为实例化对象,new person 这个操作是构造函数的实例化
let p = new Person({name:"大巷",age:"26"})
console.log(p.name,p.age)
// ==============es6
class Person{
constructor(obj){
this.name = obj.name
this.age = obj.age
}
say(){
console.log(this.name)
}
}
let p = new Person({name:"老大",age:"27"})
console.log(p.name,p.age)
p.say()
2、原型链
原型链是实例对象与原型之间的链接。
当函数自身有相应的方法或者属性时就用自己的,当自身没有时才通过_proto_原型链查找
原型和原型链
prototype是函数才有的属性,_proto_是每个对象都有的属性
大多数情况下,_proto_可以理解为“构造器的原型”,即:_proto_ === constructor.prototype
原型链:由于_proto_是任何对象都有的属性,而js里万物皆对象,所以会形成一个_proto_连起来的链条,递归访问_protu_必须最终到头,并且值是null
new操作符做了什么
1、创建一个新对象
2、将构造函数的作用域赋给新对象(因此这个this就指向了这个新对象)
3、执行构造函数中的代码(为这个新对象添加属性)
4、返回新对象
3、闭包
1、有权访问另一个函数作用域变量的函数都是闭包。
2、闭包简单来说就是函数嵌套函数,外部访问函数内部变量,从而导致垃圾回收机制没有把当前变量回收掉,这样的操作带来了内存泄漏的影响,
当内存泄漏到一定程度会影响你的项目运行变得卡顿等等问题。因此在项目中我们要尽量避免内存泄漏
怎么形成一个闭包
这里的c函数访问了构造函数a里的变量,所以形成了一个闭包
function a(){
var n=0;
function b(){
n++;
console.log(n)
}
return b;
}
var c=a();
c();
为什么使用闭包
我们知道,JS的每个函数都是独立的,可以获取外界信息,但是外界却无法直接看到里面的内容,我们将变量n放在函数里,除了函数b,没有其他办法可以接触到n,
而且在函数a外定义变量n也不会受到影响,这就是"封装性"。而之所以return是因为函数a外无法直接调用b函数,所以return出去
4、介绍一下vuex以及使用和注意事项
vuex是基于vue框架的一个状态管理库,可以管理复杂应用的数据状态,比如:兄弟组件通讯,多层嵌套的组件信息等
核心概念
action、mutation、state、getter、moudle
1、store是核心对象,他记录了vue应用的数据状态以及操作数据的方法
state就是store操作的数据状态对象
2、moutation提供了一种简单易用的同步的方式改变state的状态,这是vuex提供的唯一更改store的属性,触发方式:store.commit(‘increment’)
3、mapState--获取多个state数据
由于计算属性只能获取一个state的变化,如果用多个就要写多个计算属性,为了减少代码冗余
4、action这个属性的作用类似于Mutation,但是它提交的是mutation,而不是变更状态。并且action可以包含任何异步状态,actions中的函数的参数是context,
这个context有commit、getter、state等属性,通过dispatch来触发
注意事项
1、mutations属性函数时必须传递的第一个参数是state,第二个参数代表传入的新参数。mutations属性函数只接受两个参数,如果要同时更改多个属性值,可以通过对象传入。
2、在actions属性函数中可以通过context.commit()方法触发mutations属性函数。定义actions属性函数时,必须传递的第一个参数是context,用于触发mutations函数
3、在组件中访问数据中心state的注意事项
在Vue实例中可以通过this.$store.state对象获取state中的数据。如果希望在state中的数据发生更改之后,组件会自动更新,则应该使用组件的computed属性定义数据,
而不是通过data属性定义。如果使用data定义组件数据,则state中的数据发生更改之后组件不会发生变化
5、DOM和虚拟DOM
1、DOM的作用就是对html文档进行增删改查,往往修改dom是牵一发而动全身的,而虚拟dom解决了这一点
2、虚拟dom是真实dom结构的映射,即一个数据集合
通过这种转换,我们就可以把对真实dom的操作,变成对该js集合进行操作(即虚拟dom),然后再映射到真是dom上,用浏览器渲染变更的部分,
渲染虚拟dom就是一个diff算法,在对虚拟dom进行操作时,比较两棵虚拟dom树的差异,对比两棵整个的dom树花费时间很多,因此提出假设,
1、两个相同的组件产生类似的dom结构,不同的组件产生不同的dom结构
2、对于同一层次的一组子节点,他们可以通过唯一的id进行区分
使得复杂度大大降低
diff核心
不同节点类型的比较
逐层进行节点比较
相同类型节点的比较
列表节点的比较
把差异应用到真正的dom树上,就是一个打补丁的过程,通过打补丁的算法,对修改的虚拟dom和真实dom不同的地方进行替换
6、vue-router以及使用和注意事项
1、vue-router有两种模式hash模式和history模式
2、hash模式的工作原理是hashchange事件,可以在window监听hash的变化,我们在url后随便添加一个#XX触发这个事件,url会改变,但是浏览器没有请求服务器,页面状态和url已经关联起来,这就是前端路由,单页面应用
3、history主要是有前进和后退
history.go(-3)后退3步
history(2)后退2次
history(0)刷新页面
history.back()后退
history.forward()前进
4、不过history模式是没有#的,就像常见的url一样,但是需要后端去配合,因为当用户访问不存在的地址,就会直接返回404,所以要在前端配置一个候选资源,给个警告,然后在vue应用里覆盖所有路由,然后再给出一个404页面
5、$router是实现路由的跳转等功能
6、$route是当前的路由to,from
动态路由传参,要在path里写入参数,如:id
或者使用path和params组合传参,{path:"/details",query:{id:66}}
7、浅拷贝/深拷贝
深拷贝:最简单就是JSON.parse(JSON.stringify())
但是这种方法不可以拷贝一些特殊的属性(正则,undefined,function)
递归拷贝
function deepCope(obj){
let objClone = Array.isArray(obj) > [] : {}
if(obj && typeof obj == 'object'){
for(const key in obj){
// 判断obj子元素是否为对象,如果是,递归复制
if(obj[key] && typeof obj[key] == 'object'){
objClone[key] = deepCope(obj[key])
}else{
objClone[key] = obj[key]
}
}
}
}
8、vue的通信方式
1、父子组件$emit和props
2、兄弟组件$emit和$on
c要获取a的数据
a 创建一个空的vue
event = new Vue()
event.$emit("data-a",this.name)
c event = new Vue()
event.$on('data-a',name=>{
this.name = name
})
一般在mounted里监听
3、vueX
1、vuex实现了一个单向数据流,在全局有一个state用于存放数据,当组件要更改state中的数据时,必须通过mutation进行,mutation提供订阅者模式供外部插件调用获取state数据的更新
2、vuex的流程
dispatch:操作行为触发方法,是唯一能执行action的方法
actions:操作行为处理模块,由组件中的$store.dispatch('action名称',data)来触发,然后由commit来触发mutation调用,简介修改state
commit:状态改变提交提交操作方法,对mutation进行提交,是唯一能执行mutation的方法
mutation:状态改变操作方法,由actions中的commit('mutation名称')来触发
state:页面状态管理容器对象
getters:state对象读取方法
3、vuex刷新页面数据会丢失问题解决方案
首次登陆后获取的vuex数据保存到sessionStorage里
刷新:可以监听浏览器的刷新事件
window.addEventListener('beforeonload',()={
sessionStorage = Item('menus',encrypt('kim'),JSON.stringify(this.$store.state.menus))
})
4、$parent/$children 和 ref
9、webpack配置入口/出口
一般的webpack的配置文件都是webpack.config.js
// 一般用uglifyjs-webpack-plugin进行js文件的压缩
// style-loader 和 css-loader 进行css打包
// sass使用需要安装 node-sass,打包需要安装sass-loader
// babel的话一般需要babel-core babel-loader babel-preset-es2015
const path = require('path')
module.exports = {
// 入口文件配置项
entry:{
// 里面的entry是可以随便写的
entry:"./src/entry.js"
},
// 出口文件配置项
output:{
需要在头部引入path
// 打包路径
path:path.resolve(__dirname,'dist'),
// 打包的文件名称
filename:"[name]].js"
},
// 模块:例如解读css,图片如何转换,压缩
module:{},
// 插件:用于生产模板和各项功能
plugins:[],
// 配置webpack开发服务功能
devServer:{
contentBase:path.resolve(__dirname,'dist'),
host:'172.16.64.59',
compress:true,
port:8080
}
}
10、webpack3和webpack4的区别
1、node环境不在支持node 4.0版本 最低支持6.11.5 2、配置项增加了mode:'production'|'development'|'none' none:退出任何默认优化配置 development:会将process.env.NODE_ENV的值设置为development,启用 optimization.nameMoudules和optimization.namedChunks TerserPlugin:替代了uglifyjs-webpack-plugin NoEmitOnErrorsPlugin:编译错误时不打印输出资源 原生支持处理json文件,不需要json-loader
11、URL输入回车后的过程
1、浏览器会先查看浏览器缓存-系统缓存-路由缓存,如果存在缓存直接显示如果没有,下一步 2查询IPS DNS缓存-递归查询根服务找到对应的ip 3、浏览器与网站建立TCP连接,连接后可传送数据 三次握手四次挥手 4、请求和传输数据,将文件传输到浏览器进行渲染 5、浏览器渲染 解析html源码,创建一个dom树 解析css计算样式形成css的对象模型 利用dom和css对象模型构造一个渲染树 根据渲染树直接把页面绘制到屏幕上
三次握手四次挥手
第一次握手,客户端发送初始序号x和syn=1的请求标志
第二次握手,服务器发送请求标志syn,发送确认标志ack,发送自己的需要seq=y发送客户端需要的确认序号ack=x+1
第三次握手,客户端发送ack确认号,发送自己的序号seq=x+1
C老王能听到我说话吗
S能听到,你能听到我说话吗
C能听到,通信开始
第一次挥手,客户端请求断开FIN,seq=u
第二次挥手,服务器确认客户端的断开请求ACK,ACK = U+1,SEQ = V
第三次挥手,服务器请求断开FIN,SEQ=W,ACK,ACK=U+1
第四次挥手,客户端确认服务器的断开ACK,ACK=W+1,SEQ=U+1`
C我说完了
S我听到你说的了,等等,我还没说完
S好了我说完了
C好了通信结束
12、http和https
http是不安全的,https是安全协议
1、https需要用到ca证书,一般免费证书比较少,因而需要一定费用,
2、http是超文本传输协议,信息是明文传输,https是具有安全性的ssl加密传输协议
3、http和https是完全不同的连接方式,用的端口也不一样,前者是80,后者是443
4、http的连接是很简单的,是无状态的,https协议是ssl和http构建的加密传输,身份认证的网路协议
http特点
简单快捷:只需传送请求方法和路径
灵活:允许传输任意格式的数据,正在传输的由content-type加以标记
无状态:其发送、传输、接收都是相互独立的
无连接:收到客户的应答后断开连接,节省传输时间
13、http常用状态码
1xx信息性状态码 接受的请求正在处理
2xx成功状态码 请求正常处理完毕
3xx重定向状态码 需要附加操作以完成请求
4xx客户端错误状态码 服务器无法处理请求
5xx服务器错误状态码 服务器处理请求出错
200 请求被正常处理
204 请求成功,但是没有资源返回给客户端
301 资源的url已经更新,永久性
302 资源的url临时更新,临时
304 资源已找到,但不符合条件请求
307 临时重定向
400 服务器端无法理解客户端发送的请求
401 需要权限
403 不允许访问资源
404 服务器没有资源
500 内部资源出错
503 服务器在忙
14、vue的路由守卫有哪些,怎么设置,使用场景等
一共有3种
全局守卫、组件守卫、路由独享守卫
1、全局守卫:前置守卫
beforeEach((to,form,next)=>{
next()=>
})
后置守卫next()
2、组件路由守卫
// 跟methods: {}等同级别书写,组件路由守卫是写在每个单独的vue文件里面的路由守卫
beforeRouteEnter (to, from, next) {
// 注意,在路由进入之前,组件实例还未渲染,所以无法获取this实例,只能通过vm来访问组件实例
next(vm => {})
}
beforeRouteUpdate (to, from, next) {
// 同一页面,刷新不同数据时调用,
}
beforeRouteLeave (to, from, next) {
// 离开当前路由页面时调用
}
3、路由独享守卫
export default new VueRouter({
routes: [
{
path: '/',
name: 'home',
component: 'Home',
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
15、数组去重
最高效正序
function distinct(a, b) {
let arr = a.concat(b) // 合并数组
let result = []
let obj = {}
for (let i of arr) {
if (!obj[i]) { // 查看obj是否有这个属性,有则为false
result.push(i)
obj[i] = 1 // 将数组对象作为key写到obj中
}
}
return result
}
function distinct(a, b) {
return Array.from(new Set([...a, ...b]))
}
function distinct(a, b) {
let arr = a.concat(b);
return arr.filter((item, index)=> {
return arr.indexOf(item) === index
})
}
16、es6新特性
1、let和const
变量提升
2、模板字符串
以前拼接字符串只能用+,es6可以用反引号扩起即可
console.log(hello ${person.name},my age ${persion.age})
3、箭头函数
this不会和其他函数一样指向调用的对象,而是继承上下文的this指向的对象
this对象是定义时的对象,而不是使用时的对象
4、函数可以设置默认参数
5、rest操作符和spread运算符
reset参数用于获取函数的多于参数
function add(...values) {
let sum = 0;
for (var val of values) {
sum += val;
}
return sum;
}
add(2, 5, 3) // 10
spread合并数组
const arr = [...arr1,...arr2]
let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1
bar // 2
baz // 3
let [ , , third] = ["foo", "bar", "baz"];
third // "baz"
let [x, , y] = [1, 2, 3];
x // 1
y // 3
let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]
let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []
17、手写冒泡
var arr = [23,2,12,13,3,5,3,4,122]
for(var i =0;i<arr.length ;i++;){
for(var j = 0;j<arr.length-1;j++){
if(arr[j]>arr[j+1]){
var max = arr[j]
arr[j] = arr[j+1]
arr[j+1] = max
}
}
}
18、什么是js语言
浏览器的脚本语言,一种轻量级的编程语言
Css3新特性
1 、过渡 transition
2 、动画 animation
3 、形状转换 transform
4 、选择器
6 、阴影 box-shadow
7 、边框 border-image
8 、背景 background-clip
9 、弹性布局
10、栅格布局 grid
11、盒模型定义
12、媒体查询
19、什么是跨域怎么解决
是指浏览器不能执行其他网站的脚本,是由浏览器的同源策略造成
同源策略:协议、域名、端口、都要相同,其中一个不同都会跨域
现在一般都是代理
20、前端性能优化方案
1、资源压缩合并、减少HTTP请求
2、非核心代码异步加载
3、利用浏览器缓存
4、使用CDN
21、sessionStorage和loaclStorage以及cookie
相信这个你都会
22、说说用过的css布局
浮动布局
弹性布局
栅格布局
圣杯布局
.container {
padding-left: 220px;//为左右栏腾出空间
padding-right: 220px;
}
.left {
float: left;
width: 200px;
height: 400px;
background: red;
margin-left: -100%;
position: relative;
left: -220px;
}
.center {
float: left;
width: 100%;
height: 500px;
background: yellow;
}
.right {
float: left;
width: 200px;
height: 400px;
background: blue;
margin-left: -200px;
position: relative;
right: -220px;
}
<article class="container">
<div class="center">
<h2>圣杯布局</h2>
</div>
<div class="left"></div>
<div class="right"></div>
</article>
双飞翼布局
23、promise是什么,解决了什么,之前是怎么实现的
是异步编程的一种解决方案,有三个状态pending(等待)、fulfiled(成功),rejected(失败)
因为js都是单线程,为了解决异步的问题,回调地狱,代码难以维护
之前是用setTimeout实现的
promise是一个构造函数,有三个参数all,reject,resolve,原型上有then、catch
resolve成功的回调
reject失败的回调