知识点记录

666 阅读14分钟

JS是按照代码块来进行编译和执行的,代码块间相互独立,但变量和方法共享

所以多个script 的时候,其中一个块报错,是不会停止其他块的执行。

如果多个js 都有变量 let a 当加载到对应的js 就会报“already declared

一、如何正确判断一个数据的基本类型?

1、typeof

typeof 对于原始类型(null undefined string number boolean symbol),除了null  都能显示正确的类型

typeof null === 'object'

typeof 对于对象来说,除了函数外其他都是object 类型

typeof [] === 'object'  
typeof console.log === 'function'

所以typeof 无法正确区分对象和null(数组和null)

2、instanceof 判断已知对象类型的方法

MDN 的解释: instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性

判断一个对象是否是数据类型的实例

因而可以衍生出 用constructor 来判断类型({}).constructor == Object,但是constructor 是可以修改的

function Fn(){};
Fn.prototype=new Array();
var f=new Fn()
console.log(f.constructor===Fn);    // false

,因而不准确。

3、通用型,借用Object.prototype.toString.call 来实现

var gettype=Object.prototype.toString 
    gettype.call('aaaa')        输出      [object String]    
    gettype.call(2222)         输出      [object Number]    
    gettype.call(true)          输出      [object Boolean]     
    gettype.call(undefined)  输出      [object Undefined]      


// 进行一层封装
let Type = (function(){
    let type = {};
    let typeArr = ['String', 'Object', 'Number', 'Array', 'Undefined', 'Null', 'Symbol'];
    for(let i = 0; i < typeArr.length; i++){
        type['Is'+ typeArr[i]] = function(obj){
            return Object.prototype.toString.call(obj) === '[object '+ typeArr[i] +']'
        }
    }
    return type
})()



eg:(第一个字母小写,第二个字母大写)
Type.IsFunction(function() {})      Type.IsObject({}) 这样使用。

二、对象的深浅拷贝

什么是浅拷贝?如何实现浅拷贝?什么是深拷贝?如何实现深拷贝?

浅拷贝是对引用地址的拷贝,还是指向同一个内存空间,深copy指向两个不同内存空间。

浅拷贝

利用Object.assign({}, obj)  or 展开运算符 ... 来实现浅拷贝

let a = {
    age: 1
}
let b = Object.assign({}, a)
a.age = 2
console.log(a.age) // 1
console.log(b.age) // 2

let a = {
    age: 1
}
let b = { ...a }
a.age = 2

深拷贝

利用JSON.parse(JSON.stringify(object)) 来解决,(基本够用了)但这个有局限性,

  • 会忽略undefined
  • 会忽略symbol
  • 会忽略函数
  • 不能解决循环引用的对象

