diff --git a/10-Node.js/01-ES6的介绍和常用语法.md b/10-Node.js/01-ES6的介绍和常用语法.md index dcf72dd..76ffb85 100644 --- a/10-Node.js/01-ES6的介绍和常用语法.md +++ b/10-Node.js/01-ES6的介绍和常用语法.md @@ -208,6 +208,12 @@ index.js: 当我们打开网页后,就可以在浏览器的控制台,看到代码的输出结果。 +本段内容的参考链接: + +- [技术胖带你玩转ES6视频教程 (共18集)](http://jspang.com/2017/06/03/es6/) + + + 接下来,我们讲一下 ES6的常见语法。 @@ -271,7 +277,7 @@ ES6 中新增了 let 和 const 来定义变量: console.log(a); ``` -上方代码的输出结果为 2。用 let 声明的变量,只在局部起作用。 +上方代码的输出结果为 2。用 let 声明的变量,只在局部(块级作用域内)起作用。 let是防止数据污染,我们来看下面这个例子: @@ -512,6 +518,10 @@ fn(1, 2, 3); //方法中定义了四个参数,但只引用了三个参数,ES ![](http://img.smyhvae.com/20180304_1650.png) + +上方代码中注意,arg参数之后,不能再加别的参数,否则编译报错。 + + **举例:**数组赋值的问题 我们来分析一段代码:(将数组 arr1 赋值给 arr2) @@ -593,6 +603,18 @@ for…of 的循环可以避免我们开拓内存空间,增加代码运行效 +注意,上面的数组中,`for ... of`获取的是数组里的值;`for ... in`获取的是index索引值。 + +### Map对象的遍历 + + +`for ... of`既可以遍历数组,也可以遍历Map对象。 + +代码举例: + + + + ## 模板字符串 我们以前让字符串进行拼接的时候,是这样做的:(传统写法的字符串拼接) @@ -627,11 +649,23 @@ for…of 的循环可以避免我们开拓内存空间,增加代码运行效 - [ES6的rest参数和扩展运算符](https://segmentfault.com/a/1190000010222698) - - ## 箭头函数 +需要说明的是,ES6中,函数新增了很多特性。例如: +- 参数默认值 + +- 扩展运算符 + +- rest参数 + +- 箭头函数 + +- this绑定 + +- 尾调用 + +这一段,我们来讲一下箭头函数。 定义和调用函数:(传统写法) @@ -656,7 +690,7 @@ console.log(fn1(1, 2)); //输出结果:3 ``` -上方代码中,箭头后面的内容,就相当于 return 的内容。 +上方代码中,箭头后面的内容,就相当于 return 的内容(**返回值**)。 在箭头函数中,如果方法体内有两句话,那就需要在方法体外边加上{}括号。如下: @@ -672,6 +706,8 @@ console.log(fn1(1, 2)); //输出结果:3 从上面的箭头函数中,我们可以很清晰地找到函数名、参数名、方法体。 +### 参数默认值 + 当然,在 ES6 中定义方法时,我们还可以给方法里的参数加一个**默认值**(缺省值): - 方法被调用时,如果没有给参数赋值,那就是用默认值; @@ -693,6 +729,42 @@ console.log(fn1(1, 2)); //输出结果:3 ``` +需要提醒的是:**默认值的后面,不能再有没有默认值的变量**。比如`(a,b,c)`这三个参数,如果我给b设置了默认值,那么就一定要给c设置默认值。 + +另外,我们来看下面这段代码: + +```javascript + let x = 'smyh'; + function fn(x, y = x) { + console.log(x, y); + } + fn('vae'); +``` + +注意第二行代码,我们给y赋值为`x`,这里的`x`是第一个参数,并不是第一行代码里定义的`x`。打印结果:`vae vae`。 + +如果我把第一个参数改一下,改成: + +20180312_2017.png + +此时打印结果是:`vae smyh`。 + + + + + + + + +### this的指向 + +ES5中,this指向的是函数被调用的对象;而ES6的箭头函数中,this指向的是函数被定义时。 + + +所以说,箭头韩注重,一定要注意this的指向。 + + + ## 模块化 diff --git a/10-Node.js/01-Node.js入门.md b/10-Node.js/01-Node.js入门.md index f717e1c..176ddb3 100644 --- a/10-Node.js/01-Node.js入门.md +++ b/10-Node.js/01-Node.js入门.md @@ -292,7 +292,9 @@ $ node -e 'console.log("Hello World")' ``` $ node index.js + $ node path/index.js + $ node path/index ``` diff --git a/06-前端基础/00-准备.md b/11-前端基础/00-准备.md similarity index 100% rename from 06-前端基础/00-准备.md rename to 11-前端基础/00-准备.md diff --git a/06-前端基础/01-页面布局.md b/11-前端基础/01-页面布局.md similarity index 100% rename from 06-前端基础/01-页面布局.md rename to 11-前端基础/01-页面布局.md diff --git a/06-前端基础/02-CSS盒模型的深度思考及BFC.md b/11-前端基础/02-CSS盒模型及BFC.md similarity index 100% rename from 06-前端基础/02-CSS盒模型的深度思考及BFC.md rename to 11-前端基础/02-CSS盒模型及BFC.md diff --git a/06-前端基础/03-DOM事件的总结.md b/11-前端基础/03-DOM事件的总结.md similarity index 100% rename from 06-前端基础/03-DOM事件的总结.md rename to 11-前端基础/03-DOM事件的总结.md diff --git a/06-前端基础/04-HTTP协议.md b/11-前端基础/04-HTTP协议.md similarity index 100% rename from 06-前端基础/04-HTTP协议.md rename to 11-前端基础/04-HTTP协议.md diff --git a/06-前端基础/05-原型链总结.md b/11-前端基础/05-原型链总结.md similarity index 100% rename from 06-前端基础/05-原型链总结.md rename to 11-前端基础/05-原型链总结.md diff --git a/06-前端基础/06-作用域和闭包.md b/11-前端基础/06-作用域和闭包.md similarity index 100% rename from 06-前端基础/06-作用域和闭包.md rename to 11-前端基础/06-作用域和闭包.md diff --git a/06-前端基础/07-面向对象:类的定义和继承的几种方式.md b/11-前端基础/07-面向对象:类的定义和继承的几种方式.md similarity index 94% rename from 06-前端基础/07-面向对象:类的定义和继承的几种方式.md rename to 11-前端基础/07-面向对象:类的定义和继承的几种方式.md index 8b6bf42..87788d9 100644 --- a/06-前端基础/07-面向对象:类的定义和继承的几种方式.md +++ b/11-前端基础/07-面向对象:类的定义和继承的几种方式.md @@ -57,7 +57,7 @@ 继承的本质就是原型链。 -**继承的方式有几种?每种形式的优缺点是?**这些问题必问的。其实就是考察你对原型链的掌握程度。 +**继承的方式有几种?每种形式的优缺点是**?这些问题必问的。其实就是考察你对原型链的掌握程度。 ### 方式一:借助构造函数 @@ -96,7 +96,7 @@ ![](http://img.smyhvae.com/20180307_1030.png) -### 方法二;通过原型链实现继承 +### 方法二:通过原型链实现继承 ```javascript /* @@ -128,7 +128,7 @@ 这种继承方式,**Child 可以继承 Parent 的原型**,但有个缺点: -缺点是:**如果修改 child1实例的name属性,Child实例中的name属性也会跟着改变。 +缺点是:**如果修改 child1实例的name属性,child2实例中的name属性也会跟着改变**。 如下: @@ -139,7 +139,7 @@ 造成这种缺点的原因是:child1和child2共用原型。即:`chi1d1.__proto__ === child2__proto__`是严格相同。而 arr方法是在 Parent 的实例上(即 Child实例的原型)的。 -## 方式三;组合的方式:构造函数 + 原型链 +## 方式三:组合的方式:构造函数 + 原型链 就是把上面的两种方式组合起来: diff --git a/06-前端基础/08-跨域通信类.md b/11-前端基础/08-跨域通信类.md similarity index 98% rename from 06-前端基础/08-跨域通信类.md rename to 11-前端基础/08-跨域通信类.md index f4f942d..3ef5f2a 100644 --- a/06-前端基础/08-跨域通信类.md +++ b/11-前端基础/08-跨域通信类.md @@ -70,7 +70,7 @@ Ajax在前后端通信中经常用到。做业务时,可以借助第三方的 XMLHttpRequest只有在高级浏览器中才支持。在回答问题时,这个兼容性问题不要忽略。 -- 3、事件的出发条件 +- 3、事件的触发条件 - 4、事件的触发顺序 @@ -451,7 +451,7 @@ url的`#`后面的内容就叫Hash。**Hash的改变,页面不会刷新**。 **使用举例:** -**场景:**我的页面 A 通过iframe或frame嵌入了跨域的页面 B。 +**场景**:我的页面 A 通过iframe或frame嵌入了跨域的页面 B。 现在,我这个A页面想给B页面发消息,怎么操作呢? @@ -476,7 +476,7 @@ url的`#`后面的内容就叫Hash。**Hash的改变,页面不会刷新**。 > H5中新增的postMessage()方法,可以用来做跨域通信。既然是H5中新增的,那就一定要提到。 -**场景:**窗口 A (`http:A.com`)向跨域的窗口 B (`http:B.com`)发送信息。步骤如下。 +**场景**:窗口 A (`http:A.com`)向跨域的窗口 B (`http:B.com`)发送信息。步骤如下。 (1)在A窗口中操作如下:向B窗口发送数据: @@ -490,7 +490,7 @@ url的`#`后面的内容就叫Hash。**Hash的改变,页面不会刷新**。 ```javascript // 在窗口B中监听 message 事件 - Awindow.addEventListener('message', function (event) { //这里强调的是B窗口里的window对象 + Awindow.addEventListener('message', function (event) { //这里强调的是A窗口里的window对象 console.log(event.origin); //获取 :url。这里指:http://A.com console.log(event.source); //获取:A window对象 console.log(event.data); //获取传过来的数据 diff --git a/06-前端基础/09-安全问题:CSRF和XSS.md b/11-前端基础/09-安全问题:CSRF和XSS.md similarity index 86% rename from 06-前端基础/09-安全问题:CSRF和XSS.md rename to 11-前端基础/09-安全问题:CSRF和XSS.md index 4e915fe..043aa62 100644 --- a/06-前端基础/09-安全问题:CSRF和XSS.md +++ b/11-前端基础/09-安全问题:CSRF和XSS.md @@ -34,8 +34,7 @@ PS:中文名一定要记住。英文全称,如果记不住也拉倒。 ### 2、CSRF的攻击原理 - -20180307_1735.png +![](http://img.smyhvae.com/20180307_1735.png) 用户是网站A的注册用户,且登录进去,于是网站A就给用户下发cookie。 @@ -48,7 +47,7 @@ PS:中文名一定要记住。英文全称,如果记不住也拉倒。 我们在讲CSRF时,一定要把上面的两点说清楚。 -温馨提示一下,网站B其实拿不到 cookie。cookie保证了用户可以处于登录状态。 +温馨提示一下,cookie保证了用户可以处于登录状态,但网站B其实拿不到 cookie。 举个例子,前端事假你,微博网站有个api接口有漏洞,导致很多用户的粉丝暴增。 @@ -67,7 +66,7 @@ PS:中文名一定要记住。英文全称,如果记不住也拉倒。 **方法二:隐藏令牌:** -把 token隐藏在 http 的 head头中。 +把 token 隐藏在 http 的 head头中。 方法二和方法一有点像,本质上没有太大区别,只是使用方式上有区别。 @@ -119,7 +118,8 @@ XSS攻击的核心原理是:不需要你做任何的登录认证,它会通 -### XSS的防范措施 +### XSS的防范措施(encode + 过滤) + XSS的防范措施主要有三个: @@ -132,11 +132,26 @@ XSS的防范措施主要有三个: 如上图所示,把字符转换成 转义字符。 +Encode的作用是将`$var`等一些字符进行转化,使得浏览器在最终输出结果上是一样的。 + +比如说这段代码: + +``` + +``` + +若不进行任何处理,则浏览器会执行alert的js操作,实现XSS注入。 + +进行编码处理之后,L在浏览器中的显示结果就是``,实现了将$var作为纯文本进行输出,且不引起JavaScript的执行。 + +参考链接:[4类防御XSS的有效方法](https://www.jianshu.com/p/599fcd03fd3b) + + **2、过滤:** - 移除用户输入的和事件相关的属性。如onerror可以自动触发攻击,还有onclick等。(总而言是,过滤掉一些不安全的内容) -- 移除用户输入的Style节点、Script节点、Iframe节点。(尤其是Script节点,可是支持跨域的呀,一定要移除)。 +- 移除用户输入的Style节点、Script节点、Iframe节点。(尤其是Script节点,它可是支持跨域的呀,一定要移除)。 diff --git a/06-前端基础/10-算法问题.md b/11-前端基础/10-算法问题.md similarity index 100% rename from 06-前端基础/10-算法问题.md rename to 11-前端基础/10-算法问题.md diff --git a/06-前端基础/12-浏览器渲染机制.md b/11-前端基础/12-浏览器渲染机制.md similarity index 89% rename from 06-前端基础/12-浏览器渲染机制.md rename to 11-前端基础/12-浏览器渲染机制.md index ccf5600..81011b3 100644 --- a/06-前端基础/12-浏览器渲染机制.md +++ b/11-前端基础/12-浏览器渲染机制.md @@ -41,9 +41,13 @@ ### 定义 -**DTD**:是一系列的语法规则,用来定义XML或者(X)HTML文件类型。**浏览器会使用DTD来判断文本类型**,决定使用何种协议来解析,以及切换浏览器模式。(说白了就是:DTD就是告诉浏览器,我是什么文档类型,你要用什么协议来解析我) +**DTD**(Document Type Definition):文档类型定义。 -**DOCTYPE**:用来声明文档类型和DTD规范,一个主要的用途便是文件的合法性验证。如果文件代码不合法,那么浏览器解析时便会出现一些差错。(说白了,DOCTYPE就是用来声明DTD的) +是一系列的语法规则,用来定义XML或者(X)HTML文件类型。**浏览器会使用DTD来判断文本类型**,决定使用何种协议来解析,以及切换浏览器模式。(说白了就是:DTD就是告诉浏览器,我是什么文档类型,你要用什么协议来解析我) + +**DOCTYPE**:用来声明DTD规范。 + +一个主要的用途便是文件的合法性验证。如果文件代码不合法,那么浏览器解析时便会出现一些差错。(说白了,DOCTYPE就是用来声明DTD的) ### 常见的DOCTYPE声明有几种 diff --git a/06-前端基础/13-js运行机制:异步和单线程.md b/11-前端基础/13-js运行机制:异步和单线程.md similarity index 95% rename from 06-前端基础/13-js运行机制:异步和单线程.md rename to 11-前端基础/13-js运行机制:异步和单线程.md index c4a734e..0ab5e5f 100644 --- a/06-前端基础/13-js运行机制:异步和单线程.md +++ b/11-前端基础/13-js运行机制:异步和单线程.md @@ -136,23 +136,17 @@ js 是单线程(同一时间只能做一件事),而且有一个**任务队 因为`setTimeout`是**异步任务**,所以程序并不会卡在那里,而是继续向下执行(即使settimeout设置了倒计时一万秒);但是`alert`函数是**同步**任务,程序会**卡在那里**,如果它没有执行,后面的也不会执行(卡在那里,自然也就造成了**阻塞**)。 -**何时需要异步:** - -- 在可能发上等待的情况。(比如按钮的点击事件,我们不可能卡在按钮那里,什么都不做。所以,应该用异步) - -- 等待的过程中,不能像 alert 那样阻塞程序运行 - -- 什么时候需要**等待**,就什么时候用异步。 ### 前端使用异步的场景 +什么时候需要**等待**,就什么时候用异步。 - 定时任务:setTimeout(定时炸弹)、setInterval(循环执行) - 网络请求:ajax请求、动态``加载 -- 事件绑定(比如说,按钮绑定点击事件之后,用户爱点不点) +- 事件绑定(比如说,按钮绑定点击事件之后,用户爱点不点。我们不可能卡在按钮那里,什么都不做。所以,应该用异步) - ES6中的Promise diff --git a/06-前端基础/14-页面性能优化.md b/11-前端基础/14-页面性能优化.md similarity index 88% rename from 06-前端基础/14-页面性能优化.md rename to 11-前端基础/14-页面性能优化.md index 94facfa..e88df37 100644 --- a/06-前端基础/14-页面性能优化.md +++ b/11-前端基础/14-页面性能优化.md @@ -1,5 +1,10 @@ +> 本文最初发表于[博客园](https://www.cnblogs.com/smyhvae/p/8550195.html),并在[GitHub](https://github.com/smyhvae/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。 + +> 以下是正文。 + + ## 前言 提升页面性能优化的方法有哪些: @@ -103,7 +108,6 @@ 同步任务 defer1 defer2 - ``` 因为defer的加载是有顺序的,所以两个引入defer文件按顺序执行。如果把引入的文件改为async的方式加载,打印的结果可能是: @@ -122,7 +126,7 @@ async1 ## 三、利用浏览器缓存 -**缓存**:资源文件(比如图片)在本地存有副本,浏览器下次请求的时候,可能直接从本地磁盘里读取,而不会重新请求图片的url。 +**缓存**:资源文件(比如图片)在**本地的硬盘**里存有副本,浏览器下次请求的时候,可能直接从本地磁盘里读取,而不会重新请求图片的url。 缓存分为: @@ -171,6 +175,9 @@ http1.1中新增的 response header。浏览器第一次请求资源之后,在 - 第二对:`ETag`、`If-None-Match` +ETag(Entity Tag):被请求变量的实体值”。 + + **1、`Last-Modified`、`If-Modified-Since`**。过程如下: (1)浏览器第一次请求一个资源,服务器在返回这个资源的同时,会加上`Last-Modified`这个 response header,这个header表示这该资源在服务器上的最后修改时间: @@ -189,7 +196,15 @@ http1.1中新增的 response header。浏览器第一次请求资源之后,在 **缺点:** -`Last-Modified`、`If-Modified-Since`一般来说都是非常可靠的,但有可能出现的问题是:**服务器上的资源变化了,但是最后的修改时间却没有变化**。这一对header就无法解决这种情况。于是,下面这一对header出场了。 +`Last-Modified`、`If-Modified-Since`一般来说都是非常可靠的,但面临的问题是: + +- **服务器上的资源变化了,但是最后的修改时间却没有变化**。 + + +- 如果服务器端在一秒内修改文件两次,但产生的`Last-Modified`却只有一个值。 + +这一对header就无法解决这种情况。于是,下面这一对header出场了。 + **2、`ETag`、`If-None-Match`**。过程如下: @@ -224,7 +239,7 @@ http1.1中新增的 response header。浏览器第一次请求资源之后,在 通过 DNS 预解析来告诉浏览器未来我们可能从某个特定的 URL 获取资源,当浏览器真正使用到该域中的某个资源时就可以尽快地完成 DNS 解析。 -### 第一步:打开和关闭DNS预解析 +**第一步**:打开或关闭DNS预解析 你可以通过在服务器端发送 X-DNS-Prefetch-Control 报头。或是在文档中使用值为 http-equiv 的meta标签: @@ -234,7 +249,7 @@ http1.1中新增的 response header。浏览器第一次请求资源之后,在 需要说明的是,在一些高级浏览器中,页面中所有的超链接(``标签),默认打开了DNS预解析。但是,如果页面中采用的https协议,很多浏览器是默认关闭了超链接的DNS预解析。如果加了上面这行代码,则表明强制打开浏览器的预解析。(如果你能在面试中把这句话说出来,则一定是你出彩的地方) -### 第二步:对指定的域名进行DNS预解析 +**第二步**:对指定的域名进行DNS预解析 如果我们将来可能从 smyhvae.com 获取图片或音频资源,那么可以在文档顶部的 标签中加入以下内容: @@ -252,3 +267,11 @@ http1.1中新增的 response header。浏览器第一次请求资源之后,在 +## 我的公众号 + +想学习**代码之外的软技能**?不妨关注我的微信公众号:**生命团队**(id:`vitateam`)。 + +扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外: + +![](http://img.smyhvae.com/2016040102.jpg) + diff --git a/06-前端基础/15-前端错误监控.md b/11-前端基础/15-前端错误监控.md similarity index 87% rename from 06-前端基础/15-前端错误监控.md rename to 11-前端基础/15-前端错误监控.md index b817794..00d4c36 100644 --- a/06-前端基础/15-前端错误监控.md +++ b/11-前端基础/15-前端错误监控.md @@ -39,21 +39,20 @@ **方式2:**`window.onerror`函数。这个函数是全局的。 ``` - window.onerror = function(message, source, lineno, colno, error) { ... } + window.onerror = function(msg, url, row, col, error) { ... } ``` 参数解释: -- mesage为异常基本信息 +- msg为异常基本信息 - source为发生异常Javascript文件的url -- lineno为发生错误的行号 - +- row为发生错误的行号 方式二中的`window.onerror`是属于DOM0的写法,我们也可以用DOM2的写法:`window.addEventListener("error", fn);`也可以。 -**问题延伸:** +**问题延伸1:** `window.onerror`默认无法捕获**跨域**的js运行错误。捕获出来的信息如下:(基本属于无效信息) @@ -63,13 +62,12 @@ **解决办法**:在方法二的基础之上,做如下操作: -(1)在静态资源服务器或者CDN的HTTP头中加 如下 response header,表示允许跨域:(或者世界给静态资源`b.js`加这个 response header) +(1)在`b.js`文件里,加入如下 response header,表示允许跨域:(或者世界给静态资源`b.js`加这个 response header) ``` Access-Control-Allow-Origin: * ``` - (2)引入第三方的文件`b.js`时,在`