1.节流和防抖,应用场景
节流的含义是在一定时间内,多次触发同一个事件,只执行第一次操作。
应用场景:a.鼠标不断点击触发,mousedown(单位时间内只触发一次)。
b. 监听滚动事件,比如是否滑到底部自动加载更多,用throttle判断。
防抖的含义是指在一定时间内,多次触发同一个事件,只执行最后一次操作。
应用场景:a.search搜索联想,用户不断输入值时,用防抖来节约请求资源。
b.window触发resize的时候,不断调整浏览器窗口大小会不断触发这个事件,用防抖 来让其只触发一次。
2.闭包
闭包就是指有权访问另一个函数作用域中的变量的函数
MDN 上面这么说:闭包是一种特殊的对象。
闭包的作用域链包含着它自己的作用域,以及包含它的函数的作用域和全局作用域。闭包的注意事项
通常,函数的作用域及其所有变量都会在函数执行结束后被销毁。但是,在创建了一个闭包以后,这个函数的作用域就会一直保存到闭包不存在为止。
我们首先知道闭包有3个特性:
①函数嵌套函数
②函数内部可以引用函数外部的参数和变量
③参数和变量不会被垃圾回收机制回收
优点:
①保护函数内的变量安全 ,实现封装,防止变量流入其他环境发生命名冲突
②在内存中维持一个变量,可以做缓存(但使用多了同时也是一项缺点,消耗内存)
③匿名自执行函数可以减少内存消耗
闭包的缺点就是常驻内存会增大内存使用量,并且使用不当很容易造成内存泄露。
如果不是因为某些特殊任务而需要闭包,在没有必要的情况下,在其它函数中创建函数是不明智的,因为闭包对脚本性能具有负面影响,包括处理速度和内存消耗。
闭包的应用场景:
- setTimeout
- 回调
- 函数防抖
- 封装私有变量
3.继承的方法
原型链继承
借用构造函数继承(伪造对象,经典继承)
实例继承(原型式继承)
组合式继承
寄生组合继承
es6继承extends
4.什么是深/浅拷贝,有哪些实现方法?
基本数据类型:string,number,blooean,undefined,null
引用数据类型:object,array,function
js数据类型分为基本数据类型和引用数据类型,基本数据类型保存的是值,引用数据类型保存的是引用地址(this指针),浅拷贝共用一个引用地址,深拷贝会创建新的内存地址。
Object.assign:对象合并(第一级属性深拷贝,第一级以下的级别属性浅拷贝)
let obj1 = { a: { b: 1}, c: 2 }
let obj2 = Object.assign({},obj1)
实现深拷贝的三种方式:
a.使用递归实现深拷贝
//使用递归的方式实现数组、对象的深拷贝
function deepClone(obj) {
//判断obj是数组还是对象.
var objClone = Array.isArray(obj) ? [] : {};
//进行深拷贝的不能为空,并且是对象或者是"object"
if (obj && typeof obj === "object") {
for (key in obj) {
if (obj.hasOwnProperty(key)) {
if (obj[key] && typeof obj[key] === "object") {
objClone[key] = deepClone(obj[key]);
} else {
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
b.使用JSON对象实现深拷贝
/*
使用js内置JSON实现深拷贝
缺陷:无法实现对对象中方法的深拷贝
*/
function deepCloneJson(obj){
let objJson=JSON.stringify(obj);
let objClone=JSON.parse(objJson);
return objClone;
}
c.通过JQuery中的extend()方法实现数组深拷贝
/*
使用JQ中的extend来实现数组深拷贝
*/
function deepCloneExtend(arr){
let arrClone=[];//es6
arrClone=$.extend(true,[],arr);
return arrClone;
}
5.slice和splice的区别
a.splice改变原数组,slice不改变原数组
b.splice除了可以删除外,还可以插入
c.splice可以传入3个参数,slice接受2个参数
let arr =[1,2,3,4,5,6]
//从第3个元素开始执行删除,删除1个,将9作为新元素从删除位置插入数组
let newArr = arr.splice(2,1,9)
console.log('newArr',newArr)//[3]
console.log('arr',arr)//[1, 2, 9, 4, 5, 6]
let arr =[1,2,3,4,5,6]
//从第三个元素开始删除,到第五个元素这里结束,不包含第五个元素
let sliceArr = arr.slice(2,4)
console.log('sliceArr',sliceArr)//[3, 4]
console.log('arr',arr)//[1, 2, 3, 4, 5, 6]
6.对Promise的理解
a.promise的产生
promise是为解决异步处理回调金字塔问题而产生的。
b.promise的状态
Promise对象的状态不受外界影响,pending(初始状态)fufilled(成功状态)rejected(失败状态)
Promise 有以上三种状态,只有异步操作的结果可以决定当前是哪一种状态,其他任何操作都无法改变这个状态,Promise的状态一旦改变,就不会再变,任何时候都可以得到这个结果,状态不可以逆,只能由 pending变成fulfilled或者由pending变成rejected。
c.promise的用法
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
6.v-show 和 v-if指令的共同点和不同点?
共同点:v-show 和 v-if 都能控制元素的显示和隐藏。
不同点:a. 实现本质方法不同 v-show 本质就是通过设置 css 中的 display 设置为 none,控制隐藏 v-if 是动态的向 DOM 树内添加或者删除 DOM 元素
b.性能比较 v-show 只编译一次,后面其实就是控制 css,而 v-if 不停的销毁和创建,故 v- show 性能更好一点。
7.什么是虚拟DOM
虚拟DOM本质上就是JavaScript对象,是对真实的DOM抽象状态变更时,记录新树和旧树的差异,最后将差异更新到真正的DOM中。
虚拟DOM的优缺点:
优点:
保证性能下限: 虚拟DOM可以经过diff找出最小差异,然后批量进行patch,这种操作虽然比不上手动优化,但是比起粗暴的DOM操作性能要好很多,因此虚拟DOM可以保证性能下限
无需手动操作DOM: 虚拟DOM的diff和patch都是在一次更新中自动进行的,我们无需手动操作DOM,极大提高开发效率
跨平台: 虚拟DOM本质上是JavaScript对象,而DOM与平台强相关,相比之下虚拟DOM可以进行更方便地跨平台操作,例如服务器渲染、移动端开发等等
缺点:
无法进行极致优化: 在一些性能要求极高的应用中虚拟DOM无法进行针对性的极致优化,比如VScode采用直接手动操作DOM的方式进行极端的性能优化。
8.v-for 中key的作用
a.key属性是DOM元素的唯一标识。当数组发生增删时, 默认需要把发生改动的项目全部进行重绘 --- 浪费资源;当添加唯一标识之后, 一旦发生 增删操作之后,重绘之前会检测新绘制的元素 和 已有的元素 是否存在相同的 key , 相同则复用 --- 不浪费。
b.没有增删操作的场景下,key没有用。
9.es6新特性:
1、let 和 const
let 表示申明变量。const 表示申明常量
常量定义了就不能改了。对象除外,因为对象指向的地址没变。
const在申明是必须被赋值。
两者都为块级作用域。
2、模板字符串
3、解构
4、函数的默认值
5、Spread / Rest 操作符,三个点…
6、箭头函数
7、for of
for of遍历的是键值对中的值
for in遍历的是键值对中的键
8、class类,原型链的语法糖表现形式
9、导入导出
导入improt
导出export default
10、promise
Promise 用于更优雅地处理异步请求。
11、async/await
比promise更好的解决了回调地狱
12、Symbol,新的基本类型
13、Set集合
存储任何类型的唯一值,即集合中所保存的元素是不重复的。类数组结构。
let arrNew = new Set(待去重的数组)
10.computed和watch
a.computed:通过属性计算而得来的属性
- computed内部的函数在调用时不加()。
- computed是依赖data的属性变化而变化的,当data中的属性发生改变的时候,当前函数才会执行,data中的属性没有改变的时候,当前函数不会执行。
- computed中的函数必须用return返回。
- 在computed中不要对data中的属性进行赋值操作。如果对data中的属性进行赋值操作了,就是data中的属性发生改变,从而触发computed中的函数,形成死循环了。
- 当computed中的函数所依赖的属性没有发生改变,那么调用当前函数的时候会从缓存中读取。
- 不支持异步操作。
b.watch:属性监听
- watch中的函数名称必须要和data中的属性名一致,因为watch是依赖data中的属性,当data中的属性发生改变的时候,watch中的函数就会执行。
- watch中的函数有两个参数,前者是newVal,后者是oldVal。
-
watch中的函数是不需要调用的。
-
watch只会监听数据的值是否发生改变,而不会去监听数据的地址是否发生改变。也就是说,watch想要监听引用类型数据的变化,需要进行深度监听。“obj.name”(){}------如果obj的属性太多,这种方法的效率很低,obj:{handler(newVal){},deep:true}------用handler+deep的方式进行深度监听。
-
特殊情况下,watch无法监听到数组的变化,特殊情况就是说更改数组中的数据时,数组已经更改,但是视图没有更新。更改数组必须要用splice()或者set.this.arr.splice (0,1,100 ) − − − − − 修 改 a r r 中 第 0 项 开 始 的 1 个 数 据 为 100 , this.set.this.arr.splice(0,1,100)-----修改arr中第0项开始的1个数据为100,this.set.this.arr.splice(0,1,100)−−−−−修改arr中第0项开始的1个数据为100,this.set(this.arr,0,100)-----修改arr第0项值为100。
-
immediate:true 页面首次加载的时候做一次监听。
-
支持异步操作。
11.vue-router 有哪几种导航钩子?
-
全局导航钩子:router.beforeEach(to,from,next)作用:跳转前进行判断拦截、组件内的钩子、单独路由独享组件
-
路由独享钩子可以在路由配置上直接定义 beforeEnter
-
组件内的导航钩子有三种:
beforeRouteEnter 在进入当前组件对应的路由前调用
beforeRouteUpdate 在当前路由改变,但是该组件被复用时调用
beforeRouteLeave 在离开当前组件对应的路由前调用
12.vuex
vuex是一个专门为vue.js开发的状态管理模式,每一个vuex应用核心就是store(仓库)。store基本上就是一个容器,它包含着你的应用中大部分的state(状态)
vuex的状态存储是响应式的,当 vue组件中store中读取状态时候,若store中的状态发生变化,那么相应的组件也会相应地得到高效更新。
改变store中的状态的唯一途径就是显示 commit(提交)mutation,这样使得我们可以方便地跟踪每一个状态的变化。
State: 定义了应用状态的数据结构,可以在这里设置默认的初始状态
Getter: 允许组件从Stroe中获取数据, mapGetters辅助函数仅仅是将store中的getter映射到计算属性。
Mutation: 唯一更改store中状态的方法,且必须是同步函数。
Action: 用于提交mutation, 而不是直接变更状态,可以包含任意异步操作。
Module: modules,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理;如果所有的状态或者方法都写在一个store里面,将会变得非常臃肿,难以维护。
13.改变this指向call、apply与bind区别:
call和apply可以自动执行,bind不会自动执行,需要手动调用
call和bind都有无数个参数,apply只有两个参数,而且第二个参数为数组
14.Vue实例的生命周期
Vue实例从创建到销毁的过程,就是生命周期。
也就是:开始创建->初始化数据->编译模板->挂载dom->数据更新重新渲染虚拟 dom->最后销毁。这一系列的过程就是vue的生命周期。所以在mounted阶段真实的DOM就已经存在了。
beforeCreate:vue实例的挂载元素el和数据对象data都还没有进行初始化,还是一个 undefined状态
created: 此时vue实例的数据对象data已经有了,可以访问里面的数据和方法, el还没有,也没有挂载dom
beforeMount: 在这里vue实例的元素el和数据对象都有了,只不过在挂载之前还是虚拟的dom节点
mounted: vue实例已经挂在到真实的dom上,可以通过对 dom操作来获取dom节点
beforeUpdate: 响应式数据更新时调用,发生在虚拟dom打补丁之前,适合在更新之前访问现有的 dom,比如手动移除已添加的事件监听器
updated: 虚拟dom重新渲染和打补丁之后调用,组成新的 dom已经更新,避免在这个钩子函数中操作数据,防止死循环。
beforeDestroy: vue实例在销毁前调用,在这里还可以使用,通过this也能访问到实例,可以在这里对一些不用的定时器进行清除,解绑事件。
destroyed:vue实例销毁后调用,调用后所有事件监听器会被移除,所有的子实例都会被销毁。
15.vue路由的两种模式
1.hash模式
特点:在url地址上有#号
实现的原理:原生的hasChange事件来实现,来监听hash值的变化
window.onhaschange=function(){}
刷新页面的时候:不会去发送请求,页面不会有任何问题,不需要后端来配合
2.history模式
特点:在url地址上没有#号,比较与hash模式看起来好看一些
实现的原理:利用的是history的api 来实现的 popState() 来实现的
刷新页面的时候:会去发送请求然后会导致页面出现找不到的情况,需要后端来配合解决
16.vue的响应式原理
vue实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 数据劫持,来劫持各个属性的setter,getter,在数据更新时发布消息给订阅者,触发相应监听回调。
当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty() 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。
vue的数据双向绑定 将MVVM作为数据绑定的入口,整合Observer,Compile和Watcher三者,通过Observer来监听自己的model的数据变化,通过Compile来解析编译模板指令(vue中是用来解析 {{}}),
最终利用watcher搭起observer和Compile之间的通信桥梁,达到数据变化 —>视图更新;视图交互变化(input)—>数据model变更双向绑定效果。
17.vue 中的 keep-alive
keep-alive 是 vue 中的内置组件,能够在组件切换过程中将状态保留在内存中,防止重复的渲染 DOM;
keep-alive 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们;
设置了 keep-alive 缓存的组件,会多出两个生命周期钩子(activated 和 deactivated )
18.webpack
1、webpack的作用是什么,谈谈你对它的理解?
现在的前端网页功能丰富,特别是SPA(single page web application 单页应用)技术流行后,JavaScript的复杂度增加和需要一大堆依赖包,还需要解决Scss,Less……新增样式的扩展写法的编译工作。
所以现代化的前端已经完全依赖于webpack的辅助了。
现在最流行的三个前端框架,可以说和webpack已经紧密相连,框架官方都推出了和自身框架依赖的webpack构建工具。
react.js+WebPack
vue.js+WebPack
AngluarJS+WebPack
2、webpack的工作原理?
WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Sass,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。在3.0出现后,Webpack还肩负起了优化项目的责任。
3、webpack打包原理
把一切都视为模块:不管是 css、JS、Image 还是 html 都可以互相引用,通过定义 entry.js,对所有依赖的文件进行跟踪,将各个模块通过 loader 和 plugins 处理,然后打包在一起。
按需加载:打包过程中 Webpack 通过 Code Splitting 功能将文件分为多个 chunks,还可以将重复的部分单独提取出来作为 commonChunk,从而实现按需加载。把所有依赖打包成一个 bundle.js 文件,通过代码分割成单元片段并按需加载
4、webpack的核心概念
Entry:入口,Webpack 执行构建的第一步将从 Entry 开始,可抽象成输入。告诉webpack要使用哪个模块作为构建项目的起点,默认为./src/index.js
output :出口,告诉webpack在哪里输出它打包好的代码以及如何命名,默认为./dist
Module:模块,在 Webpack 里一切皆模块,一个模块对应着一个文件。Webpack 会从配置的 Entry 开始递归找出所有依赖的模块。
Chunk:代码块,一个 Chunk 由多个模块组合而成,用于代码合并与分割。
Loader:模块转换器,用于把模块原内容按照需求转换成新内容。
Plugin:扩展插件,在 Webpack 构建流程中的特定时机会广播出对应的事件,插件可以监听这些事件的发生,在特定时机做对应的事情。
5、Webpack的基本功能有哪些?
代码转换:TypeScript 编译成 JavaScript、SCSS 编译成 CSS 等等
文件优化:压缩 JavaScript、CSS、html 代码,压缩合并图片等
代码分割:提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载
模块合并:在采用模块化的项目有很多模块和文件,需要构建功能把模块分类合并成一个文件
自动刷新:监听本地源代码的变化,自动构建,刷新浏览器
代码校验:在代码被提交到仓库前需要检测代码是否符合规范,以及单元测试是否通过
自动发布:更新完代码后,自动构建出线上发布代码并传输给发布系统。
6、gulp/grunt 与 webpack的区别是什么?
三者都是前端构建工具,grunt和gulp在早期比较流行,现在webpack相对来说比较主流,不过一些轻量化的任务还是会用gulp来处理,比如单独打包CSS文件等。grunt和gulp是基于任务和流(Task、Stream)的。
类似jQuery,找到一个(或一类)文件,对其做一系列链式操作,更新流上的数据, 整条链式操作构成了一个任务,多个任务就构成了整个web的构建流程。webpack是基于入口的。
webpack会自动地递归解析入口所需要加载的所有资源文件,然后用不同的Loader来处理不同的文件,用Plugin来扩展webpack功能。
7、webpack是解决什么问题而生的?
如果像以前开发时一个html文件可能会引用十几个js文件,而且顺序还不能乱,因为它们存在依赖关系,同时对于ES6+等新的语法,less, sass等CSS预处理都不能很好的解决……,此时就需要一个处理这些问题的工具。
19.原型、构造函数、实例、原型链
- 实例
- 通俗地讲一个对象就是一个实例
- 构造函数
- 通俗地讲任何一个函数只要被new使用了,那么这么函数就是构造函数;eg: new A()
- 构造函数就是个函数,它和普通函数的唯一区别就是可以用new 创建实例,且构造函数都有contructor属性
- 原型
- 每个对象都有一个原型对象,对象以其原型为模板,从原型继承方法和属性,这些属性和方法定义在对象的构造器函数的
prototype
属性上,而非实例本身。
- 每个对象都有一个原型对象,对象以其原型为模板,从原型继承方法和属性,这些属性和方法定义在对象的构造器函数的
- 原型链
- 每个对象都有一个原型对象,通过__proto__指针指向上一个原型,并从中继承方法和属性,同时原型对象也会拥有原型,这样一层一层的,最终指向null,这就是原型链
20.移动端适配的五种方案
- @media 媒体查询
- 百分比布局
- flex布局
- rem实现
-
vh、vw 方案即将视觉视口宽度 window.innerWidth 和视觉视口高度 window.innerHeight 等分为 100 份。
21.组件生命周期执行顺序
-
加载渲染过程
父beforecreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted
-
子组件更新,影响到父组件的情况
父组件 beforeUpdate -> 子组件 beforeUpdate -> 子组件 updated -> 父组件 updated -
子组件更新,不影响到父组件的情况
子组件beforeUpdate -> 子组件updated
-
父组件更新,不影响到子组件的情况
父组件 beforeUpdate -> 父组件 updated -
父组件更新影响到子组件的情况
父组件beforeUpdate -> 子组件beforeUpdate -> 子组件updated -> 父组件updated
-
销毁过程
父组件 beforeDestroy -> 子组件 beforeDestroy -> 子组件 destroyed -> 父组件 destroyed
22.Promise.all() 的使用
promise.all()用于一个异步操作需要在几个异步操作完成后再进行时使用。
promise.all()接受一个promise对象组成的数组参数,返回promise对象。
当数组中所有promise都完成了,就执行当前promise对象的then方法,如果数组中有一个promise执行失败了,就执行当前promise对象的catch方法。
const p1 = new Promise((resolve, reject) => resolve(1))
const p2 = new Promise((resolve, reject) => resolve(2))
Promise.all([p1, p2]).then(res => console.log(res)).catch(res =>
console.log(res));
23.宏任务和微任务
js是一种单线程语言,js中的任务按顺序一个一个的执行,但是如果一个任务耗时太长的话,后面的任务就要慢慢等待,为了解决这个问题,将任务分为了同步任务和异步任务。而异步任务又分为微任务和宏任务。
宏任务:setTimeout,setInterval,UI交互事件,I/O等。
微任务:promise.then(),Object.observe等。
24.websocket和http的区别
- websocket是双向通信协议,模拟socket协议,可以双向发送或者接收信息,而http是单向的;
- websocket是需要浏览器和服务器握手进行建立连接的,而http是浏览器发起向服务器的连接。
-
WebSocket是HTML5规范提出的一种协议;目前除了IE浏览器,其他浏览器都基本支持。他是一种协议,万变不离其宗,也是基于TCP协议的;和HTTP协议是并存的两种协议。
25.箭头函数和普通函数的区别
- 箭头函数比普通函数更加简洁。
- 箭头函数没有自己的this。
- 箭头函数继承来的this指向永远不会被改变。
- call(),apply(),bind()等方法不能改变箭头函数中的this指向。
var id = 'Global'; let fun1 = () => { console.log(this.id) }; fun1(); // 'Global' fun1.call({id: 'Obj'}); // 'Global' fun1.apply({id: 'Obj'}); // 'Global' fun1.bind({id: 'Obj'})(); // 'Global'
- 箭头函数不能作为构造函数使用。
- 箭头函数没有自己的arguments。
箭头函数没有自己的arguments对象。在箭头函数中访问arguments实际上 获得的是它外层函数的arguments值。
- 箭头函数没有prototype。
- 箭头函数的this指向哪里?
箭头函数不同于传统JavaScript中的函数,箭头函数并没有属于⾃⼰的this,它所谓的this 是捕获其所在上下⽂的 this 值,作为⾃⼰的 this 值,并且由于没有属于⾃⼰的this,所以 是不会被new调⽤的,这个所谓的this也不会被改变。
26.事件循环机制(event loop)
Event Loop 即事件循环, 是JavaScript或Node为解决单线程代码执行不阻塞主进程一种机制,也就是我们所说的异步原理。
事件循环负责执行代码、收集和处理事件以及执行队列中的子任务。
27.语义化标签
28.keep-alive原理
keep-alive是vue中的一个内置组件,会缓存不活动的组件实例,防止重复渲染Dom。vue的缓存机制并不是直接存储dom结构,而是将dom节点抽象成了一个个vnode节点。因此,vue的keep-alive缓存也是基于vnode节点而不是直接存储dom节点。 它将满足条件(include与exclude)的组件在cache对象中缓存起来,在需要重新渲染的时候再将vnode节点从cache对象中取出并渲染。
29.vue2检测数据的变化
-
使用
Vue.set
API(在组件中,使用this.$set
)进行修改。this.$set(要修改的数组,要修改的索引值,改变后的值)
change() { this.$set(this.list, 0, 改变后的值) }
-
Vue 对数组常见的 7个操作方法进行了重新包装,保证在数组操作前能监听到数组变化。包括以下七种:
- push:从数组尾部插入
- pop:从数组尾部移除
- unshift:从数组头部插入
- shift:从数组头部移除
- splice:替换
- sort:排序
- reverse:颠倒顺序
// 方法1
change() {
this.$set(this.list, 0, '改变后的值')
}
// 方法2
change() {
// 能监听到 hobby 的变化
this.list.splice(0, 1, '改变后的值')
}
30.vue组件中的data为什么是函数?
- 如果data是一个函数的话,这样每复用一次组件,就会返回一份新的data(类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据)
- Object是引用数据类型,里面保存的是内存地址,单纯的写成对象形式,就使得所有组件实例共用了一份data,就会造成一个变了全都会变的结果。
31. jq中的ready方法 和 js中的onload方法的区别
- 两个方法的执行顺序不一样,jQuery版本不同,方法的执行顺序不同。在jQuery3.0.0版本之前的版本中,$(document).ready会先于window.onload执行,在jQuery3.0.0版本及之后的版本中,window.onload先执行。
- 编写个数不同。window.onload不能同时编写多个,如果有多个window.onload方法,只会执行最后一个onload方法。 $(document).ready()可以同时编写多个,并且都可以得到执行。
-
简化写法。window.onload没有简化写法 ;$(document).ready(function(){}) ,可以简写成$(function(){});
32.diff算法
概念:
diff算法就是进行虚拟节点对比,并返回一个patch对象,用来存储两个节点不同的地方,最后用patch记录的消息去局部更新Dom。
理解: diff的过程就是调用名为patch的函数,比较新旧节点,一边比较一边给真实的DOM打补丁 。
33.回流和重绘
什么是回流和重绘?
重绘简单来说就是重新绘画,当给一个元素更换颜色、更换背景,虽然不会影响页面布局,但是颜色或背景变了,就会重新渲染页面,这就是重绘。
当增加或删除dom节点,或者给元素修改宽高时,会改变页面布局,那么就会重新构造dom树然后再次进行渲染,这就是回流。
什么时候会发生回流?
1、添加或者删除可见的DOM元素的时候
2、元素的位置发生改变
3、元素的尺寸发生改变
4、内容改变
5、页面第一次渲染的时候
34.css3新增属性有哪些?
border-color:为边框设置多种颜色
border-image:图片边框
border-radius:圆角边框
box-shadow:阴影效果
background-size:指定背景图片尺寸
background-origin:指定背景图片从哪里开始显示
background-clip:指定背景图片从什么位置开始裁剪
text-shadow:文本阴影
word-wrap:自动换行
transform变换效果
transform-origin 属性可以设置变换的起点
animation动画效果
transition过渡效果
35.http和http的区别
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
36.三次握手四次挥手
握手:
1、第一次握手:客户端给服务器发送一个 SYN 报文。
2、第二次握手:服务器收到 SYN 报文之后,会应答一个 SYN+ACK 报文。
3、第三次握手:客户端收到 SYN+ACK 报文之后,会回应一个 ACK 报文。
4、服务器收到 ACK 报文之后,三次握手建立完成。
挥手:
1、第一次挥手:客户端发送一个 FIN 报文,报文中会指定一个序列号。此时客户端处于FIN_WAIT1状态。
2、第二次握手:服务端收到 FIN 之后,会发送 ACK 报文,且把客户端的序列号值 + 1 作为 ACK 报文的序列号值,表明已经收到客户端的报文了,此时服务端处于 CLOSE_WAIT状态。
3、第三次挥手:如果服务端也想断开连接了,和客户端的第一次挥手一样,发给 FIN 报文,且指定一个序列号。此时服务端处于 LAST_ACK 的状态。
4、第四次挥手:客户端收到 FIN 之后,一样发送一个 ACK 报文作为应答,且把服务端的序列号值 + 1 作为自己 ACK 报文的序列号值,此时客户端处于 TIME_WAIT 状态。需要过一阵子以确保服务端收到自己的 ACK 报文之后才会进入 CLOSED 状态
5、服务端收到 ACK 报文之后,就处于关闭连接了,处于 CLOSED 状态。
37.在浏览器输入一个网址,发生了什么?
1. 浏览器查找该域名的 IP 地址
2.浏览器根据解析得到的IP地址向 web 服务器发送一个 HTTP 请求
3. 服务器收到请求并进行处理
4. 服务器返回一个响应
5. 浏览器对该响应进行解码,渲染显示。
6. 页面显示完成后,浏览器发送异步请求。
7.整个过程结束之后,浏览器关闭TCP连接。