转眼间9月的到来,十分感慨这时光的飞逝。9月对程序员有着十分重要的意义,想在这个优胜劣汰的代码世界活下去,金3银4,金9银10,都属于选择的机会。javascript
在这优点略汰且经济回陇的状态下,笔者身处央企现在也开始考虑本身工做的问题,咱们能够选择的只能是,逐步的打好本身的基础,才能在不安稳的社会形态下,逆行保持本身的安稳。笔者也该复习复习,在此汇总一下本身过去所学过的基础。css
本文的难度级别,我的定位为中级前端开发工程师。我的任务是前端重要基础的均汇总,若有遗漏,及时提醒,愿听闻。笔者也是逐步前进的小伙,当前也须要及时的补充本身,过程若有不对的地方,尽快指出。如文章对你有帮助,但愿能给于鼓励,手动点个赞吧。html
汇总内容包含看过的书籍,本身对程序的理解,以及部分大神的借鉴(不少都是曾经记下的知识点,来源我也忘记是从哪里,如没有说起但愿包涵)。前端
但文章全文,均为笔者一字一字手敲。写给本身供于复习,同时分享给在前端一块儿努力朋友。vue
本章一共有两篇:java
下篇:juejin.cn/post/687316…node
前端基础,我的认为就是html + js + css。不管过程如何,不管你用的是less仍是sass,不管你用的vue仍是react,输出的结果,只有html + js + css。react
此部分列举,笔者以为重点的知识点,若有遗漏,欢迎指出。jquery
html章节,本文仅列出笔者任务相对重要的知识点,且介绍上,针对重点。固然,遗漏很正常,但愿能收到你的意见。css3
所谓,语义化的标签,说明让标签有本身的含义。也是近十年。最典型的栗子就是header,footer等,它可让你在没有样式的状况下,就大概能想到,他就是个头部或者底部。他存在的意义,就是让前端开发人员,在开发过程当中,更容易去阅读代码,以及明白这些代码的意义。
它的好处是: 1.可以更好的展现内容结构 2.便于团队的维护与开发 3.有利于SEO,爬虫能够分析每一个关键词的权重。 4.方便其余设备解析 (如屏幕阅读器)
做为前端,你不得不知道的SEO,这涉及到公司的网站推广。
SEO,中文称搜索引擎优化,一种利用搜索引擎的搜索规则来提升目前网站在有关搜索引擎内的天然排名的方式。他的实现原来分别为,页面抓取,分析入库,检索排序。
如何优化SEO:
1)title、description、keywords 2)利用好html语义化 3)重要的东西放前面 4)少用iframe
有兴趣深刻SEO优化的朋友:segmentfault.com/a/119000001…
前端常常在html头部看到DOCTYPE的声明,通常常位于文档的第一行。那么他的做用是什么,可能对新的浏览器或者新的网站暂无什么影响,可是相对古老的浏览器或者是网站,可能会出现不一样。由于浏览器有标准模式与兼容模式,差别相对比较大。
标准模式的渲染方式和 JS 引擎的解析方式都是以该浏览器支持的最高标准运行。 兼容模式中,页面以宽松的向后兼容的方式显示 ,模拟老式浏览器的行为以防止站点没法工做。
而DOCTYPE的存在,就是为了声明,该页面使用标准模式。不声明,可能一些旧的网站会出现兼容模式。
link与import , 本质使用上,咱们都是用他来引入css,可是他们有必定的区别。
link是一种引入资源的标签,import是引入css的方式。因此,import引入的只能是css,而link能够引入全部的资源,包括图片,RSS等。
加载顺序上也有一些差别。 link引用的CSS会同时被加载。 import引用的CSS会等到页面所有被下载完再加载。
兼容性的差异。 link无任何兼容问题,import兼容IE5以上。(固然,IE5估计也找不到了)
动态引入样式 link能够后期引入样式,而import是不能够后期引入的,只能初始化页面以前引入。
复用率的问题 import能够复用以前的css文件,而link只能一次引用一个文件。 固然,import复用文件时,在浏览器其实是加载了多个文件,会有多个请求。而每个link只是一个http请求。
首先这两个东西为何而存在的问题。 在日渐复杂的前端,异常已是程序的一部分。若是出现一些小问题,或者服务器加载上出现延迟。而咱们默认的引入的script脚本,会阻塞后续的DOM渲染。一旦没有部分异常没法及时加载完成,那么咱们的页面由于阻塞问题,将整个白屏。
也许咱们能够保证本身服务器的正常,可是你决定保证不了第三方服务器的正常,因而引入了async和defer来优化这个问题。
再来谈谈script的默认,async,defer的以前的差别。
默认状况下: 浏览器会当即加载并执行指定的脚本。指定的脚本,指在script标签之上的脚本。因此,若是script放在header中,而对应的文件还未加载完成,会造成阻塞。因此这就是如今不少页面,都会使用默认且把scipt放在页面结尾的缘由。
async状况下: async ,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。async是乱序的。
defer状况下: defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),可是 script.js 的执行要在全部元素解析完成以后,DOMContentLoaded 事件触发以前完成。defer是顺序执行。
此外,async跟defer,不支持或者不兼容IE9一下浏览器,整体来讲,笔者仍是以为script放最下方靠谱一些。
适合用事件委托的事件:click,mousedown,mouseup,keydown,keyup,keypress。
执行顺序:捕捉--》目标--》冒泡
event.stopPropagation()阻止事件的传递行为. event.preventDefault();阻止默认行为,好比阻止a的href
优势: 1.减小事件注册,节省内存。例如上面代码,只指定 父元素的处理程序,便可管理全部全部子元素的“click”事件; 2.简化了dom节点更新时,相应事件的更新
缺点: 1.利用事件冒泡的原理,不支持不冒泡的事件; 2.层级过多,冒泡过程当中,可能会被某层阻止掉; 3. 理论上委托会致使浏览器频繁调用处理函数,虽然极可能不须要处理。因此建议就近委托,好比在ol上代理li,而不是在document上代理li。 4. 把全部事件都用代理就可能会出现事件误判。好比,在document中代理了全部button的click事件,另外的人在引用改js时,可能不知道,形成单击button触发了两个click事件。
渐进加强:针对低版本浏览器进行构建页面,保证最基本的功能,而后再针对高级浏览器进行效果、交互等改进,达到更好的用户体验。 优雅降级:一开始就构建完整的功能,而后再针对低版本浏览器进行兼容。
css章节,本文仅列出笔者任务相对重要的知识点,且介绍上,针对重点。固然,遗漏很正常,但愿能收到你的意见。
盒子模型,我的的理解,就是一个来装html标签的容器,包装的内容包括content+padding+border+margin。由这四个组成咱们的"盒子"。
咱们平常可能会遇到不一样的浏览器,元素的高宽不一致。除了多是浏览器内置的margin跟padding不一样以外,也多是IE跟w3c的盒子模型组成不一样。
如下是两种不一样盒子的分类:
简单的我的理解,block formatting context,块级格式化上下文。产生了BFC的,造成了独立容器,他的特性就是不会再布局中影响到外边的元素。
他的特性:
触发的条件是:
此外,除了BFC,还有IFC、GFC、FFC的概念。咱们简单了解一下。
水平方向上的 margin,border 和 padding在框之间获得保留。框在垂直方向上能够以不一样的方式对齐:它们的顶部或底部对齐,或根据其中文字的基线对齐。包含那些框的长方形区域,会造成一行,叫作行框。 inline-block的元素的内部是一个BFC,可是它自己能够和其它inline元素一块儿造成IFC。
flex,即弹性布局。一个由css3引入,为咱们的盒子属性带来灵活性的一种布局方式。一旦父级采用了flex布局,里边的子控件将收flex布局限制,部分本来的样式(如float:left)也会失效。
基本api不作讲解,不熟悉能够看看:www.ruanyifeng.com/blog/2015/0…
特别注意: flex:0 0 30%的意义: 等于flex-grow=0(默认不放大)+flex-shrink=0(不缩小)+flex-basis=30%( 项目占据主轴的空间)
前端的图片分类格式,实际上是性能优化的很大部分。选择好图片的类型,对前端的性能影响很是大。
而前端对图片的精髓,一方面是对图片大小的评估,一方面是对图片的类型选择。
他的大小能够这样判断:
好比一张200*200的图片大小,这时候,他的像素点有40000个。每一个像素有 4 个通道, 因此一共有160000个字节,因此,咱们评估该图片的大小大概为:160000/1024 约等于 156(KB), 若是大不少,说明图片大小有优化控件。若是小不少,说明此时是模糊的。
图片类型 | 介绍 | 使用场景 |
---|---|---|
png | 适合颜色简单,可是对图片质量比较高。平常用的png8,此外还有png32, | 适合logo体积太大通常不用 |
jpeg | 不影响图片质量的状况有损压缩,banner图。适合大图。 | 压缩后大小可省略不少,通常大图使用 |
svg | 对性能有损耗,体积小,压缩性抢。可在质量不降低的过程被放大 | 部分浏览器兼容性不太好 |
webp | 只针对谷歌,兼容性很差。图片大小能压缩30~40%。 | 谷歌浏览器用,若有很是注重性能的产品,可判断浏览器加载不一样类型图片 |
base64 | 压缩成字符流,实际大小是变大了,可是好处就是减小了http请求 | 通常也针对小图标 |
#### 6.移动端适配 | ||
列举一下笔者所知道的适配方式: |
该方案的话,我的以为是最佳的方案,也是经常使用UI库很是喜欢的用处理方式之一。惟一很差的是:多套媒体方案,也意味多份的工做量。
利用单位vw/vh进行布局。该方案的话,对总体的布局仍是相对稳定,可是对部分细节等处理仍是不优化。且遇到手机屏幕差别较大的话,会出现严重的视差。
相对稳定的方法。根据屏幕大小计算出font-size;可是只能求良好,很难求精。若是UI对一像素很是的敏感,这个方案多是个很是糟糕的选择。
相信原生小程序开发者都用过rpx。这里其实原理有点相似rem。可是,却不是按屏幕大小去计算,而是不一样的屏幕定义了本身的标准。
这个问题本次只列举了几个常见的,非所有列出。如需具体,可另查资料。
1)间距差别是否大,致使文本换行,或者间隔太大。 缘由:每一个浏览器的margin和padding的默认值不一样。 解决方案:全局文件设置统一默认margin和padding。
2)图片默认有间距 缘由:由于img标签是行内属性标签,因此只要不超出容器宽度,img标签都会排在一行里,可是部分浏览器的img标签之间会有个间距。去掉这个间距使用float是正道。(个人一个学生使用负margin,虽然能解决,但负margin自己就是容易引发浏览器兼容问题的用法,因此我禁止他们使用) 解决方案:使用float属性为img布局
3)较小的高度(小于10px),时,ie可能会超出高度 缘由:IE有一个默认的行高的高度 解决方案:给超出高度的标签设置overflow:hidden;或者设置行高line-height 小于你设置的高度。
为min-height自己就是一个不兼容的CSS属性
4)透明度兼容设置 缘由:不一样浏览器各自透明度关键字不统一。 解决方案:filter:alpha(opacity=50); -moz-opacity:0.5; -khtml-opacity: 0.5; opacity: 0.5;
5)IE的hover图片会闪烁 缘由:IE6的每次触发 hover 的时候都会从新加载 解决方案:提早缓存文件。document.execCommand("BackgroundImageCache", false, true);
该回复只给与思路,没有具体写法。由于我以为你们都应该懂。
已知宽高: 1.margin 本身算高宽 2.定位 + margin-top + margin-left 3.定位 + margin:auto
未知宽高: 1.transform 但有IE兼容的问题 2.flex 布局 3.display: table-cell
首先你可能须要了解一下物理像素跟独立像素的区别。
物理像素: 一个物理像素是显示器(手机屏幕)上最小的物理显示单元,如:iPhone6上就有7501334个物理像素颗粒。 独立像素:逻辑像素,程序使用的虚拟像素。如:iPhone6上就有375677个独立像素。
那么如何实现1px呢: 1.利用 transfrom 的 scale 缩放来实现 2.利用 background 的 linear-gradient 线性渐变来实现 3.meta viewport修改为1比0.5。这样整个屏幕的大小缩小了0.5。 4.利用box-shadow
该回复只给思路
1.CSS浮动 第一个float:left,第二个float:right,第三个设置margin-left和margin-right
2.绝对定位法 第一个定位到left,第二个定位到right,第三个设置margin-left和margin-right
3.flex布局
初步聊聊我的的样式优化方案以下:
1.避免css层级太深。有兴趣了解一下css tree如何跟html tree融合成dom tree。 2.首屏(特别是缓冲效果图)可适当使用内联元素。这样有利于更快的显示。 3.异步加载CSS。非首次重要引入的css文件,不放在head里边。这样会引发阻塞。 4.减小 回流 的属性。如display:none能够考虑使用visibility 5.适当使用GPU渲染。如tranfrom等。 6.css动画的性能,是远远的大于js动画性能。 7.利用工具压缩,去重。
伪类和伪元素的根本区别在于:它们是否创造了新的元素
伪类,指能够经过元素选择器,就能够实现的效果,如frist-child,active等。 而伪元素,是指须要经过创元素,才能够实现的效果,如first-letter,before,after等。
具体元素跟写法有兴趣,可参考:blog.csdn.net/qq_27674439…
javaScript篇,因为扩展性十分全。对于大神来讲,每个点,均可以作一篇简介参考。 本文只能是概念上的简介,或者是我的对应的理解。如理解有误,欢迎吐槽。
内置对象,也叫原始类型。
原始类型有5个,null,undefined,boolean,number,string。 es6引入了symbol,能够用来作独立标识用。 es10引入了bigint, 主要用的大数据。number最大值2的53次方,超过只能使用bigint。 截至目前为止,一共是7个。
原始类型存储的都是值,他的原型汇总,是没有任何函数的。若是你看到类型有函数,好比toString,那说明类型给转换为了对象类型,此时才有toString方法。
原始类型存储的是值,对象类型存储的是地址。
简单的理解是,一个绑定了执行环境的函数,能够访问到外部环境的变量。
他的好处就是: 变量常驻内存,对于实现某些业务颇有帮助,好比计数器之类的。 架起了一座桥梁,让函数外部访问函数内部变量成为可能。 私有化,必定程序上解决命名冲突问题,能够实现私有变量。
缺陷是: 他的变量常驻在内存中,其占用内存没法被GC回收,致使内存溢出。
注意,闭包的原理是做用域链,因此闭包访问的上级做用域中的变量是个对象,其值为其运算结束后的最后一个值。
代码运行时,产生一个对应的执行环境,这个叫作执行上下文。
一般执行上下文,有三个环境: 1.全局环境:代码首先进入的环境 2.函数环境:函数被调用时执行的环境 3.eval函数:www.cnblogs.com/chaoguo1234…
执行上下文,可分为三个阶段,分别为建立,执行,销毁阶段。咱们简单的分析一下,各个阶段分别处理了什么。
(1).生成变量对象 (2).创建做用域链 (3).肯定 this 指向
指构造函数的内置属性,即prototype属性。每一个构造函数都自带prototype属性,指向一个对象,经常使用实例共享属性和方法的。
Prototype.constructor会指向原构造函数
对象的原型,也是个对象。只要对象的原型有值,不为null,他就还有原型。因此构成了原型链。
变量随着做用长辈函数一级一级往上搜索,直到找到为止,找不到就报错,这个过程就是做用域链起的做用。
做用域链的原理和原型链很相似,若是这个变量在本身的做用域中没有,那么它会寻找父级的,直到最顶层。 注意:JS没有块级做用域,若要造成块级做用域,可经过(function(){})();当即执行的形式实现。
继承的几种方式:
1.原型链继承 本质是重写了对象。 缺点: 1)对象实例共享全部继承的属性和方法
2)不能传递参数
2.构造函数继承 在子类构造函数的内部调用超类型构造函数。使用apply()和call() 方法 缺点: 1)函数复用性不高 ,每一个实例都是从新实例化构造函数,不存在共享属性 2)只能继承实例上的属性,原型上的方法不可见
3.组合继承 本质:原型链 + 构造函数 Parent.call(this) new Parent()避免了上述的缺点,经常使用。 优势:可传参,不会与父类引用属性共享 缺点:继承父类函数的时候调用了父类构造函数,致使子类的原型上多了不须要的父类属性,存在内存上的浪费。
4.原型式继承 实现本质:object()函数对传入其中的对象执行了一次浅复制
5.寄生式继承 借用构造函数来继承属性,经过原型链的混成形式来继承方法
6.寄生组合 高效率只调用了一次构造函数,集寄生式继承和组合继承的优势于一身,是实现基于类型继承的最有效方式。 就是将父类的原型赋值给了子类,而且将构造函数设置为子类,这样既解决了无用的父类属性问题 Parent.call + Object.create()
详细可参考:juejin.cn/post/684490…
this大概有如下五种场景: 1.绑定事件指向事件自己 2.普通函数的,指向方法体。 3.new函数的指向当前类 4.箭头函数,指向上级上下文 5.call/apply/bind
看如下代码,这就是new的总体过程。 · function createThis( proto ){ var obj = new Object; obj.proto = proto.prototype; let [ constructor, ...args] = [ ...arguments ]; let result = constructor.apply( obj, args ); return typeof result === 'object' ? result : obj; }
能够从代码中看到new的执行过程,新建一个对象,设置原型链,改变this指向,根据对象返回结果。
谈到js类型的判断,咱们能想起 typeof,instanceof,constructor,Object.prototype.toString.call()。(没了吧?还有的话提醒我一下)
那么咱们对比一下他们的做用与区别。
typeof 对于原始类型来讲,除了 null 均可以显示正确的类型。可是对于对象来讲,除了函数都会显示 object,因此他的做用,仅仅只能判断原始类型,判断不了对象。
instanceof,用于判断一个变量是否某个对象的实例,内部机制是经过原型链来判断的。他的确能判断是否类型的是否正确。但一点值得注意,instanceof 检测的是原型,原型链上,每个类型,都会返回true。因此,只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪一种类型。
constructor, 是原型prototype的一个属性,当函数被定义时候,js引擎会为函数添加原型prototype,而且这个prototype中constructor属性指向函数引用, 所以重写prototype会丢失原来的constructor。
可是他也有明显的缺陷:
1:null 和 undefined 无constructor,这种方法判断不了。 2:还有,若是自定义对象,开发者重写prototype以后,原有的constructor会丢失,所以,为了规范开发,在重写对象原型时通常都须要从新给 constructor 赋值,以保证对象实例的类型不被篡改。
toString是几个方案中,相对比较不错的方案。建议使用。toString() 是 Object 的原型方法,调用该方法,默认返回当前对象的 [[Class]] 。这是一个内部属性,其格式为 [object Xxx] ,其中 Xxx 就是对象的类型。
js类型的转换,能够分为三种状况:
其中,转化为boolean,除了 undefined, null, false, NaN, '', 0, -0,其余全部值都转为 true。咱们平常能够用它来判断对象是否未赋值。
比较运算符,是咱们经常使用到的。若是都为number类型,比较值的大小,那么固然简单咯。若是是非number值的时候如何处理呢?
顺序以下: 将值转换为原始值(ToPrimitive方法) 转换为数字(valueOf方法) 转换为字符串(toString方法)
补充: 有人提到ToPrimitive的过程,ToPrimitive有两种状况,一个是Number,一个是String。
若是是Number,执行以下:
若是是String, 则步骤2跟3调换。
那么何时ToPrimitive的类型是String,何时type类型是Number。
这里笔者的记忆是这样的,分为两类:
只要有运算有字符串,那么将所有转为字符串。 若是不是字符串(且数字),那就把它转换为(字符串)或数字。
那么如何判断先转为数字仍是转为字符串呢?这涉及到加法运算会触发三种类型转换。 参考“比较运算符”,ToPrimitive方法。
只要其中一方是数字,那么另外一方就转为数字。
拷贝,任何语言都有本身的深拷贝以及浅拷贝。深拷贝有利于数据的彻底独立,可是全是深拷贝的话,内存又不会不断的往上涨,因而又有了浅拷贝。
基于内存的节省,咱们平常用到的函数,不少都属于浅拷贝,好比咱们的扩展运算符,还有Object.assign,contact,slice等。都属于浅拷贝。
而深拷贝:
* 能够使用JSON.parse(JSON.stringify(obj))。性能最快。其弊端也必将明显,首先没法拷贝函数、undefined、或symbol等值。其二对象要是有自身循环调用,会报错。
* 利用递归来实现每一层都从新建立对象并赋值
* 如何用jquery,能够考虑,$.extend( [deep ], target, object1 [, objectN ] ),这也是深拷贝的一种。
* 也能够利用lodash.js,cloneDeep方法进行深拷贝。
复制代码
js的函数调用,有四种方式:
函数调用,自身携带的,记住有 this 和 arguments
接收函数做为参数或者返回函数的函数,均可成为高阶函数。 因此常见的方法有:map,filter,bind,apply等。
须要了解一下,高阶函数实现AOP。
高阶函数,高阶组件,有兴趣深刻的朋友:juejin.cn/post/684490…
柯里化,实现上,就是返回一个高阶函数,经过闭包把传入的参数保存起来。当传入的参数数量不足时,递归调用 bind 方法;数量足够时则当即执行函数。学习一下 javascript 的高阶用法仍是有意义的。
柯里化是一种将使用多个参数的一个函数转换成一系列使用一个参数的函数的技术。
柯里化函数就是一种分步传参的函数,能够提早传参而不让他执行内容,可是参数知足时再调用函数。感受能够用来作一些未知的判断。
数组的方法能够写的实在是太多了。 借助一下这位小伙伴的博客:juejin.cn/post/684490…
伪数组,说明它不是真正意义上的数组,他的输出是个对象,但他的原型并不指向Array。
常见的伪数组包括:arguments、getElementsByTagName等获取的NodeList对象
它的特性是:
伪数组也能够转换为数组,能够经过:
call,apply,bind,三者都是用来改变函数的this对象的指向的。且第一个参数都是this要指向的对象,也就是想指定的上下文。
但传参的值也不一样,apply后续只能传递数组,而call与bind能够传递多个参数。
bind 是返回对应函数,便于稍后调用;apply 、call 则是当即调用。
use strict是否很熟悉?了解一下他的大概做用:
首先效率问题: for > forEach > map
如何选择对应的循环呢:
此外,咱们要明白传统for
这个 for-of 循环首先调用了 values 数组的 Symbol.iterator 方法,获取了一个迭代器 (对 Symbol.iterator 的调用发生在 JS 引擎后台)。接下来 iterator.next() 被调用,迭 代器结果对象的 value 属性被读出并放入了第一个结果变量。 若是你只是简单地迭代数组或集合的值,那么使用 for-of 循环而不是 for 循环就是个好 主意。 for-of 循环通常不易出错,由于须要留意的条件更少;传统的 for 循环被保留用 于处理更复杂的控制条件。 在不可迭代对象、 null 或 undefined 上使用 for-of 语句,会抛出错误。
在之前,js一直没有模块化的体系。这就会产生一个问题,当项目到达大型时,很大可能性出现方法重叠,以及安全性问题,成为大型项目的一个痛点与障碍。而es6模块化正式为此诞生。
这里简述前端模块化的区别:
1)AMD, commonJS, 与es6,都属于预加载类型。然后期引入的CDM是懒加载。 何为预加载, 也就是说,在程序调用,全部的模块都加载完成。 而懒加载,是用到什么的时候,才去加载什么。
2)AMD跟cmd专一于前端的规范。而commonjs跟es6 moudle可用于先后端。
3)AMD的表明作为requirejs,cmd的表明做为seajs。commonjs 与 es6,则无需引入, 只须要引入编译器(如babel)便可。 seajs为淘宝引入的规范,咱们都知道淘宝相对很大, 不采用懒加载,首屏的时间将会很长,不过如今已经中止维护。
4)es6 跟 commonJS作了以下改变:
1.ES6只能新增值,没法从新赋值就会报错 2.CommonJS 输出是值的拷贝,即原来模块中的值改变不会影响已经加载的该值, ES6静态分析,动态引用,输出的是值的引用,值改变,引用也改变,即原来模块中的值改变则该加载的值也改变。 3.CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。 4.CommonJS 加载的是整个模块,即将全部的接口所有加载进来, ES6 能够单独加载其中的某个接口(方法)。 5.CommonJS this 指向当前模块,ES6 this指向undefined
变量声明(var)会有变量提高。变量会提早初始化,也能够提早访问。当项目变量复杂的时候,很容易产生bug。es6就在这个时候,引入了let跟const。
固然,引入let与const不只仅解决了变量提高的问题,他们的不一样以下:
新引入的let,const声明,再不会再产生变量提高。避免了变量提早访问的场景,间接的提升了严谨性。咱们能够在程序运行时就知道了报错,而非后期的调试中。
若是一个标识符已经在代码块内部被定义,那么在此代码块内使用同一个标识符进行 let 声明就会致使抛出错误
这是let与const的区别。const 声明会阻止对于变量绑定与变量自身值的修改,避免了咱们平常开发中,了不当心改到常量的问题。
4)暂时性死区 下述案例,用let跟var定义的结果,就明白什么叫暂时性死区
for( let i = 0; i<10; i++ ){
setTimeOut( function(){
alert(i );
}, 1000);
}
复制代码
Symbol是JS新引入的基本类型。咱们都知道在ES5以前,JS 已有的基本类型(字符串、数值、布尔类型、 null 与 undefined )以外, ES6 引入 了一种新的基本类型。
符号起初被设计用于建立对象私有成员,而这也 是 JS 开发者期待已久的特性。 在符号诞生以前,将字符串做为属性名称致使属性能够被轻易 访问,不管命名规则如何。 而“私有名称”意味着开发者能够建立非字符串类型的属性名称,由 此能够防止使用常规手段来探查这些名称。
咱们经常使用于: 1.做为内置属性名称。能够避免同参数名的覆盖。 2.使用Symbol来替代常量。Symbol来建立一些常量。好比订单状态等,能够也能够避免重复。 3.做为私有变量,防止暴露
须要明白Array.of跟Array.from的意义。
首先上述提到,数组有了伪数组的概念,而转化为数组,能够经过 Array.prototype.slice.call(arguments)。可是这个方法并不直观,因此引入了更为直观的Array.form。
只要是部署了iterator(下边会说起)接口的数据结构,Array.from都能将其转为数组。
而Array.of是为了解决new Array()的严谨性的问题。 new Array( )后边的值,可能表明长度,可能表明数值。
Array.of基本上能够用来替代Array()或newArray(),而且不存在因为参数不一样而致使的重载,并且他们的行为很是统一。
es6对函数的扩展,主要针对两个,一个是箭头函数,一个是解构函数。
箭头函数跟普通函数的区别:
这里,简单说起解构函数,解构数组,以及字符串模版等概念。
数组在 JS 中的使用正如其余语言的数组同样,但缺乏更多类型的集合致使数组也常常被看成队列与栈来使用。 数组只使用了数值型的索引,而若是非数值型的索引是必要的,开发者便会使用非数组的对 象。
Map Map与Object,其最本质的区别,键值对的集合(Hash 结构),可是传统上只能用字符串看成键。
对于Map来讲,undefined和null是两个不一样的键,布尔值true和字符串true是两个不一样的键,而NaN之间视为同一个键 ,0和-0也是一个键,
const map = new Map();
map.set(['a'], 1);
map.get(['a'])
复制代码
会输出underfined。
WeakMap
WeakMap跟Map结构相似,也是用于生成键值对的集合,可是他只能用对象,来做为键值。其次,WeakMap的键名所指向的对象,不计入垃圾回收机制。
WeakMap 与 Map 在 API 上的区别主要是两个,一是没有遍历操做(即没有keys()、values()和entries()方法),也没有size属性。由于没有办法列出全部键名,某个键名是否存在彻底不可预测,跟垃圾回收机制是否运行相关。这一刻能够取到键名,下一刻垃圾回收机制忽然运行了,这个键名就没了,为了防止出现不肯定性,就统一规定不能取到键名。二是没法清空,即不支持clear方法。所以,WeakMap只有四个方法可用:get()、set()、has()、delete()。
WeakMap的实例比较少,我的历来没有在实践中使用。但有这么一个实例相对适合:好比咱们要统计一个页面统计该页面全部节点的点击次数。
Set Set可能相对更好理解,他能够简单理解为是一个“无重复值”的“有序”列表,且运行值方便快速访问以及判断。
咱们能够利用他去重。包括数组,字符串等。
也能够利用他去接受一些具备 iterable 接口的其余数据结构,例如咱们统计页面有几个div? new Set(document.querySelectorAll('div'));
WeakSet 跟WeakMap相似,仍是两个关键字:“对象”,“内存”。
迭代器iterator, 能够理解成一个为不一样的数据结构,统一访问的机制(Symbol.iterator属性)。只要对应的数据结构有Symbol.iterator属性,就能够完成遍历操做。
function createIterator(items) {
var i = 0;
return {
next: function() {
var done = (i >= items.length);
var value = !done ? items[i++] : undefined;
return {
done: done,
value: value
};
}
};
}
var iterator = createIterator([1, 2, 3]);
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: 2, done: false }"
console.log(iterator.next()); // "{ value: 3, done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"
复制代码
咱们的字符串,数组、类数组的对象、Set和Map,都具有Iterator接口。因此他们都是可迭代对象。
可迭代的做用有三个:
经常使用到iterator的场景包括:
严格来讲generator(生成器)属于ES5,并非ES6。但因为涉及迭代器等,因此并入es6模块。
生成器( generator )是能返回一个迭代器的函数。生成器函数由放在 function 关键字之 后的一个星号( * )来表示,并能使用新的 yield 关键字。将星号紧跟在 function 关键 字以后,或是在中间留出空格,都是没问题的.
形式上,Generator 函数是一个普通函数,可是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式,定义不一样的内部状态(yield在英语里的意思就是“产出”)。
Generator有着"中止","开始"的状态,那咱们能够用他来控制异步编程,因此,他也是异步的解决方案之一。
Generator要next一步一步往下执行。若是想一步执行,能够借助Thunk 函数(固然他的原理也是遍历帮咱们执行了next。)
Promise 被设计用于改善 JS 中的异步编程,与事件及回调函数对比,在异步操做方面为你提供了更多的控制权与组合性。 Promise 调度被添加到 JS 引擎做业队列,以便稍后执行。不过此处有另外一个做业队列追踪着 Promise 的完成与拒绝处理函数,以确保适当的执行。
Promise 具备三种状态:挂起、已完成、已拒绝。一个 Promise 起始于挂起态,并在成功时转为完成态,或在失败时转为拒绝态。在这两种状况下,处理函数都能被添加以代表Promise 什么时候被解决。
Promise的缺陷:
proxy: 代理对目标对象进行了虚拟,所以该代理与该目标对象表面上能够被看成同一个对象来对待。代理容许你拦截在目标对象上的底层操做,而这本来是 JS 引擎的内部能力。拦截行为使用了一个可以响应特定操做的函数(被称为陷阱)。
Reflect: 是给底层操做提供默认行为的方法的集合,这些操做是可以被代理重写的。每一个代理陷阱都有一个对应的反射方法,每一个方法都与对应的陷阱函数同名,而且接收的参数也与之一致。
JS 运行环境包含一些不可枚举、不可写入的 对象属性,然而在 ES5 以前开发者没法定义他们本身的不可枚举属性或不可写入属性。 ES5引入了 Object.defineProperty() 方法以便开发者在这方面可以像 JS 引擎那样作。
ES6 让开发者能进一步接近 JS 引擎的能力,这些能力原先只存在于内置对象上。语言经过代理( proxy )暴露了在对象上的内部工做,代理是一种封装,可以拦截并改变 JS 引擎的底层操做。
Class写法,能够简单理解成ES6的一个语法糖。咱们平常用他所实现的功能,其实用ES5均可以作到,可是class的写法,让对象原型的写法更加清晰。 但不只仅是糖语法。
此外,咱们须要了解一下Class写法中关键super、static、constructor、new.target。本文不作详细介绍。
** cookie,localStorage,sessionStorage.IndexedDB **
比较一下差别:
cookie在浏览器和服务器间来回传递; sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存;
localStorage<=5M; sessionStorage<=5M; cookie<4K;(ie内核浏览器占主流地位,且ie6仍占有至关大的市场份额,因此在程序中应当使用少于20个cookie,且不大于4k)
localStorage:始终有效,窗口或浏览器关闭也一直保存,所以用做持久数据; sessionStorage:仅在当前浏览器窗口关闭前有效,不能持久保持; cookie:只在设置的cookie过时时间以前一直有效,即便窗口或浏览器关闭也不会消失;
localStorage :在全部同源窗口中都是共享的; sessionStorage:同时“独立”打开的不一样窗口,即便是同一页面,sessionStorage对象也是不一样的; cookie:在全部同源窗口中都是共享的
sessionStorage的浏览器最小版本:IE八、Chrome 5。
cookie:保存回话信息 localStorage:持久保存的数据 sessionStorage:拥有独立特性的数据
1.Service Worker 是运行在浏览器背后的独立线程。 必须HTTPS。
三个步奏:注册(下载:sw.js),监听(等其余worker失效),查看缓存 1)sw线程可以用来和服务器沟通数据(service worker的上下文内置了fetch和Push API) 2)可以用来进行大量复杂的运算而不影响UI响应。 3)它能拦截全部的请求
2.Memory Cache 将资源缓存在了内存中。事实上,全部的网络请求都会被浏览器缓存到内存中,固然,内存容量有限,缓存不能无限存放在内存中,所以,注定是个短时间缓存。 内存缓存的控制权在浏览器,先后端都不能干涉。
3.Disk Cache 存储在硬盘中的缓存 强缓存和协商缓存, HTTP Header 来实现的。 Cache-Control > Expires(http1.0产物, 受本地时间影响) > ETag(http1.1出现) > Last-Modified(Last-Modified 打开文件的时候会变,以秒计算的)
4.Push Cache
服务器推送,http2
字节数据-->字符串-->标记(token)-->node-->dom
字节数据-->字符串-->标记(token)-->node-->cssdom
总体的渲染过程:
两个重要的概念,重绘与回流:
回流一定会发生重绘,重绘不必定会引起回流。 回流所需的成本比重绘高的多,改变深层次的节点极可能致使父节点的一系列回流。 当 Event loop 执行完 Microtasks 后,会判断 document 是否须要更新。由于浏览器是 60Hz 的刷新率,每 16ms 才会更新一次。
致使性能问题:
减小重绘和回流的细节:
原理:(1)构造URL (2)发布内容式 (3)蠕虫式
1)验证码。 2)HTTP Referer是header的一部分 3)token
拼接脚本
(1)检查服务器是否判断了上传文件类型及后缀。 (2) 定义上传文件类型白名单,即只容许白名单里面类型的文件上传。 (3) 文件上传目录禁止执行脚本解析,避免攻击者进行二次攻击。
首先什么是跨域,违反浏览器同源策略的就是跨域。跨域自己就是就是为了保护浏览器的安全, 主要是用来防止 CSRF 攻击的
那什么是同源策略?所谓的同源,指的是协议,域名,端口相同。浏览器处于安全方面的考虑,只容许本域名下的接口交互,不一样源的客户端脚本,在没有明确受权的状况下,不能读写对方的资源。
解决同源策略的方案:
浏览器(一般指)的内存分配,64位系统下大约为1.4GB,在32位系统下大约为0.7G。
咱们一般定义变量时候就完成了分配内存,使用时候是对内存的读写操做,内存的释放依赖于浏览器的垃圾回收机制。
形成内存泄露
64位下新生代的空间为64M,老生代为1400M 32位下新生代的空间为16M,老生代为700M.
javaScript使用垃圾回收机制来自动管理内存,垃圾回收是一把双刃剑
一、V8最初是为了浏览器设计的,不太可能遇到大内存的场景 二、js垃圾回收的时候程序会暂停线程执行,会占用必定时间。
它有两种状况会回收,一种是定时回收,一种内存不够了回收。
1.新生代算法 Scavenge GC(GC 复制算法) 分为两个空间:form 跟 to。
2.老生代算法 标记清除算法 标记压缩算法
对垃圾回收算法有兴趣的朋友:www.jianshu.com/p/a8a04fd00…
javascript是一门单线程语言, Event Loop是javascript的执行机制libuv
需明白什么叫事件循环事件,微任务,宏任务。以及如何运行。
不知觉中,文章已来到了2W字。貌似掘金的限制是2W字?笔者决定分开多篇文章来汇总,避免有人关心下一章节的内容,因此本文先给出大概菜单,预计时间一周之内,有兴趣敬请关注!