JSON.stringify()方法的序列化顺序

  1. 如果有toJSON()方法且能取到值,就先这个,否则按默认顺序

  2. 如果提供了第2个参数,应用这个过滤器。传入值是步骤1的结果

  3. 对第2步的返回的每个值进行相应的序列化

  4. 如果有第3个参数,执行相应的格式化

    var bookCopy = JSON.parse(jsonText, function(key, value){ // 序列化后的入参 if(key == "date"){ return new Date(value); }else{ return value; } });

自个封装 lodash 深拷贝函数

function deepClone(obj){
    function isObject(o){
        return (typeof o === 'object' || typeof o === 'function') && o !== null
    }
    if(!isObject(obj)){
        throw new Error('not object')
    }
    // 补是函数的情况
    if(typeof obj === 'function'){
        return obj
    }
    let isArray = Array.isArray(obj)
    // n = new Array(o.length);
    let newObj = isArray? [...obj] : { ...obj }
    Reflect.ownKeys(newObj).forEach((key)=>{
        newObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
    })
    return newObj
}
// eg 
let obj = {
    a: [1,2,3],
    b:{
        c:2,
        d:3
    }
}
let newObj = deepClone(obj)
newObj.b.c = 33
console.log(obj.b.c)  // 2

三、call、apply 和 组合继承

function Product(name, price){
    this.name = name;
    this.price = price;
}
function Food(name, price){
    Product.call(this, name, price)
    this.category = 'food'
}
let foot1 = new Food('chees', 5);
foot1 // 

通过Food 构造方法里的call(),成功使Food 扩展了name 以及price .(借用)

apply()call() 都是为了改变某个函数运行时的上下文而存在的(就是为了改变函数内部的 this 指向)。然后,因为这两个方法会立即调用,所以为了弥补它们的缺失,还有个方法 bind()

/*apply()方法 参数是已数组的形式 add.apply(sub, [4,2]) */
function.apply(thisObj[, argArray])

/*call()方法  参数*/
function.call(thisObj[, arg1[, arg2[, [,...argN]]]]);

四、寄生组合继承(经典例子):

function Parent(value){
    this.val = value
}
Parent.prototype.getValue = function(){
    console.log(this.val)
}
function Child(value){
    Parent.call(this, name)
}
// Child.prototype = new Parent()  组合继承
// 缺点就是在继承父类函数的时候调用了父类构造函数,导致子类的原型上多了不需要的父类属性,存在内存上的浪费
Child.prototype = Object.assign(Parent.prototype, {
    constructor:{
        value: Child,
        enumerable: false,
        writable: true,
        configurable: true
    }
})
const child = new Child(1)
child.getValue() // 1
child instanceof Parent // true

继承实现的核心就是将父类的原型赋值给了子类,并且将构造函数设置为子类,这样既解决了无用的父类属性问题,还能正确的找到子类的构造函数。

es6 class 继承

class Parent{
    constructor(value){
        this.val = value
    }
    getValue(){
        console.log(this.val)
    }
}
class Child extends Parent{
    constructor(value){
        super(value)
        this.val = value
    }
}

let child = new Child(1)
child.getValue()  // 1
child instanceof Parent  //true

js 原型与原型链可以参考这个: juejin.im/post/684490…

五、防抖与节流

防抖即延时执行,指触发事件后在规定时间内回调函数只能执行一次,如果在规定时间内又触发该事件,则会重新开始算规定时间。

应用场景: 输入联想功能,用户不断输入时,用防抖来节约资源。

function callFn(content){
    console.log('这是防抖回调函数')
}
// 利用回调函数 保存定时器标识
function debounce(func ,delay = 500){
    let timer = null
    return function(args){
        let that = this
        let _args = args
        if(timer) clearTimeout(timer)
        timer = setTimeout(function(){
            func.call(that, _args)
        }, delay)
    }
}
let currDebounce = debounce(callFn, 500) // 返回延时函数

// 使用
let evtFn= document.querySelector('body')
evtFn.addEventListener('click', function(e){
    currDebounce (e.target.value)
})

节流

当持续触发事件时,在规定时间段内只能调用一次,如再规定时间内又触发该事件,则return ,什么也不做。

应用场景,频繁触发事件,如滚动、resize 等。

// 定时器版
function throttle(func, delay = 500){
    let timer = null;
    return function(args){
        let that = this;
        let _args = args;
        if(!timer){
            timer = setTimeout(function(){
                timer = null;
                func.apply(that, _args)
            }, delay)
        }
    }
}

// 时间戳版
function throttle(fun, delay = 500){
    let previous = 0;
    return function(args){
        let now = Date.now();
        let that = this;
        let _args = args;
        if(now - previous > delay){ // 如果时间差大于规定时间,则触发
            fun.apply(that, _args)
            previous = now
        }
    }
}

垃圾回收主要分为:标记清除算法(主流都是这个)与引用计数算法。

将cookie设置成HttpOnly是为了防止XSS攻击,窃取cookie内容,这样就增加了cookie的安全性。
把cookie设置为secure,只保证 cookie 与服务器之间的数据传输过程加密

六、渲染机制及重绘和回流

浏览器的渲染机制一般分为以下几个步骤:

    1. 处理 HTML 并构建 DOM 树。
    2. 处理 CSS 构建 CSSOM 树。
    3. 将 DOM 与 CSSOM 合并成一个渲染树(Render Tree)。
    4. 根据渲染树来布局,计算每个节点的位置。
    5. 调用 GPU 绘制,合成图层,显示在屏幕上。
  • 重绘是 当节点需要更改外观而不会影响布局的,比如改变 color、background-color、visibility, outline等就叫称为重绘

  • 回流是 布局或者几何属性需要改变 就称为回流。回流是影响浏览器性能的关键因素,因为其变化涉及到部分页面(或是整个页面)的布局更新。

回流必定会发生重绘,重绘不一定会引发回流

浏览器优化:

现代浏览器大多都是通过队列机制来批量更新布局,浏览器会把修改操作放在队列中,至少一个浏览器刷新(即16.6ms)才会清空队列,但当你获取布局信息的时候,队列中可能有会影响这些属性或方法返回值的操作,即使没有,浏览器也会强制清空队列,触发回流与重绘来确保返回正确的值

主要包括以下属性或方法:

  • offsetTopoffsetLeftoffsetWidthoffsetHeight
  • scrollTopscrollLeftscrollWidthscrollHeight
  • clientTopclientLeftclientWidthclientHeight
  • widthheight
  • getComputedStyle()
  • getBoundingClientRect()

所以,我们应该避免频繁的使用上述的属性,他们都会强制渲染刷新队列。

减少重绘与回流

1、CSS

  • 使用 transform 替代 top
  • 使用 visibility 替换 display: none ,因为前者只会引起重绘,后者会引发回流
  • 避免使用table布局,可能很小的一个小改动会造成整个 table 的重新布局。
  • 尽可能在DOM树的最末端改变class,回流是不可避免的,但可以减少其影响。尽可能在DOM树的最末端改变class,可以限制了回流的范围,使其影响尽可能少的节点。
  • 避免设置多层内联样式,CSS 选择符从右往左匹配查找,避免节点层级过多。
  • CSS3 硬件加速(GPU加速),使用css3硬件加速,可以让transformopacityfilters这些动画不会引起回流重绘 。但是对于动画的其它属性,比如background-color这些,还是会引起回流重绘的,不过它还是可以提升这些动画的性能。

2、JavaScript

  • 避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性。

  • 避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中。

  • 避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。

documentFragment 节点不属于文档树,因此当把创建的节点添加到该对象时,并不会导致页面的回流。

重绘和回流

七、前端安全性XSS 攻击与CSRF攻击

Cross-Site Scripting (跨站脚本攻击)简称XSS,是一种代码注入攻击。攻击者通过在目标网站上注入恶意脚本,使之在用户的浏览器上运行,进而实现攻击。

XSS 常见的注入方法:

  • 在 HTML 中内嵌的文本中,恶意内容以 script 标签形成注入。

  • 在内联的 JavaScript 中,拼接的数据突破了原本的限制(字符串,变量,方法名等)。

  • 在标签属性中,恶意内容包含引号,从而突破属性值的限制,注入其他属性或者标签。

  • 在标签的 href、src 等属性中,包含 javascript: (伪协议)等可执行代码。

  • 在 onload、onerror、onclick 等事件中,注入不受控制代码。

  • 在 style 属性和标签中,包含类似 background-image:url("javascript:..."); 的代码(新版本浏览器已经可以防范)。

  • 在 style 属性和标签中,包含类似 expression(...) 的 CSS 表达式代码(新版本浏览器已经可以防范)。

常用防范方法:

对输入(和url参数)进行过滤,对输出进行编码,cookie 设置成 http-only

用户输入、url参数、post 请求参数、ajax

  • httpOnly(服务端设置): 在 cookie 中设置 HttpOnly 属性后,js脚本将无法读取到 cookie 信息。

  • 输入过滤: 一般是用于对于输入格式的检查,例如:邮箱,电话号码,用户名,密码……等,按照规定的格式输入。不仅仅是前端负责,后端也要做相同的过滤检查。因为攻击者完全可以绕过正常的输入流程,直接利用相关接口向服务器发送设置。

  • 转义 HTML: 如果拼接 HTML 是必要的,就需要对于引号,尖括号,斜杠进行转义。

    function escape(str) { str = str.replace(/&/g, '&') str = str.replace(/</g, '<') str = str.replace(/>/g, '>') str = str.replace(/"/g, '&quto;') str = str.replace(/'/g, ''') str = str.replace(/`/g, '`') str = str.replace(///g, '/') return str }

  • 白名单: 对于显示富文本来说,不能通过上面的办法来转义所有字符,因为这样会把需要的格式也过滤掉。这种情况通常采用白名单过滤的办法,当然也可以通过黑名单过滤,但是考虑到需要过滤的标签和标签属性实在太多,更加推荐使用白名单的方式。

跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF

1、验证码;强制用户必须与应用进行交互,才能完成最终请求。此种方式能很好的遏制 csrf,但是用户体验比较差。

2、Referer check;请求来源限制,此种方法成本最低,但是并不能保证 100% 有效,因为服务器并不是什么时候都能取到 Referer,而且低版本的浏览器存在伪造 Referer 的风险。

常见scrf 攻击形态

<img src="http://bank.example/withdraw?amount=10000&for=hacker" >

在受害者访问含有这个img的页面后,浏览器会自动向发出一次get请求。bank.example就会收到包含受害者登录信息的一次跨域请求。

<form action="http://bank.example/withdraw" method=POST>   

访问该页面后,表单会自动提交,相当于模拟用户完成了一次POST操作。

案例:

1、利用HTML拼接展示攻击。如下图:对value进行赋值“>形成脚本攻击。

<input type="text" value=""><script>alert('xss');</script>

通过html输入和输出进行预防:

  • HTML输出:使用vue框架的v-model和{{}}有框架过滤敏感字符处理,v-html不会进行处理,需要慎用。
  • HTML输入方案:表单校验组件跳转required规则、并新增raw_required和html_encode规则。
    ① 调整required规则:非空校验;检验是否有特殊字符,自动转义,不抛错。
    ② 新增raw_required规则:非空校验。
    ③ 新增html_encode规则:校验是否有特殊字符,自动转义,不抛错。

2、利用href 的url属性攻击

在链接跳转前进行校验,判断URL是否合法,如果不合法则过滤JavaScript等关键词

xxx.com/?url=去除script

XSS攻击与CSRF攻击

八、Object.assign 模拟实现

if( typeof Object.assign2 !== 'function' ){
    Object.defineProperty(Object, 'assign2', {
        value: function(target){
            if(!target){
                throw new Error('cannot convert undefined or null to object')
            }
            var to = Object(target)
            for(var index = 1; index < arguments.length;index++){
                var nextSource = arguments[index]
                if(nextSource){
                    for( var nextKey in nextSource ){
                        if(Object.prototype.hasOwnProperty.call(nextSource, nextKey)){
                            to[nextKey] = nextSource[nextKey]
                        }
                    }
                }
            }
            return to;
        },
        writable: true,
        configurable: true
    })
}



// 测试用例
let a = {
    name: "advanced",
    age: 18
}
let b = {
    name: "muyiy",
    book: {
        title: "You Don't Know JS",
        price: "45"
    }
}
let c = Object.assign2(a, b);
console.log(c);
// {
//     name: "muyiy",
//  age: 18,
//     book: {title: "You Don't Know JS", price: "45"}
// } 
console.log(a === c);
// true

**九、**vue 记录

一般来说,vue 组件分成三类:

1、 由vue-router 产生的每个页面,它本质上也是一个组件(.vue),主要承载当前页面的html 结构,会包含数据获取、数据整理、数据展示等业务操作,在实际项目开发中,我们写的大部分代码都是这类组件,在协同开发时,每人维护自己的路由页面,很少有交集。这类相对也是最好写的,能完成需求就行。

2、 不包含业务,是个独立、具体的功能基础组件,比如模态框、日期选择器。独立组件的开发难度要高于第一类组件,它侧重点是API的设计、兼容性、性能、以及复杂的功能,也会包含非常多的技巧,比如在不依赖vuex 的情况下,各组件间的通信。一个具有数据校验功能的输入框。

3、 业务组件,在业务中被多个页面复用,会包含页面元素,通用性要差一些,(依托于项目,可以使用项目中的技术栈,如vuex、axios等)。通用弹层

一个再复杂的组件,都是由三部分组成:prop、event、slot 。 Props 最好用对象的写法,这样可以针对每个属性设置类型、默认值或自定义校验属性值。

十、JavaScript模块化方案

在es6之前,js 并没有原生的模块。模块化方案的三个阶段过程:

1、全局变量+命名空间 (window.XX ,以及自执行函数等操作)

2、AMD&commonjs 各类规范带到前端

AMD模块类似:

define(function(require){
    const bar = require('./bar')
    return function(){}
})

commonJs 规范,它本不适合浏览器环境,但依赖现代打包工具进行转换之后就可以在浏览器中执行。commonjs 规范格式更加简洁,(nodejs 模块正在使用的就是commonjs 规范)

const bar = require('./bar')
module.exports = function(){
// ....
}

3、es6模块

模块化方案

import bar from './bar'
export default function(){
 // ...
}

[commonjs & es6](juejin.cn/post/692077…)

 CommonJS规范和ES6规范的区别:

  • CommonJS模块是运行时加载,ES6模块是编译时输出接口
  • CommonJS模块输出的是一个值的复制,ES6模块输出的是值的引用
  • CommonJS加载的是整个模块,即将所有的方法全部加载进来,ES6可以单独加载其中的某个方法
  • CommonJS中this指向当前模块module.exports,ES6中this指向undefined
  • CommonJS默认非严格模式,ES6的模块自动采用严格模式

十一、webpack 与gulp 有什么本质区别

gulp 是工具链,构建工具,可以配合各种插件做js 压缩,css 压缩,less 压缩,替代手工实现自动化工作。 1、 构建工具 2、自动化、3、提高效率

webpack 是文件打包工具,把项目的各种js ,css 打包合并成一个或多个文件,主要用于模块化打包。1、打包工具 2、模块化识别 3、编译模块代码 4、代码拆分5、模块热更新。

十二、常用es6 以及es6 规范

到时候移到掘金

blog.csdn.net/u010427666/…

十三、seo 相关知识以及如何优化

文档&文章链接

十四、内部原型继承原理

需重新整理

blog.csdn.net/u010427666/…

十五、你需要知道的css

css 动画、flex 布局等

juejin.im/post/684490…

十五、性能优化点

代码层面、网络层面、打包依赖等

segmentfault.com/a/119000000…

十六、浏览器缓存机制(强缓存&协商缓存)

是否过期根据header中的Cache-Control和Expires来判断,(缓存过期后Etag 与last-modify 是由服务器来判断)

etag适合重要量小的资源,last modify适合不重要的量大的资源

www.jianshu.com/p/9c95db596…

nginx 开启强缓存

location ~ ^/static/.*(jpg|jpeg|png|gif|ico|js|css|ttf)$ {
   root /home/service/www/web;
   expires 12h;
   add_header Cache-Control "public";
}

 nginx 开启gizp 压缩(压缩效率特高)

    gzip on; #开启gzip压缩输出
    gzip_min_length 1k;    #最小压缩文件大小
    gzip_buffers 4 16k;    #压缩缓冲区
    # gzip_http_version 1.0;    #压缩版本(默认1.1,前端如果是squid2.5请使用1.0)
    gzip_comp_level 3;    #压缩等级
    gzip_types text/plain application/javascript  application/x-javascript text/css application/xml;
    gzip_vary on;
    gzip_disable "MSIE [1-7]\.";

 十七、数组乱序

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
arr.sort(function () {
    return Math.random() - 0.5;
});

洗牌算法:

function shuffle (arr) {    var len = arr.length    for (var i = 0;i < len - 1;i++) {        var idx = Math.floor(Math.random() * (len - i))        var temp = arr[idx]        arr[idx] = arr[len - i - 1]        arr[len - i - 1] = temp    }    return arr}

十八、BFC(块级格式化上下文)

产生BFC:

  1. 根元素或包含根元素的元素
  2. 浮动元素 float = left | right 或 inherit**(≠ none)**
  3. 绝对定位元素 position = absolute 或 fixed
  4. display = inline-block | flex | inline-flex | table-cell 或 table-caption
  5. overflow = hidden | auto 或 scroll (≠ visible)

BFC 作用:

1、 清除浮动,即在容器中创建BFC 

2、导致外边距折叠塌陷

我们必须记住的是外边距折叠(Margin collapsing)只会发生在属于同一BFC的块级元素之间。如果它们属于不同的 BFC,它们之间的外边距则不会折叠。所以通过创建一个不同的 BFC ,就可以避免外边距折叠。

segmentfault.com/a/119000001…

**十九、单线程的JavaScript引擎是怎么配合浏览器内核处理这些定时器和响应浏览器事件的呢?
**

1、单线程,多进程

  • 执行一个宏任务(栈中没有就从事件队列中获取)
  • 执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
  • 宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
  • 当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染
  • 渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)
  • tips: 宏任务按顺序执行,且浏览器在每个宏任务之间渲染页面

答案:promise 、console、setTimeout

答案:1,7,6,8,2,4,3,5,9,11,10,12

async function fun() {
    console.log(1)
    let a = await 2
    console.log(a)
    console.log(3)
}
console.log(4)
fun()
console.log(5)

输出结果:4 1 5 2 3

等价于:
function fun(){
    return new Promise(() => {
        console.log(1)
        Promise.resolve(2).then( a => {
            console.log(a)
            console.log(3)
        })
    })
}
console.log(4)
fun()
console.log(5)作者:沐华链接:https://juejin.cn/post/6992985462163898382来源:稀土掘金著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

www.cnblogs.com/joyco773/p/…

**www.xuanfengge.com/js-realizes…
**

**segmentfault.com/a/119000001…
**

二十、websocket 实时推送

相关链接: juejin.im/post/684490…

二十一、http2.0的新特性有哪些?(选项是多路复用、头部压缩、设置优先级、服务端推送、二进制传输)

相关链接: juejin.im/post/684490…

http1.0与http1.1都不支持持久性的链接,http1.1中的connection: keep-alive,将多个http请求合并为1个(即在一个http链接中,可以发送多个Request,接受多个Response)。

http2.0 /http1.0

多路复用:多路复用允许同时通过单一的http连接发送多重请求-响应信息,改善了再http1.1中,浏览器客户端在同一时间,针对同一域名下的请求有一定数量限制,超过会被阻塞。

二进制分帧: Http2.0 会将所有的传输信息分割为更小的信息或帧,并对他们进行二进制编码。

302 与304 的区别 206

二十二、讲解一下https 的工作原理(握手过程)

http 是超文本传输协议,信息是明文传输的,https 是在http下加入ssl层,https协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议。

HTTPS在传输数据之前需要客户端(浏览器)与服务端(网站)之间进行一次握手,在握手过程中将确立双方加密传输数据的密码信息。TLS/SSL协议是一套加密传输的协议,TLS/SSL中使用了非对称加密,对称加密以及HASH算法。握手过程的简单描述如下:

  • 浏览器将自己支持的一套加密规则发送给网站。

  • 网站从中选出一组加密算法与HASH算法,并将自己的身份信息以证书的形式发回给浏览器。证书里面包含了网站地址,加密公钥,以及证书的颁发机构等信息。

  • 获得网站证书之后浏览器要做以下工作:

  • a) 验证证书的合法性(颁发证书的机构是否合法,证书中包含的网站地址是否与正在访问的地址一致等),如果证书受信任,则浏览器栏里面会显示一个小锁头,否则会给出证书不受信的提示。

  • b)如果证书受信任,或者是用户接受了不受信的证书,浏览器会生成一串随机数的密码,并用证书中提供的公钥加密。

  • 使用约定好的HASH计算握手消息,并使用生成的随机数对消息进行加密,最后将之前生成的所有信息发送给网站。

  • 网站接收浏览器发来的数据之后要做以下的操作:

  • a) 使用自己的私钥将信息解密取出密码,使用密码解密浏览器发来的握手消息,并验证HASH是否与浏览器发来的一致。

  • b) 使用密码加密一段握手消息,发送给浏览器。

  • 浏览器解密并计算握手消息的HASH,如果与服务端发来的HASH一致,此时握手过程结束,之后所有的通信数据将由之前浏览器生成的随机密码并利用对称加密算法进行加密。

