前端
文章平均质量分 55
lznism666
这个作者很懒,什么都没留下…
展开
-
2021 前端面试点总结
以下内容收集于各个技术网站,总结在我们github上https://github.com/GuoLizhi/awesomejs, 求star~1. CSS相关flex2. 设计模式相关单例模式3. 工程化CSRFXSSwebpack性能优化4. 手写JavaScript代码系列apply实现原理bind实现原理call实现原理将字符串复制到剪切板创建一个文件夹函数柯里化防抖函数简易版的深拷贝判断当前处于移动端还是桌面端判断父元素是否包含子元素检查指定的元原创 2021-02-23 14:28:47 · 321 阅读 · 1 评论 -
Vue父组件向子组件传递props过程分析二
props也和data一样做了一层代理,实际上的props时挂载到_props上的function proxy(target, sourceKey, key) { Object.defineProperty(taget, key, { get() { return target[sourceKey][key]; }, set(val) { target[sourceKey][key] = val;原创 2020-09-10 08:24:32 · 151 阅读 · 0 评论 -
Vue父组件向子组件传递props过程分析一
假设我们有以下Vue代码<div> <child-component :name="name" /></div><script>export default { data() { return { name: 'lznism' } }}</script>父组件中包含一个子组件child-component,要弄清楚父组件如何想子组件传递props,首先必原创 2020-09-09 19:21:11 · 184 阅读 · 0 评论 -
Vue初始化data流程
初始化data流程如下将data中的属性,挂载到实例vm下的_data属性。如果data是函数,会首先对data函数求值对vm._data做代理工作。遍历_data中的每一个key执行proxy(vm, '_data', key)核心proxy的代码如下function proxy(target, sourceKey, key) { Object.defineProperty(target, key, { get() { return this[s原创 2020-09-09 10:48:13 · 907 阅读 · 1 评论 -
Vue响应式原理
Vue响应式原理的核心内容是依赖收集和依赖更新。而以上两个功能是使用Object.defineProperty()来实现的,Object.defineProperty()使用其get和set方法实现依赖收集和依赖更新的。Object.defineProperty(obj, property, { get() { // 依赖收集 }, set() { // 依赖更新 }});依赖在Vue内部是一个数组,该数组里面保存一个个的Watcher原创 2020-09-09 10:11:38 · 65 阅读 · 0 评论 -
线程和进程的区别
做个简单的比喻:进程=火车,线程=车厢线程在进程下行进(单纯的车厢无法运行)一个进程可以包含多个线程(一辆火车可以有多个车厢)不同进程间数据很难共享(一辆火车上的乘客很难换到另外一辆火车,比如站点换乘)同一进程下不同线程间数据很易共享(A车厢换到B车厢很容易)进程要比线程消耗更多的计算机资源(采用多列火车相比多个车厢更耗资源)进程间不会相互影响,一个线程挂掉将导致整个进程挂掉(一列火车不会影响到另外一列火车,但是如果一列火车上中间的一节车厢着火了,将影响到所有车厢)进程可以拓展到多机,进程最多转载 2020-09-08 11:24:17 · 185 阅读 · 0 评论 -
webpack中splitChunks
splitChunks中chunks总共有3中类型的取值,这也是整个splitChunks的核心所在all 不管文件是动态引入还是非动态引入,统一将文件分离。当页面首次载入会引入所有的包async 将异步加载的文件分离,首次一般不引入,当页面加载时,需要这个组件了才会引入initial 将异步和非异步文件分离,如果一个文件被异步引入也被同步引入,那它会被打包两次,用于分离页面首次需要加载的包...原创 2020-09-08 10:38:54 · 2113 阅读 · 1 评论 -
webpack打包体积优化
1. 引入webpack-bundle-analyzer分析打包后的文件这个插件可以直观展示打包之后,每个包的大小,分析出是否重复打包了某个模块。2. externals项目中我们通过CDN引入了某个库,但是又不想这个库被打包到webpack最终模块中,我们可以使用externalsexternals: { jquery: 'jQuery'}3. tree-shakingwebpack4中production模式下会自动开启tree-shaking模式,但是想要其生效,代码必须是ES原创 2020-09-07 16:03:57 · 207 阅读 · 0 评论 -
webpack性能优化-提升构建速度
1. 合理配置mode和devtool参数mode可以设置为development和production, 默认为production, 而production下默认会开启tree shaking。此时打包的速度会变慢。2. 缩小文件的搜索范围webpack打包时,如果你的代码中import或者require了别的模块或者第三方库,webpack会按照一定的规则去搜索这些模块。aliasinclude/excludenoParse 告诉webpack不去解析noParse模块所依赖的库ext原创 2020-09-07 15:47:23 · 611 阅读 · 0 评论 -
Vue单元测试-点击事件
Vue默认会批量处理data的更新,我们在书写测试用例时,触发事件之后,data可能不会立即更新,我们通常可以使用async/await来解决这个问题import { shallowMount } from '@vue/test-utils'import Counter from './Counter.vue'describe('Counter', () => { test('updated count', async () => { const wrapper = shal原创 2020-09-07 11:29:55 · 1042 阅读 · 0 评论 -
flex-grow/flex-shrink/flex-basis
1.flex-grow该属性定义弹性盒子的拉伸因子,默认值为0,即表示不拉伸来看一个简单的例子,总宽度为500px的container下面有3个item,他们的宽度均设置为100px,flex-grow分别设置为1, 2, 3,如果忽略flex-grow的话,container会有200px的剩余空间,加上flex-grow之后,这200px会按照1:2:3的比例分配剩余空间,也就是a将分得33.33px的剩余空间,b将分得66.66px的剩余空间,c将分得100px的剩余空间 <style&原创 2020-09-03 17:06:53 · 95 阅读 · 0 评论 -
前端安全-CSRF攻击
CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。一个经典的CSRF请求受害者登录了a.com,并保留了登录凭证cookie攻击者引诱受害者访问了b.comb.com向a.com发送了一个请求a.com接收到请求后,对请求进行验证,确定是受害者的凭证,误以为是受害者自己发送的请求a.co原创 2020-09-02 17:20:41 · 112 阅读 · 0 评论 -
前端安全-XSS攻击
XSS:跨站脚本攻击,是一种代码注入攻击。攻击者通过在目标网站上注入恶意脚本,使之在用户的浏览器上运行。利用这些脚本,攻击者可以获取用户的敏感信息,例如cookie, session等,进而危害数据安全。XSS的本质:恶意代码未经过过滤,与正常的代码混合在一起;浏览器无法区分哪些脚本是可信的,导致恶意脚本被执行。XSS可以分为以下几大类存储型 用户将恶意代码提交到数据库,当用户打开目标网站是,数据库中的恶意代码被读取,插入到页面的代码中。反射型 攻击者构造出特殊的URL,其中包含恶意代码,页面中读取原创 2020-09-02 16:13:46 · 2941 阅读 · 0 评论 -
将error-fisrt风格的异步函数promise化
function promisify(asyncFunc) { return function(...args) { return new Promise((resolve, reject) => { args.push(function callback(err, ...values) { if (err) { return reject(err);原创 2020-09-01 21:58:09 · 97 阅读 · 0 评论 -
前端手写系列-实现简单的EventEmitter
const { delete } = require("superagent");class EventEmitter { constructor() { this.subs = {}; } on(event, cb) { if (!this.subs[event]) { this.subs[event] = []; } this.subs[event].push(cb); }原创 2020-09-01 21:31:30 · 267 阅读 · 0 评论 -
async/await优雅的处理异步函数
async function errorCaptured(asyncFunc) { try { const result = await asyncFunc(); return [null, result]; } catch (err) { return [err, null]; }}const [err, result] = errorCaptured(asyncFunc);原创 2020-09-01 21:17:40 · 132 阅读 · 0 评论 -
webpack中hash/chunkhash/contenthash
webpack中有3中hash1.hash主要用于开发环境中,当项目中的一个文件发生了改变,整个项目的hash就会发生改变。这样每次更新,文件都不会让浏览器缓存下来,保证页面每次都加载的是最新的资源2.chunkhash跟打包的chunk有关,具体来说就是根据入口entry配置文件来分析其依赖项,并由此来构建该entry的chunk,并生成对应的hash,不同的chunk会有不同的hash。在生产环境中,我们会把第三方或者公共类库进行单独打包,所以不改动公共库的代码,该chunk的hash就不会发原创 2020-09-01 16:56:00 · 157 阅读 · 0 评论 -
HTTP2带来的优化点
http2的出现主要是为了解决http1中存在的问题,http1中存在的问题如下:线头阻塞:http1在当初设计的时候,单个TCP连接上只能发送一个请求,在前面的请求未完成之前,后序的请求只能排队等待多个TCP连接:虽然HTTP1.1中出现了管线化可以支持请求的并发,但是建立TCP连接的成本还是很高的,每次TCP的连接都需要经过3次握手,每次TCP的连接断开都需要经过4次挥手。头部字段冗余:HTTP1.X版本采用文本格式,首部未压缩,而且每个请求都会带上cookie, user-agent等完全相同原创 2020-08-28 17:31:05 · 601 阅读 · 0 评论 -
前端手写系列-实现map/filter
1. map// callback接受3个参数// 1. 当前遍历到的arr[i]// 2. 当前遍历到的索引i// 3. 当前遍历的数组function map(arr = [], callback) { if ( !Array.isArray(arr) || typeof callback !== "function" || arr.length === 0 ) { return []; } const result = []; for (原创 2020-08-26 19:19:01 · 377 阅读 · 0 评论 -
前端手写系列-手写防抖,节流函数
函数防抖:最后一个事件结束后n秒后,再执行回调。如果这n秒内再有事件被触发,则重新开始计时function debounce(fn, wait) { let timer = null; return function() { const context = this; // 如果此时存在定时器,则清掉定时器,重新计时 if (timer) { clearTimeout(timer); } timer = setTimeout(() => {原创 2020-08-26 19:08:02 · 243 阅读 · 0 评论 -
前端手写系列-手写简易版深拷贝
深拷贝:将对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改不会影响源对象浅拷贝:创建一个新对象,这个对象有着原始属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用数据类型,拷贝的就是这个地址,修改这个对象,也会影响到原对象。浅拷贝的方式通常有扩展运算符,Object.assign(), Array.prototype.slice()深拷贝方式1:JSON.parse(JSON.stringify(obj)),这种方式有很多缺点,会忽略unde.原创 2020-08-26 17:59:21 · 231 阅读 · 0 评论 -
前端手写系列-手写reduce函数
reduce函数常用于对数组,reduce函数接受3个参数被迭代的数组用于迭代计算的函数迭代的初始值注意点:如果没有提供初始值时,会默认使用数组的第一个元素来作为初始值function reduce(arr, callback, initialVal) { if ( !Array.isArray(arr) || typeof callback !== "function" || arr.length === 0 ) { return []; }原创 2020-08-26 17:21:32 · 430 阅读 · 0 评论 -
前端手写系列-手写call/apply/bind
call和apply的作用是一致的,都是在调用函数的同时,给函数绑定一个上下文context对象,call和apply的实现都利用了调用对象内部方法时,这个方法中的this属性指向这个对象本身。比如var obj = { name: "lznism", sayName() { console.log(this.name); }}obj.sayName();call和apply唯一的不同点在于,接受参数的格式不同,其中call接受一个一个的参数,而apply接原创 2020-08-26 17:04:28 · 143 阅读 · 0 评论 -
前端体验优化-懒加载和预加载
1. 懒加载懒加载的原理很简单,就是当图片滚动到视口中时,将img的src替换成真是的图片地址。通常我们将真实的图片地址存放于data-original这个属性中const viewHeight = document.documentElement.clientHeight;function lazyLoad() { const elements = document.querySelectorAll("img[data-original][lazyload]"); [...elements]原创 2020-08-26 14:56:25 · 291 阅读 · 0 评论 -
前端性能优化-缓存优化
1. 强缓存控制浏览器强缓存主要靠两个响应头部字段来实现:Expires和Cache-Control,浏览器在访问静态资源时,会首先判断该资源是否做了强缓存。如果发现是强缓存并且缓存还在有效期内,那就不会去发送http请求,而直接使用本地的缓存(这个缓存可能来自于内存,也可能来自本地磁盘空间)。其中Expires表示资源的过期时间(GMT格式),是一个时间点。Cache-Control使用max-age来表示资源可以被缓存多久,是一个时间区间。如果强缓存过期了,那就会去协商缓存。以上二者的优先级Cach原创 2020-08-26 11:30:19 · 626 阅读 · 0 评论 -
前端手写系列-手写JSONP请求
jsonp的核心原理是利用script标签没有同源限制的方式,可以发送跨域的get请求(只能发送get请求)。script标签中的src属性将请求参数和当前请求的回调函数名拼接在链接上。最终由服务端接收到请求之后拼接成前端可执行的字符串的形式返回。这个结果字符串最终会在前端的script标签中解析并执行。// 比如后端可以返回一下文本jsonpCallbackName({ name: "lznism", age: 10});发送jsonp请求分为以下几个步骤将jsonp回调函数原创 2020-08-25 19:26:20 · 379 阅读 · 1 评论 -
前端手写系列-手写原生ajax请求
发送原生ajax请求分为以下几个步骤实例化XMLHttpRequest对象获取xhr对象调用xhr对象的open方法。open方法接受3个参数,请求方法(get或者post), 请求url(get请求的内容会拼接在url上面), 请求是否异步(99%的情况下我们会选择异步);调用xhr对象的send方法,其中get请求无需传参,对于post请求需要传参监听xhr对象onreadystatechange回调函数,如果readyState为4(表示响应内容解析完成,可以在客户端调用)。然后根据xhr对原创 2020-08-25 18:50:37 · 632 阅读 · 0 评论 -
scss常用的mixin
1. 文本垂直居中@mixin utils-vertical-center { $selector: &; @at-root { #{$selector}::after { display: inline-block; content: ""; height: 100%; vertical-align: middle; } }}2. 文本溢出显示省略号@mixin utils-ellipsis { overf原创 2020-08-25 16:09:30 · 420 阅读 · 1 评论 -
scss中@at-root的使用
SCSS中的@at-root可以用来放弃当前的嵌套层级,让其内部的CSS规则到根部。比如我们通常会这样使用SCSS的嵌套.bar { .foo { color: red }}编译出来的css为.bar .foo { color: red}但是如果我们这里使用@at-root,那编译出来的效果就不一样了.bar { @at-root .foo { color: red; }}编译出来就是.bar {}.foo原创 2020-08-25 16:08:52 · 1906 阅读 · 0 评论 -
scss中!default和mix函数的使用
1. !default该标记也是用于表示SCSS变量的默认值,在UI组件库中使用广发。其用法如下:$primary: #ddd !default;如果没有给$primary变量赋值,那就采用#ddd的默认值$primary: #ccc;$primary: #ddd !default;如果$primary已经赋值了,那就不会采用#ddd这个默认值,而是采用#ccc这个值。2. mix函数该函数用于将两种颜色混合在一起,在UI组件库中使用比较广泛mix($color1, $color2,原创 2020-08-25 16:08:03 · 3654 阅读 · 0 评论 -
JavaScript数据类型判断终极解决方案
1. JavaScript数据类型基本数据类型:null, undefined, boolean, number, string, symbol引用数据类型:Object(包含Function, Date, Array, RegExp, Error, Arguments等)基本数据类型存放于栈内存中,引用数据类型在栈内存和堆内存中均有,其中栈中存储了指针,指向堆中该实体的起始位置,当访问引用数据类型时,会首先在栈内存中查找器指针,然后到堆中获得实体2. 判断数据类型typeof instanceo原创 2020-07-21 16:22:10 · 103 阅读 · 0 评论 -
前端手写系列-实现new
1. 完整代码/** * 手动实现一个new * 1. 创建一个全新对象 * 2. 取出arguments中的构造函数(这里我们将构造函数放在第一个参数) * 3. 将这个新对象的__proto__属性指向构造函数的prototype * 4. 调用这个构造函数,获取返回值;这里的主要目的是看构造函数是否有返回值,类似于Function, Array, Date, RegExp * ...原创 2020-04-23 20:58:58 · 370 阅读 · 0 评论