浏览器的缓存
- 强缓存
- exprices 绝对时间 格林尼治时间 时间点
- cache-control 相对时间 优先级高于 exprices
- 协商缓存
- last-modified (文件最后修改的时间) if-modified-since (文件最后修改的时间) --- 304 状态码
- Etag(哈希值) 和 if-none-match
从浏览器地址输入到页面渲染
HTML -- ke.qq.com -- 缓存 -- HTTP -- TCP ------ Server
DNS -- IP地址
HTML -- DOM Tree -- Render Tree -- Paint -- 页面
[图片上传失败...(image-7851ac-1620039458971)]
[图片上传失败...(image-e11f5b-1620039458971)]
https和http的区别
- https协议需要到ca申请证书,一般免费证书较少,因而需要一定的费用
- http是超文本协议传输,信息是明文传输,https则是具有安全性的ssl加密传输协议
- http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443
- http的连接很简单,是无状态的;https协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全
vue
1.什么是vue生命周期?
答: Vue 实例从创建到销毁的过程,就是生命周期。从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、销毁等一系列过程,称之为 Vue 的生命周期。
2.vue生命周期的作用是什么?
答:它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。
3.vue生命周期总共有几个阶段?
答:它可以总共分为8个阶段:创建前/后, 载入前/后,更新前/后,销毁前/销毁后。
4.第一次页面加载会触发哪几个钩子?
答:会触发 下面这几个beforeCreate, created, beforeMount, mounted 。
5.DOM 渲染在 哪个周期中就已经完成?
答:DOM 渲染在 mounted 中就已经完成了。
- router的区别
- $route是“路由信息对象”,包括path,params, hash, query, fullPath, matched, name等信息参数,
- $router是“路由实例”对象包括了路由的跳转方法,钩子函数等
- vue.js的两个核心是什么 数据驱动,组件系统
- vue常用的修饰符
- .stop 该修饰符将阻止事件向上冒泡,同理于调用 event.stopPropagation() 方法
- .prevent 该修饰符会阻止当前事件的默认行为。同理于调用 event.preventDefault() 方法
- .self 该指令只当事件是从事件绑定的元素本身触发时才触发回调
- vue中key值的作用
- 当vue.js用v-for正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,vue将不会移动DOM元素来匹配数据项的顺序,而是简单的复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。key的作用主要是为了高效的更新虚拟DOM
- 什么是vue的计算属性
- 在模版中放入太多的逻辑会让模版过重且难于维护,在需要对数据进行复杂处理,切可能多次使用的情况下,尽量采取计算属性的方式。好处
- 使得逻辑处理结构清晰
- 依赖于数据,数据更新,处理结果自动更新
- 计算属性内部this指向vm实例
- 在 template 调用时, 直接写计算属性名即可
- 常用的是 getter 方法,获取数据,也可以使用set方法改变数据
- 相较于methods,不管依赖的数据变不变,methods都会重新计算,但是依赖数据不变的时候 computed 从缓存中获取,不会重新计算
- vue等单页面应用及其优缺点
- 优点:Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件,核心是一个响应的数据绑定系统。MVVM、数据驱动、组件化、轻量、简洁、高效、快速、模块友好。
- 不支持低版本的浏览器,最低只支持到IE9;不利于SEO的优化(如果要支持SEO,建议通过服务端来进行渲染组件);第一次加载首页耗时相对长一些;不可以使用浏览器的导航按钮需要自行实现前进、后退。
vuex
[图片上传失败...(image-548611-1620039458971)]
state
Vuex 使用单一状态树,即每个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。
mutations
mutations定义的方法动态修改Vuex 的 store 中的状态或数据。
getters
类似vue的计算属性,主要用来过滤一些数据。
action
actions可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。view 层通过 store.dispath 来分发 action。
==闭包(对闭包的看法,为什么要用闭包)==
闭包是指有权访问另一个函数作用域中的变量的函数
- 匿名自执行函数
- 结果缓存
- 封装
优点
1.可以读取函数内部的变量
2.可以让这些局部变量保存在内存中,实现变量数据共享。
缺点
1.由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
2.闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
两种策略:
1.标记清除; (最常用的垃圾回收方式。当变量进入环境时,将变量标记为"进入环境";当变量离开环境时,将其标记为"离开环境"。)
2.引用计数
引用计数是跟踪每个值被引用的次数;当有一个变量被引用时,则这个值的引用次数加1,当取消一个引用时,次数减1。当引用值变为0 时,将由垃圾收集器回收
引用计数方式有严重的问题,就是,当变量相互引用时,如:
var obj1 = {}
var obj2 = {}
obj1.a = obj2;
obj2.b = obj1;
对于上面的代码,存在相互引用,其引用计数永远为2,就会导致对象永远不会被回收。
obj = null;
css3 动画性能优化
实现丝般顺滑主要决定因素有二:
- 时机(Frame Timing): RAF
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback, 1000 / 60);
};
})();
- 成本(Frame Budget):
- 避免layout: 先读后写
- 尽量少paint: 注意样式的使用
- 适当的硬件加速
js中查找字符串
- charAt()
- indexOf()
==箭头函数和普通函数的重要区别==
- 没有自己的this、super、arguments 和 new.target, 它们是离该箭头函数最近的非箭头函数的绑定
- 不能使用new 来调用
- 没有原形对象
- 内部的this无法改变
- 行参名称不能重复
箭头函数和箭头函数的指向
- 箭头函数的写法
- 箭头函数只能用赋值式写法,不能用声明式写法
- 如果参数只有一个,可以不加括号,如果没有参数或者参数多于一个就需要加括号
- 如果函数体只有一句话,可以不加花括号
- 如果函数体没有括号,可以不写return,箭头函数会帮你return
- 理解常规函数中的this
- 纯粹的函数调用
- 对象中函数的调用
- 构造函数中的this (每个构造函数在new之后都会返回一个对象,这个对象就是this,也就是context上下文。)
- window.setTimeout()和window.setInterval()中函数的调用
- 理解箭头函数中的this
- 默认绑定外层this
- 不能使用call方法修改里面的this
- 多层对象嵌套里函数的this (多层对象嵌套里箭头函数里this是和最最外层保持一致的。)
Set—Map与数组和对象的比较
通过对比:
在这个数据开发中涉及数据结构,能使用Map不使用数组,尤其是复杂的数据结构;
如果对数据结构要求存储的唯一性,考虑使用Set,(优先使用Map,如果对数据要求比较高,保证每个数据的唯一性,用Set)放弃使用object;
--Map删除的成本最低;
--Set和Map的语义上最优
JavaScript专题之数组去重
- 双层循环
- indexOf
- 排序后去重
- es6
https://juejin.im/post/5949d85f61ff4b006c0de98b#heading-8
// Set
function unique(array) {
return [...new Set(array)];
}
// Map
function unique (arr) {
const seen = new Map()
return arr.filter((a) => !seen.has(a) && seen.set(a, 1))
}
事件循环进阶
Promise里有了一个一个新的概念:microtask
或者,进一步,JS中分为两种任务类型:macrotask和microtask,在ECMAScript中,microtask称为jobs,macrotask可称为task
- macrotask(又称之为宏任务),可以理解是每次执行栈执行的代码就是一个宏任务(包括每次从事件队列中获取一个事件回调并放到执行栈中执行)
- microtask(又称为微任务),可以理解是在当前 task 执行结束后立即执行的任务
分别很么样的场景会形成macrotask和microtask呢?
macrotask:主代码块,setTimeout,setInterval等(可以看到,事件队列中的每一个事件都是一个macrotask)
microtask:Promise,process.nextTick等
再根据线程来理解下:
macrotask中的事件都是放在一个事件队列中的,而这个队列由事件触发线程维护
microtask中的所有微任务都是添加到微任务队列(Job Queues)中,等待当前macrotask执行完毕后执行,而这个队列由JS引擎线程维护
盒子模型
什么是“盒子”
初学 CSS 的朋友,一开始学 CSS 基础知识的时候一定学过padding border和margin,即内边距、边框和外边距。它们三者就构成了一个“盒子”。就像我们收到的快递,本来买了一部小小的手机,收到的却是那么大一个盒子。因为手机白色的包装盒和手机机器之间有间隔层(内边距),手机白色盒子有厚度,虽然很薄(边框),盒子和快递箱子之间还有一层泡沫板(外边距)。这就是一个典型的盒子。
简单的说每个html标签都是一个方块,然后这个方块又包着几个小方块。分别是:margin、border、paddding、content。它们的关系是margin包着border包着padding包着content。就像盒子一层一层地包着一样。这就是我们所说的盒模型。
Vue 兄弟组件通讯
- 新建中央事件线
- $emit 发送数据
- $on 监听并接受数据
原生click时间绑定
element.addEventListener(event, function, useCapture)
event 指定事件名
function 指定要事件触发时执行的函数
useCapture 指定事件是否在捕获或冒泡阶段执行
事件委托就是利用冒泡的原理,把事件加到父元素或祖先元素上,触发执行效果。
- 提高JavaScript性能。事件委托可以显著的提高事件的处理速度,减少内存的占用
- 动态的添加DOM元素,不需要因为元素的改动而修改事件绑定。
canvas性能优化
- 将渲染阶段的开销转嫁到计算阶段之上。
- 使用多个分层的 Canvas 绘制复杂场景。
- 不要频繁设置绘图上下文的 font 属性。
- 不在动画中使用 putImageData 方法。
- 通过计算和判断,避免无谓的绘制操作。
- 将固定的内容预先绘制在离屏 Canvas 上以提高性能。
- 使用 Worker 和拆分任务的方法避免复杂算法阻塞动画运行。
canvas 绘制一个三角形
/*
* 题目:
* 在画布上绘制一个三角形轮廓,三角形三个点分别是 (20, 50)、(150, 200)、(20, 200)
* 在画布上绘制一个三角形填充图形,三角形三个点分别是 (180, 140)、(230, 200)、 (180, 200)
*/
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
// 绘制三角形轮廓
context.beginPath();
context.moveTo(20, 50);
context.lineTo(150, 200);
context.lineTo(20, 200);
// 调用stroke()时不会自动闭合,所以需要调用 closePath() 函数
context.closePath();
context.stroke();// 绘制轮廓使用 stroke
// 绘制三角形填充图形
context.beginPath();
context.moveTo(180, 140);
context.lineTo(230, 200);
context.lineTo(180, 200);
// 当你调用fill()函数时,所有没有闭合的形状都会自动闭合,所以你不需要调用 closePath() 函数。
context.fill(); // 绘制填充区域使用 fill
vue 和 react 的比较
- 都支持组件化
- 都是数据驱动试图
性能优化
[图片上传失败...(image-31f2d1-1620039458971)]
flex 子元素属性
- flex-grow 属性表示当父元素空间有剩余时,将剩余空间分配给各子元素的比例,默认为0,表示不分配;当为数值时,表示父元素剩余空间分配给各子元素的比例,不是扩张后子元素的尺寸比例 (是否扩张)
- flex-shrink flex-shrink 属性与flex-grow属性的作用相反,表示当子元素宽度总和大于父元素宽度,且未换行显示时,各子元素压缩大小,默认未1,表示各子元素等比压缩;当数值不一时,表示各子元素因为压缩空间而减少的尺寸的比例,不是压缩后子元素尺寸的比例。
- flex-basis 属性可以用来设置子元素的空间,默认值为auto,表示为原本大小。当父元素有剩余空间时,可通过此属性扩充子元素的空间;各子元素通过扩充之后的空间总和超过了父元素的空间大小时,按flex-basis值比例来设置子元素的大小,没有flex-basis属性时,默认flex-basis值为子元素原本大小,使子元素大小总和不超过父元素空间大小。
JavaScript设计模式之面向对象编程
//为类的原型对象属性赋值
Person.prototype.showInfo = function () {
//展示信息
console.log('My name is ' + this.name , ', I\'m ' + this.age + ' years old!');
}
//将对象赋值给类的原型对象
Person.prototype = {
showInfo : function () {
//展示信息
console.log('My name is ' + this.name , ', I\'m ' + this.age + ' years old!');
}
}
通过 this 添加的属性和方法是在当前对象添加的,而 javascript 语言的特点是基于prototype 的,是通过 原型prototype 指向其继承的属性和方法的;通过 prototype 继承的方法并不是对象自身的,使用的时候是通过 prototype 一级一级查找的,这样我们通过 this 定义的属性或者方法都是该对象自身拥有的,我们每次通过 new 运算符创建一个新对象时, this 指向的属性和方法也会得到相应的创建,但是通过 prototype 继承的属性和方法是每个对象通过 prototype 访问得到,每次创建新对象时这些属性和方法是不会被再次创建的
原因在于第二种方式是将一整个对象赋值给了原型对象(prototype),这样会导致原来的原型对象(prototype)上的属性和方法会被全部覆盖掉(pass: 实际开发中两种方式不要混用),那么 constructor 的指向当然也发生了变化,这就导致了原型链的错乱,因此,我们需要手动修正这个问题,在原型对象(prototype)上手动添加上 constructor 属性,重新指向 Person ,保证原型链的正确,即:
Person.prototype = {
constructor : Person ,
showInfo : function () {
//展示信息
console.log('My name is ' + this.name , ', I\'m ' + this.age + ' years old!');
}
}
console.log(Person.prototype.constructor === Person ) // true
//创建一个类
var Person = function (name, age ) {
//私有属性
var IDNumber = '01010101010101010101' ;
//私有方法
function checkIDNumber () {}
//特权方法
this.getIDNumber = function () {}
//实例属性
this.name = name;
this.age = age;
//实例方法
this.getName = function () {}
}
//类静态属性
Person.isChinese = true;
//类静态方法
Person.staticMethod = function () {
console.log('this is a staticMethod')
}
//公有属性
Person.prototype.isRich = false;
//公有方法
Person.prototype.showInfo = function () {}
var person = new Person('Tom',24);
console.log(person.IDNumber) // undefined
console.log(person.isRich) // false
console.log(person.name) // Tom
console.log(person.isChinese) // undefined
console.log(Person.isChinese) // true
console.log(Person.staticMethod()) // this is a staticMethod
https://juejin.im/post/5b87b393e51d4557631bf5f0#heading-0
https://zhuanlan.zhihu.com/p/24964910?refer=muyichuanqi
js原型链继承,借用构造函数继承,组合继承,寄生式继承,寄生组合继承
数组扁平化
https://juejin.im/post/59716f15f265da6c4c500fc7
介绍下Promise的用途和性质 Promise和Callback有什么区别
http://es6.ruanyifeng.com/#docs/promise
https://segmentfault.com/a/1190000013141641
手写算法
https://juejin.im/post/5b72f0caf265da282809f3b5
https://juejin.im/post/59ac1c4ef265da248e75892b#heading-12
https://www.jianshu.com/p/8376170fb228
https://juejin.im/post/5b31a4b7f265da595725f322#heading-8
https://segmentfault.com/a/1190000012692321#articleHeader18
用 Throttle 来优化 Debounce
debounce 的问题在于它“太有耐心了”。试想,如果用户的操作十分频繁——他每次都不等 debounce 设置的 delay 时间结束就进行下一次操作,于是每次 debounce 都为该用户重新生成定时器,回调函数被延迟了不计其数次。频繁的延迟会导致用户迟迟得不到响应,用户同样会产生“这个页面卡死了”的观感。
为了避免弄巧成拙,我们需要借力 throttle 的思想,打造一个“有底线”的 debounce——等你可以,但我有我的原则:delay 时间内,我可以为你重新生成定时器;但只要delay的时间到了,我必须要给用户一个响应。这个 throttle 与 debounce “合体”思路,已经被很多成熟的前端库应用到了它们的加强版
【微信小程序】性能优化
小程序启动加载性能
控制代码包的大小
分包加载
首屏体验(预请求,利用缓存,避免白屏,及时反馈
小程序渲染性能
避免不当的使用setData
合理利用事件通信
避免不当的使用onPageScroll
优化视图节点
使用自定义组件
作者:小平果118
链接:https://juejin.im/post/5b496d5d5188251a90187635
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
JavaScript 中有几种原始类型数据?请再列举几个引用对象。
7 种,分别为:Boolean,Null,Undefined,Number,BigInt,String,Symbol
列举几种引用对象:
普通对象 Object
数组对象 Array
正则对象 RegExp
函数 Function
服务端渲染的优化
Vue组件的设计
CDN 的缓存与回源机制解析
事件冒泡喝事件捕获
JS中事件冒泡与捕获
原型与原型链(继承)
当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的proto(即它的构造函数的prototype)中寻找。
作用域和闭包
px、em、rem区别介绍
https://segmentfault.com/a/1190000012225828?utm_source=tag-newest
https://juejin.cn/post/6844903988488306701
数组扁平化
重绘和回流 占用的线程
优化的时间
webpack打包的时间和速度
v8
https://juejin.im/book/5a36661851882538e2259c0f/section/5a37bbb35188257d167a4d64
https://juejin.im/book/5b936540f265da0a9624b04b/section/5bb1826af265da0a972e3038
http://www.imooc.com/read/68/article/1558
http://www.imooc.com/read/68/article/1546
https://juejin.im/book/5bdc715fe51d454e755f75ef/section/5bdc715f6fb9a049c15ea4e0
new的实现
- 创建一个空对象
- 获取构造函数
- 设置空对象的原型
- 绑定 this 并执行构造函数
- 确保返回值为对象
实现一个简易的DOM选择器
var $ = jQuery = function (selector,context) { //定义类
return new jQuery.fn.init(selector,context); //返回选择器的实例
};
jQuery.fn = jQuery.prototype = { //jQuery的原型对象
init: function(selector,context) { //定义选择器的构造器
selector = selector || document; //默认值为document
context = context || document; //默认值为document
if (selector.nodeType) { //如果传入的参数是DOM节点
this[0] = selector; //把参数节点传递给实例对象的index
this.length = 1; //设置长度为1
this.context = selector;
return this; //返回jQuery对象
}
if (typeof selector === 'string') {//如果传进来的是标签字符串
let ele = document.getElementsByTagName(selector); //获取指定名称的元素
for (let i = 0; i < ele.length; i++) { //将获取到的元素放入实例对象中
this[i] = ele[i];
}
this.length = ele.length;
return this;
} else {
this.length = 0;
this.context = context;
return this;
}
},
name : "jQuery",
size : function () {
return this.length;
}
};
jQuery.prototype.init.prototype = jQuery.prototype;let div = $('div').size();
实现$('div').html("hello")功能
var $ = jQuery = function (selector,context) { //定义类
return new jQuery.fn.init(selector,context); //返回选择器的实例
};
jQuery.fn = jQuery.prototype = { //jQuery的原型对象
init: function(selector,context) {
//定义选择器的构造器 //省略初始化构造器的主体代码
},
constructor: jQuery,
//定义jQuery中的html()方法
html: function(val) {
if (val) {
for(let i = 0; i < this['length']; i++){
this[i].innerHTML = val;
}
}else {
return this[0].innerHTML;
}
},
name : "jQuery",
size : function () {
return this.length;
}
};
jQuery.prototype.init.prototype = jQuery.prototype;
let div = $('div').html('hello');
https://juejin.cn/post/6844903827036962824
HTTP面试问题之(三):HTTP状态码(HTTP Status Code)一般有哪些?
https://blog.csdn.net/peipeiluo/article/details/80157232
bind的实现
tigger remove 的实现
数组perent_id 分类
promise
排序