[copy链接](github.com/airuikun/We…)

[热更新原理](zhuanlan.zhihu.com/p/30669007)

vue 3.0 新特性

目前,Vue 的反应系统是使用 Object.defineProperty 的 getter 和 setter。 Vue 3 将使用 ES2015 Proxy 作为其观察者机制。 这消除了以前存在的警告,使速度加倍,并节省了一半的内存开销。

为了继续支持 IE11,Vue 3 将发布一个支持旧观察者机制和新 Proxy 版本的构建。

www.html.cn/archives/10…

二十三、前端代码日志收集

思路:

参照:

别人优质汇总:

juejin.im/post/684490… 

总结排序:!important > 行内样式>ID选择器 > 类选择器 > 标签 > 通配符

万能npm清缓存大法:

rm -rf package-lock.json
rm -rf node_modules
npm cache clean —force

闭包的形式、模块模式:

var myNamespace=(function(){
    //私有计数器变量
    var myPrivateVar=0;
    //记录所有参数的私有函数
    var myPrivateMethod=function(foo){
    }
    return{
        //公有变量
        myPublicVar:"foo",
        //调用私有变量和方法的公有函数
        myPublicFunction:function(bar){
            //增加私有计数器值
            myPrivateVar++;
            //传入bar调用私有方法
            myPrivateMethod(bar);
        }
    };
})();

私有MyModule

  var MyModule = (function () {    var modules = {};    function define(name, deps, impl) {      for (var i = 0; i < deps.length; i++) {        deps[i] = modules[deps[i]];      }      modules[name] = impl.apply(impl, deps);    }    function get(name) {      return modules[name];    }    return {      get,      define,    };  })(); 

vue单页面应用首次访问速度优化

解决方法:

**0-**工具使用查看各个js占用的大小

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;// use
new BundleAnalyzerPlugin(),

懒加载组件

const tabar = resolve => require(['./components/tabar'], resolve)Vue.component('tabar', tabar);

资源cdn (theme-chalk.css xxx

npm install --save-dev compression-webpack-plugin@1.1.12 强烈推荐

eg: cloud.tencent.com/developer/a…