From 20b8a41137dc42d47b10186a7d185d09501aface Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Wed, 16 May 2018 22:00:00 +0800 Subject: [PATCH 001/835] 2018.05.16 --- ...6\347\202\271\346\225\264\347\220\2061.md" | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git "a/10-\347\237\245\350\257\206\347\202\271\346\225\264\347\220\2061.md" "b/10-\347\237\245\350\257\206\347\202\271\346\225\264\347\220\2061.md" index fe117fcf..7310569c 100644 --- "a/10-\347\237\245\350\257\206\347\202\271\346\225\264\347\220\2061.md" +++ "b/10-\347\237\245\350\257\206\347\202\271\346\225\264\347\220\2061.md" @@ -400,7 +400,27 @@ console.log(samesums[0]); // 1 > * `defer`并行加载js文件,会按照页面上`script`标签的顺序执行 > * `async`并行加载js文件,下载完成立即执行,不会按照页面上`script`标签的顺序执行 - +### 13、检测属性 +用于判断对象是否存在某个属性: +```js +let a = { + x : 11, + y : 22 +} +``` +> 1.通过 in 运算符判断: +```js +'x' in a ; // true +'z' in a ; // false +``` +> 2.通过hasOwnProperty()方法判断: +```js +a.hasOwnProperty("x") ; //true : a有一个自有属性x,若是继承属性,返回false +``` +> 3.更便捷 !== undefined: +```js +a.x !== undefined ;//true: a 中有属性 x +``` ### 最近更新 2018.04.09 回到顶部 [介绍](#介绍) From 106f570ff81f0f8ad830859ca40d7bf65944cc96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Thu, 17 May 2018 21:59:13 +0800 Subject: [PATCH 002/835] 2018.05.17 --- ...237\245\350\257\206\347\202\271\346\225\264\347\220\2061.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/10-\347\237\245\350\257\206\347\202\271\346\225\264\347\220\2061.md" "b/10-\347\237\245\350\257\206\347\202\271\346\225\264\347\220\2061.md" index 7310569c..44ed17a6 100644 --- "a/10-\347\237\245\350\257\206\347\202\271\346\225\264\347\220\2061.md" +++ "b/10-\347\237\245\350\257\206\347\202\271\346\225\264\347\220\2061.md" @@ -422,5 +422,5 @@ a.hasOwnProperty("x") ; //true : a有一个自有属性x,若是继承属性 a.x !== undefined ;//true: a 中有属性 x ``` -### 最近更新 2018.04.09 +### 最近更新 2018.05.17 回到顶部 [介绍](#介绍) From 0e0730dd17c7caa0009f7b2354e4c3ef28e2d3ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 18 May 2018 22:33:23 +0800 Subject: [PATCH 003/835] 2018.05.17 --- ...76\350\256\241\346\250\241\345\274\217.md" | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 "38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" diff --git "a/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" "b/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" new file mode 100644 index 00000000..b6c54263 --- /dev/null +++ "b/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" @@ -0,0 +1,90 @@ +开发中,我们或多或少地接触了设计模式,但是很多时候不知道自己使用了哪种设计模式或者说该使用何种设计模式。本文意在梳理常见设计模式的特点,从而对它们有比较清晰的认知。 + +### JavaScript 中常见设计模式 +* 单例模式 +* 策略模式 +* 代理模式 +* 迭代器模式 +* 发布-订阅模式 +* 命令模式 +* 组合模式 +* 模板方法模式 +* 享元模式 +* 职责链模式 +* 中介者模式 +* 装饰者模式 +* 状态模式 +* 适配者模式 + +### 各设计模式关键词 +看完了上述设计模式后,把它们的关键词特点罗列出来,以后提到某种设计模式,进而联想相应的关键词和例子,从而心中有数。 + +|设计模式|特点|案例| +|-|-|-| +|单例模式|一个类只能构造出唯一实例|创建菜单对象| +|策略模式|根据不同参数可以命中不同的策略|动画库里的算法函数| +|代理模式|代理对象和本体对象具有一致的接口|图片预加载| +|迭代器模式|能获取聚合对象的顺序和元素|each([1, 2, 3], cb)| +|发布-订阅模式|PubSub|瀑布流库| +|命令模式|不同对象间约定好相应的接口|按钮和命令的分离| +|组合模式|组合模式在对象间形成一致对待的树形结构|扫描文件夹| +|模板方法模式|父类中定好执行顺序|咖啡和茶| +|享元模式|减少创建实例的个数|男女模具试装| +|职责链模式|通过请求第一个条件,会持续执行后续的条件,直到返回结果为止|if else 优化| +|中介者模式|对象和对象之间借助第三方中介者进行通信|测试结束告知结果| +|装饰者模式|动态地给函数赋能|天冷了穿衣服,热了脱衣服| +|状态模式|每个状态建立一个类,状态改变会产生不同行为|电灯换挡| +|适配者模式|一种数据结构改成另一种数据结构|枚举值接口变更| + + +## 1.策略模式 +> 定义:根据不同参数可以命中不同的策略 + +### JavaScript 中的策略模式 +观察如下获取年终奖的 demo,根据不同的参数(level)获得不同策略方法(规则),这是策略模式在 JS 比较经典的运用之一。 +```js +const strategy = { + 'S': function(salary) { + return salary * 4 + }, + 'A': function(salary) { + return salary * 3 + }, + 'B': function(salary) { + return salary * 2 + } +} + +const calculateBonus = function(level, salary) { + return strategy[level](salary) +} + +calculateBonus('A', 10000) // 30000 +``` +在函数是一等公民的 JS 中,策略模式的使用常常隐藏在高阶函数中,稍微变换下上述 demo 的形式如下,可以发现我们平时已经在使用它了,恭喜我们又掌握了一种设计模式。 +```js +const S = function(salary) { + return salary * 4 +} + +const A = function(salary) { + return salary * 3 +} + +const B = function(salary) { + return salary * 2 +} + +const calculateBonus = function(func, salary) { + return func(salary) +} + +calculateBonus(A, 10000) // 30000 +``` +### 优点 +* 能减少大量的 if 语句 +* 复用性好 + + + +> 原文地址 [JavaScript 中常见设计模式整理](https://juejin.im/post/5afe6430518825428630bc4d) \ No newline at end of file From c8bc6e6fea480c1d925b6b1f1a1f32586bd1a52b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 18 May 2018 22:37:14 +0800 Subject: [PATCH 004/835] 2018.05.18 --- ...76\350\256\241\346\250\241\345\274\217.md" | 70 ++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git "a/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" "b/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" index b6c54263..a4848b50 100644 --- "a/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" +++ "b/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" @@ -37,7 +37,72 @@ |适配者模式|一种数据结构改成另一种数据结构|枚举值接口变更| -## 1.策略模式 +## 1.单例模式 +### 两个条件 +* 确保只有一个实例 +* 可以全局访问 + +### 适用 +适用于弹框的实现,全局缓存 +### 实现单例模式 +```js +const singleton = function(name) { + this.name = name + this.instance = null +} + +singleton.prototype.getName = function() { + console.log(this.name) +} + +singleton.getInstance = function(name) { + if (!this.instance) { // 关键语句 + this.instance = new singleton(name) + } + return this.instance +} + +// test +const a = singleton.getInstance('a') // 通过 getInstance 来获取实例 +const b = singleton.getInstance('b') +console.log(a === b) +``` +### JavaScript 中的单例模式 +因为 JavaScript 是无类的语言,而且 JS 中的全局对象符合单例模式两个条件。很多时候我们把全局对象当成单例模式来使用, +```js +var obj = {} +``` +### 弹框层的实践 +实现弹框的一种做法是先创建好弹框,然后使之隐藏,这样子的话会浪费部分不必要的 DOM 开销,我们可以在需要弹框的时候再进行创建,同时结合单例模式实现只有一个实例,从而节省部分 DOM 开销。下列为登入框部分代码: +```js +const createLoginLayer = function() { + const div = document.createElement('div') + div.innerHTML = '登入浮框' + div.style.display = 'none' + document.appendChild(div) + return div +} +``` +使单例模式和创建弹框代码解耦 +```js +const getSingle = function(fn) { + const result + return function() { + return result || result = fn.apply(this, arguments) + } +} +``` +```js +const createSingleLoginLayer = getSingle(createLoginLayer) + +document.getElementById('loginBtn').onclick = function() { + createSingleLoginLayer() +} +``` + +*** + +## 2.策略模式 > 定义:根据不同参数可以命中不同的策略 ### JavaScript 中的策略模式 @@ -85,6 +150,9 @@ calculateBonus(A, 10000) // 30000 * 能减少大量的 if 语句 * 复用性好 +*** + + > 原文地址 [JavaScript 中常见设计模式整理](https://juejin.im/post/5afe6430518825428630bc4d) \ No newline at end of file From 869b506a583ac8ae211bbb928623c3913fd2a7a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 18 May 2018 22:44:59 +0800 Subject: [PATCH 005/835] 2018.05.18 --- ...76\350\256\241\346\250\241\345\274\217.md" | 398 ++++++++++++++++++ 1 file changed, 398 insertions(+) diff --git "a/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" "b/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" index a4848b50..4115fd94 100644 --- "a/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" +++ "b/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" @@ -152,6 +152,404 @@ calculateBonus(A, 10000) // 30000 *** +## 3.代理模式 +情景:小明追女生 A +* 非代理模式:小明 =花=> 女生A +* 代理模式:小明 =花=> 让女生A的好友B帮忙 =花=> 女生A + +### 代理模式的特点 +* 代理对象和本体对象具有一致的接口,对使用者友好 + +代理模式的种类有很多,在 JS 中最常用的为虚拟代理和缓存代理。 +#### 虚拟代理实现图片预加载 +下面这段代码运用代理模式来实现图片预加载,可以看到通过代理模式巧妙地将创建图片与预加载逻辑分离,并且在未来如果不需要预加载,只要改成请求本体代替请求代理对象就行。 +```js +const myImage = (function() { + const imgNode = document.createElement('img') + document.body.appendChild(imgNode) + return { + setSrc: function(src) { + imgNode.src = src + } + } +})() + +const proxyImage = (function() { + const img = new Image() + img.onload = function() { // http 图片加载完毕后才会执行 + myImage.setSrc(this.src) + } + return { + setSrc: function(src) { + myImage.setSrc('loading.jpg') // 本地 loading 图片 + img.src = src + } + } +})() + +proxyImage.setSrc('http://loaded.jpg') +``` + +缓存代理实现乘积计算 +```js +const mult = function() { + let a = 1 + for (let i = 0, l; l = arguments[i++];) { + a = a * l + } + return a +} + +const proxyMult = (function() { + const cache = {} + return function() { + const tag = Array.prototype.join.call(arguments, ',') + if (cache[tag]) { + return cache[tag] + } + cache[tag] = mult.apply(this, arguments) + return cache[tag] + } +})() + +proxyMult(1, 2, 3, 4) // 24 +``` + +### 小 tip +在开发时候不要先去猜测是否需要使用代理模式,如果发现直接使用某个对象不方便时,再来优化不迟。 + +*** + +## 4.迭代器模式 +> 定义:能访问到聚合对象的顺序与元素 +### 实现一个内部迭代器 +```js +function each(arr, fn) { + for (let i = 0; i < arr.length; i++) { + fn(i, arr[i]) + } +} + +each([1, 2, 3], function(i, n) { + console.log(i) // 0 1 2 + console.log(n) // 1 2 3 +}) +``` +可以看出内部迭代器在调用的时候非常简单,使用者不用关心迭代器内部实现的细节,但这也是内部迭代器的缺点。比如要比较两数组是否相等,只能在其回调函数中作文章了,代码如下: +```js +const compare = function(arr1, arr2) { + each(arr1, function(i, n) { + if (arr2[i] !== n) { + console.log('两数组不等') + return + } + }) + console.log('两数组相等') +} + +const arr1 = [1, 2, 3] +const arr2 = [1, 2, 3] +compare(arr1, arr2) // 两数组相等 +``` +### 实现一个外部迭代器 + +相较于内部迭代器,外部迭代器将遍历的权利转移到外部,因此在调用的时候拥有了更多的自由性,不过缺点是调用方式较复杂。 +```js +const iterator = function(arr) { + let current = 0 + const next = function() { + current = current + 1 + } + const done = function() { + return current >= arr.length + } + const value = function() { + return arr[current] + } + return { + next, + done, + value, + } +} + +const arr1 = [1, 2 ,3] +const arr2 = [1, 2, 3] +const iterator1 = iterator(arr1) +const iterator2 = iterator(arr2) + +const compare = function(iterator1, iterator2) { + while (!iterator1.done() && !iterator2.done()) { + if (iterator1.value() !== iterator2.value()) { + console.log('两数组不等') + return + } + iterator1.next() // 外部迭代器将遍历的权利转移到外部 + iterator2.next() + } + console.log('两数组相等') +} + +compare(iterator1, iterator2) +``` + +*** + +## 5.发布订阅模式 + +事件发布/订阅模式 (PubSub) 在异步编程中帮助我们完成更松的解耦,甚至在 MVC、MVVC 的架构中以及设计模式中也少不了发布-订阅模式的参与。 +优点:在异步编程中实现更深的解耦 +缺点:如果过多的使用发布订阅模式,会增加维护的难度 + +### 实现一个发布订阅模式 +```js +var Event = function() { + this.obj = {} +} + +Event.prototype.on = function(eventType, fn) { + if (!this.obj[eventType]) { + this.obj[eventType] = [] + } + this.obj[eventType].push(fn) +} + +Event.prototype.emit = function() { + var eventType = Array.prototype.shift.call(arguments) + var arr = this.obj[eventType] + for (let i = 0; i < arr.length; i++) { + arr[i].apply(arr[i], arguments) + } +} + +var ev = new Event() + +ev.on('click', function(a) { // 订阅函数 + console.log(a) // 1 +}) + +ev.emit('click', 1) // 发布函数 +``` + +### 订阅函数逻辑一定要优先于发布函数吗 +考虑以下场景: +```js +$.ajax('', () => { + // 异步订阅函数逻辑 +}) + +// 在其他地方执行发布函数,此时并不能保证执行发布函数的时候,订阅函数已经执行 +``` +我们需要实现这样的逻辑: +```js +var ev = new Event() +ev.emit('click', 1) + +ev.on('click', function(a) { + console.log(a) // 1 +}) +``` +目标明确后,来着手实现它: +```js +var Event = function() { + this.obj = {} + this.cacheList = [] +} + +Event.prototype.on = function(eventType, fn) { + if (!this.obj[eventType]) { + this.obj[eventType] = [] + } + this.obj[eventType].push(fn) + + for (let i = 0; i < this.cacheList.length; i++) { + this.cacheList[i]() + } +} + +Event.prototype.emit = function() { + const arg = arguments + const that = this + function cache() { + var eventType = Array.prototype.shift.call(arg) + var arr = that.obj[eventType] + for (let i = 0; i < arr.length; i++) { + arr[i].apply(arr[i], arg) + } + } + this.cacheList.push(cache) +} +``` +以上代码实现思路就是把原本在 `emit` 里触发的函数存到 `cacheList`,再转交到 `on` 中触发。从而实现了发布函数先于订阅函数执行。 + +*** + +## 6.命令模式 +命令模式与策略模式有些类似,在 JavaScript 中它们都是隐式的。 +重要性:较低 +### JavaScript 中的命令模式 +命令模式在 JavaScript 中也比较简单,下面代码中对按钮和命令进行了抽离,因此可以复杂项目中可以使用命令模式将界面的代码和功能的代码交付给不同的人去写。 +```js +const setCommand = function(button, command) { + button.onClick = function() { + command.excute() + } +} + +// -------------------- 上面的界面逻辑由A完成,下面的由B完成 + +const menu = { + updateMenu: function() { + console.log('更新菜单') + }, +} + +const UpdateCommand = function(receive) { + return { + excute: receive.updateMenu, + } +} + +const updateCommand = UpdateCommand(menu) // 创建命令 + +const button1 = document.getElementById('button1') +setCommand(button1, updateCommand) +``` + +*** + +## 7.组合模式 +* 组合模式在对象间形成树形结构; +* 组合模式中基本对象和组合对象被一致对待; +* 无须关心对象有多少层,调用时只需在根部进行调用; + +### demo1 —— 宏命令 + +想象我们现在手上有个万能遥控器,当我们回家,按一下开关,下列事情将被执行: +1. 煮咖啡 +2. 打开电视、打开音响 +3. 打开空调、打开电脑 + +我们把任务划分为 3 类,效果图如下: +![任务划分](https://camo.githubusercontent.com/a44e97b789bd6e25d1aa13b15b12239c0566b015/687474703a2f2f6f71687473637573302e626b742e636c6f7564646e2e636f6d2f39633837636538333535313566336439623630613836613066323838393764392e6a70672d343030) +接着看看结合了命令模式和组合模式的具体实现: +```js +const MacroCommand = function() { + return { + lists: [], + add: function(task) { + this.lists.push(task) + }, + excute: function() { // ①:组合对象调用这里的 excute, + for (let i = 0; i < this.lists.length; i++) { + this.lists[i].excute() + } + }, + } +} + +const command1 = MacroCommand() // 基本对象 + +command1.add({ + excute: () => console.log('煮咖啡') // ②:基本对象调用这里的 excute, +}) + +const command2 = MacroCommand() // 组合对象 + +command2.add({ + excute: () => console.log('打开电视') +}) + +command2.add({ + excute: () => console.log('打开音响') +}) + +const command3 = MacroCommand() + +command3.add({ + excute: () => console.log('打开空调') +}) + +command3.add({ + excute: () => console.log('打开电脑') +}) + +const macroCommand = MacroCommand() +macroCommand.add(command1) +macroCommand.add(command2) +macroCommand.add(command3) + +macroCommand.excute() + +// 煮咖啡 +// 打开电视 +// 打开音响 +// 打开空调 +// 打开电脑 +``` + +可以看出在组合模式中基本对象和组合对象被一致对待,所以要保证基本对象(叶对象)和组合对象具有一致方法。 + +### demo2 —— 扫描文件夹 +扫描文件夹时,文件夹下面可以为另一个文件夹也可以为文件,我们希望统一对待这些文件夹和文件,这种情形适合使用组合模式。 +```js +const Folder = function(folder) { + this.folder = folder + this.lists = [] +} + +Folder.prototype.add = function(resource) { + this.lists.push(resource) +} + +Folder.prototype.scan = function() { + console.log('开始扫描文件夹:', this.folder) + for (let i = 0, folder; folder = this.lists[i++];) { + folder.scan() + } +} + +const File = function(file) { + this.file = file +} + +File.prototype.add = function() { + throw Error('文件下不能添加其它文件夹或文件') +} + +File.prototype.scan = function() { + console.log('开始扫描文件:', this.file) +} + +const folder = new Folder('根文件夹') +const folder1 = new Folder('JS') +const folder2 = new Folder('life') + +const file1 = new File('深入React技术栈.pdf') +const file2 = new File('JavaScript权威指南.pdf') +const file3 = new File('小王子.pdf') + +folder1.add(file1) +folder1.add(file2) + +folder2.add(file3) + +folder.add(folder1) +folder.add(folder2) + +folder.scan() + +// 开始扫描文件夹: 根文件夹 +// 开始扫描文件夹: JS +// 开始扫描文件: 深入React技术栈.pdf +// 开始扫描文件: JavaScript权威指南.pdf +// 开始扫描文件夹: life +// 开始扫描文件: 小王子.pdf +``` + +*** + + From 021a26a81074f07d5153e3326a4d76645feb240d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 18 May 2018 23:20:38 +0800 Subject: [PATCH 006/835] 2018.05.18 --- ...76\350\256\241\346\250\241\345\274\217.md" | 694 +++++++++++++++++- 1 file changed, 692 insertions(+), 2 deletions(-) diff --git "a/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" "b/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" index 4115fd94..1551a08f 100644 --- "a/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" +++ "b/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" @@ -14,7 +14,7 @@ * 中介者模式 * 装饰者模式 * 状态模式 -* 适配者模式 +* [适配者模式](#14) ### 各设计模式关键词 看完了上述设计模式后,把它们的关键词特点罗列出来,以后提到某种设计模式,进而联想相应的关键词和例子,从而心中有数。 @@ -431,7 +431,7 @@ setCommand(button1, updateCommand) 3. 打开空调、打开电脑 我们把任务划分为 3 类,效果图如下: -![任务划分](https://camo.githubusercontent.com/a44e97b789bd6e25d1aa13b15b12239c0566b015/687474703a2f2f6f71687473637573302e626b742e636c6f7564646e2e636f6d2f39633837636538333535313566336439623630613836613066323838393764392e6a70672d343030) +![任务划分](https://camo.githubusercontent.com/a44e97b789bd6e25d1aa13b15b12239c0566b015/687474703a2f2f6f71687473637573302e626b742e636c6f7564646e2e636f6d2f39633837636538333535313566336439623630613836613066323838393764392e6a70672d343030) 接着看看结合了命令模式和组合模式的具体实现: ```js const MacroCommand = function() { @@ -549,8 +549,698 @@ folder.scan() *** +## 8.模板方法模式 +> 定义:在继承的基础上,在父类中定义好执行的算法。 +### 泡茶和泡咖啡 +来对比下泡茶和泡咖啡过程中的异同 +|步骤 | 泡茶 | 泡咖啡| +|-|-|-| +|1 |烧开水 | 烧开水| +|2 |浸泡茶叶 | 冲泡咖啡| +|3 |倒入杯子 | 倒入杯子| +|4 |加柠檬 | 加糖| + +可以清晰地看出仅仅在步骤 2 和 4 上有细微的差别,下面着手实现: +```js +const Drinks = function() {} + +Drinks.prototype.firstStep = function() { + console.log('烧开水') +} + +Drinks.prototype.secondStep = function() {} + +Drinks.prototype.thirdStep = function() { + console.log('倒入杯子') +} + +Drinks.prototype.fourthStep = function() {} + +Drinks.prototype.init = function() { // 模板方法模式核心:在父类上定义好执行算法 + this.firstStep() + this.secondStep() + this.thirdStep() + this.fourthStep() +} + +const Tea = function() {} + +Tea.prototype = new Drinks + +Tea.prototype.secondStep = function() { + console.log('浸泡茶叶') +} + +Tea.prototype.fourthStep = function() { + console.log('加柠檬') +} + +const Coffee = function() {} + +Coffee.prototype = new Drinks + +Coffee.prototype.secondStep = function() { + console.log('冲泡咖啡') +} + +Coffee.prototype.fourthStep = function() { + console.log('加糖') +} + +const tea = new Tea() +tea.init() + +// 烧开水 +// 浸泡茶叶 +// 倒入杯子 +// 加柠檬 + +const coffee = new Coffee() +coffee.init() + +// 烧开水 +// 冲泡咖啡 +// 倒入杯子 +// 加糖 +``` + +### 钩子 +假如客人不想加佐料(糖、柠檬)怎么办,这时可以引人钩子来实现之,实现逻辑如下: +```js +// ... + +Drinks.prototype.ifNeedFlavour = function() { // 加上钩子 + return true +} + +Drinks.prototype.init = function() { // 模板方法模式核心:在父类上定义好执行算法 + this.firstStep() + this.secondStep() + this.thirdStep() + if (this.ifNeedFlavour()) { // 默认是 true,也就是要加调料 + this.fourthStep() + } +} + +// ... +const Coffee = function() {} + +Coffee.prototype = new Drinks() +// ... + +Coffee.prototype.ifNeedFlavour = function() { + return window.confirm('是否需要佐料吗?') // 弹框选择是否佐料 +} +``` + +*** + +## 9.享元模式 +享元模式是一种优化程序性能的模式,本质为减少对象创建的个数。 + +以下情况可以使用享元模式: +* 有大量相似的对象,占用了大量内存 +* 对象中大部分状态可以抽离为外部状态 + +### demo +某商家有 50 种男款内衣和 50 种款女款内衣,要展示它们 + +方案一:造 50 个塑料男模和 50 个塑料女模,让他们穿上展示,代码如下: +```js +const Model = function(gender, underwear) { + this.gender = gender + this.underwear = underwear +} + +Model.prototype.takephoto = function() { + console.log(`${this.gender}穿着${this.underwear}`) +} + +for (let i = 1; i < 51; i++) { + const maleModel = new Model('male', `第${i}款衣服`) + maleModel.takephoto() +} + +for (let i = 1; i < 51; i++) { + const female = new Model('female', `第${i}款衣服`) + female.takephoto() +} +``` + +方案二:造 1 个塑料男模特 1 个塑料女模特,分别试穿 50 款内衣 +```js +const Model = function(gender) { + this.gender = gender +} + +Model.prototype.takephoto = function() { + console.log(`${this.sex}穿着${this.underwear}`) +} + +const maleModel = new Model('male') +const femaleModel = new Model('female') + +for (let i = 1; i < 51; i++) { + maleModel.underwear = `第${i}款衣服` + maleModel.takephoto() +} + +for (let i = 1; i < 51; i++) { + femaleModel.underwear = `第${i}款衣服` + femaleModel.takephoto() +} +``` +对比发现:方案一创建了 100 个对象,方案二只创建了 2 个对象,在该 demo 中,gender(性别) 是内部对象,underwear(穿着) 是外部对象。 + +当然在方案二的 demo 中,还可以进一步改善: + +* 一开始就通过构造函数显示地创建实例,可用工场模式将其升级成可控生成 +* 在实例上手动添加 underwear 不是很优雅,可以在外部单独在写个 manager 函数 +```js +const Model = function(gender) { + this.gender = gender +} + +Model.prototype.takephoto = function() { + console.log(`${this.gender}穿着${this.underwear}`) +} + +const modelFactory = (function() { // 优化第一点 + const modelGender = {} + return { + createModel: function(gender) { + if (modelGender[gender]) { + return modelGender[gender] + } + return modelGender[gender] = new Model(gender) + } + } +}()) + +const modelManager = (function() { + const modelObj = {} + return { + add: function(gender, i) { + modelObj[i] = { + underwear: `第${i}款衣服` + } + return modelFactory.createModel(gender) + }, + copy: function(model, i) { // 优化第二点 + model.underwear = modelObj[i].underwear + } + } +}()) + +for (let i = 1; i < 51; i++) { + const maleModel = modelManager.add('male', i) + modelManager.copy(maleModel, i) + maleModel.takephoto() +} + +for (let i = 1; i < 51; i++) { + const femaleModel = modelManager.add('female', i) + modelManager.copy(femaleModel, i) + femaleModel.takephoto() +} +``` + +*** + +## 10.职责链模式 +职责链模式:类似多米诺骨牌,通过请求第一个条件,会持续执行后续的条件,直到返回结果为止。 +![职责链模式](https://camo.githubusercontent.com/cb2073f5e9c165843754e0b5984652c3291e88a6/687474703a2f2f6f71687473637573302e626b742e636c6f7564646e2e636f6d2f63626338633130626261653230326263643234336636623037303464653362612e6a70672d333030) +重要性:4 星,在项目中能对 if-else 语句进行优化 +### 场景 demo +场景:某电商针对已付过定金的用户有优惠政策,在正式购买后,已经支付过 500 元定金的用户会收到 100 元的优惠券,200 元定金的用户可以收到 50 元优惠券,没有支付过定金的用户只能正常购买。 +```js +// orderType: 表示订单类型,1:500 元定金用户;2:200 元定金用户;3:普通购买用户 +// pay:表示用户是否已经支付定金,true: 已支付;false:未支付 +// stock: 表示当前用于普通购买的手机库存数量,已支付过定金的用户不受此限制 + +const order = function( orderType, pay, stock ) { + if ( orderType === 1 ) { + if ( pay === true ) { + console.log('500 元定金预购,得到 100 元优惠券') + } else { + if (stock > 0) { + console.log('普通购买,无优惠券') + } else { + console.log('库存不够,无法购买') + } + } + } else if ( orderType === 2 ) { + if ( pay === true ) { + console.log('200 元定金预购,得到 50 元优惠券') + } else { + if (stock > 0) { + console.log('普通购买,无优惠券') + } else { + console.log('库存不够,无法购买') + } + } + } else if ( orderType === 3 ) { + if (stock > 0) { + console.log('普通购买,无优惠券') + } else { + console.log('库存不够,无法购买') + } + } +} + +order( 3, true, 500 ) // 普通购买,无优惠券 +``` + +下面用职责链模式改造代码: +```js +const order500 = function(orderType, pay, stock) { + if ( orderType === 1 && pay === true ) { + console.log('500 元定金预购,得到 100 元优惠券') + } else { + order200(orderType, pay, stock) + } +} + +const order200 = function(orderType, pay, stock) { + if ( orderType === 2 && pay === true ) { + console.log('200 元定金预购,得到 50 元优惠券') + } else { + orderCommon(orderType, pay, stock) + } +} + +const orderCommon = function(orderType, pay, stock) { + if (orderType === 3 && stock > 0) { + console.log('普通购买,无优惠券') + } else { + console.log('库存不够,无法购买') + } +} + +order500( 3, true, 500 ) // 普通购买,无优惠券 +``` + +改造后可以发现代码相对清晰了,但是链路代码和业务代码依然耦合在一起,进一步优化: +```js +// 业务代码 +const order500 = function(orderType, pay, stock) { + if ( orderType === 1 && pay === true ) { + console.log('500 元定金预购,得到 100 元优惠券') + } else { + return 'nextSuccess' + } +} + +const order200 = function(orderType, pay, stock) { + if ( orderType === 2 && pay === true ) { + console.log('200 元定金预购,得到 50 元优惠券') + } else { + return 'nextSuccess' + } +} +const orderCommon = function(orderType, pay, stock) { + if (orderType === 3 && stock > 0) { + console.log('普通购买,无优惠券') + } else { + console.log('库存不够,无法购买') + } +} + +// 链路代码 +const chain = function(fn) { + this.fn = fn + this.sucessor = null +} +chain.prototype.setNext = function(sucessor) { + this.sucessor = sucessor +} + +chain.prototype.init = function() { + const result = this.fn.apply(this, arguments) + if (result === 'nextSuccess') { + this.sucessor.init.apply(this.sucessor, arguments) + } +} + +const order500New = new chain(order500) +const order200New = new chain(order200) +const orderCommonNew = new chain(orderCommon) + +order500New.setNext(order200New) +order200New.setNext(orderCommonNew) + +order500New.init( 3, true, 500 ) // 普通购买,无优惠券 +``` + +重构后,链路代码和业务代码彻底地分离。假如未来需要新增 order300,那只需新增与其相关的函数而不必改动原有业务代码。 +另外结合 AOP 还能简化上述链路代码: +```js +// 业务代码 +const order500 = function(orderType, pay, stock) { + if ( orderType === 1 && pay === true ) { + console.log('500 元定金预购,得到 100 元优惠券') + } else { + return 'nextSuccess' + } +} + +const order200 = function(orderType, pay, stock) { + if ( orderType === 2 && pay === true ) { + console.log('200 元定金预购,得到 50 元优惠券') + } else { + return 'nextSuccess' + } +} + +const orderCommon = function(orderType, pay, stock) { + if (orderType === 3 && stock > 0) { + console.log('普通购买,无优惠券') + } else { + console.log('库存不够,无法购买') + } +} + +// 链路代码 +Function.prototype.after = function(fn) { + const self = this + return function() { + const result = self.apply(self, arguments) + if (result === 'nextSuccess') { + return fn.apply(self, arguments) // 这里 return 别忘记了~ + } + } +} + +const order = order500.after(order200).after(orderCommon) + +order( 3, true, 500 ) // 普通购买,无优惠券 +``` +职责链模式比较重要,项目中能用到它的地方会有很多,用上它能解耦 1 个请求对象和 n 个目标对象的关系。 + +*** + +## 11.中介者模式 +中介者模式:对象和对象之间借助第三方中介者进行通信。 +![中介者模式](https://camo.githubusercontent.com/8411d6ad7b3c4e4f4fa3a14115f33428f5e4ab0f/687474703a2f2f6f71687473637573302e626b742e636c6f7564646e2e636f6d2f61653039353866383539393039373863343862336136616132636137366561312e6a70672d343030) +### 场景 demo +一场测试结束后,公布结果:告知解答出题目的人挑战成功,否则挑战失败。 +```js +const player = function(name) { + this.name = name + playerMiddle.add(name) +} + +player.prototype.win = function() { + playerMiddle.win(this.name) +} + +player.prototype.lose = function() { + playerMiddle.lose(this.name) +} + +const playerMiddle = (function() { // 将就用下这个 demo,这个函数当成中介者 + const players = [] + const winArr = [] + const loseArr = [] + return { + add: function(name) { + players.push(name) + }, + win: function(name) { + winArr.push(name) + if (winArr.length + loseArr.length === players.length) { + this.show() + } + }, + lose: function(name) { + loseArr.push(name) + if (winArr.length + loseArr.length === players.length) { + this.show() + } + }, + show: function() { + for (let winner of winArr) { + console.log(winner + '挑战成功;') + } + for (let loser of loseArr) { + console.log(loser + '挑战失败;') + } + }, + } +}()) + +const a = new player('A 选手') +const b = new player('B 选手') +const c = new player('C 选手') + +a.win() +b.win() +c.lose() + +// A 选手挑战成功; +// B 选手挑战成功; +// C 选手挑战失败; +``` +在这段代码中 A、B、C 之间没有直接发生关系,而是通过另外的 playerMiddle 对象建立链接,姑且将之当成是中介者模式了。 + +*** + +## 12.装饰者模式 +装饰器模式:动态地给函数赋能。 + +### JavaScript 的装饰者模式 +生活中的例子:天气冷了,就添加衣服来保暖;天气热了,就将外套脱下;这个例子很形象地含盖了装饰器的神韵,随着天气的冷暖变化,衣服可以动态的穿上脱下。 +```js +let wear = function() { + console.log('穿上第一件衣服') +} + +const _wear1 = wear + +wear = function() { + _wear1() + console.log('穿上第二件衣服') +} + +const _wear2 = wear + +wear = function() { + _wear2() + console.log('穿上第三件衣服') +} + +wear() + +// 穿上第一件衣服 +// 穿上第二件衣服 +// 穿上第三件衣服 +``` + +这种方式有以下缺点:1:临时变量会变得越来越多;2:this 指向有时会出错 +### AOP 装饰函数 +```js +// 前置代码 +Function.prototype.before = function(fn) { + const self = this + return function() { + fn.apply(this, arguments) + return self.apply(this, arguments) + } +} + +// 后置代码 +Function.prototype.after = function(fn) { + const self = this + return function() { + self.apply(this, arguments) + return fn.apply(this, arguments) + } +} +``` +用后置代码来实验下上面穿衣服的 demo, +```js +const wear1 = function() { + console.log('穿上第一件衣服') +} + +const wear2 = function() { + console.log('穿上第二件衣服') +} + +const wear3 = function() { + console.log('穿上第三件衣服') +} + +const wear = wear1.after(wear2).after(wear3) +wear() + +// 穿上第一件衣服 +// 穿上第二件衣服 +// 穿上第三件衣服 +``` + +但这样子有时会污染原生函数,可以做点通变 +```js +const after = function(fn, afterFn) { + return function() { + fn.apply(this, arguments) + afterFn.apply(this, arguments) + } +} + +const wear = after(after(wear1, wear2), wear3) +wear() +``` + +*** + +## 13.状态模式 +状态模式:将事物内部的每个状态分别封装成类,内部状态改变会产生不同行为。 + +优点:用对象代替字符串记录当前状态,状态易维护 +缺点:需编写大量状态类对象 + +### 场景 demo +某某牌电灯,按一下按钮打开弱光,按两下按钮打开强光,按三下按钮关闭灯光。 +```js +// 将状态封装成不同类 +const weakLight = function(light) { + this.light = light +} + +weakLight.prototype.press = function() { + console.log('打开强光') + this.light.setState(this.light.strongLight) +} + +const strongLight = function(light) { + this.light = light +} + +strongLight.prototype.press = function() { + console.log('关灯') + this.light.setState(this.light.offLight) +} + +const offLight = function(light) { + this.light = light +} + +offLight.prototype.press = function() { + console.log('打开弱光') + this.light.setState(this.light.weakLight) +} + +const Light = function() { + this.weakLight = new weakLight(this) + this.strongLight = new strongLight(this) + this.offLight = new offLight(this) + this.currentState = this.offLight // 初始状态 +} + +Light.prototype.init = function() { + const btn = document.createElement('button') + btn.innerHTML = '按钮' + document.body.append(btn) + const self = this + btn.addEventListener('click', function() { + self.currentState.press() + }) +} + +Light.prototype.setState = function(state) { // 改变当前状态 + this.currentState = state +} + +const light = new Light() +light.init() + +// 打开弱光 +// 打开强光 +// 关灯 +``` + +### 非面向对象实现的状态模式 +借助于 JavaScript 的委托机制,可以像如下实现状态模式: +```js +const obj = { + 'weakLight': { + press: function() { + console.log('打开强光') + this.currentState = obj.strongLight + } + }, + 'strongLight': { + press: function() { + console.log('关灯') + this.currentState = obj.offLight + } + }, + 'offLight': { + press: function() { + console.log('打开弱光') + this.currentState = obj.weakLight + } + }, +} + +const Light = function() { + this.currentState = obj.offLight +} + +Light.prototype.init = function() { + const btn = document.createElement('button') + btn.innerHTML = '按钮' + document.body.append(btn) + const self = this + btn.addEventListener('click', function() { + self.currentState.press.call(self) // 通过 call 完成委托 + }) +} + +const light = new Light() +light.init() +``` + +*** + +## 14.适配者模式{#14} +适配者模式:主要用于解决两个接口之间不匹配的问题。 +### demo +```js +// 老接口 +const zhejiangCityOld = (function() { + return [ + { + name: 'hangzhou', + id: 11, + }, + { + name: 'jinhua', + id: 12 + } + ] +}()) + +console.log(getZhejiangCityOld()) + +// 新接口希望是下面形式 +{ + hangzhou: 11, + jinhua: 12, +} + +// 这时候就可采用适配者模式 +const const adaptor = (function(oldCity) { + const obj = {} + for (let city of zhejiangCityOld) { + obj[city.name] = city.id + } + return obj +}()) +``` > 原文地址 [JavaScript 中常见设计模式整理](https://juejin.im/post/5afe6430518825428630bc4d) \ No newline at end of file From a242e72c5a1b524926bfb39b47a9ff479717cb31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 18 May 2018 23:22:56 +0800 Subject: [PATCH 007/835] 2018.05.18 --- ...\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" "b/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" index 1551a08f..7f497479 100644 --- "a/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" +++ "b/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" @@ -1206,7 +1206,7 @@ light.init() *** -## 14.适配者模式{#14} +## 14.适配者模式 适配者模式:主要用于解决两个接口之间不匹配的问题。 ### demo ```js From 8442c5f12f86340e0a5a22f4ce97a91c2d5bed21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 18 May 2018 23:25:18 +0800 Subject: [PATCH 008/835] 2018.05.18 --- ...47\201\350\256\276\350\256\241\346\250\241\345\274\217.md" | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git "a/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" "b/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" index 7f497479..895f28d6 100644 --- "a/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" +++ "b/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" @@ -14,7 +14,7 @@ * 中介者模式 * 装饰者模式 * 状态模式 -* [适配者模式](#14) +* [适配者模式](#title14) ### 各设计模式关键词 看完了上述设计模式后,把它们的关键词特点罗列出来,以后提到某种设计模式,进而联想相应的关键词和例子,从而心中有数。 @@ -1206,7 +1206,7 @@ light.init() *** -## 14.适配者模式 +## 14.适配者模式 适配者模式:主要用于解决两个接口之间不匹配的问题。 ### demo ```js From 800f812be835765f99fc6a89b3dfcd0f36b0c071 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 18 May 2018 23:27:40 +0800 Subject: [PATCH 009/835] 2018.05.18 --- ...47\201\350\256\276\350\256\241\346\250\241\345\274\217.md" | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git "a/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" "b/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" index 895f28d6..36309afa 100644 --- "a/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" +++ "b/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" @@ -14,7 +14,7 @@ * 中介者模式 * 装饰者模式 * 状态模式 -* [适配者模式](#title14) +* 适配者模式 ### 各设计模式关键词 看完了上述设计模式后,把它们的关键词特点罗列出来,以后提到某种设计模式,进而联想相应的关键词和例子,从而心中有数。 @@ -1206,7 +1206,7 @@ light.init() *** -## 14.适配者模式 +## 14.适配者模式 适配者模式:主要用于解决两个接口之间不匹配的问题。 ### demo ```js From 89a3e3f7caf875a3d052dacd227236980fafcaaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 18 May 2018 23:28:43 +0800 Subject: [PATCH 010/835] 2018.05.18 --- ...\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" "b/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" index 36309afa..da956cc5 100644 --- "a/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" +++ "b/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" @@ -1206,7 +1206,7 @@ light.init() *** -## 14.适配者模式 +## 14.适配者模式 适配者模式:主要用于解决两个接口之间不匹配的问题。 ### demo ```js From 3c6959e6b67c1c24a87de240a28ec88211d1208f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 18 May 2018 23:30:37 +0800 Subject: [PATCH 011/835] 2018.05.18 --- ...\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" "b/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" index da956cc5..98712d9f 100644 --- "a/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" +++ "b/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" @@ -1206,7 +1206,7 @@ light.init() *** -## 14.适配者模式 +## 14.适配者模式 适配者模式:主要用于解决两个接口之间不匹配的问题。 ### demo ```js From 374c2d88a341381aacf06c038d066e40d8b96b14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 18 May 2018 23:35:14 +0800 Subject: [PATCH 012/835] 2018.05.18 --- ...76\350\256\241\346\250\241\345\274\217.md" | 53 +++++++++---------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git "a/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" "b/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" index 98712d9f..1db24aef 100644 --- "a/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" +++ "b/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" @@ -1,19 +1,19 @@ 开发中,我们或多或少地接触了设计模式,但是很多时候不知道自己使用了哪种设计模式或者说该使用何种设计模式。本文意在梳理常见设计模式的特点,从而对它们有比较清晰的认知。 ### JavaScript 中常见设计模式 -* 单例模式 -* 策略模式 -* 代理模式 -* 迭代器模式 -* 发布-订阅模式 -* 命令模式 -* 组合模式 -* 模板方法模式 -* 享元模式 -* 职责链模式 -* 中介者模式 -* 装饰者模式 -* 状态模式 +* 单例模式 +* 策略模式 +* 代理模式 +* 迭代器模式 +* 发布-订阅模式 +* 命令模式 +* 组合模式 +* 模板方法模式 +* 享元模式 +* 职责链模式 +* 中介者模式 +* 装饰者模式 +* 状态模式 * 适配者模式 ### 各设计模式关键词 @@ -37,7 +37,7 @@ |适配者模式|一种数据结构改成另一种数据结构|枚举值接口变更| -## 1.单例模式 +## 1.单例模式 ### 两个条件 * 确保只有一个实例 * 可以全局访问 @@ -102,7 +102,7 @@ document.getElementById('loginBtn').onclick = function() { *** -## 2.策略模式 +## 2.策略模式 > 定义:根据不同参数可以命中不同的策略 ### JavaScript 中的策略模式 @@ -152,7 +152,7 @@ calculateBonus(A, 10000) // 30000 *** -## 3.代理模式 +## 3.代理模式 情景:小明追女生 A * 非代理模式:小明 =花=> 女生A * 代理模式:小明 =花=> 让女生A的好友B帮忙 =花=> 女生A @@ -220,7 +220,7 @@ proxyMult(1, 2, 3, 4) // 24 *** -## 4.迭代器模式 +## 4.迭代器模式 > 定义:能访问到聚合对象的顺序与元素 ### 实现一个内部迭代器 ```js @@ -295,8 +295,7 @@ compare(iterator1, iterator2) *** -## 5.发布订阅模式 - +## 5.发布订阅模式 事件发布/订阅模式 (PubSub) 在异步编程中帮助我们完成更松的解耦,甚至在 MVC、MVVC 的架构中以及设计模式中也少不了发布-订阅模式的参与。 优点:在异步编程中实现更深的解耦 缺点:如果过多的使用发布订阅模式,会增加维护的难度 @@ -384,7 +383,7 @@ Event.prototype.emit = function() { *** -## 6.命令模式 +## 6.命令模式 命令模式与策略模式有些类似,在 JavaScript 中它们都是隐式的。 重要性:较低 ### JavaScript 中的命令模式 @@ -418,7 +417,7 @@ setCommand(button1, updateCommand) *** -## 7.组合模式 +## 7.组合模式 * 组合模式在对象间形成树形结构; * 组合模式中基本对象和组合对象被一致对待; * 无须关心对象有多少层,调用时只需在根部进行调用; @@ -549,7 +548,7 @@ folder.scan() *** -## 8.模板方法模式 +## 8.模板方法模式 > 定义:在继承的基础上,在父类中定义好执行的算法。 ### 泡茶和泡咖啡 来对比下泡茶和泡咖啡过程中的异同 @@ -655,7 +654,7 @@ Coffee.prototype.ifNeedFlavour = function() { *** -## 9.享元模式 +## 9.享元模式 享元模式是一种优化程序性能的模式,本质为减少对象创建的个数。 以下情况可以使用享元模式: @@ -767,7 +766,7 @@ for (let i = 1; i < 51; i++) { *** -## 10.职责链模式 +## 10.职责链模式 职责链模式:类似多米诺骨牌,通过请求第一个条件,会持续执行后续的条件,直到返回结果为止。 ![职责链模式](https://camo.githubusercontent.com/cb2073f5e9c165843754e0b5984652c3291e88a6/687474703a2f2f6f71687473637573302e626b742e636c6f7564646e2e636f6d2f63626338633130626261653230326263643234336636623037303464653362612e6a70672d333030) 重要性:4 星,在项目中能对 if-else 语句进行优化 @@ -941,7 +940,7 @@ order( 3, true, 500 ) // 普通购买,无优惠券 *** -## 11.中介者模式 +## 11.中介者模式 中介者模式:对象和对象之间借助第三方中介者进行通信。 ![中介者模式](https://camo.githubusercontent.com/8411d6ad7b3c4e4f4fa3a14115f33428f5e4ab0f/687474703a2f2f6f71687473637573302e626b742e636c6f7564646e2e636f6d2f61653039353866383539393039373863343862336136616132636137366561312e6a70672d343030) ### 场景 demo @@ -1007,7 +1006,7 @@ c.lose() *** -## 12.装饰者模式 +## 12.装饰者模式 装饰器模式:动态地给函数赋能。 ### JavaScript 的装饰者模式 @@ -1096,7 +1095,7 @@ wear() *** -## 13.状态模式 +## 13.状态模式 状态模式:将事物内部的每个状态分别封装成类,内部状态改变会产生不同行为。 优点:用对象代替字符串记录当前状态,状态易维护 From b1c35a7d0f4b07d142c5113fa706cf8d39cbc9a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 18 May 2018 23:42:14 +0800 Subject: [PATCH 013/835] 2018.05.18 --- ...0\256\276\350\256\241\346\250\241\345\274\217.md" | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git "a/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" "b/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" index 1db24aef..b1578d37 100644 --- "a/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" +++ "b/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" @@ -550,14 +550,16 @@ folder.scan() ## 8.模板方法模式 > 定义:在继承的基础上,在父类中定义好执行的算法。 +> ### 泡茶和泡咖啡 来对比下泡茶和泡咖啡过程中的异同 -|步骤 | 泡茶 | 泡咖啡| + +|步骤|泡茶|泡咖啡| |-|-|-| -|1 |烧开水 | 烧开水| -|2 |浸泡茶叶 | 冲泡咖啡| -|3 |倒入杯子 | 倒入杯子| -|4 |加柠檬 | 加糖| +|1|烧开水|烧开水| +|2|浸泡茶叶|冲泡咖啡| +|3|倒入杯子|倒入杯子| +|4|加柠檬|加糖| 可以清晰地看出仅仅在步骤 2 和 4 上有细微的差别,下面着手实现: ```js From 5fc8ad335f1e1c8d3895888b43dc40249300771d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 21 May 2018 22:50:50 +0800 Subject: [PATCH 014/835] 2018.05.21 --- ...17\350\256\256\347\237\245\350\257\206.md" | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 "39-\344\275\234\344\270\272\345\211\215\347\253\257\351\234\200\350\246\201\344\272\206\350\247\243\347\232\204\345\274\200\346\272\220\345\215\217\350\256\256\347\237\245\350\257\206.md" diff --git "a/39-\344\275\234\344\270\272\345\211\215\347\253\257\351\234\200\350\246\201\344\272\206\350\247\243\347\232\204\345\274\200\346\272\220\345\215\217\350\256\256\347\237\245\350\257\206.md" "b/39-\344\275\234\344\270\272\345\211\215\347\253\257\351\234\200\350\246\201\344\272\206\350\247\243\347\232\204\345\274\200\346\272\220\345\215\217\350\256\256\347\237\245\350\257\206.md" new file mode 100644 index 00000000..6df635aa --- /dev/null +++ "b/39-\344\275\234\344\270\272\345\211\215\347\253\257\351\234\200\350\246\201\344\272\206\350\247\243\347\232\204\345\274\200\346\272\220\345\215\217\350\256\256\347\237\245\350\257\206.md" @@ -0,0 +1,91 @@ + 作为前端工程师,开发中在所难免会用到一些开源框架,而每个框架都有自己的开源协议,每个开源协议之间有什么差别呢? 如果你要开源一个项目,又应该选择哪种开源协议呢? + 许多开发者,对于开源协议的认知很少,本文从这些常用的前端框架入手,介绍开源常用开源协议的基础知识。 + +### 什么是开源协议? +根据 [开源协议](https://en.wikipedia.org/wiki/Open-source_license) 在维基百科的定义: +> 开源许可是一种计算机软件和其他产品的许可类型,允许使用、修改或在定义的条款和条件下使用、修改或共享的源代码、蓝图和设计。这允许终端用户和商业公司对源代码、图纸或设计进行审查和修改,以满足自己的定制、好奇心或故障排除的需要。开源许可的软件大多是免费的,尽管这并不一定是必须的。许可证只允许非商业的重新分配或修改个人使用的源代码,通常不被认为是开源许可。然而,开源许可可能会有一些限制,尤其是对软件的起源的表达,比如要求保留作者的名字和代码中的版权声明,或要求重新分配授权软件只有在相同的许可(如copyleft许可证)。一组流行的开源软件许可证是由开源计划(OSI)根据其开源定义(OSD)批准的。 + + +### 为什么要选用开源协议? +在 [GcsSloop](http://www.gcssloop.com/) 写的文章 [程序员不可不知的版权协议](http://www.gcssloop.com/tips/choose-license) 中给出了很好的概括。 +* 首先是对作者的保护,防止知识成果被恶意利用。开源协议中一般都包含免责声明(禁止代码的作者承担代码被使用后产生的风险及后果),比如你开源了一个破解智能锁的代码,如果有人利用这个去盗窃导致他人损失,你是无需承担责任的。 +* 其次是对使用者的保护,方便使用者。使用者一看就知道自己允许进行哪些操作,不允许进行哪些操作。未添加协议的代码默认是作者保留所有权利的(对此不同国家的法律可能稍微存在区别),这就像一颗定时炸弹,如果你在项目中使用了这一份没有协议的代码,原作者只要能证明你未经许可使用了他的代码,是能够起诉你的。 + +### 当前主流开源许可证(GPL、BSD、MIT、Mozilla、Apache、LGPL)和它们的异同? +![当前主流开源许可证](https://pic2.zhimg.com/80/v2-1c76c3c63f4db1727ebe07815423f3b7_hd.jpg) +相关概念解析: +> * 协议和版权信息(License and copyright notice):在代码中保留作者提供的协议和版权信息 +> * 声明变更(State Changes):在代码中声明对原来代码的重大修改及变更 +> * 公开源码(Disclose Source):代码必需公开。如果是基于LGPL协议 下,则只需使用的开源代码公开,不必将整个软件源码公开 +> * 库引用(Library usage):该库可以用于商业软件中 +> * 责任承担(Hold Liable):代码的作者承担代码使用后的风险及产生的后果 +> * 商标使用(Use Trademark):可以使用作者的姓名,作品的Logo,或商标 +> * 附加协议(Sublicensing):允许在软件分发传播过程中附加上原来没有的协议条款等 + + +### 当前前端主流框架选取的开源协议 +纵观比较常用的前端框架,用的最广泛的便是 MIT 开源协议。 +> * Vue: MIT [点击阅读](https://github.com/vuejs/vue/blob/dev/LICENSE ) +> * React:MIT [点击阅读]( https://github.com/facebook/react/blob/master/LICENSE) +> * Element: MIT [点击阅读](https://github.com/ElemeFE/element/blob/master/LICENSE ) +> * Ant Design:MIT [点击阅读](https://github.com/ant-design/ant-design/blob/master/LICENSE ) + + 列举的框架开源协议都是 MIT 。那么为什么选择 MIT 呢? + MIT是一种简短而简单的许可,只需要保留版权和许可通知。许可的作品、修改和更大的作品可以在不同的条件下分发,并且没有源代码。MIT允许别人用作者的代码做任何事情,但必须保证作者的所有权,并且作者无须承担代码使用产生的风险。 + 其中,要重点说一下 React 的开源协议,从 github 的提交历史来看,React 的开源协议经历了一个动荡的过程。从 LICENCE 的提交历史看,Facebook 对专利的重视程度可见一斑。 +![React的开源协议](https://pic2.zhimg.com/80/v2-3d9fea33d17605fefe04d121b0a55b4d_hd.jpg) + 去年知乎上一个《如何看待百度要求内部全面停止使用 React / React Native?》的文章引起了前端界的热议,事情的起因是大家发现了 Facebook 专利许可证上的描述暗藏玄机。在技术开源的世界,对于开发者而言,许可证就是他们使用开源软件的 “用户协议”。而 Facebook 的开源方式跟其他家都不太一样,别家一般用的都是开源社区公认通用的许可证,而 Facebook 使用的是两个许可证,第一个是通用的 BSD 许可证,第二个是自己写的专利许可证 (patent grant)。 +而在 React 的开源协议中这么写到: +![ React 的开源协议](https://pic4.zhimg.com/80/v2-a04b940e9f42b1c9801b2612d04a6bee_hd.jpg) +意思就是: +当发生下列情况时,facebook 有权益吊销你的 React 使用权: +> * 与 facebook 及其附属机构发生利益冲突 +> * 同任何一个和 facebook 有关的组织发生了法律纠纷 +> * 同任何与 React 有关的组织发生利益冲突 + + +翻译成大白话就是:如果你觉得 Facebook 侵犯了你的知识产权,同时你的核心产品是基于 React 实现,如果你想起诉 Facebook,就要权衡一下了,因为根据条款它有权利吊销你的 React 使用权。或者说你用 React 做了一个产品并且在某些领域对 Facebook 构成了利益冲突,那么它就可以强制你的产品下线。 + +可以说,一旦你开始使用 React 去构建你的核心产品,你的公司就被 facebook 埋下了一颗定时炸弹,并且,炸弹的引爆按钮就握在 facebook 手中。 + +其实这种事情,从去年就在前端技术圈开吵,后来愈演愈烈,形势每况日下:开源社区在更多 Facebook 开源的热门项目中发现了相同的许可证模式和条款。开发者认为 Facebook 的这种许可证模式正在毒害社区,污染开源精神。而且 Apache 软件基金会宣布所有使用 Apache 开源协议的软件都不得使用带有 Facebook BSD + 专利许可证模式的组件。 + +不过 Facebook 最后还是意识到了这些问题,修改了开源协议。 +![Facebook开源协议](https://pic2.zhimg.com/80/v2-6809df1f7f8a7915a3f8909a5b9cff5d_hd.jpg) + +### 如何为我们的项目选择一个开源协议? +首先,我们要清楚我们选择开源的目的是什么? + 作为个人,在开源的情况下,我们可以帮助他人,也可以获得他人的帮助,还是一个提升个人代码质量的好方法,同样,也是一个展示自己能力的好方法。世界上开源软件协议的种类非常之多,并且同一款协议有很多变种,协议太宽松会导致作者丧失对作品的很多权利,太严格又不便于使用者使用及作品的传播,所以开源作者要考虑自己对作品想保留哪些权利,放开哪些限制。 + 作为公司,代码开源后,会提升公司的地位,树立一个良好的品牌形象,也可以帮助公司发掘潜在员工。 +那么,我们如何选择适合我们的开源许可证呢? + +由一张图直观了解如何选取所需要的开源许可证。(原著:乌克兰程序员Paul Bagwell,翻译:阮一峰) +![开源许可证](https://pic4.zhimg.com/80/v2-253a7b1819e2af555ed0a7e0f11a0b59_hd.jpg) + +举例来说: + 如果我只是想专心的写代码,那么可以选择 MIT ,MIT在保证了作者的所有权的前提下允许别人使用作者的代码,且作者不需要承担使用时的风险。如果我想保护我的代码、专利,那么可以选择 Apache ,Apache 与 MIT 的区别就是提供了专利贡献者的授权,使用者需要明确这一点。 + +Github 专门发布了一个网站 [Choosing an OSS license doesn’t need to be scary](https://choosealicense.com/) 来帮助开源项目开发者。 + +> * 我想要一个简单宽松的许可证建议: MIT 许可证。这是一个宽松的、简明扼要的许可证,只要用户在项目副本中包含了版权声明和许可声明,他们就可以拿你的代码做任何想做的事情,你也无需承担任何责任。 +> 使用该许可证的项目:jQuery、Rails +> * 我比较关心专利 +> 建议: Apache许可证。这类似于 MIT 许可证,但它同时还包含了贡献者向用户提供专利授权相关的条款。 +> 使用该许可证的项目:Apache、SVN和NuGet +> * 我关心项目的共享改进 +> 建议:GPL( V2或 V3)许可证。这是一种 copyleft 许可证,要求修改项目代码的用户再次分发源码或二进制代码时,必须公布他的相关修改。V3版本与V2类>似,但其进一步约束了在某些限制软件更改的硬件上的使用范围。 +> 使用该许可证的项目:Linux、Git +> * 我的开源项目不是代码 +> 建议: Creative Commons。这是一个相对宽松的版权协议。它只保留几种了权利(some rights reserved)。使用者可以明确知道所有者的权利,不容易侵犯对>方的版权,作品可以得到有效传播。作为作者,你可以选择以下1~4种权利组合: +> 1) 署名(Attribution,简写为BY):必须提到原作者。 +> 2) 非商业用途(Noncommercial,简写为NC):不得用于盈利性目的。 +> 3) 禁止演绎(No Derivative Works,简写为ND):不得修改原作品, 不得再创作。 +> 4) 相同方式共享(Share Alike,简写为SA):允许修改原作品,但必须使用相同的许可证发布。 +> * 更多选择 +> Licenses - [http://ChooseALicense.com](https://choosealicense.com/),这里提供了Apache/ GPL/ MIT/ Artistic/ Eclipse/ BSD/ LGPL/ Mozilla/ No License/ Public Domain >Dedication 协议的适用情形、许可内容、禁止内容,及协议全文。 + + + + + +> [作为前端,你需要了解的开源协议知识](https://zhuanlan.zhihu.com/p/35876146) \ No newline at end of file From 106d851a781c2d1900f7aae979e05a6d843630ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 21 May 2018 22:55:23 +0800 Subject: [PATCH 015/835] 2018.05.21 --- ...17\350\256\256\347\237\245\350\257\206.md" | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git "a/39-\344\275\234\344\270\272\345\211\215\347\253\257\351\234\200\350\246\201\344\272\206\350\247\243\347\232\204\345\274\200\346\272\220\345\215\217\350\256\256\347\237\245\350\257\206.md" "b/39-\344\275\234\344\270\272\345\211\215\347\253\257\351\234\200\350\246\201\344\272\206\350\247\243\347\232\204\345\274\200\346\272\220\345\215\217\350\256\256\347\237\245\350\257\206.md" index 6df635aa..6f52b951 100644 --- "a/39-\344\275\234\344\270\272\345\211\215\347\253\257\351\234\200\350\246\201\344\272\206\350\247\243\347\232\204\345\274\200\346\272\220\345\215\217\350\256\256\347\237\245\350\257\206.md" +++ "b/39-\344\275\234\344\270\272\345\211\215\347\253\257\351\234\200\350\246\201\344\272\206\350\247\243\347\232\204\345\274\200\346\272\220\345\215\217\350\256\256\347\237\245\350\257\206.md" @@ -84,8 +84,25 @@ Github 专门发布了一个网站 [Choosing an OSS license doesn’t need to be > * 更多选择 > Licenses - [http://ChooseALicense.com](https://choosealicense.com/),这里提供了Apache/ GPL/ MIT/ Artistic/ Eclipse/ BSD/ LGPL/ Mozilla/ No License/ Public Domain >Dedication 协议的适用情形、许可内容、禁止内容,及协议全文。 - - - - -> [作为前端,你需要了解的开源协议知识](https://zhuanlan.zhihu.com/p/35876146) \ No newline at end of file +### 如何为代码添加开源协议? +#### GitHub +1. 首先需要注册一个 GitHub 账号,并登录 +2. 在 GitHub 上选择创建一个新的 repository +![GitHub](https://pic4.zhimg.com/80/v2-5ab3d4f220e6524d445135c029014fe6_hd.jpg) +3. 进入创建 repository 页面后,输入基本信息后,点击右下角的 Add a license 选择开源协议,默认是 none。对应的 license 可以直接选择,也可以输入自己想要的 license +![GitHub](https://pic4.zhimg.com/80/v2-fb3c51c8d10b9767792603877e32ec65_hd.jpg) +![GitHub](https://pic1.zhimg.com/80/v2-209460d2fa43ea984f1f19de8606be3e_hd.jpg) + +4. 点击最下方 Create repository,就创建成功了。 +5. 创建成功后,代码库中就可以看到自动生成了一个 LICENSE 文件。 + +### 参考文献 +> [选择一个开源软件协议](http://choosealicense.online/) +> [程序员不可不知的版权协议](http://www.gcssloop.com/tips/choose-license) +> [开源许可证都有什么区别,一般开源项目用什么许可证?](https://www.zhihu.com/question/28292322) +> [都在封杀 React/React Native ,那我到底还该不该继续学呢?](https://zhuanlan.zhihu.com/p/29492362) +> [React开源协议之争知多少?](https://cauu.github.io/2017/09/React-Opensource-license/) +> [how to choose a license](https://www.cnblogs.com/Wayou/p/how_to_choose_a_license.html) + + +> [原文地址](https://zhuanlan.zhihu.com/p/35876146) \ No newline at end of file From 949450099a5b49407673b4bc7ebcae9eea9253fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 21 May 2018 23:01:25 +0800 Subject: [PATCH 016/835] 2018.05.21 --- ...17\350\256\256\347\237\245\350\257\206.md" | 104 +++++++++--------- README.md | 6 +- 2 files changed, 58 insertions(+), 52 deletions(-) diff --git "a/39-\344\275\234\344\270\272\345\211\215\347\253\257\351\234\200\350\246\201\344\272\206\350\247\243\347\232\204\345\274\200\346\272\220\345\215\217\350\256\256\347\237\245\350\257\206.md" "b/39-\344\275\234\344\270\272\345\211\215\347\253\257\351\234\200\350\246\201\344\272\206\350\247\243\347\232\204\345\274\200\346\272\220\345\215\217\350\256\256\347\237\245\350\257\206.md" index 6f52b951..8345ff42 100644 --- "a/39-\344\275\234\344\270\272\345\211\215\347\253\257\351\234\200\350\246\201\344\272\206\350\247\243\347\232\204\345\274\200\346\272\220\345\215\217\350\256\256\347\237\245\350\257\206.md" +++ "b/39-\344\275\234\344\270\272\345\211\215\347\253\257\351\234\200\350\246\201\344\272\206\350\247\243\347\232\204\345\274\200\346\272\220\345\215\217\350\256\256\347\237\245\350\257\206.md" @@ -1,9 +1,13 @@ - 作为前端工程师,开发中在所难免会用到一些开源框架,而每个框架都有自己的开源协议,每个开源协议之间有什么差别呢? 如果你要开源一个项目,又应该选择哪种开源协议呢? - 许多开发者,对于开源协议的认知很少,本文从这些常用的前端框架入手,介绍开源常用开源协议的基础知识。 +* 作为前端工程师,开发中在所难免会用到一些开源框架,而每个框架都有自己的开源协议,每个开源协议之间有什么差别呢? 如果你要开源一个项目,又应该选择哪种开源协议呢? +* 许多开发者,对于开源协议的认知很少,本文从这些常用的前端框架入手,介绍开源常用开源协议的基础知识。 ### 什么是开源协议? 根据 [开源协议](https://en.wikipedia.org/wiki/Open-source_license) 在维基百科的定义: -> 开源许可是一种计算机软件和其他产品的许可类型,允许使用、修改或在定义的条款和条件下使用、修改或共享的源代码、蓝图和设计。这允许终端用户和商业公司对源代码、图纸或设计进行审查和修改,以满足自己的定制、好奇心或故障排除的需要。开源许可的软件大多是免费的,尽管这并不一定是必须的。许可证只允许非商业的重新分配或修改个人使用的源代码,通常不被认为是开源许可。然而,开源许可可能会有一些限制,尤其是对软件的起源的表达,比如要求保留作者的名字和代码中的版权声明,或要求重新分配授权软件只有在相同的许可(如copyleft许可证)。一组流行的开源软件许可证是由开源计划(OSI)根据其开源定义(OSD)批准的。 +> 开源许可是一种计算机软件和其他产品的许可类型,允许使用、修改或在定义的条款和条件下使用、修改或共享的源代码、蓝图和设计。 +> 这允许终端用户和商业公司对源代码、图纸或设计进行审查和修改,以满足自己的定制、好奇心或故障排除的需要。 +> 开源许可的软件大多是免费的,尽管这并不一定是必须的。许可证只允许非商业的重新分配或修改个人使用的源代码,通常不被认为是开源许可。 +> 然而,开源许可可能会有一些限制,尤其是对软件的起源的表达,比如要求保留作者的名字和代码中的版权声明,或要求重新分配授权软件只有在相同的许可(如copyleft许可证)。 +> 一组流行的开源软件许可证是由开源计划(OSI)根据其开源定义(OSD)批准的。 ### 为什么要选用开源协议? @@ -14,33 +18,33 @@ ### 当前主流开源许可证(GPL、BSD、MIT、Mozilla、Apache、LGPL)和它们的异同? ![当前主流开源许可证](https://pic2.zhimg.com/80/v2-1c76c3c63f4db1727ebe07815423f3b7_hd.jpg) 相关概念解析: -> * 协议和版权信息(License and copyright notice):在代码中保留作者提供的协议和版权信息 -> * 声明变更(State Changes):在代码中声明对原来代码的重大修改及变更 -> * 公开源码(Disclose Source):代码必需公开。如果是基于LGPL协议 下,则只需使用的开源代码公开,不必将整个软件源码公开 -> * 库引用(Library usage):该库可以用于商业软件中 -> * 责任承担(Hold Liable):代码的作者承担代码使用后的风险及产生的后果 -> * 商标使用(Use Trademark):可以使用作者的姓名,作品的Logo,或商标 +> * 协议和版权信息(License and copyright notice):在代码中保留作者提供的协议和版权信息 +> * 声明变更(State Changes):在代码中声明对原来代码的重大修改及变更 +> * 公开源码(Disclose Source):代码必需公开。如果是基于LGPL协议 下,则只需使用的开源代码公开,不必将整个软件源码公开 +> * 库引用(Library usage):该库可以用于商业软件中 +> * 责任承担(Hold Liable):代码的作者承担代码使用后的风险及产生的后果 +> * 商标使用(Use Trademark):可以使用作者的姓名,作品的Logo,或商标 > * 附加协议(Sublicensing):允许在软件分发传播过程中附加上原来没有的协议条款等 ### 当前前端主流框架选取的开源协议 纵观比较常用的前端框架,用的最广泛的便是 MIT 开源协议。 -> * Vue: MIT [点击阅读](https://github.com/vuejs/vue/blob/dev/LICENSE ) -> * React:MIT [点击阅读]( https://github.com/facebook/react/blob/master/LICENSE) -> * Element: MIT [点击阅读](https://github.com/ElemeFE/element/blob/master/LICENSE ) -> * Ant Design:MIT [点击阅读](https://github.com/ant-design/ant-design/blob/master/LICENSE ) - - 列举的框架开源协议都是 MIT 。那么为什么选择 MIT 呢? - MIT是一种简短而简单的许可,只需要保留版权和许可通知。许可的作品、修改和更大的作品可以在不同的条件下分发,并且没有源代码。MIT允许别人用作者的代码做任何事情,但必须保证作者的所有权,并且作者无须承担代码使用产生的风险。 - 其中,要重点说一下 React 的开源协议,从 github 的提交历史来看,React 的开源协议经历了一个动荡的过程。从 LICENCE 的提交历史看,Facebook 对专利的重视程度可见一斑。 +> * Vue: MIT [点击阅读](https://github.com/vuejs/vue/blob/dev/LICENSE ) +> * React:MIT [点击阅读]( https://github.com/facebook/react/blob/master/LICENSE) +> * Element: MIT [点击阅读](https://github.com/ElemeFE/element/blob/master/LICENSE ) +> * Ant Design:MIT [点击阅读](https://github.com/ant-design/ant-design/blob/master/LICENSE ) + +列举的框架开源协议都是 MIT 。那么为什么选择 MIT 呢? +MIT是一种简短而简单的许可,只需要保留版权和许可通知。许可的作品、修改和更大的作品可以在不同的条件下分发,并且没有源代码。MIT允许别人用作者的代码做任何事情,但必须保证作者的所有权,并且作者无须承担代码使用产生的风险。 +其中,要重点说一下 React 的开源协议,从 github 的提交历史来看,React 的开源协议经历了一个动荡的过程。从 LICENCE 的提交历史看,Facebook 对专利的重视程度可见一斑。 ![React的开源协议](https://pic2.zhimg.com/80/v2-3d9fea33d17605fefe04d121b0a55b4d_hd.jpg) - 去年知乎上一个《如何看待百度要求内部全面停止使用 React / React Native?》的文章引起了前端界的热议,事情的起因是大家发现了 Facebook 专利许可证上的描述暗藏玄机。在技术开源的世界,对于开发者而言,许可证就是他们使用开源软件的 “用户协议”。而 Facebook 的开源方式跟其他家都不太一样,别家一般用的都是开源社区公认通用的许可证,而 Facebook 使用的是两个许可证,第一个是通用的 BSD 许可证,第二个是自己写的专利许可证 (patent grant)。 +去年知乎上一个《如何看待百度要求内部全面停止使用 React / React Native?》的文章引起了前端界的热议,事情的起因是大家发现了 Facebook 专利许可证上的描述暗藏玄机。在技术开源的世界,对于开发者而言,许可证就是他们使用开源软件的 “用户协议”。而 Facebook 的开源方式跟其他家都不太一样,别家一般用的都是开源社区公认通用的许可证,而 Facebook 使用的是两个许可证,第一个是通用的 BSD 许可证,第二个是自己写的专利许可证 (patent grant)。 而在 React 的开源协议中这么写到: ![ React 的开源协议](https://pic4.zhimg.com/80/v2-a04b940e9f42b1c9801b2612d04a6bee_hd.jpg) 意思就是: 当发生下列情况时,facebook 有权益吊销你的 React 使用权: -> * 与 facebook 及其附属机构发生利益冲突 -> * 同任何一个和 facebook 有关的组织发生了法律纠纷 +> * 与 facebook 及其附属机构发生利益冲突 +> * 同任何一个和 facebook 有关的组织发生了法律纠纷 > * 同任何与 React 有关的组织发生利益冲突 @@ -51,43 +55,43 @@ 其实这种事情,从去年就在前端技术圈开吵,后来愈演愈烈,形势每况日下:开源社区在更多 Facebook 开源的热门项目中发现了相同的许可证模式和条款。开发者认为 Facebook 的这种许可证模式正在毒害社区,污染开源精神。而且 Apache 软件基金会宣布所有使用 Apache 开源协议的软件都不得使用带有 Facebook BSD + 专利许可证模式的组件。 不过 Facebook 最后还是意识到了这些问题,修改了开源协议。 -![Facebook开源协议](https://pic2.zhimg.com/80/v2-6809df1f7f8a7915a3f8909a5b9cff5d_hd.jpg) +![Facebook开源协议](https://pic2.zhimg.com/80/v2-6809df1f7f8a7915a3f8909a5b9cff5d_hd.jpg) ### 如何为我们的项目选择一个开源协议? 首先,我们要清楚我们选择开源的目的是什么? - 作为个人,在开源的情况下,我们可以帮助他人,也可以获得他人的帮助,还是一个提升个人代码质量的好方法,同样,也是一个展示自己能力的好方法。世界上开源软件协议的种类非常之多,并且同一款协议有很多变种,协议太宽松会导致作者丧失对作品的很多权利,太严格又不便于使用者使用及作品的传播,所以开源作者要考虑自己对作品想保留哪些权利,放开哪些限制。 - 作为公司,代码开源后,会提升公司的地位,树立一个良好的品牌形象,也可以帮助公司发掘潜在员工。 +作为个人,在开源的情况下,我们可以帮助他人,也可以获得他人的帮助,还是一个提升个人代码质量的好方法,同样,也是一个展示自己能力的好方法。世界上开源软件协议的种类非常之多,并且同一款协议有很多变种,协议太宽松会导致作者丧失对作品的很多权利,太严格又不便于使用者使用及作品的传播,所以开源作者要考虑自己对作品想保留哪些权利,放开哪些限制。 +作为公司,代码开源后,会提升公司的地位,树立一个良好的品牌形象,也可以帮助公司发掘潜在员工。 那么,我们如何选择适合我们的开源许可证呢? 由一张图直观了解如何选取所需要的开源许可证。(原著:乌克兰程序员Paul Bagwell,翻译:阮一峰) ![开源许可证](https://pic4.zhimg.com/80/v2-253a7b1819e2af555ed0a7e0f11a0b59_hd.jpg) 举例来说: - 如果我只是想专心的写代码,那么可以选择 MIT ,MIT在保证了作者的所有权的前提下允许别人使用作者的代码,且作者不需要承担使用时的风险。如果我想保护我的代码、专利,那么可以选择 Apache ,Apache 与 MIT 的区别就是提供了专利贡献者的授权,使用者需要明确这一点。 +如果我只是想专心的写代码,那么可以选择 MIT ,MIT在保证了作者的所有权的前提下允许别人使用作者的代码,且作者不需要承担使用时的风险。如果我想保护我的代码、专利,那么可以选择 Apache ,Apache 与 MIT 的区别就是提供了专利贡献者的授权,使用者需要明确这一点。 Github 专门发布了一个网站 [Choosing an OSS license doesn’t need to be scary](https://choosealicense.com/) 来帮助开源项目开发者。 -> * 我想要一个简单宽松的许可证建议: MIT 许可证。这是一个宽松的、简明扼要的许可证,只要用户在项目副本中包含了版权声明和许可声明,他们就可以拿你的代码做任何想做的事情,你也无需承担任何责任。 -> 使用该许可证的项目:jQuery、Rails -> * 我比较关心专利 -> 建议: Apache许可证。这类似于 MIT 许可证,但它同时还包含了贡献者向用户提供专利授权相关的条款。 -> 使用该许可证的项目:Apache、SVN和NuGet -> * 我关心项目的共享改进 -> 建议:GPL( V2或 V3)许可证。这是一种 copyleft 许可证,要求修改项目代码的用户再次分发源码或二进制代码时,必须公布他的相关修改。V3版本与V2类>似,但其进一步约束了在某些限制软件更改的硬件上的使用范围。 -> 使用该许可证的项目:Linux、Git -> * 我的开源项目不是代码 -> 建议: Creative Commons。这是一个相对宽松的版权协议。它只保留几种了权利(some rights reserved)。使用者可以明确知道所有者的权利,不容易侵犯对>方的版权,作品可以得到有效传播。作为作者,你可以选择以下1~4种权利组合: -> 1) 署名(Attribution,简写为BY):必须提到原作者。 -> 2) 非商业用途(Noncommercial,简写为NC):不得用于盈利性目的。 -> 3) 禁止演绎(No Derivative Works,简写为ND):不得修改原作品, 不得再创作。 -> 4) 相同方式共享(Share Alike,简写为SA):允许修改原作品,但必须使用相同的许可证发布。 -> * 更多选择 -> Licenses - [http://ChooseALicense.com](https://choosealicense.com/),这里提供了Apache/ GPL/ MIT/ Artistic/ Eclipse/ BSD/ LGPL/ Mozilla/ No License/ Public Domain >Dedication 协议的适用情形、许可内容、禁止内容,及协议全文。 - -### 如何为代码添加开源协议? +> * 我想要一个简单宽松的许可证建议: MIT 许可证。这是一个宽松的、简明扼要的许可证,只要用户在项目副本中包含了版权声明和许可声明,他们就可以拿你的代码做任何想做的事情,你也无需承担任何责任。 +> 使用该许可证的项目:jQuery、Rails +> * 我比较关心专利 +> 建议: Apache许可证。这类似于 MIT 许可证,但它同时还包含了贡献者向用户提供专利授权相关的条款。 +> 使用该许可证的项目:Apache、SVN和NuGet +> * 我关心项目的共享改进 +> 建议:GPL( V2或 V3)许可证。这是一种 copyleft 许可证,要求修改项目代码的用户再次分发源码或二进制代码时,必须公布他的相关修改。V3版本与V2类>似,但其进一步约束了在某些限制软件更改的硬件上的使用范围。 +> 使用该许可证的项目:Linux、Git +> * 我的开源项目不是代码 +> 建议: Creative Commons。这是一个相对宽松的版权协议。它只保留几种了权利(some rights reserved)。使用者可以明确知道所有者的权利,不容易侵犯对>方的版权,作品可以得到有效传播。作为作者,你可以选择以下1~4种权利组合: +> 1) 署名(Attribution,简写为BY):必须提到原作者。 +> 2) 非商业用途(Noncommercial,简写为NC):不得用于盈利性目的。 +> 3) 禁止演绎(No Derivative Works,简写为ND):不得修改原作品, 不得再创作。 +> 4) 相同方式共享(Share Alike,简写为SA):允许修改原作品,但必须使用相同的许可证发布。 +> * 更多选择 +> Licenses - [http://ChooseALicense.com](https://choosealicense.com/),这里提供了Apache/ GPL/ MIT/ Artistic/ Eclipse/ BSD/ LGPL/ Mozilla/ No License/ Public Domain >Dedication 协议的适用情形、许可内容、禁止内容,及协议全文。 + +### 如何为代码添加开源协议? #### GitHub -1. 首先需要注册一个 GitHub 账号,并登录 -2. 在 GitHub 上选择创建一个新的 repository +1. 首先需要注册一个 GitHub 账号,并登录 +2. 在 GitHub 上选择创建一个新的 repository ![GitHub](https://pic4.zhimg.com/80/v2-5ab3d4f220e6524d445135c029014fe6_hd.jpg) 3. 进入创建 repository 页面后,输入基本信息后,点击右下角的 Add a license 选择开源协议,默认是 none。对应的 license 可以直接选择,也可以输入自己想要的 license ![GitHub](https://pic4.zhimg.com/80/v2-fb3c51c8d10b9767792603877e32ec65_hd.jpg) @@ -97,12 +101,12 @@ Github 专门发布了一个网站 [Choosing an OSS license doesn’t need to be 5. 创建成功后,代码库中就可以看到自动生成了一个 LICENSE 文件。 ### 参考文献 -> [选择一个开源软件协议](http://choosealicense.online/) -> [程序员不可不知的版权协议](http://www.gcssloop.com/tips/choose-license) -> [开源许可证都有什么区别,一般开源项目用什么许可证?](https://www.zhihu.com/question/28292322) -> [都在封杀 React/React Native ,那我到底还该不该继续学呢?](https://zhuanlan.zhihu.com/p/29492362) -> [React开源协议之争知多少?](https://cauu.github.io/2017/09/React-Opensource-license/) -> [how to choose a license](https://www.cnblogs.com/Wayou/p/how_to_choose_a_license.html) +> [选择一个开源软件协议](http://choosealicense.online/) +> [程序员不可不知的版权协议](http://www.gcssloop.com/tips/choose-license) +> [开源许可证都有什么区别,一般开源项目用什么许可证?](https://www.zhihu.com/question/28292322) +> [都在封杀 React/React Native ,那我到底还该不该继续学呢?](https://zhuanlan.zhihu.com/p/29492362) +> [React开源协议之争知多少?](https://cauu.github.io/2017/09/React-Opensource-license/) +> [how to choose a license](https://www.cnblogs.com/Wayou/p/how_to_choose_a_license.html) > [原文地址](https://zhuanlan.zhihu.com/p/35876146) \ No newline at end of file diff --git a/README.md b/README.md index 6e93ee5e..94e8059f 100644 --- a/README.md +++ b/README.md @@ -57,8 +57,10 @@ * [33-javascript的纯函数](https://github.com/pingan8787/Leo-JavaScript/blob/master/33-javascript%E7%9A%84%E7%BA%AF%E5%87%BD%E6%95%B0.md) * [36-好好学习toLocaleString方法](https://github.com/pingan8787/Leo-JavaScript/blob/master/36-%E5%A5%BD%E5%A5%BD%E5%AD%A6%E4%B9%A0toLocaleString%E6%96%B9%E6%B3%95.md) * [37-JavaScript事件委托详解](https://github.com/pingan8787/Leo-JavaScript/blob/master/37-JavaScript%E4%BA%8B%E4%BB%B6%E5%A7%94%E6%89%98%E8%AF%A6%E8%A7%A3.md) +* [38-JavaScript中常见设计模式](https://github.com/pingan8787/Leo-JavaScript/blob/master/38-JavaScript%E4%B8%AD%E5%B8%B8%E8%A7%81%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.md) * ### 7、其他 -* [★ 27-Markdowm语法整理](https://github.com/pingan8787/Leo-JavaScript/blob/master/27-Markdowm%E8%AF%AD%E6%B3%95%E6%95%B4%E7%90%86.md) * [2017-全年总结](https://github.com/pingan8787/Leo-JavaScript/blob/master/2017-%E5%85%A8%E5%B9%B4%E6%80%BB%E7%BB%93.md) -* [2018-全年计划](https://github.com/pingan8787/Leo-JavaScript/blob/master/2018-%E5%85%A8%E5%B9%B4%E8%AE%A1%E5%88%92.md) \ No newline at end of file +* [2018-全年计划](https://github.com/pingan8787/Leo-JavaScript/blob/master/2018-%E5%85%A8%E5%B9%B4%E8%AE%A1%E5%88%92.md) +* [★ 27-Markdowm语法整理](https://github.com/pingan8787/Leo-JavaScript/blob/master/27-Markdowm%E8%AF%AD%E6%B3%95%E6%95%B4%E7%90%86.md) +* [39-作为前端需要了解的开源协议知识](https://github.com/pingan8787/Leo-JavaScript/blob/master/39-%E4%BD%9C%E4%B8%BA%E5%89%8D%E7%AB%AF%E9%9C%80%E8%A6%81%E4%BA%86%E8%A7%A3%E7%9A%84%E5%BC%80%E6%BA%90%E5%8D%8F%E8%AE%AE%E7%9F%A5%E8%AF%86.md) \ No newline at end of file From c0f1043420ccfd83d22cffd58757614152f18ba9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 21 May 2018 23:21:05 +0800 Subject: [PATCH 017/835] 2018.05.21 --- "40-\350\247\243\345\257\206Vue SSR.md" | 251 ++++++++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 "40-\350\247\243\345\257\206Vue SSR.md" diff --git "a/40-\350\247\243\345\257\206Vue SSR.md" "b/40-\350\247\243\345\257\206Vue SSR.md" new file mode 100644 index 00000000..ab2faccf --- /dev/null +++ "b/40-\350\247\243\345\257\206Vue SSR.md" @@ -0,0 +1,251 @@ +## 1.引言 +最近笔者和小伙伴在研究Vue SSR,但是市面上充斥了太多的从0到1的文章,对大家理解这其中的原理帮助并不是很大,因此,本文将从 *Vue SSR的构建流程、运行流程、SSR的特点和利弊* 这几方面对Vue SSR有一个较为详细的介绍。最后还将附上一个笔者实现的 *去除Vue全家桶的Demo案例* 。 + +## 2.剖析构建流程 +首先我们镇上一张官网给出的构建图: +![Vue SSR构建流程](https://pic3.zhimg.com/80/v2-8f5dc75e94e8cfe49416e460f6bd2a0e_hd.jpg) + +### app.js入口文件 +`app.js` 是我们的通用`entry`,它的作用就是构建一个Vue的实例以供服务端和客户端使用,注意一下,在纯客户端的程序中我们的`app.js`将会挂载实例到`dom`中,而在`ssr`中这一部分的功能放到了`Client entry`中去做了。 + +### 两个entry +接下里我们来看`Client entry`和`Server entry`,这两者分别是客户端的入口和服务端的入口。*Client entry的功能很简单,就是挂载我们的Vue实例到指定的dom元素上*;`Server entry`是一个使用`export`导出的函数。主要负责调用组件内定义的获取数据的方法,获取到SSR渲染所需数据,并存储到上下文环境中。*这个函数会在每一次的渲染中重复的调用*。 + +### webpack打包构建 +然后我们的服务端代码和客户端代码通过`webpack`分别打包,生成`Server Bundle`和`Client Bundle`,前者会运行在服务器上通过node生成预渲染的`HTML字符串`,发送到我们的客户端以便完成初始化渲染;而客户端bundle就自由了,初始化渲染完全不依赖它了。客户端拿到服务端返回的HTML字符串后,会去“激活”这些静态HTML,是其变成由`Vue动态管理`的DOM,以便响应后续数据的变化。 + +## 3.剖析运行流程 +到这里我们该谈谈`ssr`的程序是怎么跑起来的了。首先我们得去构建一个vue的实例,也就是我们前面构建流程中说到的`app.js`做的事情,但是这里不同于传统的客户端渲染的程序,我们*需要用一个工厂函数去封装它,以便每一个用户的请求都能够返回一个新的实例,也就是官网说到的避免交叉污染了*。 + +然后我们可以暂时移步到服务端的`entry`中了,这里要做的就是拿到当前路由匹配的组件,调用组件里定义的一个方法(官网取名叫`asyncData`)拿到初始化渲染的数据,而这个方法要做的也很简单,就是去调用我们`vuex store`中的方法去异步获取数据。 + +接下来`node服务器`如期启动了,跑的是我们刚写好的服务端`entry`里的函数。在这里还要做的就是将我们刚刚构建好的Vue实例渲染成`HTML字符串`,然后将拿到的数据混入我们的`HTML字符串`中,最后发送到我们客户端。 + +打开浏览器的network,我们看到了初始化渲染的HTML,并且是我们想要初始化的结构,且完全不依赖于客户端的js文件了。再仔细研究研究,里面有初始化的dom结构,有css,还有一个script标签。script标签里把我们在服务端`entry`拿到的数据挂载了`window`上。原来只是一个纯静态的HTML页面啊,没有任何的交互逻辑,所以啊,现在知道为啥子需要服务端跑一个`vue客户端`再跑一个`vue`了,服务端的`vue`只是混入了个数据渲染了个静态页面,客户端的`vue`才是去实现交互的! +![chrome network](https://pic1.zhimg.com/80/v2-8354c78be3249def1cfc6b40d795c3a4_hd.jpg) + +顺着前面的思路,我们该看客户端的`entry`了。在这里客户端拿到存在`window`中的数据混入我们客户端的`vuex`中,然后分析数据去执行我们熟悉的其余客户端操作了。 + +## 4.SSR独特之处 +在SSR中,创建`Vue实例`、创建`store`和创建`router`都是套了一层`工厂函数`的,目的就是`避免数据的交叉污染`。 + +在服务端只能执行生命周期中的`created`和`beforeCreate`,原因是在服务端是无法操纵dom的,所以可想而知其他的周期也就是不能执行的了。 + +服务端渲染和客户端渲染不同,需要创建两个`entry`分别跑在`服务端`和`客户端`,并且需要*webpack对其分别打包*; + +SSR服务端请求不带`cookie`,需要手动拿到浏览器的`cookie`传给服务端的请求。[实现方式戳这里](https://www.mmxiaowu.com/article/596cbb2d436eb550a5423c30)。 + +SSR要求dom结构规范,因为浏览器会自动给HTML添加一些结构比如tbody,但是客户端进行混淆服务端放回的HTML时,不会添加这些标签,导致混淆后的HTML和浏览器渲染的HTML不匹配。 + +*性能问题需要多加关注*。 +* vue.mixin、axios拦截请求使用不当,会内存泄漏。[原因戳这里](https://github.com/vuejs/vue/issues/5089) +* lru-cache向内存中缓存数据,需要合理缓存改动不频繁的资源。 + +## 5.可能是把双刃剑 +### SSR的优点 + +* 更利于SEO。 + +不同爬虫工作原理类似,只会爬取源码,不会执行网站的任何脚本(Google除外,据说Googlebot可以运行javaScript)。 +使用了`Vue`或者其它`MVVM框架`之后,页面大多数DOM元素都是在客户端根据js动态生成,可供爬虫抓取分析的内容大大减少。 +另外,浏览器爬虫不会等待我们的数据完成之后再去抓取我们的页面数据。服务端渲染返回给客户端的是已经获取了异步数据并执行JavaScript脚本的最终HTML,网络爬中就可以抓取到完整页面的信息。 + +* 更利于首屏渲染 +首屏的渲染是node发送过来的html字符串,并不依赖于js文件了,这就会使用户更快的看到页面的内容。尤其是针对大型单页应用,打包后文件体积比较大,普通客户端渲染加载所有所需文件时间较长,首页就会有一个很长的白屏等待时间。 + + +## 6.SSR的局限 + +* 服务端压力较大 +本来是通过客户端完成渲染,现在统一到服务端node服务去做。尤其是高并发访问的情况,会大量占用服务端CPU资源; + +* 开发条件受限 +在服务端渲染中,`created`和`beforeCreate`之外的生命周期钩子不可用,因此项目引用的第三方的库也不可用其它生命周期钩子,这对引用库的选择产生了很大的限制; + +* 学习成本相对较高 +除了对`webpack`、`Vue`要熟悉,还需要掌握`node`、`Express`相关技术。相对于客户端渲染,项目构建、部署过程更加复杂。 + +## 6.去除VUEX的SSR实践 +先附上demo地址,[戳这里](https://github.com/LNoe-lzy/vue-ssr-demo/tree/vue-ssr-without-vuex)! + +说在前面: + +* vue-router不是必须的,不用router其实做个vue的[preRender](https://github.com/chrisvfritz/prerender-spa-plugin)就可以了,完全没必要做ssr; +* vuex不是必须的,vuex是实现我们客户端和服务端的状态共享的关键,我们可以不使用vuex,但是我们得去实现一套数据预取的逻辑; + +官网的demo大而全,集成了`vue-router`和`vuex`,想想我们的项目如果没有使用到这两者,光引入就又需要改造成本,这并不是我们想搞的“丝滑般”过渡,接下来笔者将带领大家一步一步的做个“啥都没有的”demo。 + +在此笔者的思路是:*构造一个Vue的实例,那么我们可以用这个实例的data来存储我们的预取数据,而用methods中的方法去做数据的异步获取,这样我们只在需要预取数据的组件中去调用这个方法就可以了*。 + +首先我们需要让我们的组件“共享”这个EventBus,为此笔者简单的封装了一个plugin: +```js +export default { + install (Vue) { + const EventBus = new Vue({ + data () { + return { + list: [], + nav: [] + } + }, + methods: { + getList () { + // get list + }, + getNav () { + // get nav + } + } + }) + + Vue.prototype.$events = EventBus + Vue.$events = EventBus + } +} +``` + +然后我们需要在`main.js`中`export`出我们的`EventBus`以便两个`entry`使用。这样我们的`main.js`就像下面这样: +```js +import Vue from 'vue' +import App from './App' +import EventBus from './event' + +Vue.use(EventBus) +Vue.config.devtools = true + +export function createApp () { + const app = new Vue({ + // 注入 router 到根 Vue 实例 + router, + render: h => h(App) + }) + + return { app, router, eventBus: app.$events } +} +``` + +接下来是我们的两个`entry`了。`server`用来匹配我们的组件并调用组件的`asyncData`方法去获取数据,`client`用来将预渲染的数据存储到我们`eventBus`中的`data`中。 +```js +// server +import { createApp } from './main' + +export default context => { + return new Promise((resolve, reject) => { + const { app, eventBus, App } = createApp() + // 这里笔者的demo比较简单,仅app组件需要预取数据,复杂业务可以递归遍历哈; + const matchedComponents = [App] + + Promise.all(matchedComponents.map(({ asyncData }) => asyncData && asyncData({ + eventBus + }))).then(() => { + context.state = eventBus._data + resolve(app) + }).catch(reject) + }) +} + + +// client +import Vue from 'vue' +import { createApp } from './main' +const { app, eventBus } = createApp() + +if (window.__INITIAL_STATE__) { + eventBus._data = window.__INITIAL_STATE__ +} + +app.$mount('#app') +``` + +然后我们需要改造我们的组件了,只需要定义一个`async`方法去调用`EventBus`中的方法获取,考虑到服务端只会执行`beforeCreate`和`created`两个生命周期而`beforeCreate`不能拿到`data`,所以我们需要在`created`中去做数据的获取。 +```js +// 服务端渲染数据预取; +asyncData ({ store, eventBus }) { + return eventBus.getNav() +} +// 将服务端拿到的数据混入vue组件中; +created () { + this.nav = this.$events.nav +} +``` + +然后是`webpack`的改造了,`webpack`的配置其实和纯客户端应用类似,为了区分客户端和服务端两个环境我们将配置分为`base`、`client`和`server`三部分,`base`就是我们的通用基础配置,而`client`和`server`分别用来打包我们的客户端和服务端代码。 + +首先是`webpack.server.conf.js`,用于生成`server bundle`来传递给`createBundleRenderer函数`在node服务器上调用,入口文件是我们的`entry-server`: +```js +const webpack = require('webpack') +const merge = require('webpack-merge') +const nodeExternals = require('webpack-node-externals') +const baseConfig = require('./webpack.base.conf.js') +const VueSSRServerPlugin = require('vue-server-renderer/server-plugin') +// 去除打包css的配置 +baseConfig.module.rules[1].options = '' + +module.exports = merge(baseConfig, { + entry: './src/entry-server.js', + // 以 Node 适用方式导入 + target: 'node', + // 对 bundle renderer 提供 source map 支持 + devtool: '#source-map', + output: { + filename: 'server-bundle.js', + libraryTarget: 'commonjs2' + }, + externals: nodeExternals({ + whitelist: /\.css$/ + }), + plugins: [ + new webpack.DefinePlugin({ + 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'), + 'process.env.VUE_ENV': '"server"' + }), + // 这是将服务器的整个输出 + // 构建为单个 JSON 文件的插件。 + // 默认文件名为 `vue-ssr-server-bundle.json` + new VueSSRServerPlugin() + ] +}) +``` +其次是`webpack.client.conf.js`,这里我们可以根据官方的配置生成`clientManifest`,自动推断和注入资源预加载,以及 css 链接 / script 标签到所渲染的 HTML。入口是我们的`client-server`: +```js +const webpack = require('webpack') +const merge = require('webpack-merge') +const base = require('./webpack.base.conf') +const VueSSRClientPlugin = require('vue-server-renderer/client-plugin') + +const config = merge(base, { + entry: { + app: './src/entry-client.js' + }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'), + 'process.env.VUE_ENV': '"client"' + }), + new webpack.optimize.CommonsChunkPlugin({ + name: 'vendor', + minChunks: function (module) { + return ( + /node_modules/.test(module.context) && + !/\.css$/.test(module.request) + ) + } + }), + // 这将 webpack 运行时分离到一个引导 chunk 中, + // 以便可以在之后正确注入异步 chunk。 + // 这也为你的 应用程序/vendor 代码提供了更好的缓存。 + new webpack.optimize.CommonsChunkPlugin({ + name: 'manifest' + }), + new VueSSRClientPlugin() + ] +}) +``` + +从`localhost`中我们看到`ssr`预取的数据已经成功出来了,大功告成! +![localhost](https://pic1.zhimg.com/80/v2-8354c78be3249def1cfc6b40d795c3a4_hd.jpg) + +## 7.结语 +本文介绍了Vue的SSR的构建和运行流程,也分析了SSR的特点和利弊,希望对大家了解SSR有一定的帮助。最后针对不使用vuex的SSR实现方案进行了介绍,如果感兴趣或者有疑问,欢迎大家留言交流。 + +[阅读原文](https://zhuanlan.zhihu.com/p/35871344) \ No newline at end of file From 41612b8c9396f656c4db5d98a4b91d9a3dac6fca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 21 May 2018 23:22:35 +0800 Subject: [PATCH 018/835] 2018.05.21 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 94e8059f..36d52db9 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ * [8-vue-cli2的webpack配置分析](https://github.com/pingan8787/Leo-JavaScript/blob/master/8-vue-cli2%E7%9A%84webpack%E9%85%8D%E7%BD%AE%E5%88%86%E6%9E%90.md) * [14-Vue的一些小注意点](https://github.com/pingan8787/Leo-JavaScript/blob/master/14-Vue%E7%9A%84%E4%B8%80%E4%BA%9B%E5%B0%8F%E6%B3%A8%E6%84%8F%E7%82%B9.md) * [★ 24-Vue折腾记-给Axios做个挺靠谱的封装(报错,鉴权,跳转,拦截,提示)](https://github.com/pingan8787/Leo-JavaScript/blob/master/24-Vue%E6%8A%98%E8%85%BE%E8%AE%B0-%E7%BB%99Axios%E5%81%9A%E4%B8%AA%E6%8C%BA%E9%9D%A0%E8%B0%B1%E7%9A%84%E5%B0%81%E8%A3%85%EF%BC%88%E6%8A%A5%E9%94%99%2C%E9%89%B4%E6%9D%83%2C%E8%B7%B3%E8%BD%AC%2C%E6%8B%A6%E6%88%AA%2C%E6%8F%90%E7%A4%BA%EF%BC%89.md) +* [40-解密Vue SSR](https://github.com/pingan8787/Leo-JavaScript/blob/master/40-%E8%A7%A3%E5%AF%86Vue%20SSR.md) ### 3、ES6/ES7/ES8... * [3-Promise简单用法](https://github.com/pingan8787/Leo-JavaScript/blob/master/3-Promise%E7%AE%80%E5%8D%95%E7%94%A8%E6%B3%95.md) From 31b92d02fcb21730de471c8f76fa876923f316e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Tue, 22 May 2018 21:38:27 +0800 Subject: [PATCH 019/835] 2018.05.22 --- ...73\243\347\240\201\346\225\264\347\220\206.md" | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git "a/9-\345\270\270\347\224\250\344\270\232\345\212\241\346\250\241\345\235\227\344\273\243\347\240\201\346\225\264\347\220\206.md" "b/9-\345\270\270\347\224\250\344\270\232\345\212\241\346\250\241\345\235\227\344\273\243\347\240\201\346\225\264\347\220\206.md" index 0338a5fa..dcf41e86 100644 --- "a/9-\345\270\270\347\224\250\344\270\232\345\212\241\346\250\241\345\235\227\344\273\243\347\240\201\346\225\264\347\220\206.md" +++ "b/9-\345\270\270\347\224\250\344\270\232\345\212\241\346\250\241\345\235\227\344\273\243\347\240\201\346\225\264\347\220\206.md" @@ -732,4 +732,17 @@ if(Object.isArray(someobj)){} if(someobj && Object.keys(someobj).length) ``` -## (更新时间2018.04.24)持续更新中··· \ No newline at end of file +## 36、生成指定位数的随机密码 +```js +// {length} 指定返回随机密码的长度 +function CreatePassword(length) { + var password = ''; + var charlist = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + for(var i = 0; i < length; i++) { + password += charlist.charAt(parseInt(Math.random()*charlist.length)); + } + return password; +} +``` + +## (更新时间2018.05.22)持续更新中··· \ No newline at end of file From ef4658642c6e6c4505c73829f06c5d7578de3962 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Tue, 5 Jun 2018 22:12:41 +0800 Subject: [PATCH 020/835] 2018.06.05 --- ...\273\243\347\240\201\346\225\264\347\220\206.md" | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git "a/9-\345\270\270\347\224\250\344\270\232\345\212\241\346\250\241\345\235\227\344\273\243\347\240\201\346\225\264\347\220\206.md" "b/9-\345\270\270\347\224\250\344\270\232\345\212\241\346\250\241\345\235\227\344\273\243\347\240\201\346\225\264\347\220\206.md" index dcf41e86..ae3c7cff 100644 --- "a/9-\345\270\270\347\224\250\344\270\232\345\212\241\346\250\241\345\235\227\344\273\243\347\240\201\346\225\264\347\220\206.md" +++ "b/9-\345\270\270\347\224\250\344\270\232\345\212\241\346\250\241\345\235\227\344\273\243\347\240\201\346\225\264\347\220\206.md" @@ -745,4 +745,15 @@ function CreatePassword(length) { } ``` -## (更新时间2018.05.22)持续更新中··· \ No newline at end of file +## 37、关于sort()方法 +```js +let a = [10, 1, 3, 20,25,8]; +// 1-默认情况 大的数值会在前面 +a.sort(); // [10, 1, 3, 20,25,8]; +// 2-升序 +a.sort((a,b)=>a-b); // [1, 3, 8, 10, 20, 25] +// 3-降序 +a.sort((a,b)=>b-a); // [25, 20, 10, 8, 3, 1] +``` + +## (更新时间2018.06.05)持续更新中··· \ No newline at end of file From 52894645384a9bc66d104ea9f7bee4bf1d5cca4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Wed, 6 Jun 2018 23:31:57 +0800 Subject: [PATCH 021/835] 2018.06.06 --- ...4\273\243\347\240\201\346\225\264\347\220\206.md" | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git "a/9-\345\270\270\347\224\250\344\270\232\345\212\241\346\250\241\345\235\227\344\273\243\347\240\201\346\225\264\347\220\206.md" "b/9-\345\270\270\347\224\250\344\270\232\345\212\241\346\250\241\345\235\227\344\273\243\347\240\201\346\225\264\347\220\206.md" index ae3c7cff..aea3bc41 100644 --- "a/9-\345\270\270\347\224\250\344\270\232\345\212\241\346\250\241\345\235\227\344\273\243\347\240\201\346\225\264\347\220\206.md" +++ "b/9-\345\270\270\347\224\250\344\270\232\345\212\241\346\250\241\345\235\227\344\273\243\347\240\201\346\225\264\347\220\206.md" @@ -755,5 +755,13 @@ a.sort((a,b)=>a-b); // [1, 3, 8, 10, 20, 25] // 3-降序 a.sort((a,b)=>b-a); // [25, 20, 10, 8, 3, 1] ``` - -## (更新时间2018.06.05)持续更新中··· \ No newline at end of file +## 38、设置时间 n分钟之前 +同理还可以设置n小时等 +```js +// 设置两分钟之前 +const d = new Date(); +const n = 2; // 分钟数 +d.setMinutes(d.getMinutes()- n) +``` + +## (更新时间2018.06.06)持续更新中··· \ No newline at end of file From 7278bc84afb79738c207bc25750abf0dcbd82e75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sun, 24 Jun 2018 19:38:44 +0800 Subject: [PATCH 022/835] 2018.06.24 --- ...04\346\226\260\347\211\271\346\200\247.md" | 226 ++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 "41-ES2018\357\274\210ES9\357\274\211\347\232\204\346\226\260\347\211\271\346\200\247.md" diff --git "a/41-ES2018\357\274\210ES9\357\274\211\347\232\204\346\226\260\347\211\271\346\200\247.md" "b/41-ES2018\357\274\210ES9\357\274\211\347\232\204\346\226\260\347\211\271\346\200\247.md" new file mode 100644 index 00000000..a10e3cdc --- /dev/null +++ "b/41-ES2018\357\274\210ES9\357\274\211\347\232\204\346\226\260\347\211\271\346\200\247.md" @@ -0,0 +1,226 @@ +在这篇文章中,我将介绍ES2018(ES9)的新特性,并介绍如何使用它们。 + +JavaScript(ECMAScript)是跨多个平台的许多厂商实施的不断发展的标准。ES6(ECMAScript 2015)花费六年的时间敲定,是一个很大的发行版。新的年度发布流程被制定,以简化流程并更快地添加功能。 ES9(ES2018)是撰写本文时的最新版本。 + +TC39由包括浏览器厂商在内的各方组成,他们开会推动JavaScript提案沿着一条严格的发展道路前进: + +* Stage 0: strawman——最初想法的提交。 +* Stage 1: proposal(提案)——由TC39至少一名成员倡导的正式提案文件,该文件包括API事例。 +* Stage 2: draft(草案)——功能规范的初始版本,该版本包含功能规范的两个实验实现。 +* Stage 3: candidate(候选)——提案规范通过审查并从厂商那里收集反馈 +* Stage 4: finished(完成)——提案准备加入ECMAScript,但是到浏览器或者Nodejs中可能需要更长的时间 + +## ES2016 +ES2016添加了两个小的特性来说明标准化过程: + +1. 数组`includes()`方法,用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回`true`,否则返回`false`。 + +2. `a ** b`指数运算符,它与 `Math.pow(a, b)`相同。 + +## ES2017 +ES2017提供了更多的新特性: + +1. `Async` 函数呈现更清晰的 `Promise` 语法 + +2. `Object.values` 方法返回一个给定对象自己的所有可枚举属性值的数组,值的顺序与使用`for...in`循环的顺序相同(区别在于`for...in`循环枚举原型链中的属性) + +3. `Object.entries()`方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用`for...in`循环遍历改对象时返回的顺序一致(区别在于`for...in`循环也枚举原型链中的属性) + +4. `Object.getOwnPropertyDescriptors()`返回一个对象的所有自身属性的描述符(`.value`,`.writable`,`.get`,`.set`,`.configurable`,`enumerable`) + +5. `padStart()`和`padEnd()`,填充字符串达到当前长度 + +6. 结尾逗号,数组定义和函数参数列表 + +7. `ShareArrayBuffer`和`Atomics`用于从共享内存位置读取和写入 + +关于ES2017的更多信息请[参阅](https://www.sitepoint.com/es2017-whats-new/) + +## ES2018 +ECMAScript 2018(或者叫ES9)现在已经可用了。以下功能已经到达 stage 4,但是在撰写本文时在各个浏览器的实现还不完整。 + +### 异步迭代 +在`async/await`的某些时刻,你可能尝试在同步循环中调用异步函数。例如: +```js +async function process(array) { + for (let i of array) { + await doSomething(i); + } +} +``` +这段代码不会正常运行,下面这段同样也不会: +```js +async function process(array) { + array.forEach(async i => { + await doSomething(i); + }); +} +``` +这段代码中,循环本身依旧保持同步,并在在内部异步函数之前全部调用完成。 +ES2018引入异步迭代器(asynchronous iterators),这就像常规迭代器,除了`next()`方法返回一个`Promise`。因此`await`可以和`for...of`循环一起使用,以串行的方式运行异步操作。例如: +```js +async function process(array) { + for await (let i of array) { + doSomething(i); + } +} +``` + +### Promise.finally() +一个`Promise`调用链要么成功到达最后一个`.then()`,要么失败触发`.catch()`。在某些情况下,你想要在无论`Promise`运行成功还是失败,运行相同的代码,例如清除,删除对话,关闭数据库连接等。 +`.finally()`允许你指定最终的逻辑: +```js +function doSomething() { + doSomething1() + .then(doSomething2) + .then(doSomething3) + .catch(err => { + console.log(err); + }) + .finally(() => { + // finish here! + }); +} +``` + +## Rest/Spread 属性 +ES2015引入了[Rest参数](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Rest_parameters)和[扩展运算符](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Spread_syntax)。三个点(...)仅用于数组。Rest参数语法允许我们将一个布丁数量的参数表示为一个数组。 +```js +restParam(1, 2, 3, 4, 5); + +function restParam(p1, p2, ...p3) { + // p1 = 1 + // p2 = 2 + // p3 = [3, 4, 5] +} +``` + +展开操作符以相反的方式工作,将数组转换成可传递给函数的单独参数。例如`Math.max()`返回给定数字中的最大值: +```js +const values = [99, 100, -1, 48, 16]; +console.log( Math.max(...values) ); // 100 +``` + +ES2018为对象解构提供了和数组一样的Rest参数()和展开操作符,一个简单的例子: +```js +const myObject = { + a: 1, + b: 2, + c: 3 +}; + +const { a, ...x } = myObject; +// a = 1 +// x = { b: 2, c: 3 } +``` + +或者你可以使用它给函数传递参数: +```js +restParam({ + a: 1, + b: 2, + c: 3 +}); + +function restParam({ a, ...x }) { + // a = 1 + // x = { b: 2, c: 3 } +} +``` +跟数组一样,Rest参数只能在声明的结尾处使用。此外,它只适用于每个对象的顶层,如果对象中嵌套对象则无法适用。 +扩展运算符可以在其他对象内使用,例如: +```js +const obj1 = { a: 1, b: 2, c: 3 }; +const obj2 = { ...obj1, z: 26 }; +// obj2 is { a: 1, b: 2, c: 3, z: 26 } +``` + +可以使用扩展运算符拷贝一个对象,像是这样`obj2 = {...obj1}`,但是 这只是一个对象的浅拷贝。另外,如果一个对象A的属性是对象B,那么在克隆后的对象cloneB中,该属性指向对象B。 + +### 正则表达式命名捕获组(Regular Expression Named Capture Groups) +JavaScript正则表达式可以返回一个匹配的对象——一个包含匹配字符串的类数组,例如:以YYYY-MM-DD的格式解析日期: +```js +const + reDate = /([0-9]{4})-([0-9]{2})-([0-9]{2})/, + match = reDate.exec('2018-04-30'), + year = match[1], // 2018 + month = match[2], // 04 + day = match[3]; // 30 +``` + +这样的代码很难读懂,并且改变正则表达式的结构有可能改变匹配对象的索引。 +ES2018允许命名捕获组使用符号`?`,在打开捕获括号(后立即命名,示例如下: +```js +const + reDate = /(?[0-9]{4})-(?[0-9]{2})-(?[0-9]{2})/, + match = reDate.exec('2018-04-30'), + year = match.groups.year, // 2018 + month = match.groups.month, // 04 + day = match.groups.day; // 30 +``` +任何匹配失败的命名组都将返回`undefined`。 +命名捕获也可以使用在`replace()`方法中。例如将日期转换为美国的 MM-DD-YYYY 格式: +```js +const + reDate = /(?[0-9]{4})-(?[0-9]{2})-(?[0-9]{2})/, + d = '2018-04-30', + usDate = d.replace(reDate, '$-$-$'); +``` + +### 正则表达式反向断言(lookbehind) +目前JavaScript在正则表达式中支持先行断言(lookahead)。这意味着匹配会发生,但不会有任何捕获,并且断言没有包含在整个匹配字段中。例如从价格中捕获货币符号: +```js +const + reLookahead = /\D(?=\d+)/, + match = reLookahead.exec('$123.89'); + +console.log( match[0] ); // $ +``` + +ES2018引入以相同方式工作但是匹配前面的反向断言(lookbehind),这样我就可以忽略货币符号,单纯的捕获价格的数字: +```js +const + reLookbehind = /(?<=\D)\d+/, + match = reLookbehind.exec('$123.89'); + +console.log( match[0] ); // 123.89 +``` + +以上是 肯定反向断言,非数字`\D`必须存在。同样的,还存在 否定反向断言,表示一个值必须不存在,例如: +```js +const + reLookbehindNeg = /(? Date: Sun, 24 Jun 2018 19:40:39 +0800 Subject: [PATCH 023/835] 2018.06.24 --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 36d52db9..f7847ea8 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,8 @@ * [19-ES6的7个实用技巧](https://github.com/pingan8787/Leo-JavaScript/blob/master/19-ES6%E7%9A%847%E4%B8%AA%E5%AE%9E%E7%94%A8%E6%8A%80%E5%B7%A7.md) * [★ 31-ES6这些就够了](https://github.com/pingan8787/Leo-JavaScript/blob/master/31-ES6%E8%BF%99%E4%BA%9B%E5%B0%B1%E5%A4%9F%E4%BA%86.md) * [★ 34-我眼中的async&await](https://github.com/pingan8787/Leo-JavaScript/blob/master/34-%E6%88%91%E7%9C%BC%E4%B8%AD%E7%9A%84async%26await.md) -* [35-ES6中的模块导入导出整理](https://github.com/pingan8787/Leo-JavaScript/blob/master/35-ES6%E4%B8%AD%E7%9A%84%E6%A8%A1%E5%9D%97%E5%AF%BC%E5%85%A5%E5%AF%BC%E5%87%BA%E6%95%B4%E7%90%86.md) +* [35-ES6中的模块导入导出整理](https://github.com/pingan8787/Leo-JavaScript/blob/master/35-ES6%E4%B8%AD%E7%9A%84%E6%A8%A1%E5%9D%97%E5%AF%BC%E5%85%A5%E5%AF%BC%E5%87%BA%E6%95%B4%E7%90%86.md) +* [41-ES2018(ES9)的新特性](https://github.com/pingan8787/Leo-JavaScript/blob/master/41-ES2018%EF%BC%88ES9%EF%BC%89%E7%9A%84%E6%96%B0%E7%89%B9%E6%80%A7.md) ### 4、Webpack * [25-Webpack入门教程整理(整理中)](https://github.com/pingan8787/Leo-JavaScript/blob/master/25-Webpack%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%E6%95%B4%E7%90%86%EF%BC%88%E6%95%B4%E7%90%86%E4%B8%AD%EF%BC%89.md) From 1d1c88b3d8b1bc7404f59704bea9ea2801dad7ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Thu, 12 Jul 2018 22:13:58 +0800 Subject: [PATCH 024/835] 2018.07.12 --- ...243\347\240\201\346\225\264\347\220\206.md" | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git "a/9-\345\270\270\347\224\250\344\270\232\345\212\241\346\250\241\345\235\227\344\273\243\347\240\201\346\225\264\347\220\206.md" "b/9-\345\270\270\347\224\250\344\270\232\345\212\241\346\250\241\345\235\227\344\273\243\347\240\201\346\225\264\347\220\206.md" index aea3bc41..2abb1525 100644 --- "a/9-\345\270\270\347\224\250\344\270\232\345\212\241\346\250\241\345\235\227\344\273\243\347\240\201\346\225\264\347\220\206.md" +++ "b/9-\345\270\270\347\224\250\344\270\232\345\212\241\346\250\241\345\235\227\344\273\243\347\240\201\346\225\264\347\220\206.md" @@ -763,5 +763,19 @@ const d = new Date(); const n = 2; // 分钟数 d.setMinutes(d.getMinutes()- n) ``` - -## (更新时间2018.06.06)持续更新中··· \ No newline at end of file + +## 39、sleep函数 +``` +// {numberMillis} 睡眠时间 +export function sleep(numberMillis) { + let now = new Date(); + let exitTime = now.getTime() + numberMillis; + while (true) { + now = new Date(); + if (now.getTime() > exitTime) + return; + } +} +``` + +## (更新时间2018.07.12)持续更新中··· \ No newline at end of file From 23e0450c0b230cf3e2aa629314c74588b90265df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Tue, 31 Jul 2018 22:34:55 +0800 Subject: [PATCH 025/835] 2018.07.31 --- ...43\345\206\263\346\226\271\346\263\225.md" | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 "42-JS\351\253\230\347\250\213\344\270\255\347\232\204\345\236\203\345\234\276\345\233\236\346\224\266\346\234\272\345\210\266\344\270\216\345\270\270\350\247\201\345\206\205\345\255\230\346\263\204\351\234\262\347\232\204\350\247\243\345\206\263\346\226\271\346\263\225.md" diff --git "a/42-JS\351\253\230\347\250\213\344\270\255\347\232\204\345\236\203\345\234\276\345\233\236\346\224\266\346\234\272\345\210\266\344\270\216\345\270\270\350\247\201\345\206\205\345\255\230\346\263\204\351\234\262\347\232\204\350\247\243\345\206\263\346\226\271\346\263\225.md" "b/42-JS\351\253\230\347\250\213\344\270\255\347\232\204\345\236\203\345\234\276\345\233\236\346\224\266\346\234\272\345\210\266\344\270\216\345\270\270\350\247\201\345\206\205\345\255\230\346\263\204\351\234\262\347\232\204\350\247\243\345\206\263\346\226\271\346\263\225.md" new file mode 100644 index 00000000..5b2d18bb --- /dev/null +++ "b/42-JS\351\253\230\347\250\213\344\270\255\347\232\204\345\236\203\345\234\276\345\233\236\346\224\266\346\234\272\345\210\266\344\270\216\345\270\270\350\247\201\345\206\205\345\255\230\346\263\204\351\234\262\347\232\204\350\247\243\345\206\263\346\226\271\346\263\225.md" @@ -0,0 +1,154 @@ +> [阅读原文 obkoro1.com](http://obkoro1.com/2018/07/08/JS%E9%AB%98%E7%A8%8B%E4%B8%AD%E7%9A%84%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6%E4%B8%8E%E5%B8%B8%E8%A7%81%E5%86%85%E5%AD%98%E6%B3%84%E9%9C%B2%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95/) + +### 内存的生命周期: +1. 分配你所需要的内存: + +由于字符串、对象等没有固定的大小,js程序在每次创建字符串、对象的时候,程序都会**分配内存来存储那个实体**。 + +2. 使用分配到的内存做点什么。 + +3. 不需要时将其释放回归: + +在不需要字符串、对象的时候,需要释放其所占用的内存,否则将会消耗完系统中所有可用的内存,造成系统崩溃,这就是**垃圾回收机制所存在的意义**。 + +**所谓的内存泄漏**指的是:由于疏忽或错误造成程序未能释放那些已经不再使用的内存,造成内存的浪费。 +*** +### 垃圾回收机制: +在C和C++之类的语言中,需要手动来管理内存的,这也是造成许多不必要问题的根源。幸运的是,在编写js的过程中,内存的分配以及内存的回收完全实现了自动管理,我们不用操心这种事情。 + +### 垃圾收集机制的原理: +垃圾收集器会按照固定的时间间隔,**周期性的找出不再继续使用的变量,然后释放其占用的内存**。 + +#### 什么叫不再继续使用的变量? + +不再使用的变量也就是生命周期结束的变量,是局部变量,局部变量只在函数的执行过程中存在,当函数运行结束,没有其他引用(闭包),那么该变量会被标记回收。 + +全局变量的生命周期直至浏览器卸载页面才会结束,也就是说**全局变量不会被当成垃圾回收**。 + +### 标记清除:当前采用的垃圾收集策略 +工作原理: + +当变量进入环境时(例如在函数中声明一个变量),将这个变量标记为“进入环境”,当变量离开环境时,则将其标记为“离开环境”。标记“离开环境”的就回收内存。 + +工作流程: + +1. 垃圾收集器会在运行的时候会给存储在内存中的**所有变量都加上标记**。 +2. 去掉环境中的变量以及被环境中的变量引用的变量的标记。 +3. 那些还存在标记的变量被视为准备删除的变量。 +4. 最后垃圾收集器会执行最后一步内存清除的工作,销毁那些带标记的值并回收它们所占用的内存空间。 +到2008年为止,IE、Chorme、Fireofx、Safari、Opera **都使用标记清除式的垃圾收集策略**,只不过垃圾收集的时间间隔互有不同。 + +### 引用计数略:被废弃的垃圾收集策 +循环引用:跟踪记录每个值被引用的技术 + +在老版本的浏览器中(对,又是IE),IE9以下BOM和DOM对象就是使用C++以COM对象的形式实现的。 + +COM的垃圾收集机制采用的就是引用计数策略,这种机制在出现循环引用的时候永远都释放不掉内存。 +```js +var element = document.getElementById('something'); +var myObject = new Object(); +myObject.element = element; // element属性指向dom +element.someThing = myObject; // someThing回指myObject 出现循环引用(两个对象一直互相包含 一直存在计数)。 +``` +解决方式是,当我们不使用它们的时候,手动切断链接: +```js +myObject.element = null; +element.someThing = null; +``` +#### 淘汰: + +IE9把BOM和DOM对象转为了真正的js对象,避免了使用这种垃圾收集策略,消除了IE9以下常见的内存泄漏的主要原因。 + +IE7以下有一个声明狼藉的性能问题,大家了解一下: + +1. 256个变量,4096个对象(或数组)字面或者64KB的字符串,达到任何一个临界值会触发垃圾收集器运行。 +2. 如果一个js脚本的生命周期一直保有那么多变量,垃圾收集器会一直频繁的运行,引发严重的性能问题。 +IE7已修复这个问题。 +*** + +### 哪些情况会引起内存泄漏? +虽然有垃圾回收机制,但我们在编写代码的时候,有些情况还是会造成内存泄漏,了解这些情况,并在编写程序的时候,注意避免,我们的程序会更具健壮性。 + +#### 意外的全局变量: +上文我们提到了**全局变量不会被当成垃圾回收**,我们在编码中有时会出现下面这种情况: +```js +function foo() { + this.bar2 = '默认绑定this指向全局' // 全局变量=> window.bar2 + bar = '全局变量'; // 没有声明变量 实际上是全局变量=>window.bar +} +foo(); +``` +当我们使用[默认绑定](https://juejin.im/post/5b3715def265da59af40a630#heading-3),this会指向全局,`this.something`也会创建一个全局变量,这一点可能很多人没有注意到。 + +**解决方法:在函数内使用严格模式or细心一点** +```js +function foo() { + "use strict"; + this.bar2 = "严格模式下this指向undefined"; + bar = "报错"; +} +foo(); +``` +当然我们也可以手动释放全局变量的内存: +```js +window.bar = undefined +delete window.bar2 +``` +#### 被遗忘的定时器和回调函数 +当不需要`setInterval`或者`setTimeout`时,**定时器没有被clear**,定时器的**回调函数以及内部依赖的变量都不能被回收**,造成内存泄漏。 +```js +var someResource = getData(); +setInterval(function() { + var node = document.getElementById('Node'); + if(node) { + node.innerHTML = JSON.stringify(someResource)); + // 定时器也没有清除 + } + // node、someResource 存储了大量数据 无法回收 +}, 1000); +``` +**解决方法**: 在定时器完成工作的时候,手动清除定时器。 + +### 闭包: +**闭包可以维持函数内局部变量,使其得不到释放,造成内存泄漏。** +```js +function bindEvent() { + var obj = document.createElement("XXX"); + var unused = function () { + console.log(obj,'闭包内引用obj obj不会被释放'); + }; + // obj = null; +} +``` +**解决方法**:手动解除引用,`obj = null`。 + +#### 循环引用问题 +就是IE9以下的循环引用问题,上文讲过了。 + +#### 没有清理DOM元素引用: +```js +var refA = document.getElementById('refA'); +document.body.removeChild(refA); // dom删除了 +console.log(refA, "refA"); // 但是还存在引用 能console出整个div 没有被回收 +``` +不信的话,可以看下这个[dom](https://codepen.io/OBKoro1/pen/vroKbg)。 + +**解决办法**:`refA = null`; + +#### console保存大量数据在内存中。 +过多的console,比如定时器的console会导致浏览器卡死。 + +**解决**:合理利用console,线上项目尽量少的使用console,当然如果你要发招聘,除外。 +*** +### 如何避免内存泄漏: +**记住一个原则:不用的东西,及时归还,毕竟你是’借的’嘛。** + +1. 减少不必要的全局变量,使用严格模式避免意外创建全局变量。 +2. 在你使用完数据后,及时解除引用(闭包中的变量,dom引用,定时器清除)。 +3. 组织好你的逻辑,避免死循环等造成浏览器卡顿,崩溃的问题。 +#### 关于内存泄漏: +1. 即使是1byte的内存,也叫内存泄漏,并不一定是导致浏览器崩溃、卡顿才能叫做内存泄漏。 +2. 一般是堆区内存泄漏,栈区不会泄漏。 +基本类型的值存在内存中,被保存在栈内存中,引用类型的值是**对象,保存在堆内存中。所以对象、数组之类的,才会发生内存泄漏**。 + +3. 使用chorme监控内存泄漏,可以看一下[这篇文章](https://jinlong.github.io/2016/05/01/4-Types-of-Memory-Leaks-in-JavaScript-and-How-to-Get-Rid-Of-Them/) From 9391a3be8356d011427518addd1b8a1a48bd39ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Tue, 31 Jul 2018 22:40:04 +0800 Subject: [PATCH 026/835] 2018.07.31 --- ...7\232\204\350\247\243\345\206\263\346\226\271\346\263\225.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/42-JS\351\253\230\347\250\213\344\270\255\347\232\204\345\236\203\345\234\276\345\233\236\346\224\266\346\234\272\345\210\266\344\270\216\345\270\270\350\247\201\345\206\205\345\255\230\346\263\204\351\234\262\347\232\204\350\247\243\345\206\263\346\226\271\346\263\225.md" "b/42-JS\351\253\230\347\250\213\344\270\255\347\232\204\345\236\203\345\234\276\345\233\236\346\224\266\346\234\272\345\210\266\344\270\216\345\270\270\350\247\201\345\206\205\345\255\230\346\263\204\351\234\262\347\232\204\350\247\243\345\206\263\346\226\271\346\263\225.md" index 5b2d18bb..b56dac9b 100644 --- "a/42-JS\351\253\230\347\250\213\344\270\255\347\232\204\345\236\203\345\234\276\345\233\236\346\224\266\346\234\272\345\210\266\344\270\216\345\270\270\350\247\201\345\206\205\345\255\230\346\263\204\351\234\262\347\232\204\350\247\243\345\206\263\346\226\271\346\263\225.md" +++ "b/42-JS\351\253\230\347\250\213\344\270\255\347\232\204\345\236\203\345\234\276\345\233\236\346\224\266\346\234\272\345\210\266\344\270\216\345\270\270\350\247\201\345\206\205\345\255\230\346\263\204\351\234\262\347\232\204\350\247\243\345\206\263\346\226\271\346\263\225.md" @@ -146,6 +146,7 @@ console.log(refA, "refA"); // 但是还存在引用 能console出整个div 没 1. 减少不必要的全局变量,使用严格模式避免意外创建全局变量。 2. 在你使用完数据后,及时解除引用(闭包中的变量,dom引用,定时器清除)。 3. 组织好你的逻辑,避免死循环等造成浏览器卡顿,崩溃的问题。 + #### 关于内存泄漏: 1. 即使是1byte的内存,也叫内存泄漏,并不一定是导致浏览器崩溃、卡顿才能叫做内存泄漏。 2. 一般是堆区内存泄漏,栈区不会泄漏。 From 3f71ef57ca97eb2235ae6932d70694ede3d30375 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 31 Aug 2018 14:08:25 +0800 Subject: [PATCH 027/835] 2018.08.31 --- ...30\345\222\214\350\247\243\345\206\263.md" | 356 ++++++++++++++++++ 1 file changed, 356 insertions(+) create mode 100644 "43-\346\211\213\346\234\272\347\253\257\351\241\265\351\235\242\345\274\200\345\217\221\345\270\270\350\247\201\351\227\256\351\242\230\345\222\214\350\247\243\345\206\263.md" diff --git "a/43-\346\211\213\346\234\272\347\253\257\351\241\265\351\235\242\345\274\200\345\217\221\345\270\270\350\247\201\351\227\256\351\242\230\345\222\214\350\247\243\345\206\263.md" "b/43-\346\211\213\346\234\272\347\253\257\351\241\265\351\235\242\345\274\200\345\217\221\345\270\270\350\247\201\351\227\256\351\242\230\345\222\214\350\247\243\345\206\263.md" new file mode 100644 index 00000000..890d10c7 --- /dev/null +++ "b/43-\346\211\213\346\234\272\347\253\257\351\241\265\351\235\242\345\274\200\345\217\221\345\270\270\350\247\201\351\227\256\351\242\230\345\222\214\350\247\243\345\206\263.md" @@ -0,0 +1,356 @@ +## 1.解决页面使用 overflow: scroll 在 iOS 上滑动卡顿的问题? +首先你可能会给页面的 html 和 body 增加了 height: 100%, 然后就可能造成 iOS 上页面滑动的卡顿问题。解决方案是: +(1) 看是否能把 body 和 html 的 height: 100% 去除掉。 +(2) 在滚动的容器中增加:`-webkit-overflow-scrolling: touch` 或者给 body 增加:`body {overflow-x: hidden}`。 + +## 2.iOS 页面橡皮弹回效果遮挡页面选项卡? +(1) 有时 body 和 html 的 height: 100% 去除掉问题可能就没有了。 +(2) 到达临界值的时候在阻止事件默认行为 +```js +var startY,endY; +//记录手指触摸的起点坐标 +$('body').on('touchstart',function (e) { + startY = e.touches[0].pageY; +}); +$('body').on('touchmove',function (e) { + endY = e.touches[0].pageY; //记录手指触摸的移动中的坐标 + //手指下滑,页面到达顶端不能继续下滑 + if(endY>startY&& $(window).scrollTop()<=0){ + e.preventDefault(); + } + //手指上滑,页面到达底部能继续上滑 + if(endY=$('body')[0].scrollHeight){ + e.preventDefault(); + } +}) +``` +有时也会碰见弹窗出来后两个层的橡皮筋效果出现问题,我们可以在弹出弹出时给底层页面加上一个类名,类名禁止页面滑动这样下层的橡皮筋效果就会被禁止,就不会影响弹窗层。 + +## 3.iOS 机型 margin 属性无效问题? +(1) 设置 html body 的高度为百分比时,margin-bottom 在 safari 里失效 +(2) 直接 padding 代替 margin + +## 4.iOS 绑定点击事件不执行? +(1) 添加样式 `cursor :pointer`。点击后消除背景闪一下的 css:`-webkit-tap-highlight-color:transparent`; + +## 5.iOS 键盘换行变为搜索? +首先,input 要放在 form 里面。 +这时 "换行" 已经变成 “前往”。 +如果想变成 “搜索”,input 设置 `type="search"`。 + +## 6.jQuery对 a 标签点击事件不生效? +出现这种情况的原因不明,有的朋友解释:我们平时都是点击的 A 标签中的文字了。 所以要想用 JS 模拟点击 A 标签事件,就得先往 A 标签中的文字添加能被 JS 捕获的元素,然后再用 JS 模拟点击该元素即可。但是我觉得不合理,虽然找不到原因但是解决办法还是有的。 +```js +// 方法1 +document.getElementById("abc").click(); +// 方法2 +$("#abc")[0].click(); +``` +## 7.有时因为服务器或者别的原因导致页面上的图片没有找到? +这是我们想需要用一个本地的图片代替没有找的的图片 +```html + + +``` + +## 8.transform 属性影响 position:fixed? +(1) 规范中有规定:如果元素的 transform 值不为 none,则该元素会生成包含块和层叠上下文。CSS Transforms Module Level 1 不只在手机上,电脑上也一样。除了 fixed 元素会受影响之外,z-index(层叠上下文)值也会受影响。绝对定位元素等和包含块有关的属性都会受到影响。当然如果 transform 元素的 display 值为 inline 时又会有所不同。最简单的解决方法就是 transform 元素内部不能有 absolute、fixed 元素. + +## 9.iOS 对 position: fixed 不太友好,有时我们需要加点处理? +在安卓上面,点击页面底部的输入框,软键盘弹出,页面移动上移。 而 iOS 上面,点击页面底部输入框,软键盘弹出,输入框看不到了。。。查资料说什么的都有,iscroll,jquery-moblie,absolute,fixe,static 都非常复杂,要改很多。。。 让他弹出时让滚动条在最低部 +```js +var u = navigator.userAgent, app = navigator.appVersion; +var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //iOS终端 +if (isiOS) { + $('textarea').focus(function () { + window.setTimeout('scrollBottom()', 500); + }); +} +function scrollBottom() { + window.scrollTo(0, $('body').height()); +} +``` + +## 10.jQuery validate 插件验证问题? +所有的 input 必须有 name 不然会出错 + +## 11.有时手机会出现断网的情况,我没可能会对断网的情况做一些处理? +`navigator.onLine` 可判断是否是脱机状态. + +## 12.判断对象的长度? +(1) 用 `Object.keys`,`Object.keys` 方法返回的是一个数组,数组里面装的是对象的属性。 +```js +var person = { + "name" : "zhangshan", + "sex" : "man", + "age" : "50", + "height" : "180", + "phone" : "1xxxxxxxxxx", + "email" : "xxxxxxxxx@xxx.com" +}; +var arr = Object.keys(person); +console.log(arr.length); +``` +(2)Object.getOwnPropertyNames(obj).length + +## 13.上一题我们用到了 Object.keys 与 Object.getOwnPropertyNames 他们的区别? +`Object.keys` 定义:返回一个对象可枚举属性的字符串数组; +`Object.getOwnPropertyNames` 定义:返回一个对象可枚举、不可枚举属性的名称; +属性的可枚举性、不可枚举性:定义:可枚举属性是指那些内部 “可枚举” 标志设置为 true 的属性,对于通过直接的赋值和属性初始化的属性,该标识值默认为即为 true,对于通过 `Object.defineProperty` 等定义的属性,该标识值默认为 false。 +```js +var obj = { "prop1": "v1" }; +Object.defineProperty(obj, "prop2", { value: "v2", enumerable: false }); +console.log(Object.keys(obj).length); //output:1 +console.log(Object.getOwnPropertyNames(obj).length); //output:2 +console.log(Object.keys(obj)); //output:Array[1] => [0: "prop1"] +console.log(Object.getOwnPropertyNames(obj)); //output:Array[2] => [0: "prop1", 1: "prop2"] +``` +[内置的判断,访问和迭代方法](https://segmentfault.com/img/bVbbQEQ?w=838&h=335) +综合实例: +```js +var obj = { "prop1": "v1" }; +Object.defineProperty(obj, "prop2", { value: "v2", enumerable: false}); +console.log(obj.hasOwnProperty("prop1")); //output: true +console.log(obj.hasOwnProperty("prop2")); //output: true +console.log(obj.propertyIsEnumerable("prop1")); //output: true +console.log(obj.propertyIsEnumerable("prop2")); //output: false +console.log('prop1' in obj); //output: true +console.log('prop2' in obj); //output: true +for (var item in obj) { + console.log(item); +} +//output:prop1 +for (var item in Object.getOwnPropertyNames(obj)) { + console.log(Object.getOwnPropertyNames(obj)[item]); +} +//ouput:[prop1,prop2] +``` + +## 14.移动开发不同手机弹出数字键盘问题? +#### 1. type="tel" +iOS 和 Android 的键盘表现都差不多 + +#### 2. type="number" +**优点**:Android 下实现的一个真正的数字键盘 +**缺点一**:iOS 下不是九宫格键盘,输入不方便 +**缺点二**:旧版 Android(包括微信所用的 X5 内核)在输入框后面会有超级鸡肋的小尾巴,好在 Android 4.4.4 以后给去掉了。 不过对于缺点二,我们可以用 webkit 私有的伪元素给 fix 掉: +```js +input[type=number]::-webkit-inner-spin-button, +input[type=number]::-webkit-outer-spin-button { + -webkit-appearance: none; + appearance: none; + margin: 0; +} +``` +#### 3. pattern 属性 +pattern 用于验证表单输入的内容,通常 HTML5 的 type 属性,比如 email、tel、number、data 类、url 等,已经自带了简单的数据格式验证功能了,加上 pattern 后,前端部分的验证更加简单高效了。 +显而易见,pattern 的属性值要用正则表达式。 +实例 简单的数字验证 +数字的验证有两个: +```html + + +``` + +## 15.input[number] 类型输入非数字字符 +js 获取的值是空;比如 - 12,+123 等 + +## 16.Javascript:history.go() 和 history.back() 的用法与区别? +`go(-1)`: 返回上一页,原页面表单中的内容会丢失; +`back()`: 返回上一页,原页表表单中的内容会保留; +`history.go(-1)`: 后退 + 刷新; +`history.back()`: 后退; + +之所以注意到这个区别,是因为不同的浏览器后退行为也是有区别的,而区别就跟 `javascript:history.go()` 和 `history.back()` 的区别类似。 +Chrome 和 ff 浏览器后退页面,会刷新后退的页面,若有数据请求也会提交数据申请。类似于 `history.go(-1)`; +而 safari(包括桌面版和 ipad 版)的后退按钮则不会刷新页面,也不会提交数据申请。类似于 `javascript:history.back()`; + +## 17.Meta 基础知识: +```html + +// width 设置viewport宽度,为一个正整数,或字符串‘device-width’ +// height 设置viewport高度,一般设置了宽度,会自动解析出高度,可以不用设置 +// initial-scale 默认缩放比例,为一个数字,可以带小数 +// minimum-scale 允许用户最小缩放比例,为一个数字,可以带小数 +// maximum-scale 允许用户最大缩放比例,为一个数字,可以带小数 +// user-scalable 是否允许手动缩放 +空白页基本meta标签 + + + + + + + + +其他meta标签 + + + + + + + + + + + + + + + + + + + + + + +``` +## 18.移动端如何定义字体 font-family? +@ ------------ 中文字体的英文名称 +@ 宋体 SimSun +@ 黑体 SimHei +@ 微信雅黑 Microsoft Yahei +@ 微软正黑体 Microsoft JhengHei +@ 新宋体 NSimSun +@ 新细明体 MingLiU +@ 细明体 MingLiU +@ 标楷体 DFKai-SB +@ 仿宋 FangSong +@ 楷体 KaiTi +@ 仿宋GB2312 FangSongGB2312 +@ 楷体GB2312 KaiTiGB2312 +**说明**:中文字体多数使用宋体、雅黑,英文用 Helvetica +```css +body {font-family: Microsoft Yahei,SimSun,Helvetica;} +``` + +## 19.打电话发短信写邮件怎么实现? +```html +// 一、打电话 +打电话给:0755-10086 +// 二、发短信,winphone系统无效 +发短信给: 10086 +// 三、写邮件 +点击我发邮件 +//2.收件地址后添加?cc=开头,可添加抄送地址(Android存在兼容问题) +点击我发邮件 +//3.跟着抄送地址后,写上&bcc=,可添加密件抄送地址(Android存在兼容问题) +点击我发邮件 +//4.包含多个收件人、抄送、密件抄送人,用分号(;)隔开多个邮件人的地址 +点击我发邮件 +//5.包含主题,用?subject= +点击我发邮件 +//6.包含内容,用?body=;如内容包含文本,使用%0A给文本换行 +点击我发邮件 +//7.内容包含链接,含http(s)://等的文本自动转化为链接 +点击我发邮件 +//8.内容包含图片(PC不支持) +点击我发邮件 +//9.完整示例 +点击我发邮件 +``` + +## 20.移动端 touch 事件(区分 webkit 和 winphone)? +#### 1. 以下支持 webkit +**touchstart**——当手指触碰屏幕时候发生。不管当前有多少只手指 +**touchmove**——当手指在屏幕上滑动时连续触发。通常我们再滑屏页面,会调用 event 的 **preventDefault() 可以阻止默认情况的发生:阻止页面滚动 +**touchend**——当手指离开屏幕时触发 +**touchcancel**——系统停止跟踪触摸时候会触发。例如在触摸过程中突然页面 alert() 一个提示框,此时会触发该事件,这个事件比较少用 + +#### 2. TouchEvent 说明: +**touches**:屏幕上所有手指的信息 +**targetTouches**:手指在目标区域的手指信息 +**changedTouches**:最近一次触发该事件的手指信息 +touchend 时,touches 与 targetTouches 信息会被删除,changedTouches 保存的最后一次的信息,最好用于计算手指信息 +#### 3.参数信息 (changedTouches[0]) +**clientX**、**clientY** 在显示区的坐标 +**target**:当前元素 +#### 4.事件响应顺序 +ontouchstart > ontouchmove > ontouchend > onclick + +## 21.点击元素产生背景或边框怎么去掉 +* **iOS用户** 点击一个链接,会出现一个半透明灰色遮罩, 如果想要禁用,可设置`-webkit-tap-highlight-color`的alpha值为`0`去除灰色半透明遮罩; +* **android用户** 点击一个链接,会出现一个边框或者半透明灰色遮罩, 不同生产商定义出来额效果不一样,可设置`-webkit-tap-highlight-color`的alpha值为`0`去除部分机器自带的效果; +* **winphone系统** 点击标签产生的灰色半透明背景,能通过设置``去掉; +* 特殊说明:有些机型去除不了,如小米2。对于按钮类还有个办法,不使用a或者input标签,直接用div标签 +```css +a,button,input,textarea { + -webkit-tap-highlight-color: rgba(0,0,0,0); + -webkit-user-modify:read-write-plaintext-only; + //-webkit-user-modify 副作用 输入法不再能够输入多个字符 +} +``` +也可以 +```css +* { -webkit-tap-highlight-color: rgba(0,0,0,0); } +``` +winphone下 +```html + +``` +## 22.美化表单元素 +#### 1. 使用 appearance 改变 webkit 浏览器的默认外观 +```css +input,select {-webkit-appearance:none; appearance: none;} +``` +#### 2.winphone 下,使用伪元素改变表单元素默认外观 +* 1) 禁用 select 默认箭头,`::-ms-expand` 修改表单控件下拉箭头,设置隐藏并使用背景图片来修饰 +```css +select::-ms-expand {display:none;} +``` +* 2) 禁用 radio 和 checkbox 默认样式,`::-ms-check` 修改表单复选框或单选框默认图标,设置隐藏并使用背景图片来修饰 +```css +input[type=radio]::-ms-check, +input[type=checkbox]::-ms-check { display:none; } +``` +* 3) 禁用 pc 端表单输入框默认清除按钮,`::-ms-clear` 修改清除按钮,设置隐藏并使用背景图片来修饰 +```css +input[type=text]::-ms-clear, +input[type=tel]::-ms-clear, +input[type=number]::-ms-clear { display:none; } +``` + +## 23.移动端字体单位 font-size 选择 px 还是 rem? +如需适配多种移动设备,建议使用 rem。以下为参考值: +```css +html {font-size: 62.5%;} //10*16 = 62.5% +``` +设置 12px 字体 这里注意在 rem 前要加上对应的 px 值,解决不支持 rem 的浏览器的兼容问题,做到优雅降级 +```css +body {font-size:12px; font-size:1.2rem;} +``` + +## 24.input 标签添加上 disable 属性在 iOS 端字体颜色不兼容的问题? +```css +input[disabled],input:disabled,input.disabled{ + color: #3e3e3e; + -webkit-text-fill-color: #3e3e3e; + -webkit-opacity:1; + opacity: 1; +} +``` + +## 25.iOS 的光标大小问题 +#### IE: +不管该行有没有文字,光标高度与 font-size 一致。 +#### FF: +该行有文字时,光标高度与 font-size 一致。该行无文字时,光标高度与 input 的 height 一致。 +#### Chrome: +该行无文字时,光标高度与 line-height 一致;该行有文字时,光标高度从 input 顶部到文字底部 (这两种情况都是在有设定 line-height 的时候),如果没有 line-height,则是与 font-size 一致。 + +iOS 中情况和 Chrome 相似。 +设置字体大小和行高一致,然后通过 padding 撑开大小,只给 IE 浏览器设置 +```css +line-height:-ms-line-height:40px; +``` + +原文:https://segmentfault.com/a/1190000015178877 作者:键盘上的眼泪 \ No newline at end of file From 25e3738513e5309a5ae5473777cc2f03967d94f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 31 Aug 2018 14:15:20 +0800 Subject: [PATCH 028/835] 2018.08.31 --- ...\227\256\351\242\230\345\222\214\350\247\243\345\206\263.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/43-\346\211\213\346\234\272\347\253\257\351\241\265\351\235\242\345\274\200\345\217\221\345\270\270\350\247\201\351\227\256\351\242\230\345\222\214\350\247\243\345\206\263.md" "b/43-\346\211\213\346\234\272\347\253\257\351\241\265\351\235\242\345\274\200\345\217\221\345\270\270\350\247\201\351\227\256\351\242\230\345\222\214\350\247\243\345\206\263.md" index 890d10c7..ffb5253f 100644 --- "a/43-\346\211\213\346\234\272\347\253\257\351\241\265\351\235\242\345\274\200\345\217\221\345\270\270\350\247\201\351\227\256\351\242\230\345\222\214\350\247\243\345\206\263.md" +++ "b/43-\346\211\213\346\234\272\347\253\257\351\241\265\351\235\242\345\274\200\345\217\221\345\270\270\350\247\201\351\227\256\351\242\230\345\222\214\350\247\243\345\206\263.md" @@ -112,7 +112,7 @@ console.log(Object.getOwnPropertyNames(obj).length); //output:2 console.log(Object.keys(obj)); //output:Array[1] => [0: "prop1"] console.log(Object.getOwnPropertyNames(obj)); //output:Array[2] => [0: "prop1", 1: "prop2"] ``` -[内置的判断,访问和迭代方法](https://segmentfault.com/img/bVbbQEQ?w=838&h=335) +![内置的判断,访问和迭代方法](http://p3nqtyvgo.bkt.clouddn.com/196513361-5b16021f6db85_articlex.png) 综合实例: ```js var obj = { "prop1": "v1" }; From 6cd467b0d0614964225cf7526c6a14ecb2e81d2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sat, 1 Sep 2018 06:05:27 +0800 Subject: [PATCH 029/835] =?UTF-8?q?2018.09.01=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E9=94=99=E5=88=AB=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...2\271\346\226\260\344\270\234\350\245\277.md" | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git "a/13-ES7\345\222\214ES8\347\232\204\344\270\200\347\202\271\346\226\260\344\270\234\350\245\277.md" "b/13-ES7\345\222\214ES8\347\232\204\344\270\200\347\202\271\346\226\260\344\270\234\350\245\277.md" index 67c3854a..e5431109 100644 --- "a/13-ES7\345\222\214ES8\347\232\204\344\270\200\347\202\271\346\226\260\344\270\234\350\245\277.md" +++ "b/13-ES7\345\222\214ES8\347\232\204\344\270\200\347\202\271\346\226\260\344\270\234\350\245\277.md" @@ -55,8 +55,8 @@ Object.keys(obj).forEach((key) => // Object.keys() 对象=>数组 }); ``` -2-不使用ES8 -使用Object.values()遍历对象的属性值,无需使用使用属性名: +2-使用ES8 +使用Object.values()遍历对象的属性值,无需使用属性名: ```js let obj = {a: 1, b: 2, c: 3} Object.values(obj).forEach(value => @@ -77,8 +77,8 @@ Object.keys(obj).forEach((key) => }) ``` -2-不使用ES8 -使用Object.values()遍历对象的属性值,无需使用使用属性名: +2-使用ES8 +使用Object.entries()遍历对象的属性值,无需使用属性名: ```js let obj = {a: 1, b: 2, c: 3}; Object.entries(obj).forEach(([key, value]) => @@ -90,14 +90,13 @@ Object.entries(obj).forEach(([key, value]) => ### 5、ES8 - padStart() 在字符串前面填充指定的字符串。 1-不使用ES8 -使用Object.keys()遍历对象的属性名和属性值: ```js console.log('0.00') // 0.00 console.log('10,000.00') // 10,000.00 console.log('250,000.00') // 250,000.00 ``` -2-不使用ES8 +2-使用ES8 使用padStart()可以在字符串前面填充指定的字符串: ```js console.log('0.00'.padStart(20)) // 0.00 @@ -108,14 +107,13 @@ console.log('250,000.00'.padStart(20)) // 250,000.00 ### 6、ES8 - padEnd() 在字符串后面填充指定的字符串。 1-不使用ES8 -使用Object.keys()遍历对象的属性名和属性值: ```js console.log('0.00 ' + '0.00' ) // 0.00 0.00 console.log('10,000.00 ' + '10,000.00' ) // 10,000.00 10,000.00 console.log('250,000.00 ' + '250,000.00') // 250,000.00 250,000.00 ``` -2-不使用ES8 +2-使用ES8 使用padEnd()可以在字符串后面填充指定的字符串: ```js console.log('0.00'.padEnd(20) + '0.00' ) // 0.00 0.00 @@ -181,4 +179,4 @@ fetchData(query).then(data => this.props.processfetchedData(data) }) ``` -`Async/Await` 是写异步代码的新方式,以前的方法有 `回调函数` 和 `Promise` 。相比于 `Promise` ,它更加简洁,并且处理错误、条件语句、中间值都更加方便,因此有望替代 `Promise` ,成为新一代的一步代码编写方式。 \ No newline at end of file +`Async/Await` 是写异步代码的新方式,以前的方法有 `回调函数` 和 `Promise` 。相比于 `Promise` ,它更加简洁,并且处理错误、条件语句、中间值都更加方便,因此有望替代 `Promise` ,成为新一代的一步代码编写方式。 From 5f0d3ea98709f4e0fcff48fa7aa7e57512be1111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sat, 1 Sep 2018 16:03:03 +0800 Subject: [PATCH 030/835] =?UTF-8?q?2018.09.01=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E9=94=99=E5=88=AB=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...05\245\345\257\274\345\207\272\346\225\264\347\220\206.md" | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git "a/35-ES6\344\270\255\347\232\204\346\250\241\345\235\227\345\257\274\345\205\245\345\257\274\345\207\272\346\225\264\347\220\206.md" "b/35-ES6\344\270\255\347\232\204\346\250\241\345\235\227\345\257\274\345\205\245\345\257\274\345\207\272\346\225\264\347\220\206.md" index 7908ac22..73ae0428 100644 --- "a/35-ES6\344\270\255\347\232\204\346\250\241\345\235\227\345\257\274\345\205\245\345\257\274\345\207\272\346\225\264\347\220\206.md" +++ "b/35-ES6\344\270\255\347\232\204\346\250\241\345\235\227\345\257\274\345\205\245\345\257\274\345\207\272\346\225\264\347\220\206.md" @@ -8,7 +8,7 @@ **** ## 1、导出export命令 -如果需要外部获取文件内部变量,需要用`expor`t将变量输出,有三种方式: +如果需要外部获取文件内部变量,需要用`export`将变量输出,有三种方式: ```js //*方式一 单独输出 //main.js @@ -102,4 +102,4 @@ function foo() { export default foo; ``` -> 参考阮一峰[ES6 Module语法](http://es6.ruanyifeng.com/#docs/module) \ No newline at end of file +> 参考阮一峰[ES6 Module语法](http://es6.ruanyifeng.com/#docs/module) From 4177e13b7306c2c2f9cc1e8c8f34fd9a3da858c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 3 Sep 2018 12:31:46 +0800 Subject: [PATCH 031/835] 2018.09.03 --- ...\345\212\250\347\233\221\345\220\254.html" | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 "demo\347\211\207\346\256\265/1-\345\261\217\345\271\225\346\273\232\345\212\250\347\233\221\345\220\254.html" diff --git "a/demo\347\211\207\346\256\265/1-\345\261\217\345\271\225\346\273\232\345\212\250\347\233\221\345\220\254.html" "b/demo\347\211\207\346\256\265/1-\345\261\217\345\271\225\346\273\232\345\212\250\347\233\221\345\220\254.html" new file mode 100644 index 00000000..a3587dc4 --- /dev/null +++ "b/demo\347\211\207\346\256\265/1-\345\261\217\345\271\225\346\273\232\345\212\250\347\233\221\345\220\254.html" @@ -0,0 +1,46 @@ + + + + + + + Dome + + + + + +
+ + + \ No newline at end of file From 07633cdeca7e4eb437de385da28ea6b31d13ca35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 3 Sep 2018 15:50:00 +0800 Subject: [PATCH 032/835] 2018.09.03 --- ...34\345\222\214\344\270\212\344\274\240.md" | 352 ++++++++++++++++++ 1 file changed, 352 insertions(+) create mode 100644 "44-\345\211\215\347\253\257\346\234\254\345\234\260\346\226\207\344\273\266\346\223\215\344\275\234\345\222\214\344\270\212\344\274\240.md" diff --git "a/44-\345\211\215\347\253\257\346\234\254\345\234\260\346\226\207\344\273\266\346\223\215\344\275\234\345\222\214\344\270\212\344\274\240.md" "b/44-\345\211\215\347\253\257\346\234\254\345\234\260\346\226\207\344\273\266\346\223\215\344\275\234\345\222\214\344\270\212\344\274\240.md" new file mode 100644 index 00000000..195d40fc --- /dev/null +++ "b/44-\345\211\215\347\253\257\346\234\254\345\234\260\346\226\207\344\273\266\346\223\215\344\275\234\345\222\214\344\270\212\344\274\240.md" @@ -0,0 +1,352 @@ +[原文地址](https://juejin.im/post/5a193b4bf265da43052e528a) + +前端无法像原生APP一样直接操作本地文件,否则的话打开个网页就能把用户电脑上的文件偷光了,所以需要通过用户触发,用户可通过以下三种方式操作触发: + +1. 通过input type="file" 选择本地文件 +2. 通过拖拽的方式把文件拖过来 +3. 在编辑框里面复制粘贴 + +### 第一种 +第一种是最常用的手段,通常还会自定义一个按钮,然后盖在它上面,因为`type="file"`的input不好改变样式。如下代码写一个选择控件,并放在form里面: +```html +
+ +
+``` +然后就可以用FormData获取整个表单的内容: +```js +$("#file-input").on("change", function() { + console.log(`file name is ${this.value}`); + let formData = new FormData(this.form); + formData.append("fileName", this.value); + console.log(formData); +}); +``` +把input的value和formData打印出来是这样的: +![预览](https://user-gold-cdn.xitu.io/2017/11/25/15ff349ac0afefa0?imageView2/0/w/1280/h/960/format/webp/ignore-error/1) + +可以看到文件的路径是一个假的路径,也就是说在浏览器无法获取到文件的真实存放位置。同时FormData打印出来是一个空的Objet,但并不是说它的内容是空的,只是它对前端开发人员是透明的,无法查看、修改、删除里面的内容,只能`append`添加字段。 + +`FormData`无法得到文件的内容,而使用`FileReader`可以读取整个文件的内容。用户选择文件之后,`input.files`就可以得到用户选中的文件,如下代码: +```js +$("#file-input").on("change", function() { + let fileReader = new FileReader(), + fileType = this.files[0].type; + fileReader.onload = function() { + if (/^image/.test(fileType)) { + // 读取结果在fileReader.result里面 + $(``).appendTo("body"); + } + } + // 打印原始File对象 + console.log(this.files[0]); + // base64方式读取 + fileReader.readAsDataURL(this.files[0]); +}); +``` +把原始的File对象打印出来是这样的: +![预览](https://user-gold-cdn.xitu.io/2017/11/25/15ff349ac079ba68?imageView2/0/w/1280/h/960/format/webp/ignore-error/1) + + +它是一个window.File的实例,包含了文件的修改时间、文件名、文件的大小、文件的mime类型等。 +如果需要`限制上传文件的大小`就可以通过判断`size`属性有没有超,单位是字节,而要判断是否为图片文件就可以通过type类型是否以image开头。通过判断文件名的后缀可能会不准,而通过这种判断会比较准。上面的代码使用了一个正则判断,如果是一张图片的话就把它赋值给img的src,并添加到dom里面,但其实这段代码有点问题,就是web不是所有的图片都能通过img标签展示出来,通常是jpg/png/gif这三种,所以你应该需要再判断一下图片格式,如可以把判断改成: +```js +/^image\/[jpeg|png|gif]/.test(this.type) +``` +然后实例化一个`FileReader`,调它的`readAsDataURL`并把`File`对象传给它,监听它的`onload`事件,load完读取的结果就在它的`result`属性里了。它是一个`base64`格式的,可直接赋值给一个img的src。 + +使用`FileReader`除了可读取为`base64`之外,还能读取为以下格式: +```js +// 按base64的方式读取,结果是base64,任何文件都可转成base64的形式 +fileReader.readAsDataURL(this.files[0]); + +// 以二进制字符串方式读取,结果是二进制内容的utf-8形式,已被废弃了 +fileReader.readAsBinaryString(this.files[0]); + +// 以原始二进制方式读取,读取结果可直接转成整数数组 +fileReader.readAsArrayBuffer(this.files[0]); +``` +其它的主要是能读取为`ArrayBuffer`,它是一个原始二进制格式的结果。把`ArrayBuffer`打印出来是这样的: +![预览](https://user-gold-cdn.xitu.io/2017/11/25/15ff349ac05a9b42?imageView2/0/w/1280/h/960/format/webp/ignore-error/1) +可以看到,它对前端开发人员也是透明的,不能够直接读取里面的内容,但可以通过`ArrayBuffer.length`得到长度,还能转成整型数组,就能知道文件的原始二进制内容了: +```js +let buffer = this.result; +// 依次每字节8位读取,放到一个整数数组 +let view = new Uint8Array(buffer); +console.log(view); +``` + +### 第二种 +如果是通过第二种拖拽的方式,应该怎么读取文件呢?如下html(样式略): +```html +
+ drop your image here +
+``` +这将在页面显示一个框: +![预览](https://user-gold-cdn.xitu.io/2017/11/25/15ff349ac1f2ebd5?imageView2/0/w/1280/h/960/format/webp/ignore-error/1) + +然后监听它的拖拽事件: +```js +$(".img-container").on("dragover", function (event) { + event.preventDefault(); +}) + +.on("drop", function(event) { + event.preventDefault(); + // 数据在event的dataTransfer对象里 + let file = event.originalEvent.dataTransfer.files[0]; + + // 然后就可以使用FileReader进行操作 + fileReader.readAsDataURL(file); + + // 或者是添加到一个FormData + let formData = new FormData(); + formData.append("fileContent", file); +}) +``` +数据在`drop`事件的`event.dataTransfer.files`里面,拿到这个`File`对象之后就可以和输入框进行一样的操作了,即使用`FileReader`读取,或者是新建一个空的`formData`,然后把它`append`到`formData`里面。 + + +### 第三种 +第三种粘贴的方式,通常是在一个编辑框里操作,如把`div`的`contenteditable`设置为true: +```html +
+ hello, paste your image here +
+``` +粘贴的数据是在`event.clipboardData.files`里面: +```js +$("#editor").on("paste", function(event) { + let file = event.originalEvent.clipboardData.files[0]; +}); +``` +但是Safari的粘贴不是通过`event`传递的,它是直接在输入框里面添加一张图片,如下图所示: +![预览](https://user-gold-cdn.xitu.io/2017/11/25/15ff349ac3330972?imageView2/0/w/1280/h/960/format/webp/ignore-error/1) + +它新建了一个`img`标签,并把`img`的`src`指向一个`blob`的本地数据。什么是`blob`呢,如何读取`blob`的内容呢? +blob是一种类文件的存储格式,它可以存储几乎任何格式的内容,如json: +```js +let data = {hello: "world"}; +let blob = new Blob([JSON.stringify(data)], + {type : 'application/json'}); +``` +为了获取本地的blob数据,我们可以用ajax发个本地的请求: +```js +$("#editor").on("paste", function(event) { + // 需要setTimeout 0等图片出来了再处理 + setTimeout(() => { + let img = $(this).find("img[src^='blob']")[0]; + console.log(img.src); + // 用一个xhr获取blob数据 + let xhr = new XMLHttpRequest(); + xhr.open("GET", img.src); + // 改变mime类型 + xhr.responseType = "blob"; + xhr.onload = function () { + // response就是一个Blob对象 + console.log(this.response); + }; + xhr.send(); + }, 0); +}); +``` +上面代码把blob打印出来是这样的: +![预览](https://user-gold-cdn.xitu.io/2017/11/25/15ff349ac408b172?imageView2/0/w/1280/h/960/format/webp/ignore-error/1) + +能得到它的大小和类型,但是具体内容也是不可见的,它有一个`slice`的方法,可用于切割大文件。和`File`一样,可以使用`FileReader`读取它的内容: +```js +function readBlob(blobImg) { + let fileReader = new FileReader(); + fileReader.onload = function() { + console.log(this.result); + } + fileReader.onerror = function(err) { + console.log(err); + } + fileReader.readAsDataURL(blobImg); +} +readBlob(this.response); +``` +除此,还能使用`window.URL`读取,这是一个新的API,经常和`Service Worker`配套使用,因为SW里面常常要解析url。如下代码: +```js +function readBlob(blobImg) { + let urlCreator = window.URL || window.webkitURL; + // 得到base64结果 + let imageUrl = urlCreator.createObjectURL(this.response); + return imageUrl; +} + +readBlob(this.response); +``` +关于src使用的是blob链接的,除了上面提到的img之外,另外一个很常见的是video标签,如youtobe的视频就是使用的blob: +![](https://user-gold-cdn.xitu.io/2017/11/25/15ff349af40951d9?imageView2/0/w/1280/h/960/format/webp/ignore-error/1) + +这种数据不是直接在本地的,而是通过持续请求视频数据,然后再通过`blob`这个容器媒介添加到`video`里面,它也是通过URL的API创建的: +```js +let mediaSource = new MediaSource(); +video.src = URL.createObjectURL(mediaSource); +let sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.42E01E, mp4a.40.2"'); +sourceBuffer.appendBuffer(buf); +``` +具体我也没实践过,不再展开讨论。 + +上面,我们使用了三种方式获取文件内容,最后得到: + +1. `FormData`格式 +2. `FileReader`读取得到的`base64`或者`ArrayBuffer`二进制格式 + +如果直接就是一个`FormData`了,那么直接用`ajax`发出去就行了,不用做任何处理: +```js +let form = document.querySelector("form"), + formData = new FormData(form), +formData.append("fileName", "photo.png"); + +let xhr = new XMLHttpRequest(); +// 假设上传文件的接口叫upload +xhr.open("POST", "/upload"); +xhr.send(formData); +``` +如果用jQuery的话,要设置两个属性为false: +```js +$.ajax({ + url: "/upload", + type: "POST", + data: formData, + processData: false, // 不处理数据 + contentType: false // 不设置内容类型 +}); +``` +因为jQuery会自动把内容做一些转义,并且根据`data`自动设置请求`mime`类型,这里告诉jQuery直接用`xhr.send`发出去就行了。 + +观察控制台发请求的数据: +![预览](https://user-gold-cdn.xitu.io/2017/11/25/15ff349b104c3494?imageView2/0/w/1280/h/960/format/webp/ignore-error/1) + +可以看到这是一种区别于用`&`连接参数的方式,它的编码格式是`multipart/form-data`,就是上传文件`form`表单写的`enctype`: +```html +
+ +
+``` +如果`xhr.send`的是`FormData`类型话,它会自动设置`enctype`,如果你用默认表单提交上传文件的话就得在`form`上面设置这个属性,因为上传文件只能使用`POST`的这种编码。常用的`POST`编码是`application/x-www-form-urlencoded`,它和`GET`一样,发送的数据里面,参数和参数之间使用`&`连接,如: +```js +key1=value1&key2=value2 +``` +特殊字符做转义,这个数据`POST`是放在请求`body`里的,而`GET`是拼在`url`上面的,如果用jq的话,jq会帮你拼并做转义。 + +而上传文件用的这种`multipart/form-data`,参数和参数之间是且一个相同的字符串隔开的,上面的是使用: +``` +------WebKitFormBoundary72yvM25iSPYZ4a3F +``` +这个字符通常会取得比较长、比较随机,因为要保证正常的内容里面不会出现这个字符串,这样内容的特殊字符就不用做转义了。 + +请求的contentType被浏览器设置成: +``` +Content-Type: +multipart/form-data; boundary=----WebKitFormBoundary72yvM25iSPYZ4a3F +``` +后端服务通过这个就知道怎么解析这么一段数据了。(通常是使用的框架处理了,而具体的接口不需要关心应该怎么解析) + +如果读取结果是`ArrayBuffer`的话,也是可以直接用`xhr.send`发送出去的,但是一般我们不会直接把一个文件的内容发出去,而是用某个字段名等于文件内容的方式。如果你读取为`ArrayBuffer`的话再上传的话其实作用不是很大,还不如直接用`formData`添加一个`File`对象的内容,因为上面三种方式都可以拿到`File`对象。如果一开始就是一个`ArrayBuffer`了,那么可以转成`blob`然后再`append`到`FormData`里面。 + +使用比较多的应该是`base64`,因为前端经常要处理图片,读取为`base64`之后就可以把它画到一个`canvas`里面,然后就可以做一些处理,如压缩、裁剪、旋转等。最后再用`canvas`导出一个`base64`格式的图片,那怎么上传`base64`格式的呢? + +### 怎么上传`base64`格式 +第一种是拼一个表单上传的`multipart/form-data`的格式,再用`xhr.sendAsBinary`发出去,如下代码: +```js +let base64Data = base64Data.replace(/^data:image\/[^;]+;base64,/, ""); +let boundary = "----------boundaryasoifvlkasldvavoadv"; +xhr.sendAsBinary([ + // name=data + boundary, + 'Content-Disposition: form-data; name="data"; filename="' + fileName + '"', + 'Content-Type: ' + "image/" + fileType, '', + atob(base64Data), boundary, + //name=imageType + boundary, + 'Content-Disposition: form-data; name="imageType"', '', + fileType, + boundary + '--' +].join('\r\n')); +``` +上面代码使用了`window.atob`的api,它可以把`base64`还原成原始内容的字符串表示,如下图所示: +![预览](https://user-gold-cdn.xitu.io/2017/11/25/15ff349b4c18f7d8?imageView2/0/w/1280/h/960/format/webp/ignore-error/1) + +`btoa`是把内容转化成`base64`编码,而`atob`是把`base64`还原。在调`atob`之前,需要把表示内容格式的不属于`base64`内容的字符串去掉,即上面代码第一行的`replace`处理。 + +这样就和使用`formData`类似了,但是由于`sendAsBinary`已经被`deprecated`了,所以新代码不建议再使用这种方式。那怎么办呢? + +可以把`base64`转化成`blob`,然后再`append`到一个`formData`里面,下面的函数(来自b64-to-blob)可以把`base64`转成`blob`: +```js +function b64toBlob(b64Data, contentType, sliceSize) { + contentType = contentType || ''; + sliceSize = sliceSize || 512; + + var byteCharacters = atob(b64Data); + var byteArrays = []; + + for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) { + var slice = byteCharacters.slice(offset, offset + sliceSize); + + var byteNumbers = new Array(slice.length); + for (var i = 0; i < slice.length; i++) { + byteNumbers[i] = slice.charCodeAt(i); + } + + var byteArray = new Uint8Array(byteNumbers); + + byteArrays.push(byteArray); + } + + var blob = new Blob(byteArrays, {type: contentType}); + return blob; +} +``` +然后就可以`append`到`formData`里面: +```js +let blob = b64toBlob(b64Data, "image/png"), + formData = new FormData(); +formData.append("fileContent", blob); +``` +这样就不用自己去拼一个`multipart/form-data`的格式数据了。 + +上面处理和上传文件的API可以兼容到IE10+,如果要兼容老的浏览器应该怎么办呢? + +可以借助一个`iframe`,原理是默认的`form`表单提交会刷新页面,或者跳到`target`指定的那个url,但是如果把`ifrmae`的`target`指向一个`iframe`,那么刷新的就是`iframe`,返回结果也会显示在`ifame`,然后获取这个`ifrmae`的内容就可得到上传接口返回的结果。 + +如下代码: +```js +let iframe = document.createElement("iframe"); +iframe.display = "none"; +iframe.name = "form-iframe"; +document.body.appendChild(iframe); +// 改变form的target +form.target = "form-iframe"; + +iframe.onload = function() { + //获取iframe的内容,即服务返回的数据 + let responseText = this.contentDocument.body.textContent + || this.contentWindow.document.body.textContent; +}; + +form.submit(); +``` +`form.submit`会触发表单提交,当请求完成(成功或者失败)之后就会触发iframe的onload事件,然后在onload事件获取返回的数据,如果请求失败了的话,iframe里的内容就为空,可以用这个判断请求有没有成功。 + + + +使用iframe没有办法获取上传进度,使用xhr可以获取当前上传的进度,这个是在XMLHttpRequest 2.0引入的: +```js +xhr.upload.onprogress = function (event) { + if (event.lengthComputable) { + // 当前上传进度的百分比 + duringCallback ((event.loaded / event.total)*100); + } +}; +``` +这样就可以做一个真实的loading进度条。 + + +本文讨论了3种交互方式的读取方式,通过`input`控件在`input.files`可以得到File文件对象,通过拖拽的是在`drop`事件的`event.dataTransfer.files`里面,而通过粘贴的`paste`事件在`event.clipboardData.files`里面,Safari这个怪胎是在编辑器里面插入一个src指向本地的img标签,可以通过发送一个请求加载本地的`blob`数据,然后再通过`FileReader`读取,或者直接`append`到`formData`里面。得到的File对象就可以直接添加到`FormData`里面,如果需要先读取`base64`格式做处理的,那么可以把处理后的`base64`转化为`blob`数据再`append`到`formData`里面。对于老浏览器,可以使用一个iframe解决表单提交刷新页面或者跳页的问题。 + +总之,前端处理和上传本地文件应该差不多就是这些内容了,但是应该还有好多细节没有提及到,读者可通过本文列的方向自行实践。如果有其它的上传方式还请告知。 \ No newline at end of file From ac751158526fcce3d9c01767610bba2b2442a265 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 3 Sep 2018 15:55:46 +0800 Subject: [PATCH 033/835] =?UTF-8?q?2018.09.03=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f7847ea8..96d683ec 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,10 @@ * [36-好好学习toLocaleString方法](https://github.com/pingan8787/Leo-JavaScript/blob/master/36-%E5%A5%BD%E5%A5%BD%E5%AD%A6%E4%B9%A0toLocaleString%E6%96%B9%E6%B3%95.md) * [37-JavaScript事件委托详解](https://github.com/pingan8787/Leo-JavaScript/blob/master/37-JavaScript%E4%BA%8B%E4%BB%B6%E5%A7%94%E6%89%98%E8%AF%A6%E8%A7%A3.md) * [38-JavaScript中常见设计模式](https://github.com/pingan8787/Leo-JavaScript/blob/master/38-JavaScript%E4%B8%AD%E5%B8%B8%E8%A7%81%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.md) -* +* [42-JS高程中的垃圾回收机制与常见内存泄露的解决方法](https://github.com/pingan8787/Leo-JavaScript/blob/master/42-JS%E9%AB%98%E7%A8%8B%E4%B8%AD%E7%9A%84%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6%E4%B8%8E%E5%B8%B8%E8%A7%81%E5%86%85%E5%AD%98%E6%B3%84%E9%9C%B2%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95.md) +* [43-手机端页面开发常见问题和解决](https://github.com/pingan8787/Leo-JavaScript/blob/master/43-%E6%89%8B%E6%9C%BA%E7%AB%AF%E9%A1%B5%E9%9D%A2%E5%BC%80%E5%8F%91%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E5%92%8C%E8%A7%A3%E5%86%B3.md) +* [44-前端本地文件操作和上传](https://github.com/pingan8787/Leo-JavaScript/blob/master/44-%E5%89%8D%E7%AB%AF%E6%9C%AC%E5%9C%B0%E6%96%87%E4%BB%B6%E6%93%8D%E4%BD%9C%E5%92%8C%E4%B8%8A%E4%BC%A0.md) + ### 7、其他 * [2017-全年总结](https://github.com/pingan8787/Leo-JavaScript/blob/master/2017-%E5%85%A8%E5%B9%B4%E6%80%BB%E7%BB%93.md) * [2018-全年计划](https://github.com/pingan8787/Leo-JavaScript/blob/master/2018-%E5%85%A8%E5%B9%B4%E8%AE%A1%E5%88%92.md) From bf679dc5976e5fdf548bfc666ffe8587134cf61c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 3 Sep 2018 19:23:48 +0800 Subject: [PATCH 034/835] =?UTF-8?q?2018.09.03=20=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E7=9B=AE=E5=BD=95=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...47\216\260\351\241\265\351\235\242\351\230\262\346\212\226.md" | 0 ...7\237\245\350\257\206\347\202\271\346\225\264\347\220\2061.md" | 0 ...46\255\243\345\210\231\350\241\250\350\276\276\345\274\217.md" | 0 ...44\272\233\347\256\200\345\206\231\346\212\200\345\267\247.md" | 0 ...44\270\200\347\202\271\346\226\260\344\270\234\350\245\277.md" | 0 ...44\272\233\345\260\217\346\263\250\346\204\217\347\202\271.md" | 0 ...57\274\214\347\256\200\345\215\225\347\220\206\350\247\243.md" | 0 ...47\232\204\345\235\221\345\222\214\347\273\206\350\212\202.md" | 0 ...avaScript \346\267\261\345\272\246\345\257\271\346\257\224.md" | 0 .../18-websocket\345\270\270\347\224\250demo.md" | 0 ...44\270\252\345\256\236\347\224\250\346\212\200\345\267\247.md" | 0 ...46\261\202\347\273\223\346\236\234\346\226\271\346\263\225.md" | 0 ...-WebSocket\351\207\215\346\226\260\345\255\246\344\271\240.md" | 0 .../2017-\345\205\250\345\271\264\346\200\273\347\273\223.md" | 0 .../2018-\345\205\250\345\271\264\350\256\241\345\210\222.md" | 0 ...46\255\245\346\234\272\345\210\266\350\257\246\350\247\243.md" | 0 ...20\214\346\255\245\345\222\214\345\274\202\346\255\245Ajax.md" | 0 ...45\274\240\346\200\235\347\273\264\345\257\274\345\233\276.md" | 0 ...6\213\246\346\210\252,\346\217\220\347\244\272\357\274\211.md" | 0 ...57\274\210\346\225\264\347\220\206\344\270\255\357\274\211.md" | 0 ...57\274\210\346\225\264\347\220\206\344\270\255\357\274\211.md" | 0 ...7-Markdowm\350\257\255\346\263\225\346\225\264\347\220\206.md" | 0 ...70\255\347\232\204void\350\277\220\347\256\227\347\254\246.md" | 0 ...47\232\204\344\270\200\344\272\233\346\200\273\347\273\223.md" | 0 .../3-Promise\347\256\200\345\215\225\347\224\250\346\263\225.md" | 0 ...44\270\252\346\255\243\345\210\231\346\226\271\346\263\225.md" | 0 ...50\277\231\344\272\233\345\260\261\345\244\237\344\272\206.md" | 0 ...\201\212\344\270\200\350\201\212JavaScript\347\232\204IIFE.md" | 0 ...javascript\347\232\204\347\272\257\345\207\275\346\225\260.md" | 0 ...346\210\221\347\234\274\344\270\255\347\232\204async&await.md" | 0 ...45\205\245\345\257\274\345\207\272\346\225\264\347\220\206.md" | 0 ...\255\246\344\271\240toLocaleString\346\226\271\346\263\225.md" | 0 ...44\273\266\345\247\224\346\211\230\350\257\246\350\247\243.md" | 0 ...50\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" | 0 ...46\272\220\345\215\217\350\256\256\347\237\245\350\257\206.md" | 0 ...4-\345\237\272\344\272\216Vue\351\205\215\347\275\256axios.md" | 0 .../40-\350\247\243\345\257\206Vue SSR.md" | 0 ...57\274\211\347\232\204\346\226\260\347\211\271\346\200\247.md" | 0 ...47\232\204\350\247\243\345\206\263\346\226\271\346\263\225.md" | 0 ...51\227\256\351\242\230\345\222\214\350\247\243\345\206\263.md" | 0 ...46\223\215\344\275\234\345\222\214\344\270\212\344\274\240.md" | 0 ...45\207\275\346\225\260\345\272\223\345\260\201\350\243\205.md" | 0 ...45\222\214\345\243\260\346\230\216\346\217\220\345\211\215.md" | 0 ...45\214\205\344\275\223\347\247\257\346\226\271\346\263\225.md" | 0 ...204webpack\351\205\215\347\275\256\345\210\206\346\236\220.md" | 0 ...45\235\227\344\273\243\347\240\201\346\225\264\347\220\206.md" | 0 ...47\253\257\345\221\275\344\273\244\345\244\247\345\205\250.md" | 0 47 files changed, 0 insertions(+), 0 deletions(-) rename "1-JavaScript\345\256\236\347\216\260\351\241\265\351\235\242\351\230\262\346\212\226.md" => "article/1-JavaScript\345\256\236\347\216\260\351\241\265\351\235\242\351\230\262\346\212\226.md" (100%) rename "10-\347\237\245\350\257\206\347\202\271\346\225\264\347\220\2061.md" => "article/10-\347\237\245\350\257\206\347\202\271\346\225\264\347\220\2061.md" (100%) rename "11-20\344\270\252\350\266\205\347\272\247\345\270\270\347\224\250\347\232\204\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.md" => "article/11-20\344\270\252\350\266\205\347\272\247\345\270\270\347\224\250\347\232\204\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.md" (100%) rename "12-javascript\345\274\200\345\217\221\347\232\204\344\270\200\344\272\233\347\256\200\345\206\231\346\212\200\345\267\247.md" => "article/12-javascript\345\274\200\345\217\221\347\232\204\344\270\200\344\272\233\347\256\200\345\206\231\346\212\200\345\267\247.md" (100%) rename "13-ES7\345\222\214ES8\347\232\204\344\270\200\347\202\271\346\226\260\344\270\234\350\245\277.md" => "article/13-ES7\345\222\214ES8\347\232\204\344\270\200\347\202\271\346\226\260\344\270\234\350\245\277.md" (100%) rename "14-Vue\347\232\204\344\270\200\344\272\233\345\260\217\346\263\250\346\204\217\347\202\271.md" => "article/14-Vue\347\232\204\344\270\200\344\272\233\345\260\217\346\263\250\346\204\217\347\202\271.md" (100%) rename "15-\347\262\276\345\277\203\346\224\266\351\233\206\347\232\20448\344\270\252JavaScript\347\211\207\346\256\265\357\274\214\347\256\200\345\215\225\347\220\206\350\247\243.md" => "article/15-\347\262\276\345\277\203\346\224\266\351\233\206\347\232\20448\344\270\252JavaScript\347\211\207\346\256\265\357\274\214\347\256\200\345\215\225\347\220\206\350\247\243.md" (100%) rename "16-\345\270\246\344\275\240\347\220\206\350\247\243 JS \345\256\271\346\230\223\345\207\272\351\224\231\347\232\204\345\235\221\345\222\214\347\273\206\350\212\202.md" => "article/16-\345\270\246\344\275\240\347\220\206\350\247\243 JS \345\256\271\346\230\223\345\207\272\351\224\231\347\232\204\345\235\221\345\222\214\347\273\206\350\212\202.md" (100%) rename "17-TypeScript\345\222\214 JavaScript \346\267\261\345\272\246\345\257\271\346\257\224.md" => "article/17-TypeScript\345\222\214 JavaScript \346\267\261\345\272\246\345\257\271\346\257\224.md" (100%) rename "18-websocket\345\270\270\347\224\250demo.md" => "article/18-websocket\345\270\270\347\224\250demo.md" (100%) rename "19-ES6\347\232\2047\344\270\252\345\256\236\347\224\250\346\212\200\345\267\247.md" => "article/19-ES6\347\232\2047\344\270\252\345\256\236\347\224\250\346\212\200\345\267\247.md" (100%) rename "2-\345\220\214\346\255\245\350\277\224\345\233\236ajax\350\257\267\346\261\202\347\273\223\346\236\234\346\226\271\346\263\225.md" => "article/2-\345\220\214\346\255\245\350\277\224\345\233\236ajax\350\257\267\346\261\202\347\273\223\346\236\234\346\226\271\346\263\225.md" (100%) rename "20-WebSocket\351\207\215\346\226\260\345\255\246\344\271\240.md" => "article/20-WebSocket\351\207\215\346\226\260\345\255\246\344\271\240.md" (100%) rename "2017-\345\205\250\345\271\264\346\200\273\347\273\223.md" => "article/2017-\345\205\250\345\271\264\346\200\273\347\273\223.md" (100%) rename "2018-\345\205\250\345\271\264\350\256\241\345\210\222.md" => "article/2018-\345\205\250\345\271\264\350\256\241\345\210\222.md" (100%) rename "21-JavaScript\345\274\202\346\255\245\346\234\272\345\210\266\350\257\246\350\247\243.md" => "article/21-JavaScript\345\274\202\346\255\245\346\234\272\345\210\266\350\257\246\350\247\243.md" (100%) rename "22-JavaScript\344\270\255\346\234\211\350\266\243\347\232\204\345\214\272\345\210\206\345\220\214\346\255\245\345\222\214\345\274\202\346\255\245Ajax.md" => "article/22-JavaScript\344\270\255\346\234\211\350\266\243\347\232\204\345\214\272\345\210\206\345\220\214\346\255\245\345\222\214\345\274\202\346\255\245Ajax.md" (100%) rename "23-JavaScript\345\205\253\345\274\240\346\200\235\347\273\264\345\257\274\345\233\276.md" => "article/23-JavaScript\345\205\253\345\274\240\346\200\235\347\273\264\345\257\274\345\233\276.md" (100%) rename "24-Vue\346\212\230\350\205\276\350\256\260-\347\273\231Axios\345\201\232\344\270\252\346\214\272\351\235\240\350\260\261\347\232\204\345\260\201\350\243\205\357\274\210\346\212\245\351\224\231,\351\211\264\346\235\203,\350\267\263\350\275\254,\346\213\246\346\210\252,\346\217\220\347\244\272\357\274\211.md" => "article/24-Vue\346\212\230\350\205\276\350\256\260-\347\273\231Axios\345\201\232\344\270\252\346\214\272\351\235\240\350\260\261\347\232\204\345\260\201\350\243\205\357\274\210\346\212\245\351\224\231,\351\211\264\346\235\203,\350\267\263\350\275\254,\346\213\246\346\210\252,\346\217\220\347\244\272\357\274\211.md" (100%) rename "25-Webpack\345\205\245\351\227\250\346\225\231\347\250\213\346\225\264\347\220\206\357\274\210\346\225\264\347\220\206\344\270\255\357\274\211.md" => "article/25-Webpack\345\205\245\351\227\250\346\225\231\347\250\213\346\225\264\347\220\206\357\274\210\346\225\264\347\220\206\344\270\255\357\274\211.md" (100%) rename "26-Webpack\345\270\270\347\224\250\351\205\215\347\275\256\346\225\264\347\220\206\357\274\210\346\225\264\347\220\206\344\270\255\357\274\211.md" => "article/26-Webpack\345\270\270\347\224\250\351\205\215\347\275\256\346\225\264\347\220\206\357\274\210\346\225\264\347\220\206\344\270\255\357\274\211.md" (100%) rename "27-Markdowm\350\257\255\346\263\225\346\225\264\347\220\206.md" => "article/27-Markdowm\350\257\255\346\263\225\346\225\264\347\220\206.md" (100%) rename "28-JavaScript\344\270\255\347\232\204void\350\277\220\347\256\227\347\254\246.md" => "article/28-JavaScript\344\270\255\347\232\204void\350\277\220\347\256\227\347\254\246.md" (100%) rename "29-\345\205\263\344\272\216\351\232\217\346\234\272\346\225\260\347\232\204\344\270\200\344\272\233\346\200\273\347\273\223.md" => "article/29-\345\205\263\344\272\216\351\232\217\346\234\272\346\225\260\347\232\204\344\270\200\344\272\233\346\200\273\347\273\223.md" (100%) rename "3-Promise\347\256\200\345\215\225\347\224\250\346\263\225.md" => "article/3-Promise\347\256\200\345\215\225\347\224\250\346\263\225.md" (100%) rename "30-\344\270\200\346\254\241\350\256\260\344\275\217js\347\232\2046\344\270\252\346\255\243\345\210\231\346\226\271\346\263\225.md" => "article/30-\344\270\200\346\254\241\350\256\260\344\275\217js\347\232\2046\344\270\252\346\255\243\345\210\231\346\226\271\346\263\225.md" (100%) rename "31-ES6\350\277\231\344\272\233\345\260\261\345\244\237\344\272\206.md" => "article/31-ES6\350\277\231\344\272\233\345\260\261\345\244\237\344\272\206.md" (100%) rename "32-\350\201\212\344\270\200\350\201\212JavaScript\347\232\204IIFE.md" => "article/32-\350\201\212\344\270\200\350\201\212JavaScript\347\232\204IIFE.md" (100%) rename "33-javascript\347\232\204\347\272\257\345\207\275\346\225\260.md" => "article/33-javascript\347\232\204\347\272\257\345\207\275\346\225\260.md" (100%) rename "34-\346\210\221\347\234\274\344\270\255\347\232\204async&await.md" => "article/34-\346\210\221\347\234\274\344\270\255\347\232\204async&await.md" (100%) rename "35-ES6\344\270\255\347\232\204\346\250\241\345\235\227\345\257\274\345\205\245\345\257\274\345\207\272\346\225\264\347\220\206.md" => "article/35-ES6\344\270\255\347\232\204\346\250\241\345\235\227\345\257\274\345\205\245\345\257\274\345\207\272\346\225\264\347\220\206.md" (100%) rename "36-\345\245\275\345\245\275\345\255\246\344\271\240toLocaleString\346\226\271\346\263\225.md" => "article/36-\345\245\275\345\245\275\345\255\246\344\271\240toLocaleString\346\226\271\346\263\225.md" (100%) rename "37-JavaScript\344\272\213\344\273\266\345\247\224\346\211\230\350\257\246\350\247\243.md" => "article/37-JavaScript\344\272\213\344\273\266\345\247\224\346\211\230\350\257\246\350\247\243.md" (100%) rename "38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" => "article/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" (100%) rename "39-\344\275\234\344\270\272\345\211\215\347\253\257\351\234\200\350\246\201\344\272\206\350\247\243\347\232\204\345\274\200\346\272\220\345\215\217\350\256\256\347\237\245\350\257\206.md" => "article/39-\344\275\234\344\270\272\345\211\215\347\253\257\351\234\200\350\246\201\344\272\206\350\247\243\347\232\204\345\274\200\346\272\220\345\215\217\350\256\256\347\237\245\350\257\206.md" (100%) rename "4-\345\237\272\344\272\216Vue\351\205\215\347\275\256axios.md" => "article/4-\345\237\272\344\272\216Vue\351\205\215\347\275\256axios.md" (100%) rename "40-\350\247\243\345\257\206Vue SSR.md" => "article/40-\350\247\243\345\257\206Vue SSR.md" (100%) rename "41-ES2018\357\274\210ES9\357\274\211\347\232\204\346\226\260\347\211\271\346\200\247.md" => "article/41-ES2018\357\274\210ES9\357\274\211\347\232\204\346\226\260\347\211\271\346\200\247.md" (100%) rename "42-JS\351\253\230\347\250\213\344\270\255\347\232\204\345\236\203\345\234\276\345\233\236\346\224\266\346\234\272\345\210\266\344\270\216\345\270\270\350\247\201\345\206\205\345\255\230\346\263\204\351\234\262\347\232\204\350\247\243\345\206\263\346\226\271\346\263\225.md" => "article/42-JS\351\253\230\347\250\213\344\270\255\347\232\204\345\236\203\345\234\276\345\233\236\346\224\266\346\234\272\345\210\266\344\270\216\345\270\270\350\247\201\345\206\205\345\255\230\346\263\204\351\234\262\347\232\204\350\247\243\345\206\263\346\226\271\346\263\225.md" (100%) rename "43-\346\211\213\346\234\272\347\253\257\351\241\265\351\235\242\345\274\200\345\217\221\345\270\270\350\247\201\351\227\256\351\242\230\345\222\214\350\247\243\345\206\263.md" => "article/43-\346\211\213\346\234\272\347\253\257\351\241\265\351\235\242\345\274\200\345\217\221\345\270\270\350\247\201\351\227\256\351\242\230\345\222\214\350\247\243\345\206\263.md" (100%) rename "44-\345\211\215\347\253\257\346\234\254\345\234\260\346\226\207\344\273\266\346\223\215\344\275\234\345\222\214\344\270\212\344\274\240.md" => "article/44-\345\211\215\347\253\257\346\234\254\345\234\260\346\226\207\344\273\266\346\223\215\344\275\234\345\222\214\344\270\212\344\274\240.md" (100%) rename "5-[\345\216\237\345\210\233]VUE\344\270\255\345\256\236\347\216\260\351\200\232\347\224\250js\345\207\275\346\225\260\345\272\223\345\260\201\350\243\205.md" => "article/5-[\345\216\237\345\210\233]VUE\344\270\255\345\256\236\347\216\260\351\200\232\347\224\250js\345\207\275\346\225\260\345\272\223\345\260\201\350\243\205.md" (100%) rename "6-\345\205\263\344\272\216js\347\232\204\344\275\234\347\224\250\345\237\237\345\222\214\345\243\260\346\230\216\346\217\220\345\211\215.md" => "article/6-\345\205\263\344\272\216js\347\232\204\344\275\234\347\224\250\345\237\237\345\222\214\345\243\260\346\230\216\346\217\220\345\211\215.md" (100%) rename "7-[\345\216\237\345\210\233]\347\274\251\345\260\217Vuejs\346\211\223\345\214\205\344\275\223\347\247\257\346\226\271\346\263\225.md" => "article/7-[\345\216\237\345\210\233]\347\274\251\345\260\217Vuejs\346\211\223\345\214\205\344\275\223\347\247\257\346\226\271\346\263\225.md" (100%) rename "8-vue-cli2\347\232\204webpack\351\205\215\347\275\256\345\210\206\346\236\220.md" => "article/8-vue-cli2\347\232\204webpack\351\205\215\347\275\256\345\210\206\346\236\220.md" (100%) rename "9-\345\270\270\347\224\250\344\270\232\345\212\241\346\250\241\345\235\227\344\273\243\347\240\201\346\225\264\347\220\206.md" => "article/9-\345\270\270\347\224\250\344\270\232\345\212\241\346\250\241\345\235\227\344\273\243\347\240\201\346\225\264\347\220\206.md" (100%) rename "\343\200\220\345\270\270\347\224\250\346\212\200\346\234\257\343\200\221Mac\347\273\210\347\253\257\345\221\275\344\273\244\345\244\247\345\205\250.md" => "article/\343\200\220\345\270\270\347\224\250\346\212\200\346\234\257\343\200\221Mac\347\273\210\347\253\257\345\221\275\344\273\244\345\244\247\345\205\250.md" (100%) diff --git "a/1-JavaScript\345\256\236\347\216\260\351\241\265\351\235\242\351\230\262\346\212\226.md" "b/article/1-JavaScript\345\256\236\347\216\260\351\241\265\351\235\242\351\230\262\346\212\226.md" similarity index 100% rename from "1-JavaScript\345\256\236\347\216\260\351\241\265\351\235\242\351\230\262\346\212\226.md" rename to "article/1-JavaScript\345\256\236\347\216\260\351\241\265\351\235\242\351\230\262\346\212\226.md" diff --git "a/10-\347\237\245\350\257\206\347\202\271\346\225\264\347\220\2061.md" "b/article/10-\347\237\245\350\257\206\347\202\271\346\225\264\347\220\2061.md" similarity index 100% rename from "10-\347\237\245\350\257\206\347\202\271\346\225\264\347\220\2061.md" rename to "article/10-\347\237\245\350\257\206\347\202\271\346\225\264\347\220\2061.md" diff --git "a/11-20\344\270\252\350\266\205\347\272\247\345\270\270\347\224\250\347\232\204\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.md" "b/article/11-20\344\270\252\350\266\205\347\272\247\345\270\270\347\224\250\347\232\204\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.md" similarity index 100% rename from "11-20\344\270\252\350\266\205\347\272\247\345\270\270\347\224\250\347\232\204\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.md" rename to "article/11-20\344\270\252\350\266\205\347\272\247\345\270\270\347\224\250\347\232\204\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.md" diff --git "a/12-javascript\345\274\200\345\217\221\347\232\204\344\270\200\344\272\233\347\256\200\345\206\231\346\212\200\345\267\247.md" "b/article/12-javascript\345\274\200\345\217\221\347\232\204\344\270\200\344\272\233\347\256\200\345\206\231\346\212\200\345\267\247.md" similarity index 100% rename from "12-javascript\345\274\200\345\217\221\347\232\204\344\270\200\344\272\233\347\256\200\345\206\231\346\212\200\345\267\247.md" rename to "article/12-javascript\345\274\200\345\217\221\347\232\204\344\270\200\344\272\233\347\256\200\345\206\231\346\212\200\345\267\247.md" diff --git "a/13-ES7\345\222\214ES8\347\232\204\344\270\200\347\202\271\346\226\260\344\270\234\350\245\277.md" "b/article/13-ES7\345\222\214ES8\347\232\204\344\270\200\347\202\271\346\226\260\344\270\234\350\245\277.md" similarity index 100% rename from "13-ES7\345\222\214ES8\347\232\204\344\270\200\347\202\271\346\226\260\344\270\234\350\245\277.md" rename to "article/13-ES7\345\222\214ES8\347\232\204\344\270\200\347\202\271\346\226\260\344\270\234\350\245\277.md" diff --git "a/14-Vue\347\232\204\344\270\200\344\272\233\345\260\217\346\263\250\346\204\217\347\202\271.md" "b/article/14-Vue\347\232\204\344\270\200\344\272\233\345\260\217\346\263\250\346\204\217\347\202\271.md" similarity index 100% rename from "14-Vue\347\232\204\344\270\200\344\272\233\345\260\217\346\263\250\346\204\217\347\202\271.md" rename to "article/14-Vue\347\232\204\344\270\200\344\272\233\345\260\217\346\263\250\346\204\217\347\202\271.md" diff --git "a/15-\347\262\276\345\277\203\346\224\266\351\233\206\347\232\20448\344\270\252JavaScript\347\211\207\346\256\265\357\274\214\347\256\200\345\215\225\347\220\206\350\247\243.md" "b/article/15-\347\262\276\345\277\203\346\224\266\351\233\206\347\232\20448\344\270\252JavaScript\347\211\207\346\256\265\357\274\214\347\256\200\345\215\225\347\220\206\350\247\243.md" similarity index 100% rename from "15-\347\262\276\345\277\203\346\224\266\351\233\206\347\232\20448\344\270\252JavaScript\347\211\207\346\256\265\357\274\214\347\256\200\345\215\225\347\220\206\350\247\243.md" rename to "article/15-\347\262\276\345\277\203\346\224\266\351\233\206\347\232\20448\344\270\252JavaScript\347\211\207\346\256\265\357\274\214\347\256\200\345\215\225\347\220\206\350\247\243.md" diff --git "a/16-\345\270\246\344\275\240\347\220\206\350\247\243 JS \345\256\271\346\230\223\345\207\272\351\224\231\347\232\204\345\235\221\345\222\214\347\273\206\350\212\202.md" "b/article/16-\345\270\246\344\275\240\347\220\206\350\247\243 JS \345\256\271\346\230\223\345\207\272\351\224\231\347\232\204\345\235\221\345\222\214\347\273\206\350\212\202.md" similarity index 100% rename from "16-\345\270\246\344\275\240\347\220\206\350\247\243 JS \345\256\271\346\230\223\345\207\272\351\224\231\347\232\204\345\235\221\345\222\214\347\273\206\350\212\202.md" rename to "article/16-\345\270\246\344\275\240\347\220\206\350\247\243 JS \345\256\271\346\230\223\345\207\272\351\224\231\347\232\204\345\235\221\345\222\214\347\273\206\350\212\202.md" diff --git "a/17-TypeScript\345\222\214 JavaScript \346\267\261\345\272\246\345\257\271\346\257\224.md" "b/article/17-TypeScript\345\222\214 JavaScript \346\267\261\345\272\246\345\257\271\346\257\224.md" similarity index 100% rename from "17-TypeScript\345\222\214 JavaScript \346\267\261\345\272\246\345\257\271\346\257\224.md" rename to "article/17-TypeScript\345\222\214 JavaScript \346\267\261\345\272\246\345\257\271\346\257\224.md" diff --git "a/18-websocket\345\270\270\347\224\250demo.md" "b/article/18-websocket\345\270\270\347\224\250demo.md" similarity index 100% rename from "18-websocket\345\270\270\347\224\250demo.md" rename to "article/18-websocket\345\270\270\347\224\250demo.md" diff --git "a/19-ES6\347\232\2047\344\270\252\345\256\236\347\224\250\346\212\200\345\267\247.md" "b/article/19-ES6\347\232\2047\344\270\252\345\256\236\347\224\250\346\212\200\345\267\247.md" similarity index 100% rename from "19-ES6\347\232\2047\344\270\252\345\256\236\347\224\250\346\212\200\345\267\247.md" rename to "article/19-ES6\347\232\2047\344\270\252\345\256\236\347\224\250\346\212\200\345\267\247.md" diff --git "a/2-\345\220\214\346\255\245\350\277\224\345\233\236ajax\350\257\267\346\261\202\347\273\223\346\236\234\346\226\271\346\263\225.md" "b/article/2-\345\220\214\346\255\245\350\277\224\345\233\236ajax\350\257\267\346\261\202\347\273\223\346\236\234\346\226\271\346\263\225.md" similarity index 100% rename from "2-\345\220\214\346\255\245\350\277\224\345\233\236ajax\350\257\267\346\261\202\347\273\223\346\236\234\346\226\271\346\263\225.md" rename to "article/2-\345\220\214\346\255\245\350\277\224\345\233\236ajax\350\257\267\346\261\202\347\273\223\346\236\234\346\226\271\346\263\225.md" diff --git "a/20-WebSocket\351\207\215\346\226\260\345\255\246\344\271\240.md" "b/article/20-WebSocket\351\207\215\346\226\260\345\255\246\344\271\240.md" similarity index 100% rename from "20-WebSocket\351\207\215\346\226\260\345\255\246\344\271\240.md" rename to "article/20-WebSocket\351\207\215\346\226\260\345\255\246\344\271\240.md" diff --git "a/2017-\345\205\250\345\271\264\346\200\273\347\273\223.md" "b/article/2017-\345\205\250\345\271\264\346\200\273\347\273\223.md" similarity index 100% rename from "2017-\345\205\250\345\271\264\346\200\273\347\273\223.md" rename to "article/2017-\345\205\250\345\271\264\346\200\273\347\273\223.md" diff --git "a/2018-\345\205\250\345\271\264\350\256\241\345\210\222.md" "b/article/2018-\345\205\250\345\271\264\350\256\241\345\210\222.md" similarity index 100% rename from "2018-\345\205\250\345\271\264\350\256\241\345\210\222.md" rename to "article/2018-\345\205\250\345\271\264\350\256\241\345\210\222.md" diff --git "a/21-JavaScript\345\274\202\346\255\245\346\234\272\345\210\266\350\257\246\350\247\243.md" "b/article/21-JavaScript\345\274\202\346\255\245\346\234\272\345\210\266\350\257\246\350\247\243.md" similarity index 100% rename from "21-JavaScript\345\274\202\346\255\245\346\234\272\345\210\266\350\257\246\350\247\243.md" rename to "article/21-JavaScript\345\274\202\346\255\245\346\234\272\345\210\266\350\257\246\350\247\243.md" diff --git "a/22-JavaScript\344\270\255\346\234\211\350\266\243\347\232\204\345\214\272\345\210\206\345\220\214\346\255\245\345\222\214\345\274\202\346\255\245Ajax.md" "b/article/22-JavaScript\344\270\255\346\234\211\350\266\243\347\232\204\345\214\272\345\210\206\345\220\214\346\255\245\345\222\214\345\274\202\346\255\245Ajax.md" similarity index 100% rename from "22-JavaScript\344\270\255\346\234\211\350\266\243\347\232\204\345\214\272\345\210\206\345\220\214\346\255\245\345\222\214\345\274\202\346\255\245Ajax.md" rename to "article/22-JavaScript\344\270\255\346\234\211\350\266\243\347\232\204\345\214\272\345\210\206\345\220\214\346\255\245\345\222\214\345\274\202\346\255\245Ajax.md" diff --git "a/23-JavaScript\345\205\253\345\274\240\346\200\235\347\273\264\345\257\274\345\233\276.md" "b/article/23-JavaScript\345\205\253\345\274\240\346\200\235\347\273\264\345\257\274\345\233\276.md" similarity index 100% rename from "23-JavaScript\345\205\253\345\274\240\346\200\235\347\273\264\345\257\274\345\233\276.md" rename to "article/23-JavaScript\345\205\253\345\274\240\346\200\235\347\273\264\345\257\274\345\233\276.md" diff --git "a/24-Vue\346\212\230\350\205\276\350\256\260-\347\273\231Axios\345\201\232\344\270\252\346\214\272\351\235\240\350\260\261\347\232\204\345\260\201\350\243\205\357\274\210\346\212\245\351\224\231,\351\211\264\346\235\203,\350\267\263\350\275\254,\346\213\246\346\210\252,\346\217\220\347\244\272\357\274\211.md" "b/article/24-Vue\346\212\230\350\205\276\350\256\260-\347\273\231Axios\345\201\232\344\270\252\346\214\272\351\235\240\350\260\261\347\232\204\345\260\201\350\243\205\357\274\210\346\212\245\351\224\231,\351\211\264\346\235\203,\350\267\263\350\275\254,\346\213\246\346\210\252,\346\217\220\347\244\272\357\274\211.md" similarity index 100% rename from "24-Vue\346\212\230\350\205\276\350\256\260-\347\273\231Axios\345\201\232\344\270\252\346\214\272\351\235\240\350\260\261\347\232\204\345\260\201\350\243\205\357\274\210\346\212\245\351\224\231,\351\211\264\346\235\203,\350\267\263\350\275\254,\346\213\246\346\210\252,\346\217\220\347\244\272\357\274\211.md" rename to "article/24-Vue\346\212\230\350\205\276\350\256\260-\347\273\231Axios\345\201\232\344\270\252\346\214\272\351\235\240\350\260\261\347\232\204\345\260\201\350\243\205\357\274\210\346\212\245\351\224\231,\351\211\264\346\235\203,\350\267\263\350\275\254,\346\213\246\346\210\252,\346\217\220\347\244\272\357\274\211.md" diff --git "a/25-Webpack\345\205\245\351\227\250\346\225\231\347\250\213\346\225\264\347\220\206\357\274\210\346\225\264\347\220\206\344\270\255\357\274\211.md" "b/article/25-Webpack\345\205\245\351\227\250\346\225\231\347\250\213\346\225\264\347\220\206\357\274\210\346\225\264\347\220\206\344\270\255\357\274\211.md" similarity index 100% rename from "25-Webpack\345\205\245\351\227\250\346\225\231\347\250\213\346\225\264\347\220\206\357\274\210\346\225\264\347\220\206\344\270\255\357\274\211.md" rename to "article/25-Webpack\345\205\245\351\227\250\346\225\231\347\250\213\346\225\264\347\220\206\357\274\210\346\225\264\347\220\206\344\270\255\357\274\211.md" diff --git "a/26-Webpack\345\270\270\347\224\250\351\205\215\347\275\256\346\225\264\347\220\206\357\274\210\346\225\264\347\220\206\344\270\255\357\274\211.md" "b/article/26-Webpack\345\270\270\347\224\250\351\205\215\347\275\256\346\225\264\347\220\206\357\274\210\346\225\264\347\220\206\344\270\255\357\274\211.md" similarity index 100% rename from "26-Webpack\345\270\270\347\224\250\351\205\215\347\275\256\346\225\264\347\220\206\357\274\210\346\225\264\347\220\206\344\270\255\357\274\211.md" rename to "article/26-Webpack\345\270\270\347\224\250\351\205\215\347\275\256\346\225\264\347\220\206\357\274\210\346\225\264\347\220\206\344\270\255\357\274\211.md" diff --git "a/27-Markdowm\350\257\255\346\263\225\346\225\264\347\220\206.md" "b/article/27-Markdowm\350\257\255\346\263\225\346\225\264\347\220\206.md" similarity index 100% rename from "27-Markdowm\350\257\255\346\263\225\346\225\264\347\220\206.md" rename to "article/27-Markdowm\350\257\255\346\263\225\346\225\264\347\220\206.md" diff --git "a/28-JavaScript\344\270\255\347\232\204void\350\277\220\347\256\227\347\254\246.md" "b/article/28-JavaScript\344\270\255\347\232\204void\350\277\220\347\256\227\347\254\246.md" similarity index 100% rename from "28-JavaScript\344\270\255\347\232\204void\350\277\220\347\256\227\347\254\246.md" rename to "article/28-JavaScript\344\270\255\347\232\204void\350\277\220\347\256\227\347\254\246.md" diff --git "a/29-\345\205\263\344\272\216\351\232\217\346\234\272\346\225\260\347\232\204\344\270\200\344\272\233\346\200\273\347\273\223.md" "b/article/29-\345\205\263\344\272\216\351\232\217\346\234\272\346\225\260\347\232\204\344\270\200\344\272\233\346\200\273\347\273\223.md" similarity index 100% rename from "29-\345\205\263\344\272\216\351\232\217\346\234\272\346\225\260\347\232\204\344\270\200\344\272\233\346\200\273\347\273\223.md" rename to "article/29-\345\205\263\344\272\216\351\232\217\346\234\272\346\225\260\347\232\204\344\270\200\344\272\233\346\200\273\347\273\223.md" diff --git "a/3-Promise\347\256\200\345\215\225\347\224\250\346\263\225.md" "b/article/3-Promise\347\256\200\345\215\225\347\224\250\346\263\225.md" similarity index 100% rename from "3-Promise\347\256\200\345\215\225\347\224\250\346\263\225.md" rename to "article/3-Promise\347\256\200\345\215\225\347\224\250\346\263\225.md" diff --git "a/30-\344\270\200\346\254\241\350\256\260\344\275\217js\347\232\2046\344\270\252\346\255\243\345\210\231\346\226\271\346\263\225.md" "b/article/30-\344\270\200\346\254\241\350\256\260\344\275\217js\347\232\2046\344\270\252\346\255\243\345\210\231\346\226\271\346\263\225.md" similarity index 100% rename from "30-\344\270\200\346\254\241\350\256\260\344\275\217js\347\232\2046\344\270\252\346\255\243\345\210\231\346\226\271\346\263\225.md" rename to "article/30-\344\270\200\346\254\241\350\256\260\344\275\217js\347\232\2046\344\270\252\346\255\243\345\210\231\346\226\271\346\263\225.md" diff --git "a/31-ES6\350\277\231\344\272\233\345\260\261\345\244\237\344\272\206.md" "b/article/31-ES6\350\277\231\344\272\233\345\260\261\345\244\237\344\272\206.md" similarity index 100% rename from "31-ES6\350\277\231\344\272\233\345\260\261\345\244\237\344\272\206.md" rename to "article/31-ES6\350\277\231\344\272\233\345\260\261\345\244\237\344\272\206.md" diff --git "a/32-\350\201\212\344\270\200\350\201\212JavaScript\347\232\204IIFE.md" "b/article/32-\350\201\212\344\270\200\350\201\212JavaScript\347\232\204IIFE.md" similarity index 100% rename from "32-\350\201\212\344\270\200\350\201\212JavaScript\347\232\204IIFE.md" rename to "article/32-\350\201\212\344\270\200\350\201\212JavaScript\347\232\204IIFE.md" diff --git "a/33-javascript\347\232\204\347\272\257\345\207\275\346\225\260.md" "b/article/33-javascript\347\232\204\347\272\257\345\207\275\346\225\260.md" similarity index 100% rename from "33-javascript\347\232\204\347\272\257\345\207\275\346\225\260.md" rename to "article/33-javascript\347\232\204\347\272\257\345\207\275\346\225\260.md" diff --git "a/34-\346\210\221\347\234\274\344\270\255\347\232\204async&await.md" "b/article/34-\346\210\221\347\234\274\344\270\255\347\232\204async&await.md" similarity index 100% rename from "34-\346\210\221\347\234\274\344\270\255\347\232\204async&await.md" rename to "article/34-\346\210\221\347\234\274\344\270\255\347\232\204async&await.md" diff --git "a/35-ES6\344\270\255\347\232\204\346\250\241\345\235\227\345\257\274\345\205\245\345\257\274\345\207\272\346\225\264\347\220\206.md" "b/article/35-ES6\344\270\255\347\232\204\346\250\241\345\235\227\345\257\274\345\205\245\345\257\274\345\207\272\346\225\264\347\220\206.md" similarity index 100% rename from "35-ES6\344\270\255\347\232\204\346\250\241\345\235\227\345\257\274\345\205\245\345\257\274\345\207\272\346\225\264\347\220\206.md" rename to "article/35-ES6\344\270\255\347\232\204\346\250\241\345\235\227\345\257\274\345\205\245\345\257\274\345\207\272\346\225\264\347\220\206.md" diff --git "a/36-\345\245\275\345\245\275\345\255\246\344\271\240toLocaleString\346\226\271\346\263\225.md" "b/article/36-\345\245\275\345\245\275\345\255\246\344\271\240toLocaleString\346\226\271\346\263\225.md" similarity index 100% rename from "36-\345\245\275\345\245\275\345\255\246\344\271\240toLocaleString\346\226\271\346\263\225.md" rename to "article/36-\345\245\275\345\245\275\345\255\246\344\271\240toLocaleString\346\226\271\346\263\225.md" diff --git "a/37-JavaScript\344\272\213\344\273\266\345\247\224\346\211\230\350\257\246\350\247\243.md" "b/article/37-JavaScript\344\272\213\344\273\266\345\247\224\346\211\230\350\257\246\350\247\243.md" similarity index 100% rename from "37-JavaScript\344\272\213\344\273\266\345\247\224\346\211\230\350\257\246\350\247\243.md" rename to "article/37-JavaScript\344\272\213\344\273\266\345\247\224\346\211\230\350\257\246\350\247\243.md" diff --git "a/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" "b/article/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" similarity index 100% rename from "38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" rename to "article/38-JavaScript\344\270\255\345\270\270\350\247\201\350\256\276\350\256\241\346\250\241\345\274\217.md" diff --git "a/39-\344\275\234\344\270\272\345\211\215\347\253\257\351\234\200\350\246\201\344\272\206\350\247\243\347\232\204\345\274\200\346\272\220\345\215\217\350\256\256\347\237\245\350\257\206.md" "b/article/39-\344\275\234\344\270\272\345\211\215\347\253\257\351\234\200\350\246\201\344\272\206\350\247\243\347\232\204\345\274\200\346\272\220\345\215\217\350\256\256\347\237\245\350\257\206.md" similarity index 100% rename from "39-\344\275\234\344\270\272\345\211\215\347\253\257\351\234\200\350\246\201\344\272\206\350\247\243\347\232\204\345\274\200\346\272\220\345\215\217\350\256\256\347\237\245\350\257\206.md" rename to "article/39-\344\275\234\344\270\272\345\211\215\347\253\257\351\234\200\350\246\201\344\272\206\350\247\243\347\232\204\345\274\200\346\272\220\345\215\217\350\256\256\347\237\245\350\257\206.md" diff --git "a/4-\345\237\272\344\272\216Vue\351\205\215\347\275\256axios.md" "b/article/4-\345\237\272\344\272\216Vue\351\205\215\347\275\256axios.md" similarity index 100% rename from "4-\345\237\272\344\272\216Vue\351\205\215\347\275\256axios.md" rename to "article/4-\345\237\272\344\272\216Vue\351\205\215\347\275\256axios.md" diff --git "a/40-\350\247\243\345\257\206Vue SSR.md" "b/article/40-\350\247\243\345\257\206Vue SSR.md" similarity index 100% rename from "40-\350\247\243\345\257\206Vue SSR.md" rename to "article/40-\350\247\243\345\257\206Vue SSR.md" diff --git "a/41-ES2018\357\274\210ES9\357\274\211\347\232\204\346\226\260\347\211\271\346\200\247.md" "b/article/41-ES2018\357\274\210ES9\357\274\211\347\232\204\346\226\260\347\211\271\346\200\247.md" similarity index 100% rename from "41-ES2018\357\274\210ES9\357\274\211\347\232\204\346\226\260\347\211\271\346\200\247.md" rename to "article/41-ES2018\357\274\210ES9\357\274\211\347\232\204\346\226\260\347\211\271\346\200\247.md" diff --git "a/42-JS\351\253\230\347\250\213\344\270\255\347\232\204\345\236\203\345\234\276\345\233\236\346\224\266\346\234\272\345\210\266\344\270\216\345\270\270\350\247\201\345\206\205\345\255\230\346\263\204\351\234\262\347\232\204\350\247\243\345\206\263\346\226\271\346\263\225.md" "b/article/42-JS\351\253\230\347\250\213\344\270\255\347\232\204\345\236\203\345\234\276\345\233\236\346\224\266\346\234\272\345\210\266\344\270\216\345\270\270\350\247\201\345\206\205\345\255\230\346\263\204\351\234\262\347\232\204\350\247\243\345\206\263\346\226\271\346\263\225.md" similarity index 100% rename from "42-JS\351\253\230\347\250\213\344\270\255\347\232\204\345\236\203\345\234\276\345\233\236\346\224\266\346\234\272\345\210\266\344\270\216\345\270\270\350\247\201\345\206\205\345\255\230\346\263\204\351\234\262\347\232\204\350\247\243\345\206\263\346\226\271\346\263\225.md" rename to "article/42-JS\351\253\230\347\250\213\344\270\255\347\232\204\345\236\203\345\234\276\345\233\236\346\224\266\346\234\272\345\210\266\344\270\216\345\270\270\350\247\201\345\206\205\345\255\230\346\263\204\351\234\262\347\232\204\350\247\243\345\206\263\346\226\271\346\263\225.md" diff --git "a/43-\346\211\213\346\234\272\347\253\257\351\241\265\351\235\242\345\274\200\345\217\221\345\270\270\350\247\201\351\227\256\351\242\230\345\222\214\350\247\243\345\206\263.md" "b/article/43-\346\211\213\346\234\272\347\253\257\351\241\265\351\235\242\345\274\200\345\217\221\345\270\270\350\247\201\351\227\256\351\242\230\345\222\214\350\247\243\345\206\263.md" similarity index 100% rename from "43-\346\211\213\346\234\272\347\253\257\351\241\265\351\235\242\345\274\200\345\217\221\345\270\270\350\247\201\351\227\256\351\242\230\345\222\214\350\247\243\345\206\263.md" rename to "article/43-\346\211\213\346\234\272\347\253\257\351\241\265\351\235\242\345\274\200\345\217\221\345\270\270\350\247\201\351\227\256\351\242\230\345\222\214\350\247\243\345\206\263.md" diff --git "a/44-\345\211\215\347\253\257\346\234\254\345\234\260\346\226\207\344\273\266\346\223\215\344\275\234\345\222\214\344\270\212\344\274\240.md" "b/article/44-\345\211\215\347\253\257\346\234\254\345\234\260\346\226\207\344\273\266\346\223\215\344\275\234\345\222\214\344\270\212\344\274\240.md" similarity index 100% rename from "44-\345\211\215\347\253\257\346\234\254\345\234\260\346\226\207\344\273\266\346\223\215\344\275\234\345\222\214\344\270\212\344\274\240.md" rename to "article/44-\345\211\215\347\253\257\346\234\254\345\234\260\346\226\207\344\273\266\346\223\215\344\275\234\345\222\214\344\270\212\344\274\240.md" diff --git "a/5-[\345\216\237\345\210\233]VUE\344\270\255\345\256\236\347\216\260\351\200\232\347\224\250js\345\207\275\346\225\260\345\272\223\345\260\201\350\243\205.md" "b/article/5-[\345\216\237\345\210\233]VUE\344\270\255\345\256\236\347\216\260\351\200\232\347\224\250js\345\207\275\346\225\260\345\272\223\345\260\201\350\243\205.md" similarity index 100% rename from "5-[\345\216\237\345\210\233]VUE\344\270\255\345\256\236\347\216\260\351\200\232\347\224\250js\345\207\275\346\225\260\345\272\223\345\260\201\350\243\205.md" rename to "article/5-[\345\216\237\345\210\233]VUE\344\270\255\345\256\236\347\216\260\351\200\232\347\224\250js\345\207\275\346\225\260\345\272\223\345\260\201\350\243\205.md" diff --git "a/6-\345\205\263\344\272\216js\347\232\204\344\275\234\347\224\250\345\237\237\345\222\214\345\243\260\346\230\216\346\217\220\345\211\215.md" "b/article/6-\345\205\263\344\272\216js\347\232\204\344\275\234\347\224\250\345\237\237\345\222\214\345\243\260\346\230\216\346\217\220\345\211\215.md" similarity index 100% rename from "6-\345\205\263\344\272\216js\347\232\204\344\275\234\347\224\250\345\237\237\345\222\214\345\243\260\346\230\216\346\217\220\345\211\215.md" rename to "article/6-\345\205\263\344\272\216js\347\232\204\344\275\234\347\224\250\345\237\237\345\222\214\345\243\260\346\230\216\346\217\220\345\211\215.md" diff --git "a/7-[\345\216\237\345\210\233]\347\274\251\345\260\217Vuejs\346\211\223\345\214\205\344\275\223\347\247\257\346\226\271\346\263\225.md" "b/article/7-[\345\216\237\345\210\233]\347\274\251\345\260\217Vuejs\346\211\223\345\214\205\344\275\223\347\247\257\346\226\271\346\263\225.md" similarity index 100% rename from "7-[\345\216\237\345\210\233]\347\274\251\345\260\217Vuejs\346\211\223\345\214\205\344\275\223\347\247\257\346\226\271\346\263\225.md" rename to "article/7-[\345\216\237\345\210\233]\347\274\251\345\260\217Vuejs\346\211\223\345\214\205\344\275\223\347\247\257\346\226\271\346\263\225.md" diff --git "a/8-vue-cli2\347\232\204webpack\351\205\215\347\275\256\345\210\206\346\236\220.md" "b/article/8-vue-cli2\347\232\204webpack\351\205\215\347\275\256\345\210\206\346\236\220.md" similarity index 100% rename from "8-vue-cli2\347\232\204webpack\351\205\215\347\275\256\345\210\206\346\236\220.md" rename to "article/8-vue-cli2\347\232\204webpack\351\205\215\347\275\256\345\210\206\346\236\220.md" diff --git "a/9-\345\270\270\347\224\250\344\270\232\345\212\241\346\250\241\345\235\227\344\273\243\347\240\201\346\225\264\347\220\206.md" "b/article/9-\345\270\270\347\224\250\344\270\232\345\212\241\346\250\241\345\235\227\344\273\243\347\240\201\346\225\264\347\220\206.md" similarity index 100% rename from "9-\345\270\270\347\224\250\344\270\232\345\212\241\346\250\241\345\235\227\344\273\243\347\240\201\346\225\264\347\220\206.md" rename to "article/9-\345\270\270\347\224\250\344\270\232\345\212\241\346\250\241\345\235\227\344\273\243\347\240\201\346\225\264\347\220\206.md" diff --git "a/\343\200\220\345\270\270\347\224\250\346\212\200\346\234\257\343\200\221Mac\347\273\210\347\253\257\345\221\275\344\273\244\345\244\247\345\205\250.md" "b/article/\343\200\220\345\270\270\347\224\250\346\212\200\346\234\257\343\200\221Mac\347\273\210\347\253\257\345\221\275\344\273\244\345\244\247\345\205\250.md" similarity index 100% rename from "\343\200\220\345\270\270\347\224\250\346\212\200\346\234\257\343\200\221Mac\347\273\210\347\253\257\345\221\275\344\273\244\345\244\247\345\205\250.md" rename to "article/\343\200\220\345\270\270\347\224\250\346\212\200\346\234\257\343\200\221Mac\347\273\210\347\253\257\345\221\275\344\273\244\345\244\247\345\205\250.md" From 0d6fa784476d1c21f7a34bf9b23639cc43da34ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 3 Sep 2018 19:25:03 +0800 Subject: [PATCH 035/835] =?UTF-8?q?2018.09.03=20=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E7=9B=AE=E5=BD=95=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 92 +++++++++++++++++++++++++++---------------------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index 96d683ec..ada09b25 100644 --- a/README.md +++ b/README.md @@ -11,61 +11,61 @@ ## 目录 ### 1、JS业务逻辑实现 -* [1-JavaScript实现页面防抖](https://github.com/pingan8787/Leo-JavaScript/blob/master/1-JavaScript%E5%AE%9E%E7%8E%B0%E9%A1%B5%E9%9D%A2%E9%98%B2%E6%8A%96.md) -* [2-同步返回ajax请求结果方法](https://github.com/pingan8787/Leo-JavaScript/blob/master/2-%E5%90%8C%E6%AD%A5%E8%BF%94%E5%9B%9Eajax%E8%AF%B7%E6%B1%82%E7%BB%93%E6%9E%9C%E6%96%B9%E6%B3%95.md) -* [★ 9-常用业务模块代码整理](https://github.com/pingan8787/Leo-JavaScript/blob/master/9-%E5%B8%B8%E7%94%A8%E4%B8%9A%E5%8A%A1%E6%A8%A1%E5%9D%97%E4%BB%A3%E7%A0%81%E6%95%B4%E7%90%86.md) -* [12-javascript开发的一些简写技巧](https://github.com/pingan8787/Leo-JavaScript/blob/master/12-javascript%E5%BC%80%E5%8F%91%E7%9A%84%E4%B8%80%E4%BA%9B%E7%AE%80%E5%86%99%E6%8A%80%E5%B7%A7.md) -* [15-精心收集的48个JavaScript片段,简单理解](https://github.com/pingan8787/Leo-JavaScript/blob/master/15-%E7%B2%BE%E5%BF%83%E6%94%B6%E9%9B%86%E7%9A%8448%E4%B8%AAJavaScript%E7%89%87%E6%AE%B5%EF%BC%8C%E7%AE%80%E5%8D%95%E7%90%86%E8%A7%A3.md) -* [29-关于随机数的一些总结](https://github.com/pingan8787/Leo-JavaScript/blob/master/29-%E5%85%B3%E4%BA%8E%E9%9A%8F%E6%9C%BA%E6%95%B0%E7%9A%84%E4%B8%80%E4%BA%9B%E6%80%BB%E7%BB%93.md) +* [1-JavaScript实现页面防抖](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/1-JavaScript%E5%AE%9E%E7%8E%B0%E9%A1%B5%E9%9D%A2%E9%98%B2%E6%8A%96.md) +* [2-同步返回ajax请求结果方法](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/2-%E5%90%8C%E6%AD%A5%E8%BF%94%E5%9B%9Eajax%E8%AF%B7%E6%B1%82%E7%BB%93%E6%9E%9C%E6%96%B9%E6%B3%95.md) +* [★ 9-常用业务模块代码整理](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/9-%E5%B8%B8%E7%94%A8%E4%B8%9A%E5%8A%A1%E6%A8%A1%E5%9D%97%E4%BB%A3%E7%A0%81%E6%95%B4%E7%90%86.md) +* [12-javascript开发的一些简写技巧](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/12-javascript%E5%BC%80%E5%8F%91%E7%9A%84%E4%B8%80%E4%BA%9B%E7%AE%80%E5%86%99%E6%8A%80%E5%B7%A7.md) +* [15-精心收集的48个JavaScript片段,简单理解](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/15-%E7%B2%BE%E5%BF%83%E6%94%B6%E9%9B%86%E7%9A%8448%E4%B8%AAJavaScript%E7%89%87%E6%AE%B5%EF%BC%8C%E7%AE%80%E5%8D%95%E7%90%86%E8%A7%A3.md) +* [29-关于随机数的一些总结](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/29-%E5%85%B3%E4%BA%8E%E9%9A%8F%E6%9C%BA%E6%95%B0%E7%9A%84%E4%B8%80%E4%BA%9B%E6%80%BB%E7%BB%93.md) ### 2、VueJS -* [4-基于Vue配置axios](https://github.com/pingan8787/Leo-JavaScript/blob/master/4-%E5%9F%BA%E4%BA%8EVue%E9%85%8D%E7%BD%AEaxios.md) -* [★ 5-[原创]VUE中实现通用js函数库封装](https://github.com/pingan8787/Leo-JavaScript/blob/master/5-%5B%E5%8E%9F%E5%88%9B%5DVUE%E4%B8%AD%E5%AE%9E%E7%8E%B0%E9%80%9A%E7%94%A8js%E5%87%BD%E6%95%B0%E5%BA%93%E5%B0%81%E8%A3%85.md) -* [★ 7-[原创]缩小Vuejs打包体积方法](https://github.com/pingan8787/Leo-JavaScript/blob/master/7-%5B%E5%8E%9F%E5%88%9B%5D%E7%BC%A9%E5%B0%8FVuejs%E6%89%93%E5%8C%85%E4%BD%93%E7%A7%AF%E6%96%B9%E6%B3%95.md) -* [8-vue-cli2的webpack配置分析](https://github.com/pingan8787/Leo-JavaScript/blob/master/8-vue-cli2%E7%9A%84webpack%E9%85%8D%E7%BD%AE%E5%88%86%E6%9E%90.md) -* [14-Vue的一些小注意点](https://github.com/pingan8787/Leo-JavaScript/blob/master/14-Vue%E7%9A%84%E4%B8%80%E4%BA%9B%E5%B0%8F%E6%B3%A8%E6%84%8F%E7%82%B9.md) -* [★ 24-Vue折腾记-给Axios做个挺靠谱的封装(报错,鉴权,跳转,拦截,提示)](https://github.com/pingan8787/Leo-JavaScript/blob/master/24-Vue%E6%8A%98%E8%85%BE%E8%AE%B0-%E7%BB%99Axios%E5%81%9A%E4%B8%AA%E6%8C%BA%E9%9D%A0%E8%B0%B1%E7%9A%84%E5%B0%81%E8%A3%85%EF%BC%88%E6%8A%A5%E9%94%99%2C%E9%89%B4%E6%9D%83%2C%E8%B7%B3%E8%BD%AC%2C%E6%8B%A6%E6%88%AA%2C%E6%8F%90%E7%A4%BA%EF%BC%89.md) -* [40-解密Vue SSR](https://github.com/pingan8787/Leo-JavaScript/blob/master/40-%E8%A7%A3%E5%AF%86Vue%20SSR.md) +* [4-基于Vue配置axios](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/4-%E5%9F%BA%E4%BA%8EVue%E9%85%8D%E7%BD%AEaxios.md) +* [★ 5-[原创]VUE中实现通用js函数库封装](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/5-%5B%E5%8E%9F%E5%88%9B%5DVUE%E4%B8%AD%E5%AE%9E%E7%8E%B0%E9%80%9A%E7%94%A8js%E5%87%BD%E6%95%B0%E5%BA%93%E5%B0%81%E8%A3%85.md) +* [★ 7-[原创]缩小Vuejs打包体积方法](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/7-%5B%E5%8E%9F%E5%88%9B%5D%E7%BC%A9%E5%B0%8FVuejs%E6%89%93%E5%8C%85%E4%BD%93%E7%A7%AF%E6%96%B9%E6%B3%95.md) +* [8-vue-cli2的webpack配置分析](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/8-vue-cli2%E7%9A%84webpack%E9%85%8D%E7%BD%AE%E5%88%86%E6%9E%90.md) +* [14-Vue的一些小注意点](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/14-Vue%E7%9A%84%E4%B8%80%E4%BA%9B%E5%B0%8F%E6%B3%A8%E6%84%8F%E7%82%B9.md) +* [★ 24-Vue折腾记-给Axios做个挺靠谱的封装(报错,鉴权,跳转,拦截,提示)](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/24-Vue%E6%8A%98%E8%85%BE%E8%AE%B0-%E7%BB%99Axios%E5%81%9A%E4%B8%AA%E6%8C%BA%E9%9D%A0%E8%B0%B1%E7%9A%84%E5%B0%81%E8%A3%85%EF%BC%88%E6%8A%A5%E9%94%99%2C%E9%89%B4%E6%9D%83%2C%E8%B7%B3%E8%BD%AC%2C%E6%8B%A6%E6%88%AA%2C%E6%8F%90%E7%A4%BA%EF%BC%89.md) +* [40-解密Vue SSR](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/40-%E8%A7%A3%E5%AF%86Vue%20SSR.md) ### 3、ES6/ES7/ES8... -* [3-Promise简单用法](https://github.com/pingan8787/Leo-JavaScript/blob/master/3-Promise%E7%AE%80%E5%8D%95%E7%94%A8%E6%B3%95.md) -* [13-ES7和ES8的一点新东西](https://github.com/pingan8787/Leo-JavaScript/blob/master/13-ES7%E5%92%8CES8%E7%9A%84%E4%B8%80%E7%82%B9%E6%96%B0%E4%B8%9C%E8%A5%BF.md) -* [19-ES6的7个实用技巧](https://github.com/pingan8787/Leo-JavaScript/blob/master/19-ES6%E7%9A%847%E4%B8%AA%E5%AE%9E%E7%94%A8%E6%8A%80%E5%B7%A7.md) -* [★ 31-ES6这些就够了](https://github.com/pingan8787/Leo-JavaScript/blob/master/31-ES6%E8%BF%99%E4%BA%9B%E5%B0%B1%E5%A4%9F%E4%BA%86.md) -* [★ 34-我眼中的async&await](https://github.com/pingan8787/Leo-JavaScript/blob/master/34-%E6%88%91%E7%9C%BC%E4%B8%AD%E7%9A%84async%26await.md) -* [35-ES6中的模块导入导出整理](https://github.com/pingan8787/Leo-JavaScript/blob/master/35-ES6%E4%B8%AD%E7%9A%84%E6%A8%A1%E5%9D%97%E5%AF%BC%E5%85%A5%E5%AF%BC%E5%87%BA%E6%95%B4%E7%90%86.md) -* [41-ES2018(ES9)的新特性](https://github.com/pingan8787/Leo-JavaScript/blob/master/41-ES2018%EF%BC%88ES9%EF%BC%89%E7%9A%84%E6%96%B0%E7%89%B9%E6%80%A7.md) +* [3-Promise简单用法](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/3-Promise%E7%AE%80%E5%8D%95%E7%94%A8%E6%B3%95.md) +* [13-ES7和ES8的一点新东西](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/13-ES7%E5%92%8CES8%E7%9A%84%E4%B8%80%E7%82%B9%E6%96%B0%E4%B8%9C%E8%A5%BF.md) +* [19-ES6的7个实用技巧](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/19-ES6%E7%9A%847%E4%B8%AA%E5%AE%9E%E7%94%A8%E6%8A%80%E5%B7%A7.md) +* [★ 31-ES6这些就够了](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/31-ES6%E8%BF%99%E4%BA%9B%E5%B0%B1%E5%A4%9F%E4%BA%86.md) +* [★ 34-我眼中的async&await](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/34-%E6%88%91%E7%9C%BC%E4%B8%AD%E7%9A%84async%26await.md) +* [35-ES6中的模块导入导出整理](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/35-ES6%E4%B8%AD%E7%9A%84%E6%A8%A1%E5%9D%97%E5%AF%BC%E5%85%A5%E5%AF%BC%E5%87%BA%E6%95%B4%E7%90%86.md) +* [41-ES2018(ES9)的新特性](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/41-ES2018%EF%BC%88ES9%EF%BC%89%E7%9A%84%E6%96%B0%E7%89%B9%E6%80%A7.md) ### 4、Webpack -* [25-Webpack入门教程整理(整理中)](https://github.com/pingan8787/Leo-JavaScript/blob/master/25-Webpack%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%E6%95%B4%E7%90%86%EF%BC%88%E6%95%B4%E7%90%86%E4%B8%AD%EF%BC%89.md) -* [26-Webpack常用配置整理(整理中)](https://github.com/pingan8787/Leo-JavaScript/blob/master/26-Webpack%E5%B8%B8%E7%94%A8%E9%85%8D%E7%BD%AE%E6%95%B4%E7%90%86%EF%BC%88%E6%95%B4%E7%90%86%E4%B8%AD%EF%BC%89.md) +* [25-Webpack入门教程整理(整理中)](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/25-Webpack%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%E6%95%B4%E7%90%86%EF%BC%88%E6%95%B4%E7%90%86%E4%B8%AD%EF%BC%89.md) +* [26-Webpack常用配置整理(整理中)](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/26-Webpack%E5%B8%B8%E7%94%A8%E9%85%8D%E7%BD%AE%E6%95%B4%E7%90%86%EF%BC%88%E6%95%B4%E7%90%86%E4%B8%AD%EF%BC%89.md) ### 5、WebSocket -* [18-websocket常用demo](https://github.com/pingan8787/Leo-JavaScript/blob/master/18-websocket%E5%B8%B8%E7%94%A8demo.md) -* [★ 20-WebSocket重新学习](https://github.com/pingan8787/Leo-JavaScript/blob/master/20-WebSocket%E9%87%8D%E6%96%B0%E5%AD%A6%E4%B9%A0.md) +* [18-websocket常用demo](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/18-websocket%E5%B8%B8%E7%94%A8demo.md) +* [★ 20-WebSocket重新学习](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/20-WebSocket%E9%87%8D%E6%96%B0%E5%AD%A6%E4%B9%A0.md) ### 6、细节知识点 -* [6-关于js的作用域和声明提前](https://github.com/pingan8787/Leo-JavaScript/blob/master/6-%E5%85%B3%E4%BA%8Ejs%E7%9A%84%E4%BD%9C%E7%94%A8%E5%9F%9F%E5%92%8C%E5%A3%B0%E6%98%8E%E6%8F%90%E5%89%8D.md) -* [★ 10-知识点整理1](https://github.com/pingan8787/Leo-JavaScript/blob/master/10-%E7%9F%A5%E8%AF%86%E7%82%B9%E6%95%B4%E7%90%861.md) -* [11-20个超级常用的正则表达式](https://github.com/pingan8787/Leo-JavaScript/blob/master/11-20%E4%B8%AA%E8%B6%85%E7%BA%A7%E5%B8%B8%E7%94%A8%E7%9A%84%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F.md) -* [16-带你理解 JS 容易出错的坑和细节](https://github.com/pingan8787/Leo-JavaScript/blob/master/16-%E5%B8%A6%E4%BD%A0%E7%90%86%E8%A7%A3%20JS%20%E5%AE%B9%E6%98%93%E5%87%BA%E9%94%99%E7%9A%84%E5%9D%91%E5%92%8C%E7%BB%86%E8%8A%82.md) -* [17-TypeScript和 JavaScript 深度对比](https://github.com/pingan8787/Leo-JavaScript/blob/master/17-TypeScript%E5%92%8C%20JavaScript%20%E6%B7%B1%E5%BA%A6%E5%AF%B9%E6%AF%94.md) -* [★ 21-JavaScript异步机制详解](https://github.com/pingan8787/Leo-JavaScript/blob/master/21-JavaScript%E5%BC%82%E6%AD%A5%E6%9C%BA%E5%88%B6%E8%AF%A6%E8%A7%A3.md) -* [22-JavaScript中有趣的区分同步和异步Ajax](https://github.com/pingan8787/Leo-JavaScript/blob/master/22-JavaScript%E4%B8%AD%E6%9C%89%E8%B6%A3%E7%9A%84%E5%8C%BA%E5%88%86%E5%90%8C%E6%AD%A5%E5%92%8C%E5%BC%82%E6%AD%A5Ajax.md) -* [23-JavaScript八张思维导图](https://github.com/pingan8787/Leo-JavaScript/blob/master/23-JavaScript%E5%85%AB%E5%BC%A0%E6%80%9D%E7%BB%B4%E5%AF%BC%E5%9B%BE.md) -* [28-JavaScript中的void运算符](https://github.com/pingan8787/Leo-JavaScript/blob/master/28-JavaScript%E4%B8%AD%E7%9A%84void%E8%BF%90%E7%AE%97%E7%AC%A6.md) -* [30-一次记住js的6个正则方法](https://github.com/pingan8787/Leo-JavaScript/blob/master/30-%E4%B8%80%E6%AC%A1%E8%AE%B0%E4%BD%8Fjs%E7%9A%846%E4%B8%AA%E6%AD%A3%E5%88%99%E6%96%B9%E6%B3%95.md) -* [31-聊一聊JavaScript的IIFE](https://github.com/pingan8787/Leo-JavaScript/blob/master/32-%E8%81%8A%E4%B8%80%E8%81%8AJavaScript%E7%9A%84IIFE.md) -* [33-javascript的纯函数](https://github.com/pingan8787/Leo-JavaScript/blob/master/33-javascript%E7%9A%84%E7%BA%AF%E5%87%BD%E6%95%B0.md) -* [36-好好学习toLocaleString方法](https://github.com/pingan8787/Leo-JavaScript/blob/master/36-%E5%A5%BD%E5%A5%BD%E5%AD%A6%E4%B9%A0toLocaleString%E6%96%B9%E6%B3%95.md) -* [37-JavaScript事件委托详解](https://github.com/pingan8787/Leo-JavaScript/blob/master/37-JavaScript%E4%BA%8B%E4%BB%B6%E5%A7%94%E6%89%98%E8%AF%A6%E8%A7%A3.md) -* [38-JavaScript中常见设计模式](https://github.com/pingan8787/Leo-JavaScript/blob/master/38-JavaScript%E4%B8%AD%E5%B8%B8%E8%A7%81%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.md) -* [42-JS高程中的垃圾回收机制与常见内存泄露的解决方法](https://github.com/pingan8787/Leo-JavaScript/blob/master/42-JS%E9%AB%98%E7%A8%8B%E4%B8%AD%E7%9A%84%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6%E4%B8%8E%E5%B8%B8%E8%A7%81%E5%86%85%E5%AD%98%E6%B3%84%E9%9C%B2%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95.md) -* [43-手机端页面开发常见问题和解决](https://github.com/pingan8787/Leo-JavaScript/blob/master/43-%E6%89%8B%E6%9C%BA%E7%AB%AF%E9%A1%B5%E9%9D%A2%E5%BC%80%E5%8F%91%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E5%92%8C%E8%A7%A3%E5%86%B3.md) -* [44-前端本地文件操作和上传](https://github.com/pingan8787/Leo-JavaScript/blob/master/44-%E5%89%8D%E7%AB%AF%E6%9C%AC%E5%9C%B0%E6%96%87%E4%BB%B6%E6%93%8D%E4%BD%9C%E5%92%8C%E4%B8%8A%E4%BC%A0.md) +* [6-关于js的作用域和声明提前](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/6-%E5%85%B3%E4%BA%8Ejs%E7%9A%84%E4%BD%9C%E7%94%A8%E5%9F%9F%E5%92%8C%E5%A3%B0%E6%98%8E%E6%8F%90%E5%89%8D.md) +* [★ 10-知识点整理1](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/10-%E7%9F%A5%E8%AF%86%E7%82%B9%E6%95%B4%E7%90%861.md) +* [11-20个超级常用的正则表达式](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/11-20%E4%B8%AA%E8%B6%85%E7%BA%A7%E5%B8%B8%E7%94%A8%E7%9A%84%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F.md) +* [16-带你理解 JS 容易出错的坑和细节](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/16-%E5%B8%A6%E4%BD%A0%E7%90%86%E8%A7%A3%20JS%20%E5%AE%B9%E6%98%93%E5%87%BA%E9%94%99%E7%9A%84%E5%9D%91%E5%92%8C%E7%BB%86%E8%8A%82.md) +* [17-TypeScript和 JavaScript 深度对比](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/17-TypeScript%E5%92%8C%20JavaScript%20%E6%B7%B1%E5%BA%A6%E5%AF%B9%E6%AF%94.md) +* [★ 21-JavaScript异步机制详解](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/21-JavaScript%E5%BC%82%E6%AD%A5%E6%9C%BA%E5%88%B6%E8%AF%A6%E8%A7%A3.md) +* [22-JavaScript中有趣的区分同步和异步Ajax](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/22-JavaScript%E4%B8%AD%E6%9C%89%E8%B6%A3%E7%9A%84%E5%8C%BA%E5%88%86%E5%90%8C%E6%AD%A5%E5%92%8C%E5%BC%82%E6%AD%A5Ajax.md) +* [23-JavaScript八张思维导图](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/23-JavaScript%E5%85%AB%E5%BC%A0%E6%80%9D%E7%BB%B4%E5%AF%BC%E5%9B%BE.md) +* [28-JavaScript中的void运算符](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/28-JavaScript%E4%B8%AD%E7%9A%84void%E8%BF%90%E7%AE%97%E7%AC%A6.md) +* [30-一次记住js的6个正则方法](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/30-%E4%B8%80%E6%AC%A1%E8%AE%B0%E4%BD%8Fjs%E7%9A%846%E4%B8%AA%E6%AD%A3%E5%88%99%E6%96%B9%E6%B3%95.md) +* [31-聊一聊JavaScript的IIFE](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/32-%E8%81%8A%E4%B8%80%E8%81%8AJavaScript%E7%9A%84IIFE.md) +* [33-javascript的纯函数](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/33-javascript%E7%9A%84%E7%BA%AF%E5%87%BD%E6%95%B0.md) +* [36-好好学习toLocaleString方法](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/36-%E5%A5%BD%E5%A5%BD%E5%AD%A6%E4%B9%A0toLocaleString%E6%96%B9%E6%B3%95.md) +* [37-JavaScript事件委托详解](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/37-JavaScript%E4%BA%8B%E4%BB%B6%E5%A7%94%E6%89%98%E8%AF%A6%E8%A7%A3.md) +* [38-JavaScript中常见设计模式](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/38-JavaScript%E4%B8%AD%E5%B8%B8%E8%A7%81%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.md) +* [42-JS高程中的垃圾回收机制与常见内存泄露的解决方法](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/42-JS%E9%AB%98%E7%A8%8B%E4%B8%AD%E7%9A%84%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6%E4%B8%8E%E5%B8%B8%E8%A7%81%E5%86%85%E5%AD%98%E6%B3%84%E9%9C%B2%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95.md) +* [43-手机端页面开发常见问题和解决](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/43-%E6%89%8B%E6%9C%BA%E7%AB%AF%E9%A1%B5%E9%9D%A2%E5%BC%80%E5%8F%91%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E5%92%8C%E8%A7%A3%E5%86%B3.md) +* [44-前端本地文件操作和上传](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/44-%E5%89%8D%E7%AB%AF%E6%9C%AC%E5%9C%B0%E6%96%87%E4%BB%B6%E6%93%8D%E4%BD%9C%E5%92%8C%E4%B8%8A%E4%BC%A0.md) ### 7、其他 -* [2017-全年总结](https://github.com/pingan8787/Leo-JavaScript/blob/master/2017-%E5%85%A8%E5%B9%B4%E6%80%BB%E7%BB%93.md) -* [2018-全年计划](https://github.com/pingan8787/Leo-JavaScript/blob/master/2018-%E5%85%A8%E5%B9%B4%E8%AE%A1%E5%88%92.md) -* [★ 27-Markdowm语法整理](https://github.com/pingan8787/Leo-JavaScript/blob/master/27-Markdowm%E8%AF%AD%E6%B3%95%E6%95%B4%E7%90%86.md) -* [39-作为前端需要了解的开源协议知识](https://github.com/pingan8787/Leo-JavaScript/blob/master/39-%E4%BD%9C%E4%B8%BA%E5%89%8D%E7%AB%AF%E9%9C%80%E8%A6%81%E4%BA%86%E8%A7%A3%E7%9A%84%E5%BC%80%E6%BA%90%E5%8D%8F%E8%AE%AE%E7%9F%A5%E8%AF%86.md) \ No newline at end of file +* [2017-全年总结](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/2017-%E5%85%A8%E5%B9%B4%E6%80%BB%E7%BB%93.md) +* [2018-全年计划](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/2018-%E5%85%A8%E5%B9%B4%E8%AE%A1%E5%88%92.md) +* [★ 27-Markdowm语法整理](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/27-Markdowm%E8%AF%AD%E6%B3%95%E6%95%B4%E7%90%86.md) +* [39-作为前端需要了解的开源协议知识](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/39-%E4%BD%9C%E4%B8%BA%E5%89%8D%E7%AB%AF%E9%9C%80%E8%A6%81%E4%BA%86%E8%A7%A3%E7%9A%84%E5%BC%80%E6%BA%90%E5%8D%8F%E8%AE%AE%E7%9F%A5%E8%AF%86.md) \ No newline at end of file From 157ae618b2b88916f15371a3b7ccb425471053fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Thu, 6 Sep 2018 17:57:08 +0800 Subject: [PATCH 036/835] =?UTF-8?q?2018.09.04=20=E6=B7=BB=E5=8A=A0reduce?= =?UTF-8?q?=E7=A5=9E=E5=A5=87=E7=94=A8=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...36\345\245\207\347\224\250\346\263\225.md" | 135 ++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 "article/45-js\344\270\255reduce\347\232\204\347\245\236\345\245\207\347\224\250\346\263\225.md" diff --git "a/article/45-js\344\270\255reduce\347\232\204\347\245\236\345\245\207\347\224\250\346\263\225.md" "b/article/45-js\344\270\255reduce\347\232\204\347\245\236\345\245\207\347\224\250\346\263\225.md" new file mode 100644 index 00000000..01b61708 --- /dev/null +++ "b/article/45-js\344\270\255reduce\347\232\204\347\245\236\345\245\207\347\224\250\346\263\225.md" @@ -0,0 +1,135 @@ +最近经常在项目中经常看到别人用reduce处理数据,很是牛掰,很梦幻, 不如自己琢磨琢磨。先看w3c语法。 +## w3c语法 +```js +array.reduce(function(total, currentValue, currentIndex, arr), initialValue); +/* +total: 必需。初始值, 或者计算结束后的返回值。 +currentValue: 必需。当前元素。 +currentIndex: 可选。当前元素的索引; +arr: 可选。当前元素所属的数组对象。 +initialValue: 可选。传递给函数的初始值,相当于total的初始值。 +*/ +``` + +## 常见用法 + +### 1.数组求和 +```js +const arr = [12, 34, 23]; +const sum = arr.reduce((total, num) => total + num); +// 设定初始值求和 +const arr = [12, 34, 23]; +const sum = arr.reduce((total, num) => total + num, 10); // 以10为初始值求和 +// 对象数组求和 +var result = [ +{ subject: 'math', score: 88 }, +{ subject: 'chinese', score: 95 }, +{ subject: 'english', score: 80 } +]; +const sum = result.reduce((prev, cur) => prev + cur.score, 0); +const sum = result.reduce((prev, cur) => prev + cur.score, -10); // 总分扣除10分 +``` + +### 2.数组最大值 +```js +const a = [23,123,342,12]; +const max = a.reduce(function(pre,cur,inde,arr){return pre>cur?pre:cur;}); // 342 +``` + +## 进阶用法 + +### 1.数组对象中的用法 +```js +// 比如生成“老大、老二和老三” +const objArr = [{name: '老大'}, {name: '老二'}, {name: '老三'}]; +const res = objArr.reduce((pre, cur, index, arr) => { +if (index === 0) { +return cur.name; +} +else if (index === (arr.length - 1)) { +return pre + '和' + cur.name; +} +else { +return pre + '、' + cur.name; +} +}, ''); +``` +### 2.求字符串中字母出现的次数 +```js +const str = 'sfhjasfjgfasjuwqrqadqeiqsajsdaiwqdaklldflas-cmxzmnha'; +const res = str.split('').reduce((prev, cur) => {prev[cur] ? prev[cur]++ : prev[cur] = 1; return prev;}, {}); +``` + +### 3.数组转数组 +```js +// 按照一定的规则转成数组 +var arr1 = [2, 3, 4, 5, 6]; // 每个值的平方 +var newarr = arr1.reduce((prev, cur) => {prev.push(cur * cur); return prev;}, []); +``` + +### 4.数组转对象 +```js +// 按照id 取出stream +var streams = [{name: '技术', id: 1}, {name: '设计', id: 2}]; +var obj = streams.reduce((prev, cur) => {prev[cur.id] = cur; return prev;}, {}); +``` + +## 高级用法 + +### 1.多维的叠加执行操作 +```js +// 各科成绩占比重不一样, 求结果 +var result = [ +{ subject: 'math', score: 88 }, +{ subject: 'chinese', score: 95 }, +{ subject: 'english', score: 80 } +]; +var dis = { +math: 0.5, +chinese: 0.3, +english: 0.2 +}; +var res = result.reduce((prev, cur) => dis[cur.subject] * cur.score + prev, 0); + +// 加大难度, 商品对应不同国家汇率不同,求总价格 +var prices = [{price: 23}, {price: 45}, {price: 56}]; +var rates = { +us: '6.5', +eu: '7.5', +}; +var initialState = {usTotal:0, euTotal: 0}; +var res = prices.reduce((prev1, cur1) => Object.keys(rates).reduce((prev2, cur2) => { +console.log(prev1, cur1, prev2, cur2); +prev1[`${cur2}Total`] += cur1.price * rates[cur2]; +return prev1; +}, {}), initialState); + +var manageReducers = function() { +return function(state, item) { +return Object.keys(rates).reduce((nextState, key) => { +state[`${key}Total`] += item.price * rates[key]; +return state; +}, {}); +} +}; +var res1= prices.reduce(manageReducers(), initialState); +``` + +### 2.扁平一个多维数组 +```js +var arr = [[1, 2, 8], [3, 4, 9], [5, 6, 10]]; +var res = arr.reduce((x, y) => x.concat(y), []); +``` + +### 3.对象数组去重 +```js +const hash = {}; +chatlists = chatlists.reduce((obj, next: Object) => { +const hashId = `${next.topic}_${next.stream_id}`; +if (!hash[hashId]) { +hash[`${next.topic}_${next.stream_id}`] = true; +obj.push(next); +} +return obj; +}, []); +``` From 340b0e91be94a886a224f844dfdf20c7fa35693d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 7 Sep 2018 17:14:30 +0800 Subject: [PATCH 037/835] 2018.09.07 --- ...77\347\224\250\346\225\260\347\273\204.md" | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 "article/46-\345\234\250JavaScript\344\270\255\346\233\264\345\245\275\347\232\204\344\275\277\347\224\250\346\225\260\347\273\204.md" diff --git "a/article/46-\345\234\250JavaScript\344\270\255\346\233\264\345\245\275\347\232\204\344\275\277\347\224\250\346\225\260\347\273\204.md" "b/article/46-\345\234\250JavaScript\344\270\255\346\233\264\345\245\275\347\232\204\344\275\277\347\224\250\346\225\260\347\273\204.md" new file mode 100644 index 00000000..fa6043b2 --- /dev/null +++ "b/article/46-\345\234\250JavaScript\344\270\255\346\233\264\345\245\275\347\232\204\344\275\277\347\224\250\346\225\260\347\273\204.md" @@ -0,0 +1,133 @@ +[阅读原文](https://juejin.im/post/5b8d0a74f265da431d0e7ec0) +[MDN Array 介绍](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array) + + +本文短小精悍,我保证。在过去的数个月里,我注意到在我审阅的 pull request 中有四个(关于数组使用的)错误经常出现。同时,我自己也会犯这些错误,因此有了这篇文章。让我们一起学习,以确保以后能正确地使用数组方法! + +## 1.使用 `Array.includes` 替代 `Array.indexOf` + +> "如果需要在数组中查找某个元素,请使用 `Array.indexOf`。" + +我记得在我学习 JavaScript 的课程中有类似的这么一句话。毫无疑问,这完全正确! +在 MDN 文档中,对 `Array.indexOf` 的描述是:返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回`-1`。因此,如果在之后的代码中需要用到(给给定元素的)索引,那么` Array.indexOf` 是不二之选。 +然而,如果我们仅需要知道数组中是否包含给定元素呢?这意味着只是是与否的区别,这是一个布尔问题(boolean question)。针对这种情况,我建议使用直接返回布尔值的 `Array.includes`。 +```js +'use strict'; + +const characters = [ + 'ironman', + 'black_widow', + 'hulk', + 'captain_america', + 'hulk', + 'thor', +]; + +console.log(characters.indexOf('hulk')); +// 2 +console.log(characters.indexOf('batman')); +// -1 + +console.log(characters.includes('hulk')); +// true +console.log(characters.includes('batman')); +// false +``` + +## 2.使用 `Array.find` 替代 `Array.filter` +`Array.filter` 是一个十分有用的方法。它通过回调函数过滤原数组,并将过滤后的项作为新数组返回。正如它的名字所示,我们将这个方法用于过滤,(一般而言)会获得一个长度更短的新数组。 +然而,如果知道经回调函数过滤后,只会剩余唯一的一项,那么我不建议使用 `Array.filter`。比如:使用等于某个唯一 ID 为过滤条件去过滤一个数组。在这个例子中,`Array.filter` 返回一个仅有一项的新数组。然而,我们仅仅是为了获取 ID 为特定 ID 的那一项,这个新数组显得毫无用处。 +让我们讨论一下性能。为了获取所有符合回调函数过滤条件的项,`Array.filter` 必须遍历整个数组。如果原数组中有成千上万项,回调函数需要执行的次数是相当多的。 +为避免这些情况,我建议使用 `Array.find`。它与 `Array.filter` 一样需要一个回调函数,(但只是返回)符合条件的第一项。当找到符合回调函数过滤条件的第一个元素时,它会立即停止往下的搜寻。不再遍历整个数组。 +```js +'use strict'; + +const characters = [ + { id: 1, name: 'ironman' }, + { id: 2, name: 'black_widow' }, + { id: 3, name: 'captain_america' }, + { id: 4, name: 'captain_america' }, +]; + +function getCharacter(name) { + return character => character.name === name; +} + +console.log(characters.filter(getCharacter('captain_america'))); +// [ +// { id: 3, name: 'captain_america' }, +// { id: 4, name: 'captain_america' }, +// ] + +console.log(characters.find(getCharacter('captain_america'))); +// { id: 3, name: 'captain_america' } +``` + +## 3.使用 `Array.some` 替代 `Array.find` +我承认我经常犯这个错误。之后,一位朋友建议我去查看 [MDN 文档](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/some) 以寻找更好的方法。事实上(这错误)与上面 `Array.indexOf`/`Array.includes` 的例子十分相像。 +在上面的例子中,我们知道 `Array.find` 需要一个回调函数作为参数,并返回(符合条件的)第一个元素。然而,当我们需要知道数组中是否存在一个元素时,`Array.find` 是最好的选择吗?不一定是,因为它返回一个元素,而不是一个布尔值。 +在下面的例子中,我建议使用 `Array.some`,它返回你需要的布尔值。 +```js +'use strict'; + +const characters = [ + { id: 1, name: 'ironman', env: 'marvel' }, + { id: 2, name: 'black_widow', env: 'marvel' }, + { id: 3, name: 'wonder_woman', env: 'dc_comics' }, +]; + +function hasCharacterFrom(env) { + return character => character.env === env; +} + +console.log(characters.find(hasCharacterFrom('marvel'))); +// { id: 1, name: 'ironman', env: 'marvel' } + +console.log(characters.some(hasCharacterFrom('marvel'))); +// true +``` +译者注:补充一下 `Array.some` 与 `Array.includes` 使用上的区别。两者都返回一个布尔值,表示某项是否存在于数组之中,一旦找到对应的项,立即停止遍历数组。不同的是 `Array.some` 的参数是回调函数,而 `Array.includes` 的参数是一个值(均不考虑第二个可选参数)。 +假设希望知道值为 value 的项是否存在于数组中,既可以编写代码:`[].includes(value)`, 也可以给 `Array.some` 传入 `item => item === value` 作为回调函数。`Array.includes` 使用更简单,`Array.some` 可操控性更强。 + +## 4.使用 `Array.reduce` 替代 `Array.filter` 与 `Array.map` 的组合 +事实上说,`Array.reduce` 不太容易理解。然而,如果我们先使用 `Array.filter` 过滤原数组,之后(对结果)再调用 `Array.map` (以获取一个新数组)。这看起似乎有点问题,是我们忽略了什么吗? +这样做的问题是:我们遍历了两次数组。第一次是过滤原数组以获取一个长度稍短的新数组,第二次遍历(译者注:指 `Array.map`)是对 `Array.filter` 的返回的新数组进行加工,再次创造了一个新数组!为得到最终的结果,我们结合使用了两个数组方法。每个方法都有它自己的回调函数,而且供 `Array.map` 使用的临时数组是由 `Array.filter` 提供的,(一般而言)该数组无法复用。 +为避免如此低效场景的出现,我的建议是使用 `Array.reduce` 。一样的结果,更好的代码!`Array.reduce` 允许你将过滤后切加工过的项放进累加器中。累加器可以是需要待递增的数字、待填充的对象、 待拼接的字符串或数组等。 +在上面的例子中,我们使用了 `Array.map`,(但更)建议使用累加器为待拼接数组的 `Array.reduce` 。在下面的例子中,根据变量 `env` 的值,我们会将它加进累加器中或保持累加器不变(即不作任何处理)。 +```js +'use strict'; + +const characters = [ + { name: 'ironman', env: 'marvel' }, + { name: 'black_widow', env: 'marvel' }, + { name: 'wonder_woman', env: 'dc_comics' }, +]; + +console.log( + characters + .filter(character => character.env === 'marvel') + .map(character => Object.assign({}, character, { alsoSeenIn: ['Avengers'] })) +); +// [ +// { name: 'ironman', env: 'marvel', alsoSeenIn: ['Avengers'] }, +// { name: 'black_widow', env: 'marvel', alsoSeenIn: ['Avengers'] } +// ] + +console.log( + characters + .reduce((acc, character) => { + return character.env === 'marvel' + ? acc.concat(Object.assign({}, character, { alsoSeenIn: ['Avengers'] })) + : acc; + }, []) +) +// [ +// { name: 'ironman', env: 'marvel', alsoSeenIn: ['Avengers'] }, +// { name: 'black_widow', env: 'marvel', alsoSeenIn: ['Avengers'] } +// ] +``` + +### 这就是本文的全部内容! +希望这对你有帮助。如果你对本文有任何意见或(关于数组方法使用的)例子需要讨论,请在评论中告诉我。如果你觉得本文不错,请给我点赞 👏 (译者注:对灯发誓,这是原文,不是译者骗赞!)并分享给更多的小伙伴。感谢你的阅读! + +注意:请在使用 `Array.find` 和 `Array.includes` 前检查浏览器是否支持相关方法,上述两个方法在 Internet Explorer 上并不支持(译者注:可以使用` Polyfill`)。 From 55f74aeb0e6c36d6bd1ed6b20d54a201129048b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 7 Sep 2018 17:18:00 +0800 Subject: [PATCH 038/835] =?UTF-8?q?2018.09.07=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 ++ ...77\347\224\250\346\225\260\347\273\204.md" | 19 ++++++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ada09b25..13c51217 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,8 @@ * [42-JS高程中的垃圾回收机制与常见内存泄露的解决方法](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/42-JS%E9%AB%98%E7%A8%8B%E4%B8%AD%E7%9A%84%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6%E4%B8%8E%E5%B8%B8%E8%A7%81%E5%86%85%E5%AD%98%E6%B3%84%E9%9C%B2%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95.md) * [43-手机端页面开发常见问题和解决](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/43-%E6%89%8B%E6%9C%BA%E7%AB%AF%E9%A1%B5%E9%9D%A2%E5%BC%80%E5%8F%91%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E5%92%8C%E8%A7%A3%E5%86%B3.md) * [44-前端本地文件操作和上传](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/44-%E5%89%8D%E7%AB%AF%E6%9C%AC%E5%9C%B0%E6%96%87%E4%BB%B6%E6%93%8D%E4%BD%9C%E5%92%8C%E4%B8%8A%E4%BC%A0.md) +* [45-js中reduce的神奇用法](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/45-js%E4%B8%ADreduce%E7%9A%84%E7%A5%9E%E5%A5%87%E7%94%A8%E6%B3%95.md) +* [46-在JavaScript中更好的使用数组](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/46-%E5%9C%A8JavaScript%E4%B8%AD%E6%9B%B4%E5%A5%BD%E7%9A%84%E4%BD%BF%E7%94%A8%E6%95%B0%E7%BB%84.md) ### 7、其他 * [2017-全年总结](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/2017-%E5%85%A8%E5%B9%B4%E6%80%BB%E7%BB%93.md) diff --git "a/article/46-\345\234\250JavaScript\344\270\255\346\233\264\345\245\275\347\232\204\344\275\277\347\224\250\346\225\260\347\273\204.md" "b/article/46-\345\234\250JavaScript\344\270\255\346\233\264\345\245\275\347\232\204\344\275\277\347\224\250\346\225\260\347\273\204.md" index fa6043b2..f6ed44b0 100644 --- "a/article/46-\345\234\250JavaScript\344\270\255\346\233\264\345\245\275\347\232\204\344\275\277\347\224\250\346\225\260\347\273\204.md" +++ "b/article/46-\345\234\250JavaScript\344\270\255\346\233\264\345\245\275\347\232\204\344\275\277\347\224\250\346\225\260\347\273\204.md" @@ -1,16 +1,17 @@ -[阅读原文](https://juejin.im/post/5b8d0a74f265da431d0e7ec0) +[阅读原文](https://juejin.im/post/5b8d0a74f265da431d0e7ec0) [MDN Array 介绍](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array) - 本文短小精悍,我保证。在过去的数个月里,我注意到在我审阅的 pull request 中有四个(关于数组使用的)错误经常出现。同时,我自己也会犯这些错误,因此有了这篇文章。让我们一起学习,以确保以后能正确地使用数组方法! ## 1.使用 `Array.includes` 替代 `Array.indexOf` > "如果需要在数组中查找某个元素,请使用 `Array.indexOf`。" -我记得在我学习 JavaScript 的课程中有类似的这么一句话。毫无疑问,这完全正确! -在 MDN 文档中,对 `Array.indexOf` 的描述是:返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回`-1`。因此,如果在之后的代码中需要用到(给给定元素的)索引,那么` Array.indexOf` 是不二之选。 -然而,如果我们仅需要知道数组中是否包含给定元素呢?这意味着只是是与否的区别,这是一个布尔问题(boolean question)。针对这种情况,我建议使用直接返回布尔值的 `Array.includes`。 +我记得在我学习 JavaScript 的课程中有类似的这么一句话。毫无疑问,这完全正确! + +在 MDN 文档中,对 `Array.indexOf` 的描述是:返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回`-1`。因此,如果在之后的代码中需要用到(给给定元素的)索引,那么` Array.indexOf` 是不二之选。 + +然而,如果我们仅需要知道数组中是否包含给定元素呢?这意味着只是是与否的区别,这是一个布尔问题(boolean question)。针对这种情况,我建议使用直接返回布尔值的 `Array.includes`。 ```js 'use strict'; @@ -36,8 +37,11 @@ console.log(characters.includes('batman')); ## 2.使用 `Array.find` 替代 `Array.filter` `Array.filter` 是一个十分有用的方法。它通过回调函数过滤原数组,并将过滤后的项作为新数组返回。正如它的名字所示,我们将这个方法用于过滤,(一般而言)会获得一个长度更短的新数组。 + 然而,如果知道经回调函数过滤后,只会剩余唯一的一项,那么我不建议使用 `Array.filter`。比如:使用等于某个唯一 ID 为过滤条件去过滤一个数组。在这个例子中,`Array.filter` 返回一个仅有一项的新数组。然而,我们仅仅是为了获取 ID 为特定 ID 的那一项,这个新数组显得毫无用处。 + 让我们讨论一下性能。为了获取所有符合回调函数过滤条件的项,`Array.filter` 必须遍历整个数组。如果原数组中有成千上万项,回调函数需要执行的次数是相当多的。 + 为避免这些情况,我建议使用 `Array.find`。它与 `Array.filter` 一样需要一个回调函数,(但只是返回)符合条件的第一项。当找到符合回调函数过滤条件的第一个元素时,它会立即停止往下的搜寻。不再遍历整个数组。 ```js 'use strict'; @@ -65,7 +69,9 @@ console.log(characters.find(getCharacter('captain_america'))); ## 3.使用 `Array.some` 替代 `Array.find` 我承认我经常犯这个错误。之后,一位朋友建议我去查看 [MDN 文档](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/some) 以寻找更好的方法。事实上(这错误)与上面 `Array.indexOf`/`Array.includes` 的例子十分相像。 + 在上面的例子中,我们知道 `Array.find` 需要一个回调函数作为参数,并返回(符合条件的)第一个元素。然而,当我们需要知道数组中是否存在一个元素时,`Array.find` 是最好的选择吗?不一定是,因为它返回一个元素,而不是一个布尔值。 + 在下面的例子中,我建议使用 `Array.some`,它返回你需要的布尔值。 ```js 'use strict'; @@ -91,8 +97,11 @@ console.log(characters.some(hasCharacterFrom('marvel'))); ## 4.使用 `Array.reduce` 替代 `Array.filter` 与 `Array.map` 的组合 事实上说,`Array.reduce` 不太容易理解。然而,如果我们先使用 `Array.filter` 过滤原数组,之后(对结果)再调用 `Array.map` (以获取一个新数组)。这看起似乎有点问题,是我们忽略了什么吗? + 这样做的问题是:我们遍历了两次数组。第一次是过滤原数组以获取一个长度稍短的新数组,第二次遍历(译者注:指 `Array.map`)是对 `Array.filter` 的返回的新数组进行加工,再次创造了一个新数组!为得到最终的结果,我们结合使用了两个数组方法。每个方法都有它自己的回调函数,而且供 `Array.map` 使用的临时数组是由 `Array.filter` 提供的,(一般而言)该数组无法复用。 + 为避免如此低效场景的出现,我的建议是使用 `Array.reduce` 。一样的结果,更好的代码!`Array.reduce` 允许你将过滤后切加工过的项放进累加器中。累加器可以是需要待递增的数字、待填充的对象、 待拼接的字符串或数组等。 + 在上面的例子中,我们使用了 `Array.map`,(但更)建议使用累加器为待拼接数组的 `Array.reduce` 。在下面的例子中,根据变量 `env` 的值,我们会将它加进累加器中或保持累加器不变(即不作任何处理)。 ```js 'use strict'; From 7130acae51d0f28f56aa6316c1a2b35e239f7b32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Tue, 11 Sep 2018 21:31:07 +0800 Subject: [PATCH 039/835] 2018.09.11 --- ...64\347\232\204\345\272\224\347\224\250.md" | 547 ++++++++++++++++++ 1 file changed, 547 insertions(+) create mode 100644 "article/47-http\350\257\267\346\261\202\345\244\264\344\270\216\345\223\215\345\272\224\345\244\264\347\232\204\345\272\224\347\224\250.md" diff --git "a/article/47-http\350\257\267\346\261\202\345\244\264\344\270\216\345\223\215\345\272\224\345\244\264\347\232\204\345\272\224\347\224\250.md" "b/article/47-http\350\257\267\346\261\202\345\244\264\344\270\216\345\223\215\345\272\224\345\244\264\347\232\204\345\272\224\347\224\250.md" new file mode 100644 index 00000000..5d93ba9c --- /dev/null +++ "b/article/47-http\350\257\267\346\261\202\345\244\264\344\270\216\345\223\215\345\272\224\345\244\264\347\232\204\345\272\224\347\224\250.md" @@ -0,0 +1,547 @@ +> [阅读原文](https://juejin.im/post/5b854ddef265da43635d9302) + +## Chap1 发现headers +当我们随便打开一个网址(比如大家经常拿来测试网络的百度)时,打开Network,会看到如下请求头,响应头: +![图1](https://user-gold-cdn.xitu.io/2018/8/28/16580c211bbcc595?imageView2/0/w/1280/h/960/ignore-error/1) +究竟这些headers都有什么用呢? 咱们挨个探个究竟。 + +## Chap2 headers用途 + +### 2.1 Content-Type +`Content-Type`表示请求头或响应头的内容类型。作为请求头时,利用它可以进行`body-parser`。 +Sooo~ What is body-parser? +body-parser是node常用的中间件,其作用是: + +> Parse incoming request bodies in a middleware before your handlers, available under the req.body property. + +即在处理数据之前用中间件对post请求体进行解析。 +[body-parser](https://www.npmjs.com/package/body-parser)的例子为: + +下面的例子展示了如何给路由添加`body parser`。通常,这是在`express`中最为推荐的使用`body-parser`的方法。 +```js +var express = require('express') +var bodyParser = require('body-parser') +var app = express() +// create application/json parser +var jsonParser = bodyParser.json() +// create application/x-www-form-urlencoded parser +var urlencodedParser = bodyParser.urlencoded({ extended: false }) +// POST /login gets urlencoded bodies +app.post('/login', urlencodedParser, function (req, res) { + if (!req.body) return res.sendStatus(400) + res.send('welcome, ' + req.body.username) +}) +// POST /api/users gets JSON bodies +app.post('/api/users', jsonParser, function (req, res) { + if (!req.body) return res.sendStatus(400) + // create user in req.body +}) +``` +`body-parser`核心源码为: +```js + // this uses a switch for static require analysis + switch (parserName) { + case 'json': + parser = require('./lib/types/json') + break + case 'raw': + parser = require('./lib/types/raw') + break + case 'text': + parser = require('./lib/types/text') + break + case 'urlencoded': + parser = require('./lib/types/urlencoded') + break + } +``` +以`json`为例: +```js +var contentType = require('content-type') +//... +/** + * Get the charset of a request. + * + * @param {object} req + * @api private + */ +function getCharset (req) { + try { + return (contentType.parse(req).parameters.charset || '').toLowerCase() + } catch (e) { + return undefined + } +} +//... +// assert charset per RFC 7159 sec 8.1 +var charset = getCharset(req) || 'utf-8' +if (charset.substr(0, 4) !== 'utf-') { + debug('invalid charset') + next(createError(415, 'unsupported charset "' + charset.toUpperCase() + '"', { + charset: charset, + type: 'charset.unsupported' + })) + return +} +``` +可以看出:其背后工作原理就是通过分析请求头中的`Content-Type`的类型,根据不同的类型进行相应数据处理,我们自己模拟一下: + +step1: 先建立`server.js`: +```js + req.on('end',function (params) { + let r = Buffer.concat(arr).toString(); + // body-parser 解析请求,根据不同的格式进行不同的解析 + if (req.headers['content-type'] === www.js){ + let querystring = require('querystring'); + r = querystring.parse(r); // a=1&b=2 + console.log(r,1); + } else if (req.headers['content-type'] === 'application/json'){ + console.log(JSON.parse(r),2); + } else{ + console.log(r,3); + } + res.end('end'); + }) +``` +step2: 客户端模拟请求: +```js +let opts = { + host:'localhost', + port:3000, + path:'/hello', + headers:{ + 'a':1, + 'Content-Type':'application/json', + "Content-Length":7 //模拟的时候需要带上长度,不然客户端会当成没有传递数据 + } +} +let http = require('http'); +let client = http.request(opts,function (res) { + res.on('data',function (data) { + console.log(data.toString()); + }) +}); +client.end("{\"a\":1}"); // 表示把请求发出去 +``` +step3: 测试。 +先启动server,再启动client,服务端收到按照`application/json`格式解析的数据: `{ a: 1 } 2`.`Content-Type`与`body-parser`之间的关系就先分析到这里了。后面我们接着看请求头。 + +### 2.2 Range:bytes +请求头通过`Range:bytes`可以请求资源的某一部分。利用这个字段可模拟部分读取。如下: +```js + http.createServer(function (req, res) { + let range = req.headers['range']; + }) +``` +server: +```js +let http = require('http'); +let fs = require('fs'); +let path = require('path'); +// 当前要下载的文件的大小 +let size = fs.statSync(path.join(__dirname, 'my.txt')).size; +let server = http.createServer(function (req, res) { + let range = req.headers['range']; // 0-3 + if (range) { + // 模拟请求 curl -v --header "Range:bytes=0-3" http://localhost:3000 + let [, start, end] = range.match(/(\d*)-(\d*)/); + start = start ? Number(start) : 0; + end = end ? Number(end) : size - 1; // 10个字节 size 10 (0-9) + res.setHeader('Content-Range', `bytes ${start}-${end}/${size - 1}`); + fs.createReadStream(path.join(__dirname, 'my.txt'), { start, end }).pipe(res); + } else { + // 会把文件的内容写给客户端 + fs.createReadStream(path.join(__dirname, 'my.txt')).pipe(res); + //可读流可以通过pipe导到可写流 + } +}); +server.listen(3000); +``` +client: +```js +let opts = { + host:'localhost', + port:3000, + headers:{} +} +let http = require('http'); +let start = 0; +let fs = require('fs'); +function download() { + opts.headers.Range = `bytes=${start}-${start+3}`; + start+=4; + console.log(`start is ${start}`) + let client = http.request(opts,function (res) { + let total = res.headers['content-range'].split('/')[1]; + // console.log(half) + res.on('data',function (data) { + fs.appendFileSync('./download1.txt',data); + }); + res.on('end',function () { + setTimeout(() => { + if ((!pause)&&(start < total)) + download(); + }, 1000); + }) + }); + client.end(); +} +download() +``` +分段读取添加暂停功能,监听用户输入 +```js +let pause = false; +process.stdin.on('data',function (data) { + if (data.toString().includes('p')){ + pause = true + }else{ + pause = false; + download() + } +}) +``` +测试结果: +![图2](https://user-gold-cdn.xitu.io/2018/9/10/165c2355ff651d7d?imageView2/0/w/1280/h/960/ignore-error/1) + +分段读取有以下好处: + +> 提高读取速度,多线程并行,分块读取 +> 断点续传 + +模拟并行下载: +```js +let halfFlag = 20 +function download() { + opts.headers.Range = `bytes=${start}-${start+3}`; + start+=4; + console.log(`start is ${start}`) + let client = http.request(opts,function (res) { + let total = res.headers['content-range'].split('/')[1]; + let halfFlag = Math.floor(total/2) + // console.log(half) + res.on('data',function (data) { + fs.appendFileSync('./download1.txt',data); + }); + res.on('end',function () { + setTimeout(() => { + if ((!pause)&&(start < halfFlag)) + download(); + }, 1000); + }) + }); + client.end(); +} +let half = halfFlag + +function downloadTwo() { + opts.headers.Range = `bytes=${half}-${half+3}`; + half+=4; + console.log(`half is ${half}`) + let client = http.request(opts,function (res) { + let total = res.headers['content-range'].split('/')[1]; + res.on('data',function (data) { + fs.appendFileSync('./download2.txt',data); + }); + res.on('end',function () { + setTimeout(() => { + if (!pause&&half < total) + downloadTwo(); + }, 1000); + }) + }); + client.end(); +} +download(); +downloadTwo(); +``` +运行结果,会把原文件分成两部分下载到download1.txt和download2.txt。 +测试: +![图3](https://user-gold-cdn.xitu.io/2018/9/10/165c23670c9165b8?imageView2/0/w/1280/h/960/ignore-error/1) + +理论上,这样的下载方式会比第一种方法节约一半的时间。但是实际中的文件下载怎样实现加速以及并行下载的,还有待考究。 + +### 2.3 Cache-Control与Expires之强制缓存 +Response Header响应头中`Cache-Control: max-age=1233`可以设置相对当前的时间的强制缓存,与它相关的`Expires`可以设置某个绝对时间点限定读取缓存的时间。 +模拟实现: +```js +let url = require('url'); // 专门用来处理url路径的核心模块 +// http://username:password@hostname:port/pathname?query +let server = http.createServer(async function (req,res) { + console.log(req.url) + let { pathname,query} = url.parse(req.url,true); + // true就是将query转化成对象 + let readPath = path.join(__dirname, 'public', pathname); + try { + let statObj = await stat(readPath); + // 根客户端说 10s 内走缓存 + res.setHeader('Cache-Control','max-age=10'); + res.setHeader('Expires',new Date(Date.now()+10*1000).toGMTString()); + // 10s之内的请求都会走cache 返回200, (from disk cache)不发生请求 + if (statObj.isDirectory()) { + let p = path.join(readPath, 'index.html'); + await stat(p); + // 如果当前目录下有html那么就返回这个文件 + fs.createReadStream(p).pipe(res); + } else { + fs.createReadStream(readPath).pipe(res); + } + }catch(e){ + res.statusCode = 404; + res.end(`Not found`); + } +}).listen(3000); +``` +测试: +![图4](https://user-gold-cdn.xitu.io/2018/9/10/165c24917e9fcc8f?imageView2/0/w/1280/h/960/ignore-error/1) +10s内刷新: +![图4](https://user-gold-cdn.xitu.io/2018/9/10/165c2498b620d636?imageView2/0/w/1280/h/960/ignore-error/1) + +### 2.4 对比缓存之Last-Modified和If-Modified-Since +对比响应头Last-Modified and 与请求头If-Modified-Since,可以通过文件修改时间看文件是否修改,从而决定是重新请求还是走缓存。 +模拟如下: +step1 不设置强制缓存 +```js +res.setHeader('Cache-Control','no-cache'); +``` +step2 应用文件修改时间比对是否修改, +```js +res.setHeader('Last-Modified', statObj.ctime.toGMTString()); +if (req.headers['if-modified-since'] === statObj.ctime.toGMTString()) { + res.statusCode = 304; + res.end(); + return; // 走缓存 +} +fs.createReadStream(readPath).pipe(res); +``` +测试: +![图6](https://user-gold-cdn.xitu.io/2018/9/10/165c25325aa08daf?imageView2/0/w/1280/h/960/ignore-error/1) + +### 2.5 对比缓存之Etag和 If-None-Match +对比响应头:Etag 与请求头:If-None-Match,Etag和If-None-Match如果相等,即返回304。 +etag如何添加? + +> 根据文件内容,生成一个md5的摘要,给实体加一个标签。 + +这种方法虽然比较耗性能,但是能够更加精确的对比出文件是否进行了修改。依靠文件修改时间进行对比并不够准确。因为有时文件有改动Last-Modified发生了变化,但是文件的内容可能根本没有变化。所以这种方案要优于2.4. + +实现方法: +```js +let rs = fs.createReadStream(p); +let md5 = crypto.createHash('md5'); // 不能写完响应体再写头 +let arr = []; +rs.on('data',function (data) { + md5.update(data); + arr.push(data); +}); +``` +设置Etag +```js +rs.on('end',function () { +let r = md5.digest('base64'); +res.setHeader('Etag', r); +if (req.headers['if-none-match'] === r ){ + res.statusCode = 304; + res.end(); + return; +} +res.end(Buffer.concat(arr)); +}) +``` +测试: +![图7](https://user-gold-cdn.xitu.io/2018/9/10/165c25456876367f?imageView2/0/w/1280/h/960/ignore-error/1) + +### 2.6 Accept-Encoding +依靠请求头: `Accept-Encoding: gzip, deflate`, br告诉服务端可接受的数据格式。服务端返回后会把数据格式通过响应格式通过Content-Encoding来标记。 +在客户端接受gzip的格式下,后端可通过文件压缩处理传递,提高性能。 +node api中提供了[zlib](http://nodejs.cn/api/zlib.html#zlib_class_zlib_gzip)模块: +> zlib模块提供通过 Gzip 和` Deflate/Inflate` 实现的压缩功能 + +下面我们来应用zlib与请求头`Accept-Encoding`来实现压缩功能。 +```js +let zlib = require('zlib'); +let fs = require('fs'); +let path = require('path'); +function gzip(filePath) { + let transform = zlib.createGzip();//转化流通过transform压缩,然后再写 + fs.createReadStream(filePath).pipe(transform).pipe(fs.createWriteStream(filePath+'.gz')); +} +gzip('2.txt') +``` +解压: +```js +function gunzip(filePath) { + let transform = zlib.createGunzip(); + fs.createReadStream(filePath).pipe(transform).pipe(fs.createWriteStream(path.basename(filePath,'.gz'))); +} +``` +`path.basename(filePath,'.gz')`用来去掉filePath文件名的后缀`.gz`。 +根据请求头接受的类型后端的具体操作 : +```js +if(req.url === '/download'){ + res.setHeader('Content-Disposition', 'attachment' ) + return fs.createReadStream(path.join(__dirname, '1.html')).pipe(res); +} +``` + +```js +let http = require('http'); +let fs = require('fs'); +let path = require('path'); +let zlib = require('zlib'); +http.createServer(function (req,res) { + if(req.url === '/download'){ + res.setHeader('Content-Disposition', 'attachment' ) + return fs.createReadStream(path.join(__dirname, '1.html')).pipe(res); + } + let rule = req.headers['accept-encoding']; + if(rule){ + if(rule.match(/\bgzip\b/)){ + res.setHeader('Content-Encoding','gzip'); + fs.createReadStream(path.join(__dirname, '1.html')) + .pipe(zlib.createGzip()) + .pipe(res); + } else if (rule.match(/\bdeflate\b/)){ + res.setHeader('Content-Encoding', 'deflate'); + fs.createReadStream(path.join(__dirname, '1.html')) + .pipe(zlib.createDeflate()) + .pipe(res); + }else{ + fs.createReadStream(path.join(__dirname, '1.html')).pipe(res); + } + }else{ + fs.createReadStream(path.join(__dirname, '1.html')).pipe(res); + } +}).listen(3000); +``` + +test deflate: +```docker +curl -v --header "Accept-Encoding:deflate" http://localhost:3000 +* Rebuilt URL to: http://localhost:3000/ +* Trying 127.0.0.1... +* TCP_NODELAY set +* Connected to localhost (127.0.0.1) port 3000 (#0) +> GET / HTTP/1.1 +> Host: localhost:3000 +> User-Agent: curl/7.54.0 +> Accept: */* +> Accept-Encoding:deflate +> +< HTTP/1.1 200 OK +< Content-Encoding: deflate +< Date: Thu, 23 Aug 2018 03:01:13 GMT +< Connection: keep-alive +< Transfer-Encoding: chunked +``` +test others: +```docker +curl -v --header "Accept-Encoding:nn" http://localhost:3000 +* Rebuilt URL to: http://localhost:3000/ +* Trying 127.0.0.1... +* TCP_NODELAY set +* Connected to localhost (127.0.0.1) port 3000 (#0) +> GET / HTTP/1.1 +> Host: localhost:3000 +> User-Agent: curl/7.54.0 +> Accept: */* +> Accept-Encoding:nn +> +< HTTP/1.1 200 OK +< Date: Thu, 23 Aug 2018 03:02:51 GMT +< Connection: keep-alive +< Transfer-Encoding: chunked +< + + + + + + + Document + + + 你好 + + +* Connection #0 to host localhost left intact +% +``` +### 2.7 referer +![图8](https://user-gold-cdn.xitu.io/2018/9/10/165c268acf50a0af?imageView2/0/w/1280/h/960/ignore-error/1) +referer表示请求文件的网址,请求时会携带。为了防止自己网站的文件被外网直接引用,可以通过比较referer,即请求的地址,与本地地址比较,设置防盗链。 +```js +let http = require('http'); +let fs = require('fs'); +let url = require('url'); +let path = require('path'); +// 这是百度的服务器 +let server = http.createServer(function (req,res) { + let { pathname } = url.parse(req.url); + let realPath = path.join(__dirname,pathname); + fs.stat(realPath,function(err,statObj) { + if(err){ + res.statusCode = 404; + res.end(); + }else{ + let referer = req.headers['referer'] || req.headers['referred']; + if(referer){ + let current = req.headers['host'] // 代表的是当前图片的地址 + referer = url.parse(referer).host // 引用图片的网址 + if (current === referer){ + fs.createReadStream(realPath).pipe(res); + }else{ + fs.createReadStream(path.join(__dirname,'images/2.jpg')).pipe(res); + } + }else{ + fs.createReadStream(realPath).pipe(res); + } + } + }) +}).listen(3000); +``` +### 2.8 Accept-Language +请求头:`Accept-Language: zh-CN,zh;q=0.9` +多个语言用 ',' 分隔,权重用 '=' 表示',没有默认权重为1 + +后端根据请求接受语言的权重一次查找,查找到就返回,找不到就用默认语言 +```js +let langs = { + en: 'hello world', + 'zh-CN':'你好世界', + zh:'你好', + ja: 'こんにちは、世界' +} +let defualtLanguage = 'en' +// 多语言之服务端方案:来做 (浏览器会发一个头) 前端来做 +// 通过url实现多语言 +let http = require('http'); +http.createServer(function (req,res) { + let lan = req.headers['accept-language']; + //[[zh,q=0.9],[zh-CN]] =>[{name:'zh-CN',q=1},{name:'zh',q:0.9}] + if(lan){ + lan = lan.split(','); + lan = lan.map(l=>{ + let [name,q] = l.split(';'); + q = q?Number(q.split('=')[1]):1 + return {name,q} + }).sort((a,b)=>b.q-a.q); // 排出 权重数组 + + for(let i = 0 ;i Date: Tue, 11 Sep 2018 21:33:45 +0800 Subject: [PATCH 040/835] =?UTF-8?q?2018.09.11=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 13c51217..11f04552 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,10 @@ * [45-js中reduce的神奇用法](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/45-js%E4%B8%ADreduce%E7%9A%84%E7%A5%9E%E5%A5%87%E7%94%A8%E6%B3%95.md) * [46-在JavaScript中更好的使用数组](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/46-%E5%9C%A8JavaScript%E4%B8%AD%E6%9B%B4%E5%A5%BD%E7%9A%84%E4%BD%BF%E7%94%A8%E6%95%B0%E7%BB%84.md) -### 7、其他 +### 7、HTTP +* [47-http请求头与响应头的应用](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/47-http%E8%AF%B7%E6%B1%82%E5%A4%B4%E4%B8%8E%E5%93%8D%E5%BA%94%E5%A4%B4%E7%9A%84%E5%BA%94%E7%94%A8.md) + +### 8、其他 * [2017-全年总结](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/2017-%E5%85%A8%E5%B9%B4%E6%80%BB%E7%BB%93.md) * [2018-全年计划](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/2018-%E5%85%A8%E5%B9%B4%E8%AE%A1%E5%88%92.md) * [★ 27-Markdowm语法整理](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/27-Markdowm%E8%AF%AD%E6%B3%95%E6%95%B4%E7%90%86.md) From f56535b98bfe76718c86f480d9305263ab9c787d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Thu, 13 Sep 2018 22:52:58 +0800 Subject: [PATCH 041/835] 2018.09.13 --- ...\346\215\256\347\273\221\345\256\232.html" | 33 +++++++++++++++++++ ...21\345\256\232\345\216\237\347\220\206.md" | 33 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 "demo\347\211\207\346\256\265/2-JS\345\256\236\347\216\260\347\256\200\345\215\225\347\232\204vuejs\345\217\214\345\220\221\346\225\260\346\215\256\347\273\221\345\256\232.html" create mode 100644 "demo\347\211\207\346\256\265/3-vuejs\345\217\214\345\220\221\346\225\260\346\215\256\347\273\221\345\256\232\345\216\237\347\220\206.md" diff --git "a/demo\347\211\207\346\256\265/2-JS\345\256\236\347\216\260\347\256\200\345\215\225\347\232\204vuejs\345\217\214\345\220\221\346\225\260\346\215\256\347\273\221\345\256\232.html" "b/demo\347\211\207\346\256\265/2-JS\345\256\236\347\216\260\347\256\200\345\215\225\347\232\204vuejs\345\217\214\345\220\221\346\225\260\346\215\256\347\273\221\345\256\232.html" new file mode 100644 index 00000000..8f888088 --- /dev/null +++ "b/demo\347\211\207\346\256\265/2-JS\345\256\236\347\216\260\347\256\200\345\215\225\347\232\204vuejs\345\217\214\345\220\221\346\225\260\346\215\256\347\273\221\345\256\232.html" @@ -0,0 +1,33 @@ + + + + + + + + Document + + + +
+ +

+
+ + + + \ No newline at end of file diff --git "a/demo\347\211\207\346\256\265/3-vuejs\345\217\214\345\220\221\346\225\260\346\215\256\347\273\221\345\256\232\345\216\237\347\220\206.md" "b/demo\347\211\207\346\256\265/3-vuejs\345\217\214\345\220\221\346\225\260\346\215\256\347\273\221\345\256\232\345\216\237\347\220\206.md" new file mode 100644 index 00000000..0f78e6ee --- /dev/null +++ "b/demo\347\211\207\346\256\265/3-vuejs\345\217\214\345\220\221\346\225\260\346\215\256\347\273\221\345\256\232\345\216\237\347\220\206.md" @@ -0,0 +1,33 @@ +## 数据双向绑定的原理 +`Object.defineProperty()` + +vue实现数据双向绑定主要是: + 采用数据劫持结合发布者-订阅者模式的方式,通过 `Object.defineProperty()` 来劫持各个属性的`setter`,`getter`,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 `data` 选项时,Vue 将遍历它的属性,用 `Object.defineProperty()` 将它们转为 `getter/setter`。用户看不到 `getter/setter`,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。 + +vue的数据双向绑定 将MVVM作为数据绑定的入口,整合`Observer`,`Compile`和`Watcher`三者,通过`Observer`来监听自己的`model`的数据变化,通过`Compile`来解析编译模板指令(vue中是用来解析 {{}}),最终利用`watcher`搭起`observer`和`Compile`之间的通信桥梁,达到数据变化 —>视图更新;视图交互变化(input)—>数据model变更双向绑定效果。 + + +## 简单实现 +```html + +
+ +

+
+ + +``` \ No newline at end of file From 779041f65c49dc4ac34a88c75bc4b67e22be98af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sun, 16 Sep 2018 20:51:36 +0800 Subject: [PATCH 042/835] 2018.09.16 --- ...71\346\263\225\346\261\207\346\200\273.md" | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 "article/48-js\350\216\267\345\217\226\345\205\203\347\264\240\351\253\230\345\272\246\345\222\214\346\265\217\350\247\210\345\231\250\345\220\204\347\247\215\351\253\230\345\272\246\346\226\271\346\263\225\346\261\207\346\200\273.md" diff --git "a/article/48-js\350\216\267\345\217\226\345\205\203\347\264\240\351\253\230\345\272\246\345\222\214\346\265\217\350\247\210\345\231\250\345\220\204\347\247\215\351\253\230\345\272\246\346\226\271\346\263\225\346\261\207\346\200\273.md" "b/article/48-js\350\216\267\345\217\226\345\205\203\347\264\240\351\253\230\345\272\246\345\222\214\346\265\217\350\247\210\345\231\250\345\220\204\347\247\215\351\253\230\345\272\246\346\226\271\346\263\225\346\261\207\346\200\273.md" new file mode 100644 index 00000000..1c290b70 --- /dev/null +++ "b/article/48-js\350\216\267\345\217\226\345\205\203\347\264\240\351\253\230\345\272\246\345\222\214\346\265\217\350\247\210\345\231\250\345\220\204\347\247\215\351\253\230\345\272\246\346\226\271\346\263\225\346\261\207\346\200\273.md" @@ -0,0 +1,99 @@ +## 一、网页可见区域宽高(浏览器窗口可视区域大小) +不包括工具栏和滚动条 +* 1.对于IE9+、chrome、firefox、Opera、Safari: +```js +// 浏览器窗口的内部高度 +let height = window.innerHeight; +// 浏览器窗口的内部宽度 +let width = window.innerWidth; +``` + +* 2.对于IE8.7.6.5: +```js +// 表示HTML文档所在窗口的当前高度 +let height = document.documentElement.clientHeight; +// 表示HTML文档所在窗口的当前宽度 +let width = document.documentElement.clientWidth; +``` +或者,因为`document`对象的`body`属性对应`HTML文档`的``标签,所以也可表示为: +```js +// 表示HTML文档所在窗口的当前高度 +let height = document.body.clientHeight; +// 表示HTML文档所在窗口的当前宽度 +let width = document.body.clientWidth; +``` +结论: +`document.body.clientWidth/Height` 的宽高偏小,高甚至默认200; +`document.documentElement.clientWidth/Height` 和 `window.innerWidth/Height` 的宽高始终相等。 +所以在不同浏览器都实用的的Javascripit方案: +```js +let height = document.documentElement.clientWidth || document.body.clientWidth; +let width = document.documentElement.clientHeight || document.body.clientHeight; +``` + +## 二、网页正文全文宽高 +`scrollWidth` 和 `scrollHeight` 获取网页内容高度和宽度: + +* 1.针对IE.Opera: +`scrollHeight`是网页内容实际高度,可以小于`clientHeight`; + +* 2.针对NS.firefox: +`scrollHeight`是网页内容高度,不过最小值是`clientHeight`;也就是说网页内容实际高度小于`clientHeight`的时候,`scrollHeight`返回`clientHeight`; + +* 3.浏览器兼容代码: +```js +let height = document.documentElement.scrollHeight || document.body.scrollHeight; +let width = document.documentElement.scrollWidth || document.body.scrollWidth; +``` + +## 三、网页可见区域宽高,包括滚动条等边线(会随窗口的显示大小改变) +* 1.值: +offsetWidth = scrollWidth + 左右滚动条 + 左右边框; +offsetHeight = scrollHeight + 上下滚动条 + 上下边框; + +* 2.浏览器兼容代码: +```js +let width = document.documentElement.offsetWidth || document.body.offsetWidth ; +let height = document.documentElement.offsetHeight || document.body.offsetHeight ; +``` + +## 四、网页卷去的距离与偏移量 +1.`scrollLeft`:设置或获取位于给定对象左边界与窗口中目前可见内容的最左端之间的距离; +2.`scrollTop`:设置或获取位于给定对象最顶端与窗口中目前可见内容的最左端之间的距离; +3.`offsetLeft`:设置或获取位于给定对象相对于版面或由offsetParent属性指定的父坐标的计算左侧位置; +4.`offsetTop`:设置或获取位于给定对象相对于版面或由offsetParent属性指定的父坐标的计算顶端位置; + +## 常用高度/宽度获取的整理 +* 1.获取屏幕的高度和宽度(屏幕分辨率): +```js +window.screen.height +window.screen.width +``` + +* 2.获取屏幕工作区域的高度和宽度(去掉状态栏): +```js +window.screen.availHeight +window.screen.availWidth +``` + +* 3.网页全文的高度和宽度: +```js +document.body.scrollHeight +document.body.scrollWidth +``` + +* 4.滚动条卷上去的高度和向右卷的宽度: +```js +document.body.scrollTop +document.body.scrollLeft +``` +* 5.网页可见区域的高度和宽度(不加边线): +```js +document.body.clientHeight +document.body.clientWidth +``` +* 6.网页可见区域的高度和宽度(加边线): +```js +document.body.offsetHeight +document.body.offsetWidth +``` \ No newline at end of file From 726b9b6af82457ec0e1b2f2dfaa3b4c0b338f393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sun, 16 Sep 2018 21:08:23 +0800 Subject: [PATCH 043/835] =?UTF-8?q?2018.09.16=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E6=96=87=E7=AB=A0=20=E5=92=8C=20=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + ...71\346\263\225\346\261\207\346\200\273.md" | 20 ++++++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 11f04552..f8d1e0e6 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ * [44-前端本地文件操作和上传](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/44-%E5%89%8D%E7%AB%AF%E6%9C%AC%E5%9C%B0%E6%96%87%E4%BB%B6%E6%93%8D%E4%BD%9C%E5%92%8C%E4%B8%8A%E4%BC%A0.md) * [45-js中reduce的神奇用法](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/45-js%E4%B8%ADreduce%E7%9A%84%E7%A5%9E%E5%A5%87%E7%94%A8%E6%B3%95.md) * [46-在JavaScript中更好的使用数组](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/46-%E5%9C%A8JavaScript%E4%B8%AD%E6%9B%B4%E5%A5%BD%E7%9A%84%E4%BD%BF%E7%94%A8%E6%95%B0%E7%BB%84.md) +* [48-js获取元素高度和浏览器各种高度方法汇总](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/48-js获取元素高度和浏览器各种高度方法汇总.md) ### 7、HTTP * [47-http请求头与响应头的应用](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/47-http%E8%AF%B7%E6%B1%82%E5%A4%B4%E4%B8%8E%E5%93%8D%E5%BA%94%E5%A4%B4%E7%9A%84%E5%BA%94%E7%94%A8.md) diff --git "a/article/48-js\350\216\267\345\217\226\345\205\203\347\264\240\351\253\230\345\272\246\345\222\214\346\265\217\350\247\210\345\231\250\345\220\204\347\247\215\351\253\230\345\272\246\346\226\271\346\263\225\346\261\207\346\200\273.md" "b/article/48-js\350\216\267\345\217\226\345\205\203\347\264\240\351\253\230\345\272\246\345\222\214\346\265\217\350\247\210\345\231\250\345\220\204\347\247\215\351\253\230\345\272\246\346\226\271\346\263\225\346\261\207\346\200\273.md" index 1c290b70..deb7c771 100644 --- "a/article/48-js\350\216\267\345\217\226\345\205\203\347\264\240\351\253\230\345\272\246\345\222\214\346\265\217\350\247\210\345\231\250\345\220\204\347\247\215\351\253\230\345\272\246\346\226\271\346\263\225\346\261\207\346\200\273.md" +++ "b/article/48-js\350\216\267\345\217\226\345\205\203\347\264\240\351\253\230\345\272\246\345\222\214\346\265\217\350\247\210\345\231\250\345\220\204\347\247\215\351\253\230\345\272\246\346\226\271\346\263\225\346\261\207\346\200\273.md" @@ -1,6 +1,7 @@ ## 一、网页可见区域宽高(浏览器窗口可视区域大小) 不包括工具栏和滚动条 -* 1.对于IE9+、chrome、firefox、Opera、Safari: +* 1.对于IE9+、chrome、firefox、Opera、Safari: + ```js // 浏览器窗口的内部高度 let height = window.innerHeight; @@ -9,6 +10,7 @@ let width = window.innerWidth; ``` * 2.对于IE8.7.6.5: + ```js // 表示HTML文档所在窗口的当前高度 let height = document.documentElement.clientHeight; @@ -40,7 +42,8 @@ let width = document.documentElement.clientHeight || document.body.clientHeight; * 2.针对NS.firefox: `scrollHeight`是网页内容高度,不过最小值是`clientHeight`;也就是说网页内容实际高度小于`clientHeight`的时候,`scrollHeight`返回`clientHeight`; -* 3.浏览器兼容代码: +* 3.浏览器兼容代码: + ```js let height = document.documentElement.scrollHeight || document.body.scrollHeight; let width = document.documentElement.scrollWidth || document.body.scrollWidth; @@ -51,48 +54,55 @@ let width = document.documentElement.scrollWidth || document.body.scrollWidth; offsetWidth = scrollWidth + 左右滚动条 + 左右边框; offsetHeight = scrollHeight + 上下滚动条 + 上下边框; -* 2.浏览器兼容代码: +* 2.浏览器兼容代码: + ```js let width = document.documentElement.offsetWidth || document.body.offsetWidth ; let height = document.documentElement.offsetHeight || document.body.offsetHeight ; ``` ## 四、网页卷去的距离与偏移量 -1.`scrollLeft`:设置或获取位于给定对象左边界与窗口中目前可见内容的最左端之间的距离; -2.`scrollTop`:设置或获取位于给定对象最顶端与窗口中目前可见内容的最左端之间的距离; +1.`scrollLeft`:设置或获取位于给定**对象左边界**与窗口中**目前可见内容的最左端**之间的距离; +2.`scrollTop`:设置或获取位于给定**对象最顶端**与窗口中**目前可见内容的最左端**之间的距离; 3.`offsetLeft`:设置或获取位于给定对象相对于版面或由offsetParent属性指定的父坐标的计算左侧位置; 4.`offsetTop`:设置或获取位于给定对象相对于版面或由offsetParent属性指定的父坐标的计算顶端位置; ## 常用高度/宽度获取的整理 * 1.获取屏幕的高度和宽度(屏幕分辨率): + ```js window.screen.height window.screen.width ``` * 2.获取屏幕工作区域的高度和宽度(去掉状态栏): + ```js window.screen.availHeight window.screen.availWidth ``` * 3.网页全文的高度和宽度: + ```js document.body.scrollHeight document.body.scrollWidth ``` * 4.滚动条卷上去的高度和向右卷的宽度: + ```js document.body.scrollTop document.body.scrollLeft ``` * 5.网页可见区域的高度和宽度(不加边线): + ```js document.body.clientHeight document.body.clientWidth ``` * 6.网页可见区域的高度和宽度(加边线): + ```js document.body.offsetHeight document.body.offsetWidth From cc00a211a951ec93c8df0eb14a66b909730905e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 17 Sep 2018 19:16:22 +0800 Subject: [PATCH 044/835] 2018.09.17 --- ...06\347\202\271\346\225\264\347\220\206.md" | 205 ++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 "article/49-Vue \351\235\242\350\257\225\344\270\255\345\270\270\351\227\256\347\237\245\350\257\206\347\202\271\346\225\264\347\220\206.md" diff --git "a/article/49-Vue \351\235\242\350\257\225\344\270\255\345\270\270\351\227\256\347\237\245\350\257\206\347\202\271\346\225\264\347\220\206.md" "b/article/49-Vue \351\235\242\350\257\225\344\270\255\345\270\270\351\227\256\347\237\245\350\257\206\347\202\271\346\225\264\347\220\206.md" new file mode 100644 index 00000000..b880ef7c --- /dev/null +++ "b/article/49-Vue \351\235\242\350\257\225\344\270\255\345\270\270\351\227\256\347\237\245\350\257\206\347\202\271\346\225\264\347\220\206.md" @@ -0,0 +1,205 @@ +看看面试题,只是为了查漏补缺,看看自己那些方面还不懂。切记不要以为背了面试题,就万事大吉了,最好是理解背后的原理,这样面试的时候才能侃侃而谈。不然,稍微有水平的面试官一看就能看出,是否有真才实学还是刚好背中了这道面试题(有空再把例子中代码补上)。 + +## 一、对于MVVM的理解? +MVVM 是 Model-View-ViewModel 的缩写。 + +* **Model** 代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。 +* **View** 代表UI 组件,它负责将数据模型转化成UI 展现出来。 +* **ViewModel** 监听模型数据的改变和控制视图行为、处理用户交互,简单理解就是一个同步View 和 Model的对象,连接Model和View。 + +在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。 + +ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM,不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。 + +## 二、Vue的生命周期 + +`beforeCreate`(创建前),在数据观测和初始化事件还未开始 + +`created`(创建后),完成数据观测,属性和方法的运算,初始化事件, $el 属性还没有显示出来 + +`beforeMount`(载入前),在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。注意此时还没有挂载html到页面上。 + +`mounted`(载入后),在el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用。实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html渲染到html页面中。此过程中进行ajax交互。 + +`beforeUpdate`(更新前),在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。 + +`updated`(更新后),在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。 + +`beforeDestroy`(销毁前),在实例销毁之前调用。实例仍然完全可用。 + +`destroyed`(销毁后),在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。 + +### 1、什么是vue生命周期? + +答: Vue 实例从创建到销毁的过程,就是生命周期。从`开始创建`、`初始化数据`、`编译模板`、`挂载Dom→渲染`、`更新→渲染`、`销毁`等一系列过程,称之为 Vue 的**生命周期**。 + +### 2、vue生命周期的作用是什么? + +答:它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。 + +### 3、vue生命周期总共有几个阶段? + +答:它可以总共分为8个阶段:创建前/后、载入前/后、更新前/后、销毁前/销毁后。 + +### 4、第一次页面加载会触发哪几个钩子? + +答:会触发下面这几个`beforeCreate`、`created`、`beforeMount`、`mounted` 。 + +### 5、DOM 渲染在哪个周期中就已经完成? + +答:DOM 渲染在 `mounted` 中就已经完成了。 + +## 三、 Vue实现数据双向绑定的原理:Object.defineProperty() + +vue实现数据双向绑定主要是: +采用**数据劫持**结合**发布者-订阅者模式**的方式,通过 `Object.defineProperty()` 来劫持各个属性的`setter`,`getter`,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 `Object.defineProperty()` 将它们转为 `getter/setter`。用户看不到 `getter/sette`r,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。 + +vue的数据双向绑定: +将MVVM作为数据绑定的入口,整合`Observer`,`Compile`和`Watcher`三者,通过`Observer`来监听自己的`model`的数据变化,通过`Compile`来解析编译模板指令(vue中是用来解析` {{}}`),最终利用`watcher`搭起`observer`和`Compile`之间的通信桥梁,达到**数据变化 —>视图更新**;视图交互变化(input)—>数据model变更双向绑定效果。 + +js实现简单的双向绑定: +```html + +   
+    +   

+
+ + + +``` + + +## 四、Vue组件间的参数传递 + +### 1、父组件与子组件传值 +父组件传给子组件:子组件通过`props`方法接受数据; + +子组件传给父组件: `$emit` 方法传递参数 + +### 2、非父子组件间的数据传递,兄弟组件传值 +`eventBus`,就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件。项目比较小时,用这个比较合适(虽然也有不少人推荐直接用VUEX,具体来说看需求咯。技术只是手段,目的达到才是王道)。 + +## 五、Vue的路由实现:hash模式 和 history模式 +**hash模式**:在浏览器中符号 `#`,#以及#后面的字符称之为`hash`,用 `window.location.hash` 读取。 +特点:`hash`虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,`hash`不会重加载页面。 + +**history模式**:`history`采用HTML5的新特性;且提供了两个新方法: `pushState()`, `replaceState()`可以对浏览器历史记录栈进行修改,以及`popState`事件的监听到状态变更。 + +## 六、Vue与Angular以及React的区别? +版本在不断更新,以下的区别有可能不是很正确。我工作中只用到vue,对angular和react不怎么熟。 + +### 1、与AngularJS的区别 +#### 相同点: +* 都支持指令:内置指令和自定义指令; +* 都支持过滤器:内置过滤器和自定义过滤器; +* 都支持双向数据绑定; +* 都不支持低端浏览器。 + +#### 不同点: +* AngularJS的学习成本高,比如增加了Dependency Injection特性,而Vue.js本身提供的API都比较简单、直观; +* 在性能上,AngularJS依赖对数据做脏检查,所以Watcher越多越慢; +* Vue.js使用基于依赖追踪的观察并且使用异步队列更新,所有的数据都是独立触发的。 + +### 2、与React的区别 +#### 相同点: +* React采用特殊的`JSX`语法,Vue.js在组件开发中也推崇编写`.vue`特殊文件格式,对文件内容都有一些约定,两者都需要编译后使用; +* 中心思想相同:一切都是组件,组件实例之间可以嵌套;都提供合理的钩子函数,可以让开发者定制化地去处理需求; +* 都不内置列数AJAX,Route等功能到核心包,而是以插件的方式加载; +* 在组件开发中都支持`mixins`的特性。 + +#### 不同点: +* React采用的Virtual DOM会对渲染出来的结果做脏检查; +* Vue.js在模板中提供了指令,过滤器等,可以非常方便,快捷地操作Virtual DOM。 + +## 七、vue路由的钩子函数 +首页可以控制导航跳转,`beforeEach`,`afterEach`等,一般用于页面`title`的修改。一些需要登录才能调整页面的重定向功能。 + +**beforeEach**主要有3个参数`to`,`from`,`next`。 +**`to`**:route即将进入的目标路由对象。 +**`from`**:route当前导航正要离开的路由。 +**`next`**:function一定要调用该方法`resolve`这个钩子。执行效果依赖`next`方法的调用参数。可以控制网页的跳转。 + +## 八、vuex是什么?怎么使用?哪种功能场景使用它? +只用来读取的状态集中放在`store`中; +改变状态的方式是提交`mutations`,这是个同步的事物; +异步逻辑应该封装在`action`中。 + +在`main.js`引入`store`,注入。新建了一个目录`store`,`… export` 。 + +场景有:单页应用中,组件之间的状态、音乐播放、登录状态、加入购物车。 +![vue生命周期](http://p3nqtyvgo.bkt.clouddn.com/vue%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F.jpg) +**state**:Vuex 使用单一状态树,即每个应用将仅仅包含一个`store` 实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。 + +**mutations**:`mutations`定义的方法动态修改`Vuex `的 `store` 中的状态或数据。 + +**getters**:类似`vue`的计算属性,主要用来过滤一些数据。 + +**action**:`actions`可以理解为通过将`mutations`里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。`view` 层通过` store.dispath` 来分发 `action`。 +```js +onst store = new Vuex.Store({ //store实例 +     state: { +        count: 0 +            }, +     mutations: {                 +        increment (state) { +         state.count++ +        } +         }, +     actions: { +        increment (context) { +         context.commit('increment') +   } + } +}) + +``` +**modules**:项目特别复杂的时候,可以让每一个模块拥有自己的`state`、`mutation`、`action`、`getters`,使得结构非常清晰,方便管理。 +```js +const moduleA = { + state: { ... }, + mutations: { ... }, + actions: { ... }, + getters: { ... } +} +const moduleB = { + state: { ... }, + mutations: { ... }, + actions: { ... } +} +const store = new Vuex.Store({ + modules: { +   a: moduleA, +   b: moduleB +}) + +``` + + +## 九、其它小知识点 + +### 1、css只在当前组件起作用 +答:在`style`标签中写入`scoped`即可 例如: `` + +### 2、`v-if` 和 `v-show` 区别 +答:`v-if`按照条件是否渲染,`v-show`是`display`的`block`或`none`; + +### 3、`$route``和$router`的区别 + +答:`$route`是 `路由信息对象`,包括`path`,`params`,`hash`,`query`,`fullPath`,`matched`,`name`等路由信息参数。而`$router`是 `路由实例` 对象包括了路由的跳转方法,钩子函数等。 + +PS:缺少的案例代码,这几天再补上去。有些地方可能描述的不够清楚,如果有歧义,可能是我理解错了。 \ No newline at end of file From 80b0f873d74863152cb695366d6e167d94f8108b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 17 Sep 2018 19:18:10 +0800 Subject: [PATCH 045/835] 2018.09.17 --- README.md | 1 + ...237\245\350\257\206\347\202\271\346\225\264\347\220\206.md" | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f8d1e0e6..e2ab4856 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ * [14-Vue的一些小注意点](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/14-Vue%E7%9A%84%E4%B8%80%E4%BA%9B%E5%B0%8F%E6%B3%A8%E6%84%8F%E7%82%B9.md) * [★ 24-Vue折腾记-给Axios做个挺靠谱的封装(报错,鉴权,跳转,拦截,提示)](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/24-Vue%E6%8A%98%E8%85%BE%E8%AE%B0-%E7%BB%99Axios%E5%81%9A%E4%B8%AA%E6%8C%BA%E9%9D%A0%E8%B0%B1%E7%9A%84%E5%B0%81%E8%A3%85%EF%BC%88%E6%8A%A5%E9%94%99%2C%E9%89%B4%E6%9D%83%2C%E8%B7%B3%E8%BD%AC%2C%E6%8B%A6%E6%88%AA%2C%E6%8F%90%E7%A4%BA%EF%BC%89.md) * [40-解密Vue SSR](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/40-%E8%A7%A3%E5%AF%86Vue%20SSR.md) +* [49-Vue 面试中常问知识点整理](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/49-Vue%20%E9%9D%A2%E8%AF%95%E4%B8%AD%E5%B8%B8%E9%97%AE%E7%9F%A5%E8%AF%86%E7%82%B9%E6%95%B4%E7%90%86.md) ### 3、ES6/ES7/ES8... * [3-Promise简单用法](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/3-Promise%E7%AE%80%E5%8D%95%E7%94%A8%E6%B3%95.md) diff --git "a/article/49-Vue \351\235\242\350\257\225\344\270\255\345\270\270\351\227\256\347\237\245\350\257\206\347\202\271\346\225\264\347\220\206.md" "b/article/49-Vue \351\235\242\350\257\225\344\270\255\345\270\270\351\227\256\347\237\245\350\257\206\347\202\271\346\225\264\347\220\206.md" index b880ef7c..f91c1f56 100644 --- "a/article/49-Vue \351\235\242\350\257\225\344\270\255\345\270\270\351\227\256\347\237\245\350\257\206\347\202\271\346\225\264\347\220\206.md" +++ "b/article/49-Vue \351\235\242\350\257\225\344\270\255\345\270\270\351\227\256\347\237\245\350\257\206\347\202\271\346\225\264\347\220\206.md" @@ -142,7 +142,8 @@ js实现简单的双向绑定: 在`main.js`引入`store`,注入。新建了一个目录`store`,`… export` 。 场景有:单页应用中,组件之间的状态、音乐播放、登录状态、加入购物车。 -![vue生命周期](http://p3nqtyvgo.bkt.clouddn.com/vue%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F.jpg) +![vue生命周期](http://p3nqtyvgo.bkt.clouddn.com/vue%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F.jpg) + **state**:Vuex 使用单一状态树,即每个应用将仅仅包含一个`store` 实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。 **mutations**:`mutations`定义的方法动态修改`Vuex `的 `store` 中的状态或数据。 From 3ab7994342c300f1a05347ba51e2a979de6553f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 17 Sep 2018 19:33:41 +0800 Subject: [PATCH 046/835] 2018.09.17 --- ...37\245\350\257\206\347\202\271\346\225\264\347\220\206.md" | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git "a/article/49-Vue \351\235\242\350\257\225\344\270\255\345\270\270\351\227\256\347\237\245\350\257\206\347\202\271\346\225\264\347\220\206.md" "b/article/49-Vue \351\235\242\350\257\225\344\270\255\345\270\270\351\227\256\347\237\245\350\257\206\347\202\271\346\225\264\347\220\206.md" index f91c1f56..b1166a77 100644 --- "a/article/49-Vue \351\235\242\350\257\225\344\270\255\345\270\270\351\227\256\347\237\245\350\257\206\347\202\271\346\225\264\347\220\206.md" +++ "b/article/49-Vue \351\235\242\350\257\225\344\270\255\345\270\270\351\227\256\347\237\245\350\257\206\347\202\271\346\225\264\347\220\206.md" @@ -1,3 +1,5 @@ +[原文](https://mp.weixin.qq.com/s/5tiAmJCLlPTQObMDY2ZgkA) + 看看面试题,只是为了查漏补缺,看看自己那些方面还不懂。切记不要以为背了面试题,就万事大吉了,最好是理解背后的原理,这样面试的时候才能侃侃而谈。不然,稍微有水平的面试官一看就能看出,是否有真才实学还是刚好背中了这道面试题(有空再把例子中代码补上)。 ## 一、对于MVVM的理解? @@ -199,7 +201,7 @@ const store = new Vuex.Store({ ### 2、`v-if` 和 `v-show` 区别 答:`v-if`按照条件是否渲染,`v-show`是`display`的`block`或`none`; -### 3、`$route``和$router`的区别 +### 3、`$route`和`$router` 区别 答:`$route`是 `路由信息对象`,包括`path`,`params`,`hash`,`query`,`fullPath`,`matched`,`name`等路由信息参数。而`$router`是 `路由实例` 对象包括了路由的跳转方法,钩子函数等。 From a338fa24d7850e95826c4f8a902020b42638bf68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Tue, 18 Sep 2018 21:38:01 +0800 Subject: [PATCH 047/835] 2018.09.18 --- ...st\347\232\204\345\214\272\345\210\253.md" | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 "article/50-js\344\270\255get\345\222\214post\347\232\204\345\214\272\345\210\253.md" diff --git "a/article/50-js\344\270\255get\345\222\214post\347\232\204\345\214\272\345\210\253.md" "b/article/50-js\344\270\255get\345\222\214post\347\232\204\345\214\272\345\210\253.md" new file mode 100644 index 00000000..f6027312 --- /dev/null +++ "b/article/50-js\344\270\255get\345\222\214post\347\232\204\345\214\272\345\210\253.md" @@ -0,0 +1,33 @@ +在常见的客户端传递参数的方式有`GET`和`POST`两种: +* **浏览器地址栏直接输入**:一定是`GET`请求; +* **超链接**:一定是`GET`请求; +* **表单**:可以是`GET`,也可以是`POST`,这取决与`
`的`method`属性值; + +### 两者区别: +#### 1.效率 +* `GET`的意思是 `得` ,从服务器获取数据(也可以上传数据,参数就是),效率较高; +* `POST`的意思是 `给` ,但可以向服务器发送数据和下载数据,效率不如`GET`; + +#### 2.缓存 +* `GET` 请求能够被缓存,默认的请求方式也是有缓存的; +* `POST` 请求默认不会缓存; + +> * 缓存是针对`URL`来进行缓存的,`GET`请求由于其参数是直接加在`URL`上的,一种参数组合就有一种URL的缓存,可以根据参数来进行一一对应,重复请求是幂等的(不论请求多少次,结果都一样); +> * 而POST请求的URL没有参数,每次请求的URL都相同,数据体(HTTPBody)可能不同,无法一一对应,所以缓存没有意义; + +#### 3.安全性 +* `GET` 的所有参数全部包装在`URL`中,明文显示,且服务器的访问日志会记录,非常不安全; +* `POST` 的`URL`中只有资源路径,不包含参数,参数封装在二进制的数据体中,服务器也不会记录参数,相对安全。所有涉及用户隐私的数据都要用 `POST` 传输; + +> `POST`的安全是**相对的**,对于普通用户来说他们看不到明文,数据封装对他们来说就是屏障。但是对于专业人士,它们会抓包会分析,没有加密的数据包对他们来说也是小case。所以POST仅仅是相对安全,唯有对数据进行加密才会更安全。当然加密也有被破解的可能性,**理论上所有的加密方式都可以破解**,只是时间长短的问题。而加密算法要做的就是使得破解需要的时间尽量长,越长越安全。由于我们也需要解密,加密算法太过复杂也并非好事,这就要结合使用情况进行折中或者足够实际使用即可。绕的有点远,具体的话,我将在后续的文章之中介提及,并介绍一些常用的加密算法。 + +#### 4.数据量 +`HTTP`协议中均没有对`GET`和`POST`请求的**数据大小**进行限制,但是实际应用中它们通常受限于软硬件平台的设计和性能。 +* `GET`:不同的浏览器和服务器不同,一般限制在`2~8K`之间,更加常见的是`1k`以内; +* `POST`:提交的数据较大,大小靠服务器的设定值限制,PHP默认是`2M`(具体的话大家以后看后端给的开发文档就行了); + +#### 5.数据获取方式 +* `GET` 需要使用` Request.QueryString `来取得变量的值; +* `POST` 通过 `Request.Form` 来获取变量的值; + +也就是说 `Get` 是通过**地址栏**来传值,而 `Post` 是通过**提交表单**来传值。 \ No newline at end of file From ce903a28f3bc3630bbd28bceece4e3b51ff05a06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Tue, 18 Sep 2018 21:40:20 +0800 Subject: [PATCH 048/835] 2018.09.18 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e2ab4856..b52b065b 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,7 @@ * [45-js中reduce的神奇用法](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/45-js%E4%B8%ADreduce%E7%9A%84%E7%A5%9E%E5%A5%87%E7%94%A8%E6%B3%95.md) * [46-在JavaScript中更好的使用数组](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/46-%E5%9C%A8JavaScript%E4%B8%AD%E6%9B%B4%E5%A5%BD%E7%9A%84%E4%BD%BF%E7%94%A8%E6%95%B0%E7%BB%84.md) * [48-js获取元素高度和浏览器各种高度方法汇总](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/48-js获取元素高度和浏览器各种高度方法汇总.md) +* [50-js中get和post的区别](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/50-js%E4%B8%ADget%E5%92%8Cpost%E7%9A%84%E5%8C%BA%E5%88%AB.md) ### 7、HTTP * [47-http请求头与响应头的应用](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/47-http%E8%AF%B7%E6%B1%82%E5%A4%B4%E4%B8%8E%E5%93%8D%E5%BA%94%E5%A4%B4%E7%9A%84%E5%BA%94%E7%94%A8.md) From 4a8c9721e1e2ea07f68c8b715659e8f7667fa185 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Wed, 19 Sep 2018 22:28:05 +0800 Subject: [PATCH 049/835] 2018.09.19 --- ...44\271\213HTTP\345\215\217\350\256\256.md" | 480 ++++++++++++++++++ 1 file changed, 480 insertions(+) create mode 100644 "article/51-Apache\344\271\213HTTP\345\215\217\350\256\256.md" diff --git "a/article/51-Apache\344\271\213HTTP\345\215\217\350\256\256.md" "b/article/51-Apache\344\271\213HTTP\345\215\217\350\256\256.md" new file mode 100644 index 00000000..87e79f96 --- /dev/null +++ "b/article/51-Apache\344\271\213HTTP\345\215\217\350\256\256.md" @@ -0,0 +1,480 @@ +**`HTTP`(Hypertext Transfer Protocol)超文本传输协议**。是一种详细规定了客户端浏览器和万维网服务器之间相互通讯的规则,通过因特网传送万维网文档的数据传送协议。 + +## 一、HTTP的前世今生 +**超文本传输协议**的前身是Xanadu项目,超文本的概念是泰德.纳尔森在1960年提出的。而HTTP在1989年诞生在CERN(欧洲量子物理实验室)。1990年12月,超文本协议在CERN首次上线。1991年夏天,继Telnet等协议之后,超文本传输协议正式成为互联网诸多协议的一份子。 + +**HTTP诞生的原因**:为了实现从一台计算机上获取并显示存放在多台计算机里的文件、数据、图片和其他类型的文件而诞生HTTP协议。因为在当时其他诸多已经诞生的协议解决不了这个问题。例如:Telnet、SMTP、POP3、IAMP4、FTP等。所以HTTP协议应运而生。 + +## 二、HTTP协议的版本 +### HTTP 0.9 +**HTTP 0.9**作为HTTP协议的第一个成熟版本。此版本功能非常薄弱。 +* 1.请求只有一行 +* 2.没有HTTP头部信息和错误代码信息 +* 3.只能接收一种类型的数据:纯文本 +* 4.只有一种方法:GET + +### HTTP 1.0 +随着互联网的发展,**HTTP 0.9**已经不能满足互联网发展的需求。因此**HTTP 1.0**就这样诞生了。**HTTP 1.0**的最大改变是引入了`POST`方法,使得客户端通过`HTML表单`向服务器发送数据成为可能。从而实现了客户端和服务器端的数据交互。这是WEB应用程序的一个基础。另一个巨大的改变是引入了`HTTP头`,使得HTTP协议不仅能返回错误代码,并且借助于MIME技术能够传输更为丰富的文件类型,不再局限于纯文本。还可以是图片、动画等其他文件格式。 + +除此之外,还允许保持连接,即一次TCP连接,可以实现多次通讯。`HTTP 1.0`默认是**传输一次数据后就关闭连接**。 + +### HTTP 1.1 +2000年5月,`HTTP 1.1`诞生。`HTTP 1.1`并不像`HTTP 1.0`对`HTTP 0.9`那样的革命性。但是对`HTTP 1.0`做了很多功能性的增强。 +* 1.增加了`Host头` + 使得GET后面只需使用相对路径; + 使得一台主机可以使用多个域名; +* 2.引入了`Range头 + 使得客户端通过`HTTP`下载时只下载内容的一部分,使得多线程下载成为可能; + +## 三、HTTP协议的特点 +* **1.支持C/S模式** + 支持基本认证和安全认证。 + +* **2.简单快速** + 客户端向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有`GET`、`HEAD`、`POST`。每种方法规定了客户端与服务器端联系的不同类型。由于`HTTP协议`简单,使得HTTP服务器的程序规模小,因而通讯速度快。 + +* **3.灵活** + HTTP协议允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。 + +* **4.HTTP 0.9和HTTP 1.0使用非持续连接** + 限制每次连接只处理一个请求,服务器处理完客户端的请求,并收到客户端的应答后,即断开连接。采用这种方式可以节省传输时间。 + HTTP 1.1使用持续连接:不必为每个Web对象创建一个新的连接,一个连接可以传送多个对象。 + +* **5.无状态:** + HTTP协议是无状态协议。 + 无状态是指协议对于事物处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。 + +## 四、HTTP实现原理 +**在TCP/IP协议栈中的位置**: + HTTP协议通常承载于TCP协议之上,有时也承载于TLS或SSL协议层之上,这个时候,就成了我们常说的HTTPS。如下图所示: +![HTTPS](http://s3.51cto.com/wyfs02/M02/38/15/wKioL1OybmbgvkXfAABJlqiTUPM914.jpg) + + 默认HTTP的端口号为80,HTTPS的端口号为443。 + +**HTTP的请求响应模型**: + HTTP协议永远都是客户端发起请求,服务器回送响应。如下图所示: +![发起请求](http://s3.51cto.com/wyfs02/M00/38/15/wKiom1OybujR2rlWAABZ59w_LlM241.jpg) + + + 这样就限制了使用HTTP协议,无法实现在客户端没有发起请求的时候,服务器将消息推送给客户端。 + + HTTP协议是一个无状态的协议,同一个客户端的这次请求和上次请求是没有对应关系。 + +**工作流程:** +一次HTTP操作称为一个事务,其工作过程可分为四步: +* 1.首先客户机与服务器需要**建立连接**。只要单击某个超级链接,HTTP的工作开始。 + +* 2.建立连接后,客户机发送一个请求给服务器,请求方式的格式为:**统一资源标识符(URL)、协议版本号**,后边是MIME信息包括请求修饰符、客户机信息和可能的内容。 + +* 3.服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括**信息的协议版本号**、**一个成功或错误的代码**,后边是MIME信息包括服务器信息、实体信息和可能的内容。 + +* 4.客户端接收服务器所返回的信息通过浏览器显示在用户的显示屏上,然后客户机与服务器**断开连接**。 + +如果在以上过程中的某一步出现错误,那么产生错误的信息将返回到客户端,有显示屏输出。对于用户来说,这些过程是由HTTP自己完成的,用户只要用鼠标点击,等待信息显示就可以了。 + +**简化版**: +* 1.建立连接 +* 2.接收请求 +* 3.处理请求 +* 4.获取资源 +* 5.构建响应 +* 6.回送响应 +* 7.记录日志 + +## 五、HTTP的几个重要概念 +### URI、URL、URN: +* **URI**: Uniform Resource Identifier,统一资源标识符; +* **URL**: Uniform Resource Locator,统一资源定位符; +* **URN**: Uniform Resource Name,统一资源命名符; + +其中,URL,URN是URI的**子集**。 + +Web上地址的**基本形式**是URI,它代表**通用资源标识符**。有两种形式: +* **URL**:目前URI的最普遍形式就是无处不在的URL或统一资源定位器。 +* **URN**:URL的一种更新形式,统一资源名称(URN, Uniform Resource Name)不依赖于位置,并且有可能减少失效连接的个数。但是其流行还需假以时日,因为它需要更精密软件的支持。 + +**URI格式**: +``` +scheme://[username:password@]HOST:port/path/to/source +``` + +### 连接(Connection): +一个传输层的实际环流,它是建立在**两个相互通讯的应用程序之间**。 + +在**http1.1**,`request`和`reponse`头中都有可能出现一个`connection`的头,此`header`的含义是当`client`和`serve`r通信时对于长链接如何进行处理。 + +在**http1.1**中,`client`和`server`都是默认**对方支持长链接**的, 如果`client`使用**http1.1协议**,但又不希望使用长链接,则需要在`header`中指明`connection`的值为`close`;如果`server`方也不想支持长链接,则在`response`中也需要明确说明`connection`的值为`close`。不论`request`还是`response`的`header`中包含了值为`close`的`connection`,都表明当前正在使用的tcp链接在**当天请求处理完毕后会被断掉**。以后client再进行新的请求时就必须**创建新的tcp链接**了。 + +### 消息(Message): + HTTP通讯的基本单位,包括一个结构化的八元组序列并通过连接传输。 + +### 请求(Request): + 一个从客户端到服务器的请求信息包括**应用于资源的方法**、**资源的标识符**和**协议的版本号**。 + +### 响应(Response): + 一个从服务器返回的信息包括**HTTP协议的版本号**、**请求的状态**(例如“成功”或“没找到”)和**文档的MIME类型**。 + +### 资源(Resource): + 由**URI**标识的网络数据对象或服务。 + +### 实体(Entity): + 数据资源或来自服务资源的回映的一种特殊表示方法,它可能被包围在一个请求或响应信息中。一个实体包括**实体头信息**和**实体的本身内容**。 + +### 客户机(Client): + 一个为发送请求目的而建立连接的应用程序。 + +### 用户代理(UserAgent): + 初始化一个请求的客户机。它们是浏览器、编辑器或其它用户工具。 + +### 服务器(Server): + 一个接受连接并对请求返回信息的应用程序。 + +### 源服务器(OriginServer): + 是一个给定资源可以在其上驻留或被创建的服务器。 + +### 代理(Proxy): + 一个中间程序,它可以充当一个**服务器**,也可以充当一个**客户机**,为其它客户机建立请求。请求是通过可能的翻译在内部或经过传递到其它的服务器中。一个代理在发送请求信息之前,必须解释并且如果可能重写它。 + + 代理经常作为通过防火墙的客户机端的门户,代理还可以作为一个帮助应用来通过协议处理没有被用户代理完成的请求。 + +### 网关(Gateway): + 一个作为**其它服务器中间媒介的服务器**。与代理不同的是,网关接受请求就好象对被请求的资源来说它就是源服务器;发出请求的客户机并没有意识到它在同网关打交道。 + + 网关经常作为通过防火墙的服务器端的门户,网关还可以作为一个协议翻译器以便存取那些存储在非HTTP系统中的资源。 + +### 通道(Tunnel): + 是作为两个连接中继的中介程序。一旦激活,通道便被认为不属于HTTP通讯,尽管通道可能是被一个HTTP请求初始化的。当被中继的连接两端关闭时,通道便消失。当一个门户(Portal)必须存在或中介(Intermediary)不能解释中继的通讯时通道被经常使用。 + +### 缓存(Cache): + 反应信息的局域存储。 + +## 六、HTTP协议头 +HTTP头按照其不同的作用,分为四类: + +### 1.通用头(General Header) + 通用头**即可以包含在HTTP请求中,也可以包含在HTTP响应中**。 + 通用头的作用是描叙HTTP协议本身。比如**描叙HTTP是否持续连接**的`Connection头`,**HTTP发送日期**的`Date头`,**描述HTTP所在的TCP连接时间**的`Keep-Alive头`,用于**缓存控制**的`Cache-Control头`等。 + +### 2.实体头(Entity Header) + 实体头是那些**描叙HTTP信息的头**。即可出现在HTTP POST方法的请求中,也可以出现在HTTP响应中。 + 例如`Content-Type`和`Content-length`都是描述实体的类型和大小的头都属于实体头。其它还有用于描述实体的`Content-Language`,`Content-MD5`,`Content-Encoding`以及控制实体缓存的`Expires`和`Last-Modifies头`等。 + +**常见的实体头**如下: +> * **Allow**:服务器支持哪些请求方法(如GET、POST等); +> * **Content-Encoding**:文档的编码(Encode)方法,例如:gzip,见“2.5 响应头”; +> * **Content-Language**:内容的语言类型,例如:zh-cn; +> * **Content-Length**:表示内容长度,eg:80,可参考“2.5响应头”; +> * **Content-Location**:表示客户应当到哪里去提取文档; +> * **Content-MD5**:MD5 实体的一种MD5摘要,用作校验和。发送方和接受方都计算MD5摘要,接受方将其计算的值与此头标中传递的值进行比较。Eg1:Content-MD5: 。`Eg2:dfdfdfdfdfdfdff==`; +> * **Content-Range**:随部分实体一同发送;标明被插入字节的低位与高位字节偏移,也标明此实体的总长度。Eg1:`Content-Range: 1001-2000/5000,eg2:bytes 2543-4532/7898`; +> * **Content-Type**:标明发送或者接收的实体的MIME类型。Eg:`text/html`; `charset=GB2312`主类型/子类型; +> * **Expires**:为0证明不缓存; +> * **Last-Modified**:WEB 服务器认为对象的最后修改时间,比如文件的最后修改时间,动态页面的最后产生时间等等。例如:`Last-Modified:Tue, 06 May 2008 02:42:43 GMT`; + +### 3.请求头(HTTP Request Header) + 请求头是那些由客户端发往服务器端以便帮助服务器端更好的满足客户端请求的头。 + 请求头只能出现在HTTP请求中。比如告诉服务器**只接收某种响应内容**的`Accept头`,**发送Cookies**的`Cookie头`,**显示请求主机域**的`HOST头`,**用于缓存**的`If-Match`,`If-Match-Since`,`If-None-Match头`,**用于只取HTTP响应信息中部分信息**的`Range头`,**用于附属HTML相关请求引用**的`Referee头`等。 + +**常见请求头如下:** + +> * **Accept**:浏览器可接受的MIME类型; +> * **Accept-Charse**t:浏览器可接受的字符集; +> * **Accept-Encoding**:浏览器能够进行解码的数据编码方式,比如gzip。Servlet能够向支持gzip的浏览器返回经gzip编码的HTML页面。许多情形下这可以减少5到10倍的下载时间; +> * **Accept-Language**:浏览器所希望的语言种类,当服务器能够提供一种以上的语言版本时要用到; +> * **Authorization**:授权信息,通常出现在对服务器发送的WWW-Authenticate头的应答中; +> * **Connection**:表示是否需要持久连接。如果Servlet看到这里的值为“Keep-Alive” ,或者看到请求使用的是HTTP 1.1(HTTP 1.1默认进行持久连接),它就可以利用持久连接的优点,当页面包含多个元素时(例如Applet,图片),显著地减少下载所需要的时间。要实现这一点,Servlet需要在应答中发送一个Content-Length头,最简单的实现方法是:先把内容写入ByteArrayOutputStream,然后在正式写出内容之前计算它的大小; +> * **Content-Length**:表示请求消息正文的长度; +> * **Cookie**:这是最重要的请求头信息之一; +> * **From**:请求发送者的email地址,由一些特殊的Web客户程序使用,浏览器不会用到它; +> * **Host**:初始URL中的主机和端口; +> * **If-Modified-Since**:只有当所请求的内容在指定的日期之后又经过修改才返回它,否则返回304“Not Modified”应答; +> * **Pragma**:指定“no-cache”值表示服务器必须返回一个刷新后的文档,即使它是代理服务器而且已经有了页面的本地拷贝; +> * **Referer**:包含一个URL,用户从该URL代表的页面出发访问当前请求的页面。 +> * **User-Agent**:浏览器类型,如果Servlet返回的内容与浏览器类型有关则该值非常有用; +> * **UA-Pixels,UA-Color,UA-OS,UA-CPU**:由某些版本的IE浏览器所发送的非标准的请求头,表示屏幕大小、颜色深度、操作系统和CPU类型。 + +### 4.响应头(HTTP Response Header) +HTTP响应头是那些描述HTTP响应本身的头,这里并不包含描述HTTP响应中第三部分也就是HTTP信息的头(这部分由实体头负责)。 +比如说定时刷新的Refresh头,当遇到503错误时自动重试的Retry-After头,显示服务器信息的Server头,设置COOKIE的Set-Cookie头,告诉客户端可以部分请求的Accept-Ranges头等。 + +**常见响应头如下:** + +> * **Allow**服务器支持哪些请求方法(如`GET`、`POST`等); +> * **Content-Encoding**文档的编码(Encode)方法。 + 只有在解码之后才可以得到` Content-Type头`指定的内容类型。利用`gzip压缩文档`能够显著地减少HTML文档的下载时间。Java的`GZIPOutputStream`可以很方便地进行`gzip压缩`,但只有`Unix`上的`Netscape`和`Windows`上的`IE 4`、`IE 5`才支持它。因此,`Servlet`应该通过查看`Accept-Encoding头`(即`request.getHeader`("`Accept-Encoding`"))检查浏览器是否支持`gzip`,为支持`gzip`的浏览器返回经`gzip`压缩的HTML页面,为其他浏览器返回普通页面; +> * **Content-Length**表示内容长度。只有当浏览器使用持久HTTP连接时才需要这个数据。如果你想要利用持久连接的优势,可以把输出文档写入`ByteArrayOutputStram`,完成后查看其大小,然后把该值放入`Content-Length头`,最后通过`byteArrayStream.writeTo(response.getOutputStream())`发送内容; +> * **Content-Type** 表示后面的文档属于什么`MIME类`型。`Servlet`默认为`text/plain`,但通常需要显式地指定为`text/html`。由于经常要设置`Content-Type`,因此`HttpServletResponse`提供了一个专用的方法`setContentTyep`。 可在web.xml文件中配置扩展名和MIME类型的对应关系; +> * **Date**当前的GMT时间。你可以用`setDateHeader`来设置这个头以避免转换时间格式 的麻烦; +> * **Server**服务器软件名称及版本。 +> * **Age**响应给客户端的文档可以缓存多长时间 +> * **Public** +> * **Vary** +> * **Set-Cookie** +> * **Set-Cookie2** +> * **Expires**指明应该在什么时候认为文档已经过期,从而不再缓存它。 +> * **Last-Modified**文档的最后改动时间。客户可以通过`If-Modified-Since`请求头提供一个日期,该请求将被视为一个条件`GET`,只有改动时间迟于指定时间的文档才会返回,否则返回一个**304**(`Not Modified`)状态。`Last-Modified`也可用`setDateHeader`方法来设置; +> * **Location**表示客户应当到哪里去提取文档。 + `Location`通常不是直接设置的,而是通过`HttpServletResponse`的`sendRedirect`方法,该方法同时设置状态代码为**302**; +> * **Refresh**表示浏览器应该在多少时间之后刷新文档,以秒计。 + 除了刷新当前文档之外,你还可以通过`setHeader("Refresh", "5; URL=http://host/path")`让浏览器读取指定的页面。注意这种功能通常是通过设置HTML页面HEAD区的``实现,这是因为,自动刷新或重定向对于那些不能使用CGI或`Servle`t的HTML编写者十分重要。但是,对于`Servlet`来说,直接设置`Refresh头`更加方便。注意`Refres`h的意义是“**N秒之后刷新本页面或访问指定页面**”,而不是“**每隔N秒刷新本页面或访问指定页面**”。因此,连续刷新要求每次都发送一个`Refresh头`,而发送**204**状态代码则可以阻止浏览器继续刷新,不管是使用`Refresh头`还是``。注意`Refresh头`不属于**HTTP 1.1正式规范**的一部分,而是一个扩展,但`Netscape`和`IE`都支持它。 + + +## 七、HTTP请求 +HTTP请求由三部分组成,分别是:**请求行**、**消息报头**、**请求正文** +请求行以一个方法符开头,以空格分开,后面跟着请求的URI和协议的版本,格式如下: +``` +Method Request-URI HTTP-Version CRLF +``` +* **Method** 表示请求方法; +* **Request-URI** 是一个统一资源标识符,也就是资源路径; +* **HTTP-Version** 表示HTTP协议版本; +* **CRLF** 表示回车和换行。 + +**请求方法:** +> * **GET** 请求获取Request-URI所标识的资源 +> * **POST** 在Request-URI所标识的资源后附加新的数据,常用于提交表单 +> * **HEAD** 请求获取由Request-URI所标识的资源的响应消息报头 +> * **PUT** 请求服务器存储一个资源,并用Request-URI作为其标识 +> * **DELETE** 请求服务器删除Request-URI所标识的资源 +> * **TRACE** 请求服务器回送收到的请求信息,主要用于测试或诊断 + 可以追踪一次请求中间所经过的代理服务器有哪些 +> * **CONNECT** 保留将来使用 +> * **OPTIONS** 请求查询服务器的性能,或者查询与资源相关的选项和需求 + 可以用来获取服务器端资源支持的方法 + + +## 八、HTTP响应 +在接收和解释请求消息后,服务器返回一个HTTP响应消息。 + +HTTP响应也是由三个部分组成,分别是:**状态行**、**消息报头**、**响应正文** + +**状态行格式如下**: +``` +HTTP-Version Status-Code Reason-Phrase CRLF +``` +> * **HTTP-Version** 表示服务器HTTP协议的版本; +> * **Status-Code** 表示服务器发回的响应状态代码; +> * **Reason-Phrase** 表示状态代码的文本描述。 + +状态代码有**三位数字**组成,第一个数字定义了响应的类别,且有五种可能取值: +> * **1xx**:指示信息--表示请求已接收,继续处理 +> * **2xx**:成功--表示请求已被成功接收、理解、接受 +> * **3xx**:重定向--信息不完整需要进一步补充 +> * **4xx**:客户端错误--请求有语法错误或请求无法实现 +> * **5xx**:服务器端错误--服务器未能实现合法的请求 + +**常见http响应状态码**: +#### 请求收到,继续处理: +> * **100**:客户端必须继续发出请求 +> * **101**:客户端要求服务器根据请求转换HTTP协议版本 + +#### 操作成功收到,分析,接受: +> * **200**:交易成功 +> * **201**:提示知道新文件的URL +> * **202**:接受和处理、但处理未完成 +> * **203**:返回信息不确定或不完整 +> * **204**:请求收到,但返回信息为空 +> * **205**:服务器完成了请求,用户代理必须复位当前已经浏览过的文件 +> * **206**:服务器已经完成了部分用户的GET请求 + +#### 重定向: +> * **300**:请求的资源可在多处得到 +> * **301**:永久重定向,在Location响应首部的值仍为当前URL(隐式重定向) +> * **302**:临时重定向,在Location响应首部的值仍为新的URL(显示重定向) +> * **303**:建议客户端访问其他URL或访问方式 +> * **304**:Not Modified 请求的资源没有改变 可以继续使用缓存 +> * **305**:请求的资源必须从服务器指定的地址得到 +> * **306**:前一版本HTTP中使用的代码,现行版本中不再使用 +> * **307**:声明请求的资源临时性删除 + +#### 客户端错误: +> * **400**:错误请求,如语法错误 +> * **401**:未授权 + **HTTP 401.1** - 未授权,登录失败 + **HTTP 401.2** - 未授权,服务器配置问题导致登录失败 + **HTTP 401.3** - ACL 禁止访问资源 + **HTTP 401.4** - 未授权 授权被筛选器拒绝 + **HTTP 401.5** - 未授权 ISAPI或CGI授权失败 +> * **402**:保留有效ChargeTo头响应 +> * **403**:禁止访问 + **HTTP 403.1** - 禁止访问 禁止可执行访问 + **HTTP 403.2** - 禁止访问 禁止读访问 + **HTTP 403.3** - 禁止访问 禁止写访问 + **HTTP 403.4** - 禁止访问 要求SSL + **HTTP 403.5** - 禁止访问 要求SSL 128 + **HTTP 403.6** - 禁止访问 IP地址被拒绝 + **HTTP 403.7** - 禁止访问 要求客户端证书 + **HTTP 403.8** - 禁止访问 禁止站点访问 + **HTTP 403.9** - 禁止访问 连接的用户过多 + **HTTP 403.10** - 禁止访问 配置无效 + **HTTP 403.11** - 禁止访问 密码更改 + **HTTP 403.12** - 禁止访问 映射器拒绝访问 + **HTTP 403.13** - 禁止访问 客户端证书已被吊销 + **HTTP 403.15** - 禁止访问 客户端访问许可过多 + **HTTP 403.16** - 禁止访问 客户端证书不可信或者无效 + **HTTP 403.17** - 禁止访问 客户端证书已经到期或者尚未生效 +> * **404**:没有发现文件、查询或URL +> * **405**:用户在Request-Line字段定义的方法不允许 +> * **406**:根据用户发送的Accept拖,请求资源不可访问 +> * **407**:类似401,用户必须首先在代理服务器上得到授权 +> * **408**:客户端没有在用户指定的饿时间内完成请求 +> * **409**:对当前资源状态,请求不能完成 +> * **410**:服务器上不再有此资源且无进一步的参考地址 +> * **411**:服务器拒绝用户定义的Content-Length属性请求 +> * **412**:一个或多个请求头字段在当前请求中错误 +> * **413**:请求的资源大于服务器允许的大小 +> * **414**:请求的资源URL长于服务器允许的长度 +> * **415**:请求资源不支持请求项目格式 +> * **416**:请求中包含Range请求头字段,在当前请求资源范围内没有range指示值, 请求也不包含If-Range请求头字段 +> * **417** 服务器不满足请求Expect头字段指定的期望值,如果是代理服务器,可能是下一级服务器不能满足请求长 + +#### 服务器端错误: +> * **500**部服务器错误 + **HTTP 500.100** - 内部服务器错误 + **HTTP 500-11** 服务器关闭 + **HTTP 500-12** 应用程序重新启动 + **HTTP 500-13** - 服务器太忙 + **HTTP 500-14** - 应用程序无效 + **HTTP 500-15** - 不允许请求 +> * **501**实现 +> * **502**关错误 +> * **503**务不可用 +> * **504**关超时 + +## 九、HTTP状态保持 + HTTP 协议本身是无状态的,这与HTTP协议本来的目的是相符的,客户端只需要简单的向服务器请求下载某些文件,无论是客户端还是服务器都没有必要纪录彼此过去的行为,每一次请求之间都是独立的,好比一个顾客和一个自动售货机或者一个普通的(非会员制)大卖场之间的关系一样。 + + 然而聪明(或者贪心?)的人们很快发现如果能够提供一些按需生成的动态信息会使web变得更加有用,就像给有线电视加上点播功能一样。这种需求一方面迫使HTML逐步添加了表单、脚本、DOM等客户端行为,另一方面在服务器端则出现了CGI规范以响应客户端的动态请求,作为传输载体的HTTP协议也添加了文件上载、 cookie这些特性。其中cookie的作用就是为了解决HTTP协议无状态的缺陷所作出的努力。至于后来出现的session机制则是又一种在客户端与服务器之间保持状态的解决方案。 + + +Cookie和Session都为了用来保存状态信息,都是保存客户端状态的机制,它们都是为了解决HTTP无状态的问题而所做的努力。 + +Session可以用Cookie来实现,也可以用URL回写的机制来实现。用Cookie来实现的Session可以认为是对Cookie更高级的应用。 + + +### Cookie和Session区别 + +* 1. Cookie将状态保存在客户端,Session将状态保存在服务器端; + +* 2. Cookies是服务器在本地机器上存储的小段文本并随每一个请求发送至同一个服务器。Cookie最早在RFC2109中实现,后续RFC2965做了增强。网络服务器用HTTP头向客户端发送cookies,在客户终端,浏览器解析这些cookies并将它们保存为一个本地文件,它会自动将同一服务器的任何请求缚上这些cookies。Session并没有在HTTP的协议中定义; + +* 3. Session是针对每一个用户的,变量的值保存在服务器上,用一个sessionID来区分是哪个用户session变量,这个值是通过用户的浏览器在访问的时候返回给服务器,当客户禁用cookie时,这个值也可能设置为由get来返回给服务器; + +* 4. 就安全性来说:当你访问一个使用session 的站点,同时在自己机子上建立一个cookie,建议在服务器端的SESSION机制更安全些.因为它不会任意读取客户存储的信息。 + + +### Session机制 + +Session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。 + +当程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识 - 称为 session id,如果已包含一个session id则说明以前已经为此客户端创建过session,服务器就按照session id把这个 session检索出来使用(如果检索不到,可能会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个 session id将被在本次响应中返回给客户端保存。 + + + +### Session的实现方式 +**使用Cookie来实现:** +服务器给每个Session分配一个唯一的JSESSIONID,并通过Cookie发送给客户端。 + +当客户端发起新的请求的时候,将在Cookie头中携带这个JSESSIONID。这样服务器能够找到这个客户端对应的Session。 + +流程如下图所示: +![session](http://s3.51cto.com/wyfs02/M00/38/13/wKiom1OyXoHjWI2aAABsbAEnTIs272.jpg) +**使用URL回显来实现** +URL回写是指服务器在发送给浏览器页面的所有链接中都携带JSESSIONID的参数,这样客户端点击任何一个链接都会把JSESSIONID带会服务器。 + +如果直接在浏览器输入服务端资源的url来请求该资源,那么Session是匹配不到的。 + +Tomcat对Session的实现,是一开始同时使用Cookie和URL回写机制,如果发现客户端支持Cookie,就继续使用Cookie,停止使用URL回写。如果发现Cookie被禁用,就一直使用URL回写。jsp开发处理到Session的时候,对页面中的链接记得使用response.encodeURL()。 + +### 与Cookie相关的HTTP扩展头 +* 1. **Cookie**:客户端将服务器设置的Cookie返回到服务器; +* 2. **Set-Cookie**:服务器向客户端设置Cookie; +* 3. **Cookie2 (RFC2965))**:客户端指示服务器支持Cookie的版本; +* 4. **Set-Cookie2 (RFC2965)**:服务器向客户端设置Cookie。 + +### Cookie的流程 +服务器在响应消息中用Set-Cookie头将Cookie的内容回送给客户端,客户端在新的请求中将相同的内容携带在Cookie头中发送给服务器。从而实现会话的保持。 + + 流程如下图所示: +![cookie](http://s3.51cto.com/wyfs02/M00/38/13/wKioL1OyX1-jc2HfAABcl6JnHeo234.jpg) + +## 十、Web缓存 +### 什么是Web缓存 + WEB缓存(cache)位于Web服务器和客户端之间。 + + 缓存会根据请求保存输出内容的副本,例如html页面,图片,文件,当下一个请求来到的时候:如果是相同的URL,缓存直接使用副本响应访问请求,而不是向源服务器再次发送请求。 + + HTTP协议定义了相关的消息头来使WEB缓存尽可能好的工作。 + + + +### Web缓存的优点 +* 1. **减少相应延迟**:因为请求从缓存服务器(离客户端更近)而不是源服务器被相应,这个过程耗时更少,让web服务器看上去相应更快。 + +* 2. **减少网络带宽消耗**:当副本被重用时会减低客户端的带宽消耗;客户可以节省带宽费用,控制带宽的需求的增长并更易于管理。 + + +### 与缓存相关的HTTP消息头 +> * **Expires**:指示响应内容过期的时间,格林威治时间GMT +> * **Cache-Control**:更细致的控制缓存的内容 +> * **Last-Modified**:响应中资源最后一次修改的时间 +> * **ETag**:响应中资源的校验值,在服务器上某个时段是唯一标识的。 +> * **Date**:服务器的时间 +> * **If-Modified-Since**:客户端存取的该资源最后一次修改的时间,同Last-Modified。 +> * **If-None-Match**:客户端存取的该资源的检验值,同ETag。 + +### 客户端缓存生效的常见流程 +服务器收到请求时,会在200 OK中回送该资源的Last-Modified和ETag头,客户端将该资源保存在cache中,并记录这两个属性。当客户端需要发送相同的请求时,会在请求中携带If-Modified-Since和If-None-Match两个头。两个头的值分别是响应中Last-Modified和ETag头的值。服务器通过这两个头判断本地资源未发生变化,客户端不需要重新下载,返回304响应。 + +常见流程如下图所示: +![缓存](http://s3.51cto.com/wyfs02/M02/38/13/wKioL1OyYpTBYuovAABlmj5y42w797.jpg) +### Web缓存机制 +HTTP/1.1中缓存的目的是为了在很多情况下减少发送请求,同时在许多情况下可以不需要发送完整响应。前者减少了网络回路的数量;HTTP利用一个“过期(expiration)”机制来为此目的。后者减少了网络应用的带宽;HTTP用“验证(validation)”机制来为此目的。 + +**HTTP定义了3种缓存机制**: +> * 1. **Freshness**:允许一个回应消息可以在源服务器不被重新检查,并且可以由服务器和客户端来控制。例如,Expires回应头给了一个文档不可用的时间。Cache-Control中的max-age标识指明了缓存的最长时间; +> * 2. **Validation**:用来检查以一个缓存的回应是否仍然可用。例如,如果一个回应有一个Last-Modified回应头,缓存能够使用If-Modified-Since来判断是否已改变,以便判断根据情况发送请求; +> * 3. **Invalidation**: 在另一个请求通过缓存的时候,常常有一个副作用。例如,如果一个URL关联到一个缓存回应,但是其后跟着POST、PUT和DELETE的请求的话,缓存就会过期。 + +## 十一、HTTP代理服务器 +代理服务器英文全称是Proxy Server,其功能就是代理网络用户去取得网络信息。形象的说:它是网络信息的中转站。 + +代理服务器是介于浏览器和Web服务器之间的一台服务器,有了它之后,浏览器不是直接到Web服务器去取回网页而是向代理服务器发出请求,Request信号会先送到代理服务器,由代理服务器来取回浏览器所需要的信息并传送给你的浏览器。 + +而且,大部分代理服务器都具有缓冲的功能,就好象一个大的Cache,它有很大的存储空间,它不断将新取得数据储存到它本机的存储器上,如果浏览器所请求的数据在它本机的存储器上已经存在而且是最新的,那么它就不重新从Web服务器取数据,而直接将存储器上的数据传送给用户的浏览器,这样就能显著提高浏览速度和效率。 + +更重要的是:Proxy Server(代理服务器)是Internet链路级网关所提供的一种重要的安全功能,它的工作主要在开放系统互联(OSI)模型的对话层。 + +### HTTP代理服务器的主要功能 + +* 1. 突破自身IP访问限制,访问国外站点。如:教育网、169网等网络用户可以通过代理访问国外网站; + +* 2. 访问一些单位或团体内部资源,如某大学FTP(前提是该代理地址在该资源的允许访问范围之内),使用教育网内地址段免费代理服务器,就可以用于对教育 网开放的各类FTP下载上传,以及各类资料查询共享等服务; + +* 3. 突破中国电信的IP封锁:中国电信用户有很多网站是被限制访问的,这种限制是人为的,不同Serve对地址的封锁是不同的。所以不能访问时可以换一个国 外的代理服务器试试; + +* 4. 提高访问速度:通常代理服务器都设置一个较大的硬盘缓冲区,当有外界的信息通过时,同时也将其保存到缓冲区中,当其他用户再访问相同的信息时, 则直接由缓冲区中取出信息,传给用户,以提高访问速度; + +* 5. 隐藏真实IP:上网者也可以通过这种方法隐藏自己的IP,免受攻击。 + +HTTP代理图示: +![代理](http://s3.51cto.com/wyfs02/M01/38/14/wKioL1OyZMLCGz4sAABIrUX08kc751.jpg) +对于客户端浏览器而言,http代理服务器相当于服务器。 +而对于Web服务器而言,http代理服务器又担当了客户端的角色。 + +## 十二、虚拟主机的实现 +### 什么是虚拟主机 + 虚拟主机:是在网络服务器上划分出一定的磁盘空间供用户放置站点、应用组件等,提供必要的站点功能与数据存放、传输功能。 + + 所谓虚拟主机,也叫“网站空间”就是把一台运行在互联网上的服务器划分成多个“虚拟”的服务器,每一个虚拟主机都具有独立的域名和完整的Internet服务器(支持WWW、FTP、E-mail等)功能。一台服务器上的不同虚拟主机是各自独立的,并由用户自行管理。但一台服务器主机只能够支持一定数量的虚拟主机,当超过这个数量时,用户将会感到性能急剧下降。 + + + +### 虚拟主机的实现原理 + 虚拟主机是用同一个WEB服务器,为不同域名网站提供服务的技术。Apache、Tomcat等均可通过配置实现这个功能。 + 相关的HTTP消息头:Host。 + 例如:Host: www.baidu.com + 客户端发送HTTP请求的时候,会携带Host头,Host头记录的是客户端输入的域名。这样服务器可以根据Host头确认客户要访问的是哪一个域名。 + + +节选自 [Apache之HTTP协议](http://blog.51cto.com/shjia/1432670) \ No newline at end of file From 7551da748e8de744299ea9801a34d88b17862162 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Wed, 19 Sep 2018 22:33:18 +0800 Subject: [PATCH 050/835] =?UTF-8?q?2018.09.19=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=96=87=E7=AB=A0=E8=B0=83=E6=95=B4=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b52b065b..9ee1d6c3 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ ### 7、HTTP * [47-http请求头与响应头的应用](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/47-http%E8%AF%B7%E6%B1%82%E5%A4%B4%E4%B8%8E%E5%93%8D%E5%BA%94%E5%A4%B4%E7%9A%84%E5%BA%94%E7%94%A8.md) +* [51-Apache之HTTP协议](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/51-Apache%E4%B9%8BHTTP%E5%8D%8F%E8%AE%AE.md) ### 8、其他 * [2017-全年总结](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/2017-%E5%85%A8%E5%B9%B4%E6%80%BB%E7%BB%93.md) From 05b9c7bc81dabc4e2bdf95ac9c006aca125414b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Thu, 20 Sep 2018 22:43:49 +0800 Subject: [PATCH 051/835] 2018.09.20 --- ...ommonJs,AMD\345\222\214CMD\357\274\211.md" | 273 ++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 "article/52-\345\211\215\347\253\257\346\250\241\345\235\227\345\214\226\357\274\210CommonJs,AMD\345\222\214CMD\357\274\211.md" diff --git "a/article/52-\345\211\215\347\253\257\346\250\241\345\235\227\345\214\226\357\274\210CommonJs,AMD\345\222\214CMD\357\274\211.md" "b/article/52-\345\211\215\347\253\257\346\250\241\345\235\227\345\214\226\357\274\210CommonJs,AMD\345\222\214CMD\357\274\211.md" new file mode 100644 index 00000000..05a10631 --- /dev/null +++ "b/article/52-\345\211\215\347\253\257\346\250\241\345\235\227\345\214\226\357\274\210CommonJs,AMD\345\222\214CMD\357\274\211.md" @@ -0,0 +1,273 @@ +前端模块规范有三种:**CommonJs**,**AMD**和**CMD**。 + +* CommonJs用在**服务器端**,AMD和CMD用在**浏览器环境**。 + +* AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。 +* CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。 + +* AMD:**提前执行**(异步加载:依赖先执行)+**延迟执行**。 +* CMD:**延迟执行**(运行到需加载,根据顺序执行)。 + +## 模块 +* **函数写法** +```js +function f1(){ + //... +} +function f2(){ + //... +} +``` + +模块就是实现特定功能的文件,把几个函数放在一个文件里就构成了一个模块。需要的时候加载这个文件,调用其中的函数即可。 +但这样做会污染全局变量,无法保证不与其他模块发生变量名冲突,而且模块成员之间没什么关系。 + +* **对象写法** +```js +var module = { +  star : 0, +  f1 : function (){ +    //... +  }, +  f2 : function (){ +    //... +  } +}; +module.f1(); +module.star = 1; +``` + +模块写成一个对象,模块成员都封装在对象里,通过调用对象属性,访问使用模块成员。但同时也暴露了模块成员,外部可以修改模块内部状态。 + +* **立即执行函数** +```js +var module = (function(){ +  var star = 0; +  var f1 = function (){ +    console.log('ok'); +  }; +  var f2 = function (){ +    //... +  }; + return { + f1:f1, + f2:f2 + }; +})(); +module.f1(); //ok +console.log(module.star) //undefined +``` + +外部无法访问内部私有变量 + +## CommonJs +CommonJS是服务器端模块的规范,由Node推广使用。由于服务端编程的复杂性,如果没有模块很难与操作系统及其他应用程序互动。使用方法如下: +```js +// math.js +exports.add = function() { + var sum = 0, i = 0, args = arguments, l = args.length; + while (i < l) { + sum += args[i++]; + } + return sum; +}; + +increment.js +var add = require('math').add; +exports.increment = function(val) { + return add(val, 1); +}; + +index.js +var increment = require('increment').increment; +var a = increment(1); //2 +``` +根据**CommonJS**规范: + +* 一个单独的文件就是一个模块。每一个模块都是一个单独的作用域,也就是说,在该模块内部定义的变量,无法被其他模块读取,除非定义为`global对象`的属性。 + +* 输出模块变量的最好方法是使用`module.exports`对象。 + +* 加载模块使用`require`方法,该方法读取一个文件并执行,返回文件内部的`module.exports`对象 + +仔细看上面的代码,您会注意到 `require` 是同步的。模块系统需要同步读取模块文件内容,并编译执行以得到模块接口。 +然而, 这在浏览器端问题多多。 + +浏览器端,加载 JavaScript 最佳、最容易的方式是在 document 中插入 +``` + +我们在html页面的input元素中设置了a属性,但是在`property`中却是访问不到的;相反我们没有在html页面中设置的`title`,访问它却没有反映`undefined`! + +这是怎么回事? + +因为所有的HTML元素都由`HTMLElement`类型表示,`HTMLElement`类型直接继承自`Element`并添加了一些属性,每个HTML元素都有下面的这5个标准特性:`id`,`title`,`lang`,`dir`,`className`(在DOM中以`property`方式操作这几个特性会同步到html标签中)。 + +所以即使在html中没有指定`id`、`title`等,也会默认赋予一个空串,通过property属性(点操作符)可以访问。而除此之外在html中设置的其他属性是不能通过`Property`访问到的(`attribute`特有的属性)。 + +如果把DOM元素看成是一个普通的Object对象,那么property就是一个以名值对(`name='value'`)的形式存放在Object中的属性。要添加和删除`property`也简单多了,和普通的对象没啥分别: +```js +var a = document.getElementById('txt'); +a.age = 10; +console.log(a.age); // 10 +delete a.age; +console.log(a.age); // undefined +``` +除了`id`、`title`等5个属性(`property`)外(每个element元素都有),个别的元素还有特别的属性,比如input元素有`name`,a元素有`href`等等。 + +## 3、Attribute vs Property + +既然说有些属性既能通过`attribute`访问修改,也能通过`property`,那么有什么值得注意的地方呢? + +之所以`attribute`和`property`容易混倄在一起的原因是,很多`attribute`节点还有一个相对应的`property`属性,比如div元素的`id`和`class`既是`attribute`,也有对应的`property`(id和className),不管使用哪种方法都可以**访问和修改**,如果在TAG对这些属性进行赋值,那么这些值就会作为初始值赋给DOM的同名property。 + + +* **input元素的value** + +input元素的`value`属性是一大坑爹处,看下面代码: + +```js +var a = document.getElementById('txt'); +a.setAttribute('value', 'test'); +console.log(a.value); // test + +a.value = 'change'; +console.log(a.getAttribute('value')); // test +``` + +用**点操作符**改变`value`值,并不会更新`attribute`的`value`值;而相反用`attribute`更新`value`值,却会反映到`property`上...坑吧,谁规定的! + +* **表单元素** + +DOM元素一些默认常见的`attribute`节点都有与之对应的`property`属性,比较特殊的是一些值为`Boolean类型`的`property`,如一些表单元素。对于这些特殊的`attribute`节点,只要存在该节点,对应的`property`的值就为`true`,如: +```html + + +``` +disabled类似。 + +* **href** + +两者对于`href`的获取也有不同之处,`attribute`取到的是实际设置的值(相对路径),而`property`取得的是绝对路径: + +```html + + +``` + +## 4、总结 +`Attribute`属性在`html`上设置,会反应在`html`代码上,两者**同步**;而`Property`属性则可以看做是DOM对象的键值对,用**点操作符**对它们进行操作。 + +实际编程中,基本上的DOM操作都是使用`property`的点操作符。 + +只有两种情况不得不使用`attribute`: + +* 1. 自定义HTML Attribute,因为它不能同步到DOM property上 + +* 2. 访问内置的HTML标签的`Attribute`,这些`attribute`不能从`property`上同步过来,比如`input标签`的`value`值(可以用来检验input值是否变化) + + +## 5、参考 +* [JavaScript中的property和attribute的区别](https://www.jianshu.com/p/rRssiL) + +* [返本求源——DOM元素的特性与属性](http://www.cnblogs.com/dojo-lzz/p/4781563.html) \ No newline at end of file From 02cc678a8b0095d2ee786739a28d3ff1073885fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Wed, 26 Sep 2018 23:05:55 +0800 Subject: [PATCH 058/835] 2018.09.26 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 139e3e0b..96b17d28 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ * [52-前端模块化(CommonJs,AMD和CMD)](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/52-%E5%89%8D%E7%AB%AF%E6%A8%A1%E5%9D%97%E5%8C%96%EF%BC%88CommonJs%2CAMD%E5%92%8CCMD%EF%BC%89.md) * [53-js中call和apply和bind方法介绍](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/53-js%E4%B8%ADcall%E5%92%8Capply%E5%92%8Cbind%E6%96%B9%E6%B3%95%E4%BB%8B%E7%BB%8D.md) * [54-ajax详解](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/54-ajax%E8%AF%A6%E8%A7%A3.md) +* [55-JS中attribute和property区别](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/55-JS%E4%B8%ADattribute%E5%92%8Cproperty%E5%8C%BA%E5%88%AB.md) ### 7、HTTP * [47-http请求头与响应头的应用](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/47-http%E8%AF%B7%E6%B1%82%E5%A4%B4%E4%B8%8E%E5%93%8D%E5%BA%94%E5%A4%B4%E7%9A%84%E5%BA%94%E7%94%A8.md) From 46a9354a92d2765f0d984dd18f67a20dd1c59c69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 28 Sep 2018 22:39:29 +0800 Subject: [PATCH 059/835] 2018.09.28 --- ...47\346\211\277\345\216\237\347\220\206.md" | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 "article/46-js\344\270\255\345\216\237\345\236\213\347\273\247\346\211\277\345\216\237\347\220\206.md" diff --git "a/article/46-js\344\270\255\345\216\237\345\236\213\347\273\247\346\211\277\345\216\237\347\220\206.md" "b/article/46-js\344\270\255\345\216\237\345\236\213\347\273\247\346\211\277\345\216\237\347\220\206.md" new file mode 100644 index 00000000..39c6924e --- /dev/null +++ "b/article/46-js\344\270\255\345\216\237\345\236\213\347\273\247\346\211\277\345\216\237\347\220\206.md" @@ -0,0 +1,86 @@ +在JavaScript当中,对象A如果要继承对象B的属性和方法,那么只要将对象B放到对象A的原型链上即可。而某个对象的原型链,就是由该对象开始,通过`__proto__`属性连接起来的一串对象。`__proto__`属性是JavaScript对象中的内部属性,任何JavaScript对象,包括我们自己构建的对象,JavaScript的`built-in`对象,任何函数(在JavaScript当中,函数也是对象)都具有这个属性。如下图就是一个原型链的例子: +![图片1](http://p3nqtyvgo.bkt.clouddn.com/20180927_01.png) + +上图中,A,B,C分别代表3个对象,**蓝色箭头**串接起来的所有对象就构成了**对象C的原型链**,其中C的`_proto__`属性指向B,B的`__proto__`属性指向A,A的`__proto__`属性可能指向更高层的对象,也可能指向`null`(表示**A不继承任何对象的属性和方法**)。 + +如果我们引用了C的某个属性或者方法,那么JavaScript就会顺着C的原型链进行查找,即首先查找对象C本身,看所引用的属性名或者方法名是否存在,如果存在就停止查找直接返回,如果不存在,就通过C的`__proto__`属性找到原型链中的B对象,继续在B对象中查找,如果B对象中找到所引用的属性名或者方法名,那么就停止查找直接返回,如果B对象中也不存在,就通过对象B的`__proto__`属性找到原型链中的A对象,继续重复上述查找过程,直到找到所引用的属性或者方法为止(同时也可能查找完对象C的整个原型链也没有找到所引用的属性或者方法,那么该属性或者方法就是`undefined`的)。 + +因此,只要能够成功的为某一个对象构造出我们需要的原型链,那么就能让该对象继承我们想要它继承的方法或者属性。而想要成功构造对象的原型链,就还必须理解`prototype`属性,JavaScript当中已经存在的原型链,以及当我们创建对象时,原型链被构造的过程。 + + +### prototype属性 +prototype属性存在于JavaScript的任何函数当中,这个属性指向的对象就是所谓的原型对象,在构造原型链时需要原型对象。 + + +### JavaScript当中已经存在的原型链 + +在JavaScript当中存在`Object`,`Function`,`Array`,`String`,`Boolean`,`Number`,`Date`,`Error`,`RegExp`这9个**built-in函数**,一个`built-in`的`Math对象`,通过这上述9个`built-in函数`我们可以创建相应的对象,同时,这9个`built-in函数`的`prototype`属性所指向的原型对象也是`built-in`的。下面的图示解释了这几个函数以及各自`prototype`属性所指向的原型对象之间的关系。 +![图片2](http://p3nqtyvgo.bkt.clouddn.com/20180927_02.png) + +(如果此图看不清,可点击 [此处下载](http://p3nqtyvgo.bkt.clouddn.com/20180927_02.png)) + +  上面的图示中,**黄色方框**代表`built-in函数对象`,**深绿色方框**代表`built-in函数`的`prototype属性`指向的原型对象,名字都叫`xx prototype object`,**浅绿色方框**(即**Math对象**)代表**普通对象**,蓝色箭头连接非built-in函数对象(无论是普通对象如Math,还是原型对象)的`__proto__`属性,而土黄色箭头连接函数对象的`__proto__`属性。 + +  通过上图可以发现,所有**built-in函数对象**的原型链最终都指向`Function prototype object`,所有**非函数对象的原型链**最终都指向`Object prototype object`,并且`Function prototype object`的`__proto__`属性也指向`Object prototype object`,`Object prototype object`的`__proto__`属性指向为`null`。 + +因此,`Object prototype object`是所有原型链的顶端,通过原型链查找规则可知,所有`built-in`函数对象同时继承了`Object prototype object`和`Function prototype object`上的属性和方法,而所有非built-in函数对象只继承了`Object prototype object`上的方法。`Function prototype object`包含了所有函数共享的属性和方法,而`Object prototype object`包含了所有对象都共享额属性和方法。 + +对于上图中原型对象包含的constructor属性,下文当中有解释。 + + + +### 创建对象时,原型链的构造过程 + +在JavaScript当中创建对象有2中方式,一种是通过定义函数使用**new方法**来构造,另一种是使用**对象字面量**的方式,即: +```js +var obj = { + name: "Jim Green" +}; +``` +使用这两种方式创建对象时,对象的原型链构造过程有所不同。 + +* **1. 使用函数的方式构造对象** + +使用函数的方式构造对象分为两步:首先需要**定义一个函数**作为构造函数,然后使用**new方法构造对象**。接下来就来看一下这两个步骤会发生什么。 + +假设我们定义了一个函数名为`F`,此时JavaScript会为我们做两件事,第一:根据我们定义的函数创建一个函数对象,第二,设置这个函数的`__proto__`属性和`prototype`属性。其中`__proto__`属性指向`built-in`的`Function prototype object`,而`prototype`属性指向一个为函数对象F新创建的原型对象,这个新创建的原型对象通过调用`new Object()`构造出来,并且为这个新创建的对象添加`constructor`属性,该属性指向函数对象`F`。最后的结果如下图所示: + +![图3](http://p3nqtyvgo.bkt.clouddn.com/20180927_03.png) + +上图中为了方便,没有画出`Function prototype object`和`Object prototype object`的`constructor`属性。而`F` `prototype object`的`__proto__`属性为何指向`Object prototype object`,下文介绍**new操作符**时有解释。 + +当我们使用**new方法**调用F函数的时候,JavaScript也会为我们做两件事,第一,分配内存作为新创建的对象,第二,将新创建的对象的__proto__属性指向函数F的原型对象,结果如下图: +![图4](http://p3nqtyvgo.bkt.clouddn.com/20180927_04.png) + +上图中,`obj`就是调用**new方法**通过`函数F`创建出来的对象,我们可以看到对象obj的原型链包含了`函数F`的原型对象,以及`Object prototype object`,这样,对象`obj`通过原型链查找规则,就能继承`函数F`的原型对象,以及`Object prototype object`上面定义的属性和方法了。并且如果我们想知道一个对象是由哪个方法构建的,只需要访问这个对象的`constructor`属性即可,上例中,只要我们访问`obj.constructor`,那么就知道obj是由`函数F`创建的。同时,由于`F` `prototype object`上文中介绍是由`new Object`函数创建的,根据此处介绍,F `prototype object`的`__proto__`属性应该指向`Object函数`的原型对象,即`Object prototype object`。 + +* **2. 使用对象字面量定义对象** + +当使用对象字面量创建对象时,JavaScript会为我们做两件事: + +> 1 分配内存作为新创建的对象。 +> 2 将新创建对象的`__proto__`属性指向`Object prototype object`。 + +结果如下图所示: +![图5](http://p3nqtyvgo.bkt.clouddn.com/20180927_05.png) + +上图为了简化,同样没有画出`Object prototype object`的`constructor`属性 + +### 继承 + +理解了上面所讲的原理之后,假设目前有一个对象`A`(这个对象可以是任意的,包括JavaScript built-in的对象,任何函数对象,任何原型对象,以及我们自己new出来的对象),现在想创建一个对象`obj`,让`obj`继承`A`的属性和方法。 + +通过上面的介绍,我们知道创建对象有两种方式,但是使用对象字面量创建的对象其原型链总是只包含两个对象,一个是其自己,一个是`Object prototype object`,根本不可能包含对象`A`,无法达到让对象`obj`继承对象`A`属性和方法的效果。因此,只能使用函数的方式创建对象,让对象A包含在新创建对象obj的原型链中即可。 + +根据上面的讲解,如果是用函数的方式创建对象,那么在调用`new`方法时,新创建对象的`__proto__`属性会指向函数的原型对象。因此,只要在调用函数之前,将函数的原型对象换成`A`,然后再调用`new`方法,就可以将对象A包含在新创建的对象`obj`的原型链中,这样通过原型链查找规则,`obj`就继承了A的属性和方法。假设用来创建对象`obj`的函数为`B`,则相关代码为: +```js +B.prototype = A; +B.prototype.constructor = B; +var obj = new B(传入的参数) +``` +上面代码中的`B.prototype.constructor = B`,是因为对象A中可能没有`constructor`属性,或者`constructor`属性不指向`B`,而为了方便通过访问任何由`B`函数创建的对象的`constructor`属性,就可以正确的知道该对象是使用函数`B`构造出来的。相关图示如下图: + +![图6](http://p3nqtyvgo.bkt.clouddn.com/20180927_06.png) + + +上图中虚线框所包围的`B prototype object`就是定义函数`B`时,JavaScript为函数B生成的原型对象,但是该对象被我们用代码替换成了对象A。由于这个被替换的`B prototype object`没有其他地方再用到,因此会被回收掉。 \ No newline at end of file From c773481ddfc669a4fdc77cb2235da1d79e9a76ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 28 Sep 2018 22:42:44 +0800 Subject: [PATCH 060/835] 2018.09.28 --- README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 96b17d28..e109b552 100644 --- a/README.md +++ b/README.md @@ -48,14 +48,12 @@ ### 6、细节知识点 * [6-关于js的作用域和声明提前](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/6-%E5%85%B3%E4%BA%8Ejs%E7%9A%84%E4%BD%9C%E7%94%A8%E5%9F%9F%E5%92%8C%E5%A3%B0%E6%98%8E%E6%8F%90%E5%89%8D.md) * [★ 10-知识点整理1](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/10-%E7%9F%A5%E8%AF%86%E7%82%B9%E6%95%B4%E7%90%861.md) -* [11-20个超级常用的正则表达式](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/11-20%E4%B8%AA%E8%B6%85%E7%BA%A7%E5%B8%B8%E7%94%A8%E7%9A%84%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F.md) -* [16-带你理解 JS 容易出错的坑和细节](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/16-%E5%B8%A6%E4%BD%A0%E7%90%86%E8%A7%A3%20JS%20%E5%AE%B9%E6%98%93%E5%87%BA%E9%94%99%E7%9A%84%E5%9D%91%E5%92%8C%E7%BB%86%E8%8A%82.md) -* [17-TypeScript和 JavaScript 深度对比](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/17-TypeScript%E5%92%8C%20JavaScript%20%E6%B7%B1%E5%BA%A6%E5%AF%B9%E6%AF%94.md) +* [16-带你理解 JS 容易出错的坑和细节](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/16-%E5%B8%A6%E4%BD%A0%E7%90%86%E8%A7%A3%20JS%20%E5%AE%B9%E6%98%93%E5%87%BA%E9%94%99%E7%9A%84%E5%9D%91%E5%92%8C%E7%BB%86%E8%8A%82.md) +* [17-TypeScript和 JavaScript 深度对比](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/17-TypeScript%E5%92%8C%20JavaScript%20%E6%B7%B1%E5%BA%A6%E5%AF%B9%E6%AF%94.md) * [★ 21-JavaScript异步机制详解](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/21-JavaScript%E5%BC%82%E6%AD%A5%E6%9C%BA%E5%88%B6%E8%AF%A6%E8%A7%A3.md) * [22-JavaScript中有趣的区分同步和异步Ajax](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/22-JavaScript%E4%B8%AD%E6%9C%89%E8%B6%A3%E7%9A%84%E5%8C%BA%E5%88%86%E5%90%8C%E6%AD%A5%E5%92%8C%E5%BC%82%E6%AD%A5Ajax.md) * [23-JavaScript八张思维导图](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/23-JavaScript%E5%85%AB%E5%BC%A0%E6%80%9D%E7%BB%B4%E5%AF%BC%E5%9B%BE.md) * [28-JavaScript中的void运算符](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/28-JavaScript%E4%B8%AD%E7%9A%84void%E8%BF%90%E7%AE%97%E7%AC%A6.md) -* [30-一次记住js的6个正则方法](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/30-%E4%B8%80%E6%AC%A1%E8%AE%B0%E4%BD%8Fjs%E7%9A%846%E4%B8%AA%E6%AD%A3%E5%88%99%E6%96%B9%E6%B3%95.md) * [31-聊一聊JavaScript的IIFE](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/32-%E8%81%8A%E4%B8%80%E8%81%8AJavaScript%E7%9A%84IIFE.md) * [33-javascript的纯函数](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/33-javascript%E7%9A%84%E7%BA%AF%E5%87%BD%E6%95%B0.md) * [36-好好学习toLocaleString方法](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/36-%E5%A5%BD%E5%A5%BD%E5%AD%A6%E4%B9%A0toLocaleString%E6%96%B9%E6%B3%95.md) @@ -77,7 +75,11 @@ * [47-http请求头与响应头的应用](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/47-http%E8%AF%B7%E6%B1%82%E5%A4%B4%E4%B8%8E%E5%93%8D%E5%BA%94%E5%A4%B4%E7%9A%84%E5%BA%94%E7%94%A8.md) * [51-Apache之HTTP协议](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/51-Apache%E4%B9%8BHTTP%E5%8D%8F%E8%AE%AE.md) -### 8、其他 +### 8、正则表达式 +* [30-一次记住js的6个正则方法](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/30-%E4%B8%80%E6%AC%A1%E8%AE%B0%E4%BD%8Fjs%E7%9A%846%E4%B8%AA%E6%AD%A3%E5%88%99%E6%96%B9%E6%B3%95.md) +* [11-20个超级常用的正则表达式](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/11-20%E4%B8%AA%E8%B6%85%E7%BA%A7%E5%B8%B8%E7%94%A8%E7%9A%84%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F.md) + +### 9、其他 * [2017-全年总结](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/2017-%E5%85%A8%E5%B9%B4%E6%80%BB%E7%BB%93.md) * [2018-全年计划](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/2018-%E5%85%A8%E5%B9%B4%E8%AE%A1%E5%88%92.md) * [★ 27-Markdowm语法整理](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/27-Markdowm%E8%AF%AD%E6%B3%95%E6%95%B4%E7%90%86.md) From bfa7ecaa621ab88e974cd5ebeb2f27796a9e9153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 28 Sep 2018 22:46:02 +0800 Subject: [PATCH 061/835] 2018.09.28 --- README.md | 1 + ...5\236\213\347\273\247\346\211\277\345\216\237\347\220\206.md" | 0 2 files changed, 1 insertion(+) rename "article/46-js\344\270\255\345\216\237\345\236\213\347\273\247\346\211\277\345\216\237\347\220\206.md" => "article/56-js\344\270\255\345\216\237\345\236\213\347\273\247\346\211\277\345\216\237\347\220\206.md" (100%) diff --git a/README.md b/README.md index e109b552..367fc1d0 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ * [53-js中call和apply和bind方法介绍](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/53-js%E4%B8%ADcall%E5%92%8Capply%E5%92%8Cbind%E6%96%B9%E6%B3%95%E4%BB%8B%E7%BB%8D.md) * [54-ajax详解](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/54-ajax%E8%AF%A6%E8%A7%A3.md) * [55-JS中attribute和property区别](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/55-JS%E4%B8%ADattribute%E5%92%8Cproperty%E5%8C%BA%E5%88%AB.md) +* [55-JS中attribute和property区别](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/55-JS%E4%B8%ADattribute%E5%92%8Cproperty%E5%8C%BA%E5%88%AB.md) ### 7、HTTP * [47-http请求头与响应头的应用](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/47-http%E8%AF%B7%E6%B1%82%E5%A4%B4%E4%B8%8E%E5%93%8D%E5%BA%94%E5%A4%B4%E7%9A%84%E5%BA%94%E7%94%A8.md) diff --git "a/article/46-js\344\270\255\345\216\237\345\236\213\347\273\247\346\211\277\345\216\237\347\220\206.md" "b/article/56-js\344\270\255\345\216\237\345\236\213\347\273\247\346\211\277\345\216\237\347\220\206.md" similarity index 100% rename from "article/46-js\344\270\255\345\216\237\345\236\213\347\273\247\346\211\277\345\216\237\347\220\206.md" rename to "article/56-js\344\270\255\345\216\237\345\236\213\347\273\247\346\211\277\345\216\237\347\220\206.md" From 1e133dca1c943919908d3ac9736da58717368ce2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 28 Sep 2018 22:46:48 +0800 Subject: [PATCH 062/835] 2018.09.28 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 367fc1d0..8bd27d46 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ * [53-js中call和apply和bind方法介绍](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/53-js%E4%B8%ADcall%E5%92%8Capply%E5%92%8Cbind%E6%96%B9%E6%B3%95%E4%BB%8B%E7%BB%8D.md) * [54-ajax详解](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/54-ajax%E8%AF%A6%E8%A7%A3.md) * [55-JS中attribute和property区别](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/55-JS%E4%B8%ADattribute%E5%92%8Cproperty%E5%8C%BA%E5%88%AB.md) -* [55-JS中attribute和property区别](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/55-JS%E4%B8%ADattribute%E5%92%8Cproperty%E5%8C%BA%E5%88%AB.md) +* [56-js中原型继承原理](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/56-js%E4%B8%AD%E5%8E%9F%E5%9E%8B%E7%BB%A7%E6%89%BF%E5%8E%9F%E7%90%86.md) ### 7、HTTP * [47-http请求头与响应头的应用](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/47-http%E8%AF%B7%E6%B1%82%E5%A4%B4%E4%B8%8E%E5%93%8D%E5%BA%94%E5%A4%B4%E7%9A%84%E5%BA%94%E7%94%A8.md) From 102ffb67180e79de6442f8e40ec20d758bd6560b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 5 Oct 2018 22:40:43 +0800 Subject: [PATCH 063/835] 2018.10.05 --- ...76\345\274\217\346\200\273\347\273\223.md" | 363 ++++++++++++++++++ 1 file changed, 363 insertions(+) create mode 100644 "article/57-ES5/ES6\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217\346\200\273\347\273\223.md" diff --git "a/article/57-ES5/ES6\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217\346\200\273\347\273\223.md" "b/article/57-ES5/ES6\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217\346\200\273\347\273\223.md" new file mode 100644 index 00000000..3d40f1e8 --- /dev/null +++ "b/article/57-ES5/ES6\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217\346\200\273\347\273\223.md" @@ -0,0 +1,363 @@ +## 1. +**ʽ**regular expressionһֱıģʽַṹķ + +ʽ**ַʽ** + +һʹ**бܱʾʼͽ** +```js +var regex = /xyz/ +``` + +һʹRegExp캯 +```js +var regex = new RegExp('xyz'); +``` + +ǵҪǣһַʱͻ½ʽڶַʱ½ʽǰߵЧʽϸߡңǰ߱ȽϱֱۣʵӦУ϶ʽ + +## 2.ʵ +* **i** :ԴСд + +* **m** :ģʽ + +* **g** :ȫ + +## 3.ʵ +### 3.1 RegExp.prototype.test() +ʵ`test`һֵʾǰģʽ**Ƿƥ**ַ +```js +/С/.test('С ѧϰִ') // true +``` +`reg.exec(str)` ƥ飬ƥ򷵻`null`ÿִһ`exec`ƥһ + +### 3.2 RegExp.prototype.exec() +* **reg.exec(str)** ƥ飬ƥ򷵻`null`ÿִһ`exec`ƥһ +```js +var s = '_x_x';var r1 = /x/;var r2 = /y/; + +r1.exec(s) // ["x"]r2.exec(s) // null +``` +* ʽ()Ϊƥ䣬ؽУһƥÿƥĽ +```js +var s = '_x_x'; +var r = /_(x)/; + +r.exec(s) // ["_x", "x"] +``` +`exec`ķ黹ԣ +**input**ԭַ + +**index**ģʽƥɹĿʼλã0ʼ +```js +var r = /a(b+)a/; +var arr = r.exec('_abbba_aba_'); + +arr // ["abbba", "bbb"] + +arr.index // 1arr.input // "_abbba_aba_" +``` +* ʽgѡȫԶʹ exec´εƥϴεĽʼ +```js +var reg = /a/g;var str = 'abc_abc_abc'var r1 = reg.exec(str); +r1 // ["a"]r1.index // 0reg.lastIndex // 1var r2 = reg.exec(str); +r2 // ["a"]r2.index // 4reg.lastIndex // 5var r3 = reg.exec(str); +r3 // ["a"]r3.index // 8reg.lastIndex // 9var r4 = reg.exec(str); +r4 // nullreg.lastIndex // 0 +``` + +## 4.ַʵ +### 4.1 str.match(reg) + `reg.exec`ƣǣʹ`g`ѡstr.match`һԷн +```js +var s = 'abba';var r = /a/g; + +s.match(r) // ["a", "a"]r.exec(s) // ["a"] +``` +### 4.2 str.search(reg) +ƥɹĵһλ,ûκƥ䣬򷵻-1 +```js +'_x_x'.search(/x/)// 1 +``` +### 4.3 str.replace(reg,newstr) +õһ`reg`ȥƥ䣬õڶ`newstr` ȥ滻ʽ`g`η滻һƥɹֵ滻ƥɹֵ +```js +'aaa'.replace('a', 'b')// "baa" +'aaa'.replace(/a/, 'b') // "baa" +'aaa'.replace(/a/g, 'b') // "bbb" +``` +### 4.4 str.split(reg[,maxLength]) +ƥģʽиڶƷؽ + +## 5. ƥ +### 5.1 ַԪַ +󲿷ַʽУĺ壬`/a/`ƥ`a``/b/`ƥ`b`ʽ֮Уijַֻʾĺ壨ǰabôǾͽ**ַ**literal characters +ַ⣬һַ⺬壬˼ǽ**Ԫַ**metacharactersҪ¼ + +* (1) ַ`.` + +ַ.ƥسr(n) зָu2028Ͷηָu2029ַ +```js +/c.t/ +``` +Уc.tƥct֮һַֻҪַͬһУcatc2tc-tȵȣDzƥcoot + +* (2)λַ + +**^** ʾַĿʼλ + +**$** ʾַĽλ +```js +// testڿʼλ/ +^test/.test('test123') // true + +// testڽλ +/test$/.test('new test') // true + +// ӿʼλõλֻ +test/^test$/.test('test') // true + +/^test$/.test('test test') // false +``` + +* (3)ѡ| + +߷ţ`|`ʽбʾ`ϵ`ORcat|dogʾƥcatdog +```js +/11|22/.test('911') // true +``` +Уʽָƥ1122 + +### 5.2 ת +ʽЩ⺬ԪַҪƥDZҪǰҪϷбܡҪƥ+Ҫд+ +```js +/1+1/.test('1+1')// false/1\+1/.test('1+1')// true +``` +ʽУҪбתģһ12ַ`^.[$()|*+?{`͡ҪرעǣʹRegExpתҪʹбܣΪַڲתһΡ +```js +(new RegExp('1\+1')).test('1+1')// false +(new RegExp('1\\+1')).test('1+1')// true +``` +### 5.3 ַ +ַࣨclassʾһϵַɹѡֻҪƥһͿˡпɹѡַڷڣ[xyz] ʾxyz֮ѡһƥ䡣 +```js +/[abc]/.test('hello world') // false +/[abc]/.test('apple') // true +``` +ַַ⺬塣 + +* 1ַ^ +ڵĵһַ[^xyz]ʾxyz֮ⶼƥ䣺 +```js +/[^abc]/.test('hello world') // true +/[^abc]/.test('bbc') // false +``` +ûַֻ[^]ͱʾƥһַаз֮£ΪԪַ.Dzзġ +```js +var s = 'Please yes\nmake my day!'; +s.match(/yes.*day/) // nulls.match(/yes[^]*day/) // [ 'yes\nmake my day'] +``` +УַsһзŲзԵһʽƥʧܣڶʽ[^]һַƥɹ + +* 2ַ- + +ijЩ£еַַ`-`ṩдʽʾַΧ磬[abc]д[`a-c`][0123456789]д[0-9]ͬ[A-Z]ʾ26дĸ +```js +/a-z/.test('b') // false +/[a-z]/.test('b') // true +``` +¶ǺϷַдʽ +```js +[0-9.,] +[0-9a-fA-F] +[a-zA-Z0-9-] +[1-31] +``` +һַ[1-31]131ֻ13 + +⣬Ҫʹַ趨һܴķΧܿѡַ֮͵Ӿ[A-z]ѡдӴдAСдz֮52ĸ ASCII ֮УдĸСдĸ֮仹ַͻ֮Ľ +```js +/[A-z]/.test('\\') // true +``` +Уڷбܣ''ASCIIڴдĸСдĸ֮䣬ᱻѡС + +### 5.4 Ԥģʽ +ԤģʽָijЩģʽļдʽ + +**d** ƥ0-9֮һ֣൱[0-9] + +**D** ƥ0-9ַ൱[^0-9] + +**w** ƥĸֺ»ߣ൱[A-Za-z0-9_] + +**W** ĸֺ»ַ൱[^A-Za-z0-9_] + +**s** ƥո񣨰зƱոȣ[ \t\r\n\v\f] + +**S** ƥǿոַ൱[^ \t\r\n\v\f] + +**b** ƥʵı߽硣 + +**B** ƥǴʱ߽磬ڴʵڲ +```js +// \s +/\s\w*/.exec('hello world') // [" world"] + +// \b + +/\bworld/.test('hello world') // true +/\bworld/.test('hello-world') // true +/\bworld/.test('helloworld') // false +// \B +/\Bworld/.test('hello-world') // false +/\Bworld/.test('helloworld') // true +``` +ͨʽзnͻֹͣƥ䡣 +```js +var html = "Hello\nworld!"; + +/.*/.exec(html)[0] +// "Hello" +``` +Уַhtmlһзַ`.`ƥ任зƥܲԭ⡣ʱʹsַ࣬ܰз +```js +var html = "Hello\nworld!"; + +/[\S\s]*/.exec(html)[0] +// "Hello\nworld!" +``` +У[Ss]ָһַ + +### 5.5 ظ +ģʽľȷƥʹôţ`{}`ʾ`{n`}ʾǡظnΣ`{n,}`ʾظnΣ`{n,m}`ʾظnΣmΡ +```js +/lo{2}k/.test('look') // true +/lo{2,5}k/.test('looook') // true +``` +Уһģʽָo2Σڶģʽָo2ε5֮䡣 + +### 5.6 ʷ +`*. ?` ʺűʾijģʽ0λ1Σͬ{0, 1} +`*. *` Ǻűʾijģʽ0λΣͬ{0,} +`*. +` Ӻűʾijģʽ1λΣͬ{1,} + +### 5.7 ̰ģʽ +һСڵʷĬ¶ƥ䣬ƥֱһַƥΪֹⱻΪ̰ģʽ +```js +var s = 'aaa'; +s.match(/a+/) // ["aaa"] +``` +Уģʽ`/a+/`ʾƥ1aaô׻ƥ伸aأΪḬ̆ģʽһֱƥ䵽ַaΪֹƥ3a + +뽫̰ģʽΪ̰ģʽʷһʺš +```js +var s = 'aaa'; +s.match(/a+?/) // ["a"] +``` +˷̰ģʽļӺţз̰ģʽǺţ`*`ͷ̰ģʽʺţ`?` + +`+?`ʾijģʽ1λΣƥʱ÷̰ģʽ + +`*?`ʾijģʽ0λΣƥʱ÷̰ģʽ + +`??`ijģʽ0λ1Σƥʱ÷̰ģʽ + +### 5.8 ƥ +* 1 + +ʽűʾƥ䣬еģʽƥݡ +```js +/fred+/.test('fredd') // true +/(fred)+/.test('fredfred') // true +``` +Уһģʽûţ`+`ֻʾظĸdڶģʽţ`+`ͱʾƥfredʡ + +һ鲶ӡ +```js +var m = 'abcabc'.match(/(.)b(.)/); +m// ['abc', 'a', 'c'] +``` +Уʽ`/(.)b(.)/`һʹţһŲaڶŲc + +ע⣬ʹƥʱͬʱʹgηmatchᲶݡ +```js +var m = 'abcabc'.match(/(.)b(.)/g); +m // ['abc', 'abc'] +``` +ʽڲnƥݣnǴ1ʼȻʾӦ˳š +```js +/(.)b(.)\1b\2/.test("abcabc")// true +``` +ĴУ1ʾһƥݣa2ʾڶƥݣc + +* 2Dz + +`(?:x)`ΪDz飨Non-capturing groupʾظƥݣƥĽвš + +Dz뿼һٶҪƥfoofoofooʽӦд`/(foo){1, 2}/`ռһƥ䡣ʱͿʹ÷Dz飬ʽΪ`/(?:foo){1, 2}/`ǰһһģDzᵥڲݡ +```js +var m = 'abc'.match(/(?:.)b(.)/); +m // ["abc", "c"] +``` +еģʽһʹšеһǷDz飬󷵻صĽûеһţֻеڶƥݡ + +* 3ж + +`x(?=y)`ΪжԣPositive look-aheadxֻyǰƥ䣬yᱻ뷵ؽ磬ҪƥŰٷֺŵ֣д`/d+(?=%)/` + +жԡУIJDz᷵صġ +```js +var m = 'abc'.match(/b(?=c)/); +m // ["b"] +``` +ĴʹжԣbcǰԱƥ䣬ŶӦcᱻء + +* 4з񶨶 + +`x(?!y)`Ϊз񶨶ԣNegative look-aheadxֻвyǰƥ䣬yᱻ뷵ؽ磬ҪƥIJǰٷֺŵ֣Ҫд`/d+(?!%)/` +```js +/\d+(?!\.)/.exec('3.14')// ["14"] +``` +УʽָֻвСǰֲŻᱻƥ䣬˷صĽ14 + +## 6. ʵս +### 6.1 ַβ˵Ŀո +```js +var str = ' #id div.class '; +str.replace(/^\s+|\s+$/g, '') // "#id div.class" +``` +### 6.2 ֻ֤ +```js +var reg = /1[24578]\d{9}/;reg.test('154554568997'); //truereg.test('234554568997'); //false +``` +### 6.3 ֻ滻 * +```js +var reg = /1[24578]\d{9}/;var str = ' ֻ18210999999 Ա'; + +str.replace(reg, '***') //" ֻ*** Ա" +``` +### 6.4 ƥҳǩ +```js +var strHtlm = 'СС
222222@.qq.com
СС'; + +var reg = /<(.+)>.+<\/\1>/; + +strHtlm.match(reg); // ["
222222@.qq.com
"] +``` +### 6.5 滻 +```js +let str = 'ййžл񹲺͹'; +let r = str.replace(/й|/g, input => { + let t = ''; + for (let i = 0; i Date: Fri, 5 Oct 2018 22:42:32 +0800 Subject: [PATCH 064/835] 2018.10.05 --- ...50\241\250\350\276\276\345\274\217\346\200\273\347\273\223.md" | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename "article/57-ES5/ES6\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217\346\200\273\347\273\223.md" => "article/57-ES5ES6\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217\346\200\273\347\273\223.md" (100%) diff --git "a/article/57-ES5/ES6\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217\346\200\273\347\273\223.md" "b/article/57-ES5ES6\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217\346\200\273\347\273\223.md" similarity index 100% rename from "article/57-ES5/ES6\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217\346\200\273\347\273\223.md" rename to "article/57-ES5ES6\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217\346\200\273\347\273\223.md" From 951f5977e6cc9c6646a7fd769ffcbb550bd29c9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 5 Oct 2018 22:43:53 +0800 Subject: [PATCH 065/835] 2018.10.05 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8bd27d46..82f7eee8 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ ### 8、正则表达式 * [30-一次记住js的6个正则方法](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/30-%E4%B8%80%E6%AC%A1%E8%AE%B0%E4%BD%8Fjs%E7%9A%846%E4%B8%AA%E6%AD%A3%E5%88%99%E6%96%B9%E6%B3%95.md) -* [11-20个超级常用的正则表达式](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/11-20%E4%B8%AA%E8%B6%85%E7%BA%A7%E5%B8%B8%E7%94%A8%E7%9A%84%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F.md) +* [11-20个超级常用的正则表达式](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/11-20%E4%B8%AA%E8%B6%85%E7%BA%A7%E5%B8%B8%E7%94%A8%E7%9A%84%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F.md) * [57-ES5ES6正则表达式总结.md](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/57-ES5ES6%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%80%BB%E7%BB%93.md) ### 9、其他 * [2017-全年总结](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/2017-%E5%85%A8%E5%B9%B4%E6%80%BB%E7%BB%93.md) From c3164f48264d4a0724bdba8e45b55f74f4f96556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sat, 6 Oct 2018 22:27:15 +0800 Subject: [PATCH 066/835] 2018.10.06 --- ...32\344\271\211\345\261\236\346\200\247.md" | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 "article/58-\350\257\246\350\247\243HTML5data-\350\207\252\345\256\232\344\271\211\345\261\236\346\200\247.md" diff --git "a/article/58-\350\257\246\350\247\243HTML5data-\350\207\252\345\256\232\344\271\211\345\261\236\346\200\247.md" "b/article/58-\350\257\246\350\247\243HTML5data-\350\207\252\345\256\232\344\271\211\345\261\236\346\200\247.md" new file mode 100644 index 00000000..2d8173b6 --- /dev/null +++ "b/article/58-\350\257\246\350\247\243HTML5data-\350\207\252\345\256\232\344\271\211\345\261\236\346\200\247.md" @@ -0,0 +1,85 @@ +**jQuery**`att`r`prop`ᵽIE9֮ǰ汾ʹ`property`ڴй¶⣬ҹ`Attribute``Property`ҲʮͷʹHTML5`data-*`ķʽ**Զ**ν`data-*`ʵϾ`data-`ǰ׺ԶʹĽṹԽݴšʹ`data-*`**ԶԻ޹״** + +### 1. дʽ +`data-*`÷ʽֱ`HTMLԪرǩ`д +```html +
+ Click Here +
+``` +е`data-age`һԶԣȻҲͨ**JavaScript**в**HTML5**Ԫضһ`dataset`ԣһ`DOMStringMap`͵ļֵԼϣ +```js +var test = document.getElementById('test'); +test.dataset.my = 'Byron'; +``` +Ϊ`div`һ`data-my`ԶԣʹJavaScript`dataset`Ҫעĵط + +- 1. ******ȡ**ԵʱҪȥǰ׺`data-*`ûʹ`test.dataset.data-my = 'Byron';`ʽ + +- 2. лַ(`-`)Ҫת**շ**ʽCSSʹѡҪʹַʽ + +ΪղŴ׷дݣ +```html + +``` + +```js +test.dataset.birthDate = '19890615'; +``` +ͨJavaScriptdata-birth-dateԶԣCSSʽΪdivһЩʽЧ + +![ͼƬ1](http://p3nqtyvgo.bkt.clouddn.com/2018100601.png) + +![ͼƬ2](http://p3nqtyvgo.bkt.clouddn.com/2018100602.png) + +ȡʱҲͨ`dataset`ʹá`.`ȡԣͬҪȥ`data-`ǰ׺ַҪתΪշ + +```js +var test = document.getElementById('test'); +test.dataset.my = 'Byron'; +test.dataset.birthDate = '19890615'; +test.onclick = function () { + alert(this.dataset.my + ' ' + this.dataset.age+' '+this.dataset.birthDate); +} +``` +![ͼƬ3](http://p3nqtyvgo.bkt.clouddn.com/2018100603.png) + +### 2. getAttribute/setAttribute +Щͬѧܻ`getAttribute`/`setAttribute`ʲôһ£ +```js +var test = document.getElementById('test'); +test.dataset.birthDate = '19890615'; +test.setAttribute('age', 25); +test.setAttribute('data-sex', 'male'); + +console.log(test.getAttribute('data-age')); //24 +console.log(test.getAttribute('data-birth-date')); //19890516 +console.log(test.dataset.age); //24 +console.log(test.dataset.sex); //male +``` + +![ͼƬ4](http://p3nqtyvgo.bkt.clouddn.com/2018100604.png) + +![ͼƬ5](http://p3nqtyvgo.bkt.clouddn.com/20181006045.png) + + +ǿԿ߶õ`attribute`ϻҪ˼ܽԶԣҲ˵`getAttribute`/`setAttribute`Բе`dataset`ݣ`dataset`ֻ`attribute`һӼˣ`dataset`ֻд`data-`ǰ׺ԣû`age=25`Ǹ + +ôΪʲôǻҪ`data-*`أһĺôǿ԰Զ`dataset`ͳһĶŶܷ㣬ɢɢˣûDzġ + +### 3. +ȽϲõϢ`data-*`ʮֲֹۡ +* **Internet Explorer 11+** +* **Chrome 8+** +* **Firefox 6.0+** +* **Opera 11.10+** +* **Safari 6+** + +IE11+ֱϹСۣҪȫʹô·Զӡ + From f8abc0ad41638dcccc2ea369dc557e6b40573d0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sat, 6 Oct 2018 22:29:05 +0800 Subject: [PATCH 067/835] 2018.10.06 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 82f7eee8..8810928e 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ * [54-ajax详解](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/54-ajax%E8%AF%A6%E8%A7%A3.md) * [55-JS中attribute和property区别](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/55-JS%E4%B8%ADattribute%E5%92%8Cproperty%E5%8C%BA%E5%88%AB.md) * [56-js中原型继承原理](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/56-js%E4%B8%AD%E5%8E%9F%E5%9E%8B%E7%BB%A7%E6%89%BF%E5%8E%9F%E7%90%86.md) +* [58-详解HTML5data-自定义属性](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/58-%E8%AF%A6%E8%A7%A3HTML5data-%E8%87%AA%E5%AE%9A%E4%B9%89%E5%B1%9E%E6%80%A7.md) ### 7、HTTP * [47-http请求头与响应头的应用](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/47-http%E8%AF%B7%E6%B1%82%E5%A4%B4%E4%B8%8E%E5%93%8D%E5%BA%94%E5%A4%B4%E7%9A%84%E5%BA%94%E7%94%A8.md) From c29edfd2eac8abc12c9d22d07a0813c2feeea28b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sun, 7 Oct 2018 20:54:03 +0800 Subject: [PATCH 068/835] 2018.10.07 --- ...17\347\232\204\346\200\273\347\273\223.md" | 269 ++++++++++++++++++ 1 file changed, 269 insertions(+) create mode 100644 "article/59-\345\211\215\347\253\257HTML5\345\207\240\347\247\215\345\255\230\345\202\250\346\226\271\345\274\217\347\232\204\346\200\273\347\273\223.md" diff --git "a/article/59-\345\211\215\347\253\257HTML5\345\207\240\347\247\215\345\255\230\345\202\250\346\226\271\345\274\217\347\232\204\346\200\273\347\273\223.md" "b/article/59-\345\211\215\347\253\257HTML5\345\207\240\347\247\215\345\255\230\345\202\250\346\226\271\345\274\217\347\232\204\346\200\273\347\273\223.md" new file mode 100644 index 00000000..7980659c --- /dev/null +++ "b/article/59-\345\211\215\347\253\257HTML5\345\207\240\347\247\215\345\255\230\345\202\250\346\226\271\345\274\217\347\232\204\346\200\273\347\273\223.md" @@ -0,0 +1,269 @@ +ҪúܽһЩ֪ʶȻкö֪ʶᣬǻҪŬһ£ֶ˭֪~ + +## + +h5֮ǰ洢Ҫ`cookies``cookies`ȱ**ͷϴ**С**4k֮**DomainȾ + +ҪӦãﳵͻ¼ + +IE`UserData`С64k,ֻIE֧֡ + +## Ŀ +4kĴС +ͷ洢Ϣ +ϵʹ洢 + + +### 1.ش洢localstorage +* **洢ʽ** + +`ֵ`(`Key-Value`)ķʽ洢**ô洢****ʧЧ****ֶɾ** + +* **С** + +ÿ**5M** + +* **֧** +![ͼƬ1](http://p3nqtyvgo.bkt.clouddn.com/2018100701.png) + +ע⣺IE9 `localStorage`ֱ֧ļҪĿ𵽷ſ֧֣ + +* **ⷽ** +```js +if(window.localStorage){ + alert('This browser supports localStorage'); +}else{ + alert('This browser does NOT support localStorage'); +} +``` + +* **õAPI** +``` +getItem //ȡ¼ + +setIten //ü¼ + +removeItem //Ƴ¼ + +key //ȡkeyӦֵ + +clear //¼ +``` + +![ͼƬ2](http://p3nqtyvgo.bkt.clouddn.com/2018100702.png) + + +* **洢** + +飬ͼƬjsonʽűֻҪлַݶԴ洢 + +### 2.ش洢sessionstorage +HTML5 ıش洢 API е `localStorage` `sessionStorage` ʹ÷ͬģ `sessionStorage` **رҳ󼴱** `localStorage` **һֱ** + +### 3.߻棨application cache +ػӦļ + +* **ʹ÷** + +**manifestļ** + +ҳϣ +```html + + +... + +``` + +**Manifest ļ** + +manifest ļǼ򵥵ıļ֪ݣԼݣ + +manifest ļɷΪ֣ + +1. **CACHE MANIFEST** - ڴ˱гļ״غл + +2. **NETWORK** - ڴ˱гļҪӣҲᱻ + +3. **FALLBACK** - ڴ˱гļ涨ҳ޷ʱĻҳ棨 404 ҳ棩 + +demo +``` +CACHE MANIFEST +# 2016-07-24 v1.0.0 +/theme.css +/main.js + +NETWORK: +login.jsp + +FALLBACK: +/html/ /offline.html +``` + +ϣmanifestļҪȷ`MIME-type` "`text/cache-manifest`" + +Tomcat: +```html + + manifest + text/cache-manifest + +``` + +**API** + +`applicationCache`и`status`ԣʾӦûĵǰ״̬ + +**0**UNCACHED : ޻棬 ûҳصӦû + +**1**IDLE : ãӦûδõ + +**2** CHECKING : Уļ + +**3** DOWNLOADING : УӦûļָԴ + +**4** UPDATEREADY : ɣԴ + +**5** IDLE : ӦûļѾˣҳ޷ٷӦû + + + +**ص¼** + +ʾӦû״̬ĸı䣺 + +**checking** : ΪӦûҸʱ + +**error** : ڼ»Դڼ䷢ʹʱ + +**noupdate** : ڼļļޱ仯ʱ + +**downloading** : ڿʼӦûԴʱ + +**progress**ļӦûĹгϵصش + +**updateready** : ҳµӦûϴ + +**cached** : Ӧûʱ + +**Application Cache** + +1. +2. ҳٶ + +3. ͷѹ + +**ע** +1. Իݵƿ̫ܲһijЩõÿվ 5MB +2. manifestļڲоٵijһļأ¹̽ΪʧܣȫʹϵĻ档 +3. manifesthtmlmanifestļͬԴͬһ¡ +4. ԶmanifestļHTMLļ͵HTMLݣҲҪ°汾¡ +5. manifestļCACHENETWORKFALLBACKλ˳ûйϵʽҪǰ档 +6. FALLBACKеԴmanifestļͬԴ +7. 汾󣬱ˢһβŻ°汾ˢһҳҪӼ汾¼ +8. վеҳ漴ʹûmanifestԣԴڻҲӻзʡ +9. manifestļıʱԴҲᴥ¡ + + +**߻봫ͳ** + +1. ߻Ӧãǵļ + +2. ߻˻ǿԴҳ棬治 + +3. ߻֪ͨԴ + +### 4.Web SQL +**ϵݿ**ͨSQL + +Web SQL ݿ API HTML5 淶һ֣һĹ淶һʹ SQL ͻݿ APIs + +**֧** +Web SQL ݿ° **Safari**, **Chrome** **Opera** й + +**ķ** + +1. **openDatabase**ʹеݿ½ݿⴴһݿ + +2. **transaction**ܹһԼִύ߻ع + +3. **executeSql**ִʵʵ SQL ѯ + + + +**ݿ** +```js +var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024,fn); +//openDatabase() ӦֱΪݿơ汾šıݿСص +``` + +**ִвѯ** +```js +var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024); +db.transaction(function (tx) { + tx.executeSql('CREATE TABLE IF NOT EXISTS WIN (id unique, name)'); +}); +``` + +**** +```js +var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024); +db.transaction(function (tx) { + tx.executeSql('CREATE TABLE IF NOT EXISTS WIN (id unique, name)'); + tx.executeSql('INSERT INTO WIN (id, name) VALUES (1, "winty")'); + tx.executeSql('INSERT INTO WIN (id, name) VALUES (2, "LuckyWinty")'); +}); +``` + +**ȡ** +```js +db.transaction(function (tx) { + tx.executeSql('SELECT * FROM WIN', [], function (tx, results) { + var len = results.rows.length, i; + msg = "

ѯ¼: " + len + "

"; + document.querySelector('#status').innerHTML += msg; + + for (i = 0; i < len; i++){ + alert(results.rows.item(i).name ); + } + + }, null); +}); +``` +ЩԿ϶SQLݿزMySQLĻӦñȽá + + +### 5.IndexedDB +ݿ (IndexedDB) APIΪ HTML5 һ֣Դзḻش洢ݵܼ͵ HTML5 Web Ӧóáͬʱ**ػ**ʹͳ Web Ӧó򣨱ƶ Web Ӧóܹ**кӦ** + +**첽API** +IndexedDB󲿷ֲdzõĵ÷ؽģʽ󡪡ӦģʽݿIJ + +![ͼƬ3](http://p3nqtyvgo.bkt.clouddn.com/2018100703.png) + +ǴݿʱʵϷһDB󣬶`result`СͼԿresult֮⡣мҪԾ`onerror``onsuccess``onupgradeneeded`򿪵ݿİ汾źѾڵݿ汾ŲһµʱãǵajaxǷ֮󲢲ȷʲôʱɹҪڻصдһЩ߼ + +**رɾ** +```js +function closeDB(db){ + db.close(); +} +function deleteDB(name){ + indexedDB.deleteDatabase(name); +} +``` + +**ݴ洢** + +**indexedDB**ûбĸ`objectStore`һݿп԰`objectStore``objectStore`һݽṹԴŶݡҲ˵һ`objectStore`൱һű洢ÿݺһ + +ǿʹÿ¼еijֶָΪ**ֵ**keyPathҲʹԶɵĵΪֵkeyGeneratorҲԲָѡͲͬobjectStoreԴ洢ݽṹҲв졣 + +е㸴ˡĽ̳̣ +1.http://www.cnblogs.com/dolphinX/p/3415761.html + +2.http://www.cnblogs.com/dolphinX/p/3416889.html +ϸAPIַhttp://www.ibm.com/developerworks/cn/web/wa-indexeddb/#ibm-pcon + +ʱȷʵЩ洢ʽδùҲֻЩ˵ˡ˽ţԺõϸ¼ɣ^_^ \ No newline at end of file From f187c52dec86fef738872fff9b8175afb77dd5e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sun, 7 Oct 2018 20:55:10 +0800 Subject: [PATCH 069/835] 2018.10.07 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8810928e..7c5c8701 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ * [55-JS中attribute和property区别](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/55-JS%E4%B8%ADattribute%E5%92%8Cproperty%E5%8C%BA%E5%88%AB.md) * [56-js中原型继承原理](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/56-js%E4%B8%AD%E5%8E%9F%E5%9E%8B%E7%BB%A7%E6%89%BF%E5%8E%9F%E7%90%86.md) * [58-详解HTML5data-自定义属性](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/58-%E8%AF%A6%E8%A7%A3HTML5data-%E8%87%AA%E5%AE%9A%E4%B9%89%E5%B1%9E%E6%80%A7.md) +* [59-前端HTML5几种存储方式的总结.md](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/59-%E5%89%8D%E7%AB%AFHTML5%E5%87%A0%E7%A7%8D%E5%AD%98%E5%82%A8%E6%96%B9%E5%BC%8F%E7%9A%84%E6%80%BB%E7%BB%93.md) ### 7、HTTP * [47-http请求头与响应头的应用](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/47-http%E8%AF%B7%E6%B1%82%E5%A4%B4%E4%B8%8E%E5%93%8D%E5%BA%94%E5%A4%B4%E7%9A%84%E5%BA%94%E7%94%A8.md) From cc7c24f0d9dac28d4a75d04feb578fb283f34080 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 12 Oct 2018 21:53:21 +0800 Subject: [PATCH 070/835] 2018.10.12 --- ...14\351\242\204\345\212\240\350\275\275.md" | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 "article/60-\346\207\222\345\212\240\350\275\275\345\222\214\351\242\204\345\212\240\350\275\275.md" diff --git "a/article/60-\346\207\222\345\212\240\350\275\275\345\222\214\351\242\204\345\212\240\350\275\275.md" "b/article/60-\346\207\222\345\212\240\350\275\275\345\222\214\351\242\204\345\212\240\350\275\275.md" new file mode 100644 index 00000000..64aec48a --- /dev/null +++ "b/article/60-\346\207\222\345\212\240\350\275\275\345\222\214\351\242\204\345\212\240\350\275\275.md" @@ -0,0 +1,143 @@ +> [ԭ](https://segmentfault.com/a/1190000016666816) + +## һ +### 1.ʲô + +Ҳ**ӳټ**ָڳҳ**ӳټͼ**һֺܺŻҳܵķʽû֮ǰͼ񲻻ءͼԤ෴ڳҳʹӳټؽʹҳظ졣ijЩ£԰**ٷ**ͼƬܶ࣬ҳܳĵվС + +### 2.ΪʲôҪ +* **û**£ûֻԱҳʱҳеͼƬҪأͼƬĿϴ󣬵ȴʱܳûԹӰû顣 + +* **ЧԴļ**Լ˷ѹҲܹСĸ + +* **ֹصԴjsļ**Ӱվʹá + +### 3.صԭ +ȽҳϵͼƬ` src `ΪַͼƬʵ·`data-original`У +ҳʱҪȥ`scroll¼``scroll¼`ĻصУжǵصͼƬǷ,ͼƬڿڽͼƬ` src `Ϊ`data-original` ֵͿʵӳټء + +### 4.ʵֲ +```html + + + + Lazyload + + + + + + + + + + + + + + + + + + +``` + +## Ԥ +### 1.ʲôԤ +ԴԤһŻǿʹøüԤȸ֪ijЩԴڽᱻʹõ**Ԥؼ˵ǽԴǰصأҪõʱֱӴӻȡԴ** + +### 2.ΪʲôҪԤ +ҳȫ֮ǰһЩҪݽмأṩûõ飬ٵȴʱ䡣һҳݹӴûʹԤؼҳͻ᳤ʱչΪһƬհףֱݼϡ + +### .ʵԤصļְ취 +* ʹHTMLǩ +```html + +``` + +* ʹ`Image` +```html + +``` +```js +//myPreload.jsļ +var image= new Image() +image.src="http://pic26.nipic.com/20121213/6168183 004444903000 2.jpg" +``` + +* ʹXMLHttpRequest,Ȼڿ⣬ᾫϸԤع +```js +var xmlhttprequest=new XMLHttpRequest(); +xmlhttprequest.onreadystatechange=callback; +xmlhttprequest.onprogress=progressCallback; +xmlhttprequest.open("GET","http://image.baidu.com/mouse,jpg",true); +xmlhttprequest.send(); +function callback(){ + if(xmlhttprequest.readyState==4&& xmlhttprequest.status==200){ + var responseText=xmlhttprequest.responseText; + }else{ + console.log("Request was unsuccessful:"+xmlhttprequest.status); + } +} +function progressCallback(e){ + e=e || event; + if(e.lengthComputable){ + console.log("Received"+e.loaded+"of"+e.total+"bytes") + } +} +``` + +* ʹPreloadJS +PreloadJSṩһԤݵһ·ʽԱHTMLӦóʹáԤؿʹHTMLǩԼXHRɡĬ£PreloadJS᳢ʹXHRݣΪṩ˶ԽȺ¼ĸ֧֣ڿ⣬ʹûڱǵļؿܸá +```js +//ʹpreload.js +var queue=new createjs.LoadQueue(); +//Ĭxhrnew createjs.LoadQueue(false)ָʹHTMLǩԿ +queue.on("complete",handleComplete,this); +queue.loadManifest([ + {id:"myImage",src:"http://pic26.nipic.com/20121213/61681830044449030002.jpg"}, + {id"myImage2"src:"http://pic9.nipic.com/20100814/28395261931471581702.jpg"} +]); +function handleComplete(){ + var image=queue.getResuLt("myImage"); + document.body.appendChild(image); +} +``` + +## غԤصĶԱ +߶ҳЧİ취ҪһǰأһdzٻءضԷǰһĻѹãԤӷǰѹ + +## ġο +[غԤ(js)](https://www.geekjc.com/post/58d94d0f16a3655650d6fafe) + +[غԤ](https://lilywei739.github.io/2017/02/06/lazyload_Img.html) \ No newline at end of file From 13ad7ebbe80147505183cf1e3a7130a1cfcc69c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 12 Oct 2018 21:55:28 +0800 Subject: [PATCH 071/835] 2018.10.12 --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7c5c8701..0dcdbeea 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,8 @@ * [55-JS中attribute和property区别](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/55-JS%E4%B8%ADattribute%E5%92%8Cproperty%E5%8C%BA%E5%88%AB.md) * [56-js中原型继承原理](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/56-js%E4%B8%AD%E5%8E%9F%E5%9E%8B%E7%BB%A7%E6%89%BF%E5%8E%9F%E7%90%86.md) * [58-详解HTML5data-自定义属性](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/58-%E8%AF%A6%E8%A7%A3HTML5data-%E8%87%AA%E5%AE%9A%E4%B9%89%E5%B1%9E%E6%80%A7.md) -* [59-前端HTML5几种存储方式的总结.md](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/59-%E5%89%8D%E7%AB%AFHTML5%E5%87%A0%E7%A7%8D%E5%AD%98%E5%82%A8%E6%96%B9%E5%BC%8F%E7%9A%84%E6%80%BB%E7%BB%93.md) +* [59-前端HTML5几种存储方式的总结](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/59-%E5%89%8D%E7%AB%AFHTML5%E5%87%A0%E7%A7%8D%E5%AD%98%E5%82%A8%E6%96%B9%E5%BC%8F%E7%9A%84%E6%80%BB%E7%BB%93.md) +* [60-懒加载和预加载](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/60-%E6%87%92%E5%8A%A0%E8%BD%BD%E5%92%8C%E9%A2%84%E5%8A%A0%E8%BD%BD.md) ### 7、HTTP * [47-http请求头与响应头的应用](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/47-http%E8%AF%B7%E6%B1%82%E5%A4%B4%E4%B8%8E%E5%93%8D%E5%BA%94%E5%A4%B4%E7%9A%84%E5%BA%94%E7%94%A8.md) @@ -80,7 +81,8 @@ ### 8、正则表达式 * [30-一次记住js的6个正则方法](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/30-%E4%B8%80%E6%AC%A1%E8%AE%B0%E4%BD%8Fjs%E7%9A%846%E4%B8%AA%E6%AD%A3%E5%88%99%E6%96%B9%E6%B3%95.md) -* [11-20个超级常用的正则表达式](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/11-20%E4%B8%AA%E8%B6%85%E7%BA%A7%E5%B8%B8%E7%94%A8%E7%9A%84%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F.md) * [57-ES5ES6正则表达式总结.md](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/57-ES5ES6%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%80%BB%E7%BB%93.md) +* [11-20个超级常用的正则表达式](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/11-20%E4%B8%AA%E8%B6%85%E7%BA%A7%E5%B8%B8%E7%94%A8%E7%9A%84%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F.md) +* [57-ES5ES6正则表达式总结](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/57-ES5ES6%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%80%BB%E7%BB%93.md) ### 9、其他 * [2017-全年总结](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/2017-%E5%85%A8%E5%B9%B4%E6%80%BB%E7%BB%93.md) From 0aa4f82db5a854526f2357592e4408217a79bdf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 15 Oct 2018 23:07:16 +0800 Subject: [PATCH 072/835] 2018.10.15 --- ...21\345\256\232\350\247\204\345\210\231.md" | 235 ++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 "article/61-JS\344\270\255this\347\232\2044\347\247\215\347\273\221\345\256\232\350\247\204\345\210\231.md" diff --git "a/article/61-JS\344\270\255this\347\232\2044\347\247\215\347\273\221\345\256\232\350\247\204\345\210\231.md" "b/article/61-JS\344\270\255this\347\232\2044\347\247\215\347\273\221\345\256\232\350\247\204\345\210\231.md" new file mode 100644 index 00000000..9732e30b --- /dev/null +++ "b/article/61-JS\344\270\255this\347\232\2044\347\247\215\347\273\221\345\256\232\350\247\204\345\210\231.md" @@ -0,0 +1,235 @@ +> [ԭĵַ](https://segmentfault.com/a/1190000016678888) + +## this +* ES6е**ͷ**õ**ʷ** +* ΪʲôҪʹthis**ʹAPIƵøڸ** +* thisָҲָĴʷ +* thisָֻȡ**ĵ÷ʽ** + +## this󶨹 +* new > ʾ > ʽ > Ĭϰ + +### Ĭϰ + +* ʱǷڵջУthisָ**ȫֶ**Ϊwindow +* ϸģʽ£ܽȫֶĬϰ󶨡 +```js +var a = 2; +function foo(){ + console.log(this.a); +} +function bar(){ + var a = 5; + foo(); +} +bar(); // 2 +``` + +### ʽ + +* Ķʱʽ󶨹Ѻе`this`󶨵Ķ +* ֻһڵλá +* Ҫ󣺶ڲһָԣöͨԼú +```js +function foo() { + console.log( this.a ); +} + +var obj2 = { + a: 42, + foo: foo +}; + +var obj1 = { + a: 2, + obj2: obj2 +}; + +obj1.obj2.foo(); // 42 +``` + +* ʽʧ +```js +function foo() { + console.log( this.a ); +} + +var obj = { + a: 2, + foo: foo +}; + +var bar = obj.foo; // barfooԲк + +var a = "oops, global"; // aȫֶ + +bar(); // "oops, global" +``` + +ͻص£ʱʽֵ + +```js +function foo() { + console.log( this.a ); +} + +function doFoo(fn) { + // ʱ൱fn = obj.fooͺϸһ + fn(); // <-- call-site! +} + +var obj = { + a: 2, + foo: foo +}; + +var a = "oops, global"; // `a` also property on global object + +doFoo( obj.foo ); // "oops, global" +``` + +### ʽ + +* `call()``apply()`ͨһΪͣᱻװתΪװ䣩`this`󶨵ö +* Ӳ + +```js +function foo() { + console.log( this.a ); +} + +var obj = { + a: 2 +}; + +var bar = function() { + foo.call( obj ); +}; + +bar(); // 2 +setTimeout( bar, 100 ); // 2 + +// Ӳ󶨺barôãӰfoothis +bar.call( window ); // 2 +``` + +Ӳ󶨵ĵӦµİ + +```js +function foo(something) { + console.log( this.a, something ); + return this.a + something; +} + +var obj = { + a: 2 +}; + +var bar = function() { + return foo.apply( obj, arguments ); // objӲȥ +}; + +var b = bar( 3 ); // 2 3 +console.log( b ); // 5 +``` + +ڲ`apply`Ӳ󶨵ijôӰڲ`this` +`bind`£ + +```js +function foo(something) { + console.log( this.a, something ); + return this.a + something; +} + +// simple `bind` helper +function bind(fn, obj) { + return function() { + return fn.apply( obj, arguments ); // òobjȥ + }; +} + +var obj = { + a: 2 +}; + +var bar = bind( foo, obj ); // bind( foo, obj )᷵һ + +var b = bar( 3 ); // 2 3 +console.log( b ); // 5 +``` +* **ܽ**ҪֻһһظдӲķʽ²ܱãijֹҪظʹʱΪ + +## new +κκܱ캯`new`****ʱִ + 1. һ¶úJSõģ򴴽һµObject󣩣 + 2. this󶨵 + 3. ִй캯еĴ루Ϊ¶ԣ + 4. ûзԶ¶returnصǷǶԶ¶󣬼ǸǶ + +```js +function foo(a) { + this.a = a; +} + +var bar = new foo( 2 ); +console.log( bar.a ); // 2 +``` + +### ˵ +* +```js +function foo() { + console.log( this.a ); +} + +var a = 2; +var o = { a: 3, foo: foo }; +var p = { a: 4 }; + +o.foo(); // 3 +(p.foo = o.foo)(); // 2p.foo = o.fooķֵĿ꺯ãԵλfoo()p.foo()o.foo() +``` + +* **ͷ**ʹĸthis򣬸**ʷ**`this` +```js +function foo() { + // һͷ + return (a) => { + // `this` here is lexically adopted from `foo()` + console.log( this.a ); + }; +} + +var obj1 = { + a: 2 +}; + +var obj2 = { + a: 3 +}; + +// foo()Ǽͷthis󶨵obj1 +var bar = foo.call( obj1 ); // foo.call( obj1 )ؼͷbarΪͷ +bar.call( obj2 ); // 2! ͷthis޷޸ģnewҲ +``` + +Ϊͼͷһģʽ + +```js +function foo() { + var self = this; // lexical capture of `this` + setTimeout( function(){ + console.log( self.a ); + }, 100 ); +} + +var obj = { + a: 2 +}; + +foo.call( obj ); // 2 +``` + +this󶨵Ȥ⣺ +[֪-arguments](https://www.zhihu.com/question/21466212) \ No newline at end of file From 9591d3c27ce621b22656abcec24189fbff01faa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 15 Oct 2018 23:23:18 +0800 Subject: [PATCH 073/835] 2018.10.15 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0dcdbeea..7f778287 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ * [58-详解HTML5data-自定义属性](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/58-%E8%AF%A6%E8%A7%A3HTML5data-%E8%87%AA%E5%AE%9A%E4%B9%89%E5%B1%9E%E6%80%A7.md) * [59-前端HTML5几种存储方式的总结](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/59-%E5%89%8D%E7%AB%AFHTML5%E5%87%A0%E7%A7%8D%E5%AD%98%E5%82%A8%E6%96%B9%E5%BC%8F%E7%9A%84%E6%80%BB%E7%BB%93.md) * [60-懒加载和预加载](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/60-%E6%87%92%E5%8A%A0%E8%BD%BD%E5%92%8C%E9%A2%84%E5%8A%A0%E8%BD%BD.md) +* [61-JS中this的4种绑定规则](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/61-JS%E4%B8%ADthis%E7%9A%844%E7%A7%8D%E7%BB%91%E5%AE%9A%E8%A7%84%E5%88%99.md) ### 7、HTTP * [47-http请求头与响应头的应用](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/47-http%E8%AF%B7%E6%B1%82%E5%A4%B4%E4%B8%8E%E5%93%8D%E5%BA%94%E5%A4%B4%E7%9A%84%E5%BA%94%E7%94%A8.md) From 63ddf7c87f67b3201d00681fa023167177b2bc00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Wed, 17 Oct 2018 00:11:49 +0800 Subject: [PATCH 074/835] 2018.10.17 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加angular官网demo练习 --- .../.editorconfig" | 13 + .../.gitignore" | 39 + .../README.md" | 27 + .../angular.json" | 127 + .../e2e/protractor.conf.js" | 28 + .../e2e/src/app.e2e-spec.ts" | 14 + .../e2e/src/app.po.ts" | 11 + .../e2e/tsconfig.e2e.json" | 13 + .../package-lock.json" | 10222 ++++++++++++++++ .../package.json" | 49 + .../src/app/app-routing.module.spec.ts" | 13 + .../src/app/app-routing.module.ts" | 25 + .../src/app/app.component.css" | 29 + .../src/app/app.component.html" | 11 + .../src/app/app.component.spec.ts" | 31 + .../src/app/app.component.ts" | 10 + .../src/app/app.module.ts" | 33 + .../app/dashboard/dashboard.component.css" | 62 + .../app/dashboard/dashboard.component.html" | 10 + .../dashboard/dashboard.component.spec.ts" | 25 + .../src/app/dashboard/dashboard.component.ts" | 22 + .../hero-detail/hero-detail.component.css" | 30 + .../hero-detail/hero-detail.component.html" | 11 + .../hero-detail.component.spec.ts" | 25 + .../app/hero-detail/hero-detail.component.ts" | 37 + .../src/app/hero.service.spec.ts" | 12 + .../src/app/hero.service.ts" | 62 + .../src/app/hero.ts" | 4 + .../src/app/heroes/heroes.component.css" | 51 + .../src/app/heroes/heroes.component.html" | 10 + .../src/app/heroes/heroes.component.spec.ts" | 25 + .../src/app/heroes/heroes.component.ts" | 26 + .../src/app/in-memory-data.service.ts" | 19 + .../src/app/message.service.spec.ts" | 12 + .../src/app/message.service.ts" | 17 + .../src/app/message/message.component.css" | 35 + .../src/app/message/message.component.html" | 12 + .../app/message/message.component.spec.ts" | 25 + .../src/app/message/message.component.ts" | 16 + .../src/app/mock-heroes.ts" | 14 + .../src/assets/.gitkeep" | 0 .../src/browserslist" | 11 + .../src/environments/environment.prod.ts" | 3 + .../src/environments/environment.ts" | 16 + .../src/favicon.ico" | Bin 0 -> 5430 bytes .../src/index.html" | 14 + .../src/karma.conf.js" | 31 + .../src/main.ts" | 13 + .../src/polyfills.ts" | 80 + .../src/styles.css" | 22 + .../src/test.ts" | 20 + .../src/tsconfig.app.json" | 11 + .../src/tsconfig.spec.json" | 18 + .../src/tslint.json" | 17 + .../tsconfig.json" | 21 + .../tslint.json" | 131 + 56 files changed, 11665 insertions(+) create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/.editorconfig" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/.gitignore" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/README.md" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/angular.json" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/e2e/protractor.conf.js" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/e2e/src/app.e2e-spec.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/e2e/src/app.po.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/e2e/tsconfig.e2e.json" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/package-lock.json" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/package.json" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/app-routing.module.spec.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/app-routing.module.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/app.component.css" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/app.component.html" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/app.component.spec.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/app.component.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/app.module.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/dashboard/dashboard.component.css" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/dashboard/dashboard.component.html" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/dashboard/dashboard.component.spec.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/dashboard/dashboard.component.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/hero-detail/hero-detail.component.css" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/hero-detail/hero-detail.component.html" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/hero-detail/hero-detail.component.spec.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/hero-detail/hero-detail.component.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/hero.service.spec.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/hero.service.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/hero.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/heroes/heroes.component.css" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/heroes/heroes.component.html" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/heroes/heroes.component.spec.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/heroes/heroes.component.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/in-memory-data.service.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/message.service.spec.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/message.service.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/message/message.component.css" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/message/message.component.html" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/message/message.component.spec.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/message/message.component.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/app/mock-heroes.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/assets/.gitkeep" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/browserslist" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/environments/environment.prod.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/environments/environment.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/favicon.ico" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/index.html" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/karma.conf.js" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/main.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/polyfills.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/styles.css" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/test.ts" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/tsconfig.app.json" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/tsconfig.spec.json" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/src/tslint.json" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/tsconfig.json" create mode 100644 "angualr/angualr\345\256\230\347\275\221demo/tslint.json" diff --git "a/angualr/angualr\345\256\230\347\275\221demo/.editorconfig" "b/angualr/angualr\345\256\230\347\275\221demo/.editorconfig" new file mode 100644 index 00000000..6e87a003 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/.editorconfig" @@ -0,0 +1,13 @@ +# Editor configuration, see http://editorconfig.org +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +max_line_length = off +trim_trailing_whitespace = false diff --git "a/angualr/angualr\345\256\230\347\275\221demo/.gitignore" "b/angualr/angualr\345\256\230\347\275\221demo/.gitignore" new file mode 100644 index 00000000..ee5c9d83 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/.gitignore" @@ -0,0 +1,39 @@ +# See http://help.github.com/ignore-files/ for more about ignoring files. + +# compiled output +/dist +/tmp +/out-tsc + +# dependencies +/node_modules + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +# misc +/.sass-cache +/connect.lock +/coverage +/libpeerconnection.log +npm-debug.log +yarn-error.log +testem.log +/typings + +# System Files +.DS_Store +Thumbs.db diff --git "a/angualr/angualr\345\256\230\347\275\221demo/README.md" "b/angualr/angualr\345\256\230\347\275\221demo/README.md" new file mode 100644 index 00000000..c9a820c6 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/README.md" @@ -0,0 +1,27 @@ +# Demo1 + +This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 6.2.4. + +## Development server + +Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. + +## Code scaffolding + +Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. + +## Build + +Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build. + +## Running unit tests + +Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). + +## Running end-to-end tests + +Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). + +## Further help + +To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). diff --git "a/angualr/angualr\345\256\230\347\275\221demo/angular.json" "b/angualr/angualr\345\256\230\347\275\221demo/angular.json" new file mode 100644 index 00000000..54db00a7 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/angular.json" @@ -0,0 +1,127 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "newProjectRoot": "projects", + "projects": { + "demo1": { + "root": "", + "sourceRoot": "src", + "projectType": "application", + "prefix": "app", + "schematics": {}, + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "outputPath": "dist/demo1", + "index": "src/index.html", + "main": "src/main.ts", + "polyfills": "src/polyfills.ts", + "tsConfig": "src/tsconfig.app.json", + "assets": [ + "src/favicon.ico", + "src/assets" + ], + "styles": [ + "src/styles.css" + ], + "scripts": [] + }, + "configurations": { + "production": { + "fileReplacements": [ + { + "replace": "src/environments/environment.ts", + "with": "src/environments/environment.prod.ts" + } + ], + "optimization": true, + "outputHashing": "all", + "sourceMap": false, + "extractCss": true, + "namedChunks": false, + "aot": true, + "extractLicenses": true, + "vendorChunk": false, + "buildOptimizer": true + } + } + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "options": { + "browserTarget": "demo1:build" + }, + "configurations": { + "production": { + "browserTarget": "demo1:build:production" + } + } + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "demo1:build" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "main": "src/test.ts", + "polyfills": "src/polyfills.ts", + "tsConfig": "src/tsconfig.spec.json", + "karmaConfig": "src/karma.conf.js", + "styles": [ + "src/styles.css" + ], + "scripts": [], + "assets": [ + "src/favicon.ico", + "src/assets" + ] + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": [ + "src/tsconfig.app.json", + "src/tsconfig.spec.json" + ], + "exclude": [ + "**/node_modules/**" + ] + } + } + } + }, + "demo1-e2e": { + "root": "e2e/", + "projectType": "application", + "architect": { + "e2e": { + "builder": "@angular-devkit/build-angular:protractor", + "options": { + "protractorConfig": "e2e/protractor.conf.js", + "devServerTarget": "demo1:serve" + }, + "configurations": { + "production": { + "devServerTarget": "demo1:serve:production" + } + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": "e2e/tsconfig.e2e.json", + "exclude": [ + "**/node_modules/**" + ] + } + } + } + } + }, + "defaultProject": "demo1" +} \ No newline at end of file diff --git "a/angualr/angualr\345\256\230\347\275\221demo/e2e/protractor.conf.js" "b/angualr/angualr\345\256\230\347\275\221demo/e2e/protractor.conf.js" new file mode 100644 index 00000000..86776a39 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/e2e/protractor.conf.js" @@ -0,0 +1,28 @@ +// Protractor configuration file, see link for more information +// https://github.com/angular/protractor/blob/master/lib/config.ts + +const { SpecReporter } = require('jasmine-spec-reporter'); + +exports.config = { + allScriptsTimeout: 11000, + specs: [ + './src/**/*.e2e-spec.ts' + ], + capabilities: { + 'browserName': 'chrome' + }, + directConnect: true, + baseUrl: 'http://localhost:4200/', + framework: 'jasmine', + jasmineNodeOpts: { + showColors: true, + defaultTimeoutInterval: 30000, + print: function() {} + }, + onPrepare() { + require('ts-node').register({ + project: require('path').join(__dirname, './tsconfig.e2e.json') + }); + jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); + } +}; \ No newline at end of file diff --git "a/angualr/angualr\345\256\230\347\275\221demo/e2e/src/app.e2e-spec.ts" "b/angualr/angualr\345\256\230\347\275\221demo/e2e/src/app.e2e-spec.ts" new file mode 100644 index 00000000..1e7f6a22 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/e2e/src/app.e2e-spec.ts" @@ -0,0 +1,14 @@ +import { AppPage } from './app.po'; + +describe('workspace-project App', () => { + let page: AppPage; + + beforeEach(() => { + page = new AppPage(); + }); + + it('should display welcome message', () => { + page.navigateTo(); + expect(page.getParagraphText()).toEqual('Welcome to demo1!'); + }); +}); diff --git "a/angualr/angualr\345\256\230\347\275\221demo/e2e/src/app.po.ts" "b/angualr/angualr\345\256\230\347\275\221demo/e2e/src/app.po.ts" new file mode 100644 index 00000000..82ea75ba --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/e2e/src/app.po.ts" @@ -0,0 +1,11 @@ +import { browser, by, element } from 'protractor'; + +export class AppPage { + navigateTo() { + return browser.get('/'); + } + + getParagraphText() { + return element(by.css('app-root h1')).getText(); + } +} diff --git "a/angualr/angualr\345\256\230\347\275\221demo/e2e/tsconfig.e2e.json" "b/angualr/angualr\345\256\230\347\275\221demo/e2e/tsconfig.e2e.json" new file mode 100644 index 00000000..a6dd6220 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/e2e/tsconfig.e2e.json" @@ -0,0 +1,13 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "outDir": "../out-tsc/app", + "module": "commonjs", + "target": "es5", + "types": [ + "jasmine", + "jasminewd2", + "node" + ] + } +} \ No newline at end of file diff --git "a/angualr/angualr\345\256\230\347\275\221demo/package-lock.json" "b/angualr/angualr\345\256\230\347\275\221demo/package-lock.json" new file mode 100644 index 00000000..6895cf46 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/package-lock.json" @@ -0,0 +1,10222 @@ +{ + "name": "demo1", + "version": "0.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@angular-devkit/architect": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.8.5.tgz", + "integrity": "sha512-UMPQVdJkvT0f8ZFuhA2teDD697Tk1rUrW0X6yigPHmRhVTS9xbuJS/DeBN36NVJRUOOGYNDn5JHTLvywQf9q7A==", + "dev": true, + "requires": { + "@angular-devkit/core": "0.8.5", + "rxjs": "~6.2.0" + } + }, + "@angular-devkit/build-angular": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.8.5.tgz", + "integrity": "sha512-dHUA+p9mL/8wyUBLnGYJmLFv98KCh5/Bwud6pidx16FhieCKE4+CmH0DdO/4s8LBMFkUJlErqY39cptFvwApPw==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.8.5", + "@angular-devkit/build-optimizer": "0.8.5", + "@angular-devkit/build-webpack": "0.8.5", + "@angular-devkit/core": "0.8.5", + "@ngtools/webpack": "6.2.5", + "ajv": "~6.4.0", + "autoprefixer": "^8.4.1", + "circular-dependency-plugin": "^5.0.2", + "clean-css": "^4.1.11", + "copy-webpack-plugin": "^4.5.2", + "file-loader": "^1.1.11", + "glob": "^7.0.3", + "html-webpack-plugin": "^3.0.6", + "istanbul": "^0.4.5", + "istanbul-instrumenter-loader": "^3.0.1", + "karma-source-map-support": "^1.2.0", + "less": "^3.7.1", + "less-loader": "^4.1.0", + "license-webpack-plugin": "^1.3.1", + "loader-utils": "^1.1.0", + "mini-css-extract-plugin": "~0.4.0", + "minimatch": "^3.0.4", + "node-sass": "^4.9.3", + "opn": "^5.1.0", + "parse5": "^4.0.0", + "portfinder": "^1.0.13", + "postcss": "^6.0.22", + "postcss-import": "^11.1.0", + "postcss-loader": "^2.1.5", + "postcss-url": "^7.3.2", + "raw-loader": "^0.5.1", + "rxjs": "~6.2.0", + "sass-loader": "^7.1.0", + "semver": "^5.5.0", + "source-map-loader": "^0.2.3", + "source-map-support": "^0.5.0", + "stats-webpack-plugin": "^0.6.2", + "style-loader": "^0.21.0", + "stylus": "^0.54.5", + "stylus-loader": "^3.0.2", + "tree-kill": "^1.2.0", + "uglifyjs-webpack-plugin": "^1.2.5", + "url-loader": "^1.0.1", + "webpack": "^4.15.1", + "webpack-dev-middleware": "^3.1.3", + "webpack-dev-server": "^3.1.4", + "webpack-merge": "^4.1.2", + "webpack-sources": "^1.1.0", + "webpack-subresource-integrity": "^1.1.0-rc.4" + } + }, + "@angular-devkit/build-optimizer": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.8.5.tgz", + "integrity": "sha512-VKzTmSz7X4VdAZm51qIx9vPrbk1WCmoVznCFp/VCEW3YJNNwiCwdkI/CQDgQbMWbkUE/3s6f1JIkTP/S+rAsuA==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "source-map": "^0.5.6", + "typescript": "~2.9.2", + "webpack-sources": "^1.1.0" + } + }, + "@angular-devkit/build-webpack": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.8.5.tgz", + "integrity": "sha512-miDdj4VrygNrIVN3JSQZJP/rRcLptVvWHViLq1lMBegiQ5uwXnKflHRbhNh+xhjadPF5pXWbduxip56AOYc1Cw==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.8.5", + "@angular-devkit/core": "0.8.5", + "rxjs": "~6.2.0" + } + }, + "@angular-devkit/core": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-0.8.5.tgz", + "integrity": "sha512-QGYuGJDzCOjZaRR7pSly9QNM8RO7Q5NawqRYQzsOVhdI4n5GJ2gAYSw+wi5tyavlrNcbvLw9//MAPhBkPrZMJw==", + "dev": true, + "requires": { + "ajv": "~6.4.0", + "chokidar": "^2.0.3", + "rxjs": "~6.2.0", + "source-map": "^0.5.6" + } + }, + "@angular-devkit/schematics": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-0.8.5.tgz", + "integrity": "sha512-rf6JyUncrTPpW33PMcDVrcQSLkt6iJEeqI9PXc65VBhGN7RaT00JQHVKdf5FNSmQ2Qenc1KpBrK3k6jrxTZv5Q==", + "dev": true, + "requires": { + "@angular-devkit/core": "0.8.5", + "rxjs": "~6.2.0" + } + }, + "@angular/animations": { + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-6.1.10.tgz", + "integrity": "sha512-dd/lq7kw3uwfHPICan8psu2nthuUpp7PvMLuNIm0XxObZ4oNs0ls6uxKEDPnEkRKoGdiJpvmsyzZZN9ACMPEAA==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/cli": { + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-6.2.5.tgz", + "integrity": "sha512-QG568QHq3X8CZ0D7aPbq9SlFiYyBEhrsfhGFr6jHNeljoCID2071GfnVsvuwj4vpeBT6axgOj0Dpm3M1r6UMMQ==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.8.5", + "@angular-devkit/core": "0.8.5", + "@angular-devkit/schematics": "0.8.5", + "@schematics/angular": "0.8.5", + "@schematics/update": "0.8.5", + "json-schema-traverse": "^0.4.1", + "opn": "^5.3.0", + "rxjs": "~6.2.0", + "semver": "^5.1.0", + "symbol-observable": "^1.2.0", + "yargs-parser": "^10.0.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "yargs-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", + "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "@angular/common": { + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-6.1.10.tgz", + "integrity": "sha512-73xxTSYJNKfiJ7C1Ajg+sz5l8y+blb/vNgHYg7O3yem5zLBnfPpidJ1UGg4W4d2Y+jwUVJbZKh8SKJarqAJVUQ==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/compiler": { + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-6.1.10.tgz", + "integrity": "sha512-FPIb2j3zfoBwb6vo/u0gQeu70h8InGlSisBr3xMACs/35/pwB6kbQR+JQiUr0D7k6QApg7AuMkvq8aFNelg0aw==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/compiler-cli": { + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-6.1.10.tgz", + "integrity": "sha512-GCWdyeNQSnF4RfzO4A0+WHsNEgxKpl5arg4ldLSWMNkj/DrhMD4TnmxhR+IVY+7ieMkUBwpcuWRnjdOdnbmV+w==", + "dev": true, + "requires": { + "chokidar": "^1.4.2", + "minimist": "^1.2.0", + "reflect-metadata": "^0.1.2", + "tsickle": "^0.32.1" + }, + "dependencies": { + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "requires": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "requires": { + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "@angular/core": { + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-6.1.10.tgz", + "integrity": "sha512-61l3rIQTVdT45eOf6/fBJIeVmV10mcrxqS4N/1OWkuDT29YSJTZSxGcv8QjAyyutuhcqWWpO6gVRkN07rWmkPg==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/forms": { + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-6.1.10.tgz", + "integrity": "sha512-zAPx2kMV1/FbP5DrY472Sd/ze1m+GS6T5ullZCtP392r62p2RkwzDCXieR51YiRJjZj3M6c3AcRND7PWBdXT7A==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/http": { + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@angular/http/-/http-6.1.10.tgz", + "integrity": "sha512-LDsSqyexh8fj23y+G2oSGLWSZVhbxBBo2ehYHnRgH/jlp0pmZVLRaGgUMNSCVtZc1rxLzpEjZjtw+P+qlutAtw==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/language-service": { + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-6.1.10.tgz", + "integrity": "sha512-nN29Ovomg21eL8acwOSUFAYwWFI1TuFwUgUu37ZssfVQrYdaV+BFx3yv3P0nKU90h3Hp+oIkWHd8U34UYrvBCg==", + "dev": true + }, + "@angular/platform-browser": { + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-6.1.10.tgz", + "integrity": "sha512-CB7pqMwtgb7KjdHDAJlsXcs0rrU+2xQVaoOaqEfJtUrKhtGMLaZh8Qoic5l92SoGattkOw7SYarAOsWlAsVfvw==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/platform-browser-dynamic": { + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-6.1.10.tgz", + "integrity": "sha512-DmBSUyFPoyKqkmBXyJ2CrP1oXDioeoBlPA8lmWUDUv2yBuoHIzIkdY/OkTZbdyu/QYa1hK2Jl9OlfoeoenKddg==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/router": { + "version": "6.1.10", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-6.1.10.tgz", + "integrity": "sha512-tekI3dkdvd65oMoxjjgRA+16uDgPUBWHhYxids6pgO8vobZNtCo8VaVlcDyLUhdmtS5kONELx0iL5E2M0Y2Bag==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/generator": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.1.3.tgz", + "integrity": "sha512-ZoCZGcfIJFJuZBqxcY9OjC1KW2lWK64qrX1o4UYL3yshVhwKFYgzpWZ0vvtGMNJdTlvkw0W+HR1VnYN8q3QPFQ==", + "dev": true, + "requires": { + "@babel/types": "^7.1.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.10", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + }, + "dependencies": { + "jsesc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz", + "integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=", + "dev": true + } + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz", + "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + } + } + }, + "@babel/parser": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.1.3.tgz", + "integrity": "sha512-gqmspPZOMW3MIRb9HlrnbZHXI1/KHTOroBwN1NcLL6pWxzqzEKGvRTq0W/PxS45OtQGbaFikSQpkS5zbnsQm2w==", + "dev": true + }, + "@babel/template": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", + "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.1.2", + "@babel/types": "^7.1.2" + } + }, + "@babel/traverse": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.4.tgz", + "integrity": "sha512-my9mdrAIGdDiSVBuMjpn/oXYpva0/EZwWL3sm3Wcy/AVWO2eXnsoZruOT9jOGNRXU8KbCIu5zsKnXcAJ6PcV6Q==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.1.3", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.1.3", + "@babel/types": "^7.1.3", + "debug": "^3.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.10" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "globals": { + "version": "11.8.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.8.0.tgz", + "integrity": "sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA==", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.1.3.tgz", + "integrity": "sha512-RpPOVfK+yatXyn8n4PB1NW6k9qjinrXrRR8ugBN8fD6hCy5RXI6PSbVqpOJBO9oSaY7Nom4ohj35feb0UR9hSA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@ngtools/webpack": { + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-6.2.5.tgz", + "integrity": "sha512-gvv4n+M+YIoHX0JPvP+ygnI1L83iiJEDelqXxqdQ65ppM8Ua55xa+jLQc3vAjLbSuC2ANKHb9JK3GihBNghMgQ==", + "dev": true, + "requires": { + "@angular-devkit/core": "0.8.5", + "rxjs": "~6.2.0", + "tree-kill": "^1.0.0", + "webpack-sources": "^1.1.0" + } + }, + "@schematics/angular": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-0.8.5.tgz", + "integrity": "sha512-2ZfnXajf7Pz5ZuZ4iwtDpVxcd58IQednhMGuNslzCeq7S2+FTnctTlmye63HoaRN8F/7M2aG4ztpm6VMYPPn2A==", + "dev": true, + "requires": { + "@angular-devkit/core": "0.8.5", + "@angular-devkit/schematics": "0.8.5", + "typescript": ">=2.6.2 <2.10" + } + }, + "@schematics/update": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.8.5.tgz", + "integrity": "sha512-kcld8R13bFE/hoY8uSy7srU2MVI8uzzo14q0AbJBAmyM+v03sBRPhQ5U03Yvb+kedlisC4D4Crr8bkJYrM2Qig==", + "dev": true, + "requires": { + "@angular-devkit/core": "0.8.5", + "@angular-devkit/schematics": "0.8.5", + "npm-registry-client": "^8.5.1", + "rxjs": "~6.2.0", + "semver": "^5.3.0", + "semver-intersect": "^1.1.2" + } + }, + "@types/jasmine": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.8.9.tgz", + "integrity": "sha512-8dPZwjosElZOGGYw1nwTvOEMof4gjwAWNFS93nBI091BoEfd5drnHOLRMiRF/LOPuMTn5LgEdv0bTUO8QFVuHQ==", + "dev": true + }, + "@types/jasminewd2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/jasminewd2/-/jasminewd2-2.0.5.tgz", + "integrity": "sha512-1awkm/O4pQCR9hI2F80HmIOda/L+ogkSL8Arj1k00eue5VLY5ooewhSOyF/cUJE0S+/34uD5EYY3zmd6fu2OCA==", + "dev": true, + "requires": { + "@types/jasmine": "*" + } + }, + "@types/node": { + "version": "8.9.5", + "resolved": "http://registry.npmjs.org/@types/node/-/node-8.9.5.tgz", + "integrity": "sha512-jRHfWsvyMtXdbhnz5CVHxaBgnV6duZnPlQuRSo/dm/GnmikNcmZhxIES4E9OZjUmQ8C+HCl4KJux+cXN/ErGDQ==", + "dev": true + }, + "@types/q": { + "version": "0.0.32", + "resolved": "http://registry.npmjs.org/@types/q/-/q-0.0.32.tgz", + "integrity": "sha1-vShOV8hPEyXacCur/IKlMoGQwMU=", + "dev": true + }, + "@types/selenium-webdriver": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.12.tgz", + "integrity": "sha512-hYn+eoOehVUIdMwp5h34ZsGAO1ydja10GDup4BwyoFCdcH5MQ35nQq+AInSaBMEMopD5hEooFCyKo2Pajbe1ag==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.8.tgz", + "integrity": "sha512-dOrtdtEyB8sInpl75yLPNksY4sRl0j/+t6aHyB/YA+ab9hV3Fo7FmG12FHzP+2MvWVAJtDb+6eXR5EZbZJ+uVg==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.7.8", + "@webassemblyjs/helper-wasm-bytecode": "1.7.8", + "@webassemblyjs/wast-parser": "1.7.8" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.8.tgz", + "integrity": "sha512-kn2zNKGsbql5i56VAgRYkpG+VazqHhQQZQycT2uXAazrAEDs23gy+Odkh5VblybjnwX2/BITkDtNmSO76hdIvQ==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.8.tgz", + "integrity": "sha512-xUwxDXsd1dUKArJEP5wWM5zxgCSwZApSOJyP1XO7M8rNUChUDblcLQ4FpzTpWG2YeylMwMl1MlP5Ztryiz1x4g==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.8.tgz", + "integrity": "sha512-WXiIMnuvuwlhWvVOm8xEXU9DnHaa3AgAU0ZPfvY8vO1cSsmYb2WbGbHnMLgs43vXnA7XAob9b56zuZaMkxpCBg==", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.8.tgz", + "integrity": "sha512-TLQxyD9qGOIdX5LPQOPo0Ernd88U5rHkFb8WAjeMIeA0sPjCHeVPaGqUGGIXjUcblUkjuDAc07bruCcNHUrHDA==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.7.8" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.8.tgz", + "integrity": "sha512-TjK0CnD8hAPkV5mbSp5aWl6SO1+H3WFcjWtixWoy8EMA99YnNzYhpc/WSYWhf7yrhpzkq5tZB0tvLK3Svr3IXA==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.8.tgz", + "integrity": "sha512-uCutAKR7Nm0VsFixcvnB4HhAyHouNbj0Dx1p7eRjFjXGGZ+N7ftTaG1ZbWCasAEbtwGj54LP8+lkBZdTCPmLGg==", + "dev": true + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.8.tgz", + "integrity": "sha512-AdCCE3BMW6V34WYaKUmPgVHa88t2Z14P4/0LjLwuGkI0X6pf7nzp0CehzVVk51cKm2ymVXjl9dCG+gR1yhITIQ==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.8.tgz", + "integrity": "sha512-BkBhYQuzyl4hgTGOKo87Vdw6f9nj8HhI7WYpI0MCC5qFa5ahrAPOGgyETVdnRbv+Rjukl9MxxfDmVcVC435lDg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.8", + "@webassemblyjs/helper-buffer": "1.7.8", + "@webassemblyjs/helper-wasm-bytecode": "1.7.8", + "@webassemblyjs/wasm-gen": "1.7.8" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.7.8.tgz", + "integrity": "sha512-tOarWChdG1a3y1yqCX0JMDKzrat5tQe4pV6K/TX19BcXsBLYxFQOL1DEDa5KG9syeyvCrvZ+i1+Mv1ExngvktQ==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.7.8.tgz", + "integrity": "sha512-GCYeGPgUFWJiZuP4NICbcyUQNxNLJIf476Ei+K+jVuuebtLpfvwkvYT6iTUE7oZYehhkor4Zz2g7SJ/iZaPudQ==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.1" + } + }, + "@webassemblyjs/utf8": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.7.8.tgz", + "integrity": "sha512-9X+f0VV+xNXW2ujfIRSXBJENGE6Qh7bNVKqu3yDjTFB3ar3nsThsGBBKdTG58aXOm2iUH6v28VIf88ymPXODHA==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.8.tgz", + "integrity": "sha512-6D3Hm2gFixrfyx9XjSON4ml1FZTugqpkIz5Awvrou8fnpyprVzcm4X8pyGRtA2Piixjl3DqmX/HB1xdWyE097A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.8", + "@webassemblyjs/helper-buffer": "1.7.8", + "@webassemblyjs/helper-wasm-bytecode": "1.7.8", + "@webassemblyjs/helper-wasm-section": "1.7.8", + "@webassemblyjs/wasm-gen": "1.7.8", + "@webassemblyjs/wasm-opt": "1.7.8", + "@webassemblyjs/wasm-parser": "1.7.8", + "@webassemblyjs/wast-printer": "1.7.8" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.8.tgz", + "integrity": "sha512-a7O/wE6eBeVKKUYgpMK7NOHmMADD85rSXLe3CqrWRDwWff5y3cSVbzpN6Qv3z6C4hdkpq9qyij1Ga1kemOZGvQ==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.8", + "@webassemblyjs/helper-wasm-bytecode": "1.7.8", + "@webassemblyjs/ieee754": "1.7.8", + "@webassemblyjs/leb128": "1.7.8", + "@webassemblyjs/utf8": "1.7.8" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.8.tgz", + "integrity": "sha512-3lbQ0PT81NHCdi1sR/7+SNpZadM4qYcTSr62nFFAA7e5lFwJr14M1Gi+A/Y3PgcDWOHYjsaNGPpPU0H03N6Blg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.8", + "@webassemblyjs/helper-buffer": "1.7.8", + "@webassemblyjs/wasm-gen": "1.7.8", + "@webassemblyjs/wasm-parser": "1.7.8" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.8.tgz", + "integrity": "sha512-rZ/zlhp9DHR/05zh1MbAjT2t624sjrPP/OkJCjXqzm7ynH+nIdNcn9Ixc+qzPMFXhIrk0rBoQ3to6sEIvHh9jQ==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.8", + "@webassemblyjs/helper-api-error": "1.7.8", + "@webassemblyjs/helper-wasm-bytecode": "1.7.8", + "@webassemblyjs/ieee754": "1.7.8", + "@webassemblyjs/leb128": "1.7.8", + "@webassemblyjs/utf8": "1.7.8" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.7.8.tgz", + "integrity": "sha512-Q/zrvtUvzWuSiJMcSp90fi6gp2nraiHXjTV2VgAluVdVapM4gy1MQn7akja2p6eSBDQpKJPJ6P4TxRkghRS5dg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.8", + "@webassemblyjs/floating-point-hex-parser": "1.7.8", + "@webassemblyjs/helper-api-error": "1.7.8", + "@webassemblyjs/helper-code-frame": "1.7.8", + "@webassemblyjs/helper-fsm": "1.7.8", + "@xtuc/long": "4.2.1" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.7.8.tgz", + "integrity": "sha512-GllIthRtwTxRDAURRNXscu7Napzmdf1jt1gpiZiK/QN4fH0lSGs3OTmvdfsMNP7tqI4B3ZtfaaWRlNIQug6Xyg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.8", + "@webassemblyjs/wast-parser": "1.7.8", + "@xtuc/long": "4.2.1" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.1.tgz", + "integrity": "sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g==", + "dev": true + }, + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "dev": true, + "requires": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + }, + "acorn-dynamic-import": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz", + "integrity": "sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==", + "dev": true, + "requires": { + "acorn": "^5.0.0" + } + }, + "adm-zip": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.11.tgz", + "integrity": "sha512-L8vcjDTCOIJk7wFvmlEUN7AsSb8T+2JrdP7KINBjzr24TJ5Mwj590sLu3BC7zNZowvJWa/JtPmD8eJCzdtDWjA==", + "dev": true + }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", + "dev": true + }, + "agent-base": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "ajv": { + "version": "6.4.0", + "resolved": "http://registry.npmjs.org/ajv/-/ajv-6.4.0.tgz", + "integrity": "sha1-06/3jpJ3VJdx2vAWTP9ISCt1T8Y=", + "dev": true, + "requires": { + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0", + "uri-js": "^3.0.2" + } + }, + "ajv-errors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.0.tgz", + "integrity": "sha1-7PAh+hCP0X37Xms4Py3SM+Mf/Fk=", + "dev": true + }, + "ajv-keywords": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "dev": true + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "angular-in-memory-web-api": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/angular-in-memory-web-api/-/angular-in-memory-web-api-0.6.1.tgz", + "integrity": "sha512-6Fls8XE3UC8NoydpcC82hY3KSRU4dXbGFjs3w+XLReL+Ry8zLeBHb/CZ9F+Kbg1yBH+eKamzd0vLr0+df+yC5g==" + }, + "ansi-colors": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.1.0.tgz", + "integrity": "sha512-hTv1qPdi+sVEk3jYsdjox5nQI0C9HTbjKShbCdYLKb1LOfNbb7wsF4d7OEKIZoxIHx02tSp3m94jcPW2EfMjmA==", + "dev": true + }, + "ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "app-root-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.1.0.tgz", + "integrity": "sha1-mL9lmTJ+zqGZMJhm6BQDaP0uZGo=", + "dev": true + }, + "append-transform": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", + "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", + "dev": true, + "requires": { + "default-require-extensions": "^2.0.0" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true, + "optional": true + }, + "array-flatten": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.1.tgz", + "integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=", + "dev": true + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", + "dev": true, + "optional": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "async": { + "version": "1.5.2", + "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "async-foreach": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", + "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=", + "dev": true, + "optional": true + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "autoprefixer": { + "version": "8.6.5", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-8.6.5.tgz", + "integrity": "sha512-PLWJN3Xo/rycNkx+mp8iBDMTm3FeWe4VmYaZDSqL5QQB9sLsQkG5k8n+LNDFnhh9kdq2K+egL/icpctOmDHwig==", + "dev": true, + "requires": { + "browserslist": "^3.2.8", + "caniuse-lite": "^1.0.30000864", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^6.0.23", + "postcss-value-parser": "^3.2.3" + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "dev": true + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, + "requires": { + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "dev": true + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", + "dev": true + }, + "base64id": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", + "dev": true + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "dev": true, + "requires": { + "callsite": "1.0.0" + } + }, + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true + }, + "binary-extensions": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", + "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==", + "dev": true + }, + "blob": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", + "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=", + "dev": true + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "dev": true, + "optional": true, + "requires": { + "inherits": "~2.0.0" + } + }, + "blocking-proxy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/blocking-proxy/-/blocking-proxy-1.0.1.tgz", + "integrity": "sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "bluebird": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz", + "integrity": "sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg==", + "dev": true + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "dev": true, + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + } + }, + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "dev": true, + "requires": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", + "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000844", + "electron-to-chromium": "^1.3.47" + } + }, + "browserstack": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.1.tgz", + "integrity": "sha512-O8VMT64P9NOLhuIoD4YngyxBURefaSdR4QdhG8l6HZ9VxtU7jc3m6jLufFwKA5gaf7fetfB2TnRJnMxyob+heg==", + "dev": true, + "requires": { + "https-proxy-agent": "^2.2.1" + } + }, + "buffer": { + "version": "4.9.1", + "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dev": true, + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "dev": true + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "builtins": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", + "dev": true + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, + "cacache": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", + "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", + "dev": true, + "requires": { + "bluebird": "^3.5.1", + "chownr": "^1.0.1", + "glob": "^7.1.2", + "graceful-fs": "^4.1.11", + "lru-cache": "^4.1.1", + "mississippi": "^2.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.2", + "ssri": "^5.2.4", + "unique-filename": "^1.1.0", + "y18n": "^4.0.0" + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true + }, + "camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "dev": true, + "requires": { + "no-case": "^2.2.0", + "upper-case": "^1.1.1" + } + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true, + "optional": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "optional": true, + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + } + }, + "caniuse-lite": { + "version": "1.0.30000892", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000892.tgz", + "integrity": "sha512-X9rxMaWZNbJB5qjkDqPtNv/yfViTeUL6ILk0QJNxLV3OhKC5Acn5vxsuUvllR6B48mog8lmS+whwHq/QIYSL9w==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chokidar": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.0", + "braces": "^2.3.0", + "fsevents": "^1.2.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "lodash.debounce": "^4.0.8", + "normalize-path": "^2.1.1", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0", + "upath": "^1.0.5" + } + }, + "chownr": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", + "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz", + "integrity": "sha512-xDbVgyfDTT2piup/h8dK/y4QZfJRSa73bw1WZ8b4XM1o7fsFubUVGYcE+1ANtOzJJELGpYoG2961z0Z6OAld9A==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "circular-dependency-plugin": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-5.0.2.tgz", + "integrity": "sha512-oC7/DVAyfcY3UWKm0sN/oVoDedQDQiw/vIiAnuTWTpE5s0zWf7l3WY417Xw/Fbi/QbAjctAkxgMiS9P0s3zkmA==", + "dev": true + }, + "circular-json": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.7.tgz", + "integrity": "sha512-/pXoV1JA847qRKPrHbBK6YIBGFF8GOP4wzSgUOA7q0ew0vAv0iJswP+2/nZQ9uzA3Azi7eTrg9L2yzXc/7ZMIA==", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "clean-css": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", + "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", + "dev": true, + "requires": { + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-deep": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-2.0.2.tgz", + "integrity": "sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ==", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.0", + "shallow-clone": "^1.0.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "codelyzer": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-4.3.0.tgz", + "integrity": "sha512-RLMrtLwrBS0dfo2/KTP+2NHofCpzcuh0bEp/A/naqvQonbUL4AW/qWQdbpn8dMNudtpmzEx9eS8KEpGdVPg1BA==", + "dev": true, + "requires": { + "app-root-path": "^2.0.1", + "css-selector-tokenizer": "^0.7.0", + "cssauron": "^1.4.0", + "semver-dsl": "^1.0.1", + "source-map": "^0.5.7", + "sprintf-js": "^1.0.3" + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "combine-lists": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", + "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", + "dev": true, + "requires": { + "lodash": "^4.5.0" + } + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "compare-versions": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.4.0.tgz", + "integrity": "sha512-tK69D7oNXXqUW3ZNo/z7NXTEz22TCF0pTE+YF9cxvaAM9XnkLo1fV621xCLrRR6aevJlKxExkss0vWqUCUpqdg==", + "dev": true + }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", + "dev": true + }, + "compressible": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.15.tgz", + "integrity": "sha512-4aE67DL33dSW9gw4CI2H/yTxqHLNcxp0yS6jB+4h+wr3e43+1z7vm0HU9qXOH8j+qjKuL8+UtkOxYQSMq60Ylw==", + "dev": true, + "requires": { + "mime-db": ">= 1.36.0 < 2" + } + }, + "compression": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.3.tgz", + "integrity": "sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.14", + "debug": "2.6.9", + "on-headers": "~1.0.1", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "connect": { + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", + "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.0", + "parseurl": "~1.3.2", + "utils-merge": "1.0.1" + }, + "dependencies": { + "finalhandler": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", + "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.3.1", + "unpipe": "~1.0.0" + } + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "dev": true + } + } + }, + "connect-history-api-fallback": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", + "integrity": "sha1-sGhzk0vF40T+9hGhlqb6rgruAVo=", + "dev": true + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "^0.1.4" + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", + "dev": true + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true + }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "copy-webpack-plugin": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.5.3.tgz", + "integrity": "sha512-VKCiNXQcc8zyznaepXfKpCH2cZD+/j3T3B+gsFY97P7qMlEsj34wr/sI9OCG7QPUUh7gAHVx3q8Q1rdQIDM4bA==", + "dev": true, + "requires": { + "cacache": "^10.0.4", + "find-cache-dir": "^1.0.0", + "globby": "^7.1.1", + "is-glob": "^4.0.0", + "loader-utils": "^1.1.0", + "minimatch": "^3.0.4", + "p-limit": "^1.0.0", + "serialize-javascript": "^1.4.0" + } + }, + "core-js": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cosmiconfig": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz", + "integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==", + "dev": true, + "requires": { + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "parse-json": "^4.0.0", + "require-from-string": "^2.0.1" + }, + "dependencies": { + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + } + } + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", + "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", + "dev": true, + "optional": true, + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "css-parse": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.7.0.tgz", + "integrity": "sha1-Mh9s9zeCpv91ERE5D8BeLGV9jJs=", + "dev": true + }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "dev": true, + "requires": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" + } + }, + "css-selector-tokenizer": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz", + "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=", + "dev": true, + "requires": { + "cssesc": "^0.1.0", + "fastparse": "^1.1.1", + "regexpu-core": "^1.0.0" + } + }, + "css-what": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", + "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", + "dev": true + }, + "cssauron": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssauron/-/cssauron-1.4.0.tgz", + "integrity": "sha1-pmAt/34EqDBtwNuaVR6S6LVmKtg=", + "dev": true, + "requires": { + "through": "X.X.X" + } + }, + "cssesc": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", + "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=", + "dev": true + }, + "cuint": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", + "integrity": "sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs=", + "dev": true + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "optional": true, + "requires": { + "array-find-index": "^1.0.1" + } + }, + "custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true + }, + "cyclist": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", + "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", + "dev": true + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "date-format": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", + "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", + "dev": true + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "default-gateway": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-2.7.2.tgz", + "integrity": "sha512-lAc4i9QJR0YHSDFdzeBQKfZ1SRDG3hsJNEkrpcZa8QhBfidLAilT60BDEIVUUGqosFp425KOgB3uYqcnQrWafQ==", + "dev": true, + "requires": { + "execa": "^0.10.0", + "ip-regex": "^2.1.0" + } + }, + "default-require-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", + "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", + "dev": true, + "requires": { + "strip-bom": "^3.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "del": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", + "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", + "dev": true, + "requires": { + "globby": "^6.1.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "p-map": "^1.1.1", + "pify": "^3.0.0", + "rimraf": "^2.2.8" + }, + "dependencies": { + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "detect-node": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", + "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", + "dev": true + }, + "di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "dev": true + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "dir-glob": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", + "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "path-type": "^3.0.0" + } + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", + "dev": true + }, + "dns-packet": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", + "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", + "dev": true, + "requires": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "dev": true, + "requires": { + "buffer-indexof": "^1.0.0" + } + }, + "dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "requires": { + "utila": "~0.4" + } + }, + "dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "dev": true, + "requires": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "dom-serializer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "dev": true, + "requires": { + "domelementtype": "~1.1.1", + "entities": "~1.1.1" + }, + "dependencies": { + "domelementtype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", + "dev": true + } + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, + "domelementtype": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", + "dev": true + }, + "domhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.1.0.tgz", + "integrity": "sha1-0mRvXlf2w7qxHPbLBdPArPdBJZQ=", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "duplexify": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz", + "integrity": "sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "ejs": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz", + "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.79", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.79.tgz", + "integrity": "sha512-LQdY3j4PxuUl6xfxiFruTSlCniTrTrzAd8/HfsLEMi0PUpaQ0Iy+Pr4N4VllDYjs0Hyu2lkTbvzqlG+PX9NsNw==", + "dev": true + }, + "elliptic": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", + "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", + "dev": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "engine.io": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.0.tgz", + "integrity": "sha512-mRbgmAtQ4GAlKwuPnnAvXXwdPhEx+jkc0OBCLrXuD/CRvwNK3AxRSnqK4FSqmAMRRHryVJP8TopOvmEaA64fKw==", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "ws": "~3.3.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "engine.io-client": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.1", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~3.3.1", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "engine.io-parser": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", + "integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==", + "dev": true, + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.4", + "has-binary2": "~1.0.2" + } + }, + "enhanced-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", + "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.4.0", + "tapable": "^1.0.0" + } + }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true + }, + "entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", + "dev": true + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", + "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.1.1", + "function-bind": "^1.1.1", + "has": "^1.0.1", + "is-callable": "^1.1.3", + "is-regex": "^1.0.4" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es6-promise": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", + "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==", + "dev": true + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true, + "requires": { + "es6-promise": "^4.0.3" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "dev": true, + "requires": { + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.2.0" + }, + "dependencies": { + "source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "eslint-scope": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", + "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + }, + "dependencies": { + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + } + } + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + }, + "dependencies": { + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + } + } + }, + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "eventemitter3": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", + "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==", + "dev": true + }, + "events": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true + }, + "eventsource": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-0.1.6.tgz", + "integrity": "sha1-Cs7ehJ7X3RzMMsgRuxG5RNTykjI=", + "dev": true, + "requires": { + "original": ">=0.0.5" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "execa": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", + "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + } + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "expand-braces": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", + "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", + "dev": true, + "requires": { + "array-slice": "^0.2.3", + "array-unique": "^0.2.1", + "braces": "^0.1.2" + }, + "dependencies": { + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", + "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", + "dev": true, + "requires": { + "expand-range": "^0.1.0" + } + }, + "expand-range": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", + "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", + "dev": true, + "requires": { + "is-number": "^0.1.1", + "repeat-string": "^0.2.2" + } + }, + "is-number": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", + "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", + "dev": true + }, + "repeat-string": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", + "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", + "dev": true + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "^2.1.0" + }, + "dependencies": { + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "express": { + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", + "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.3", + "content-disposition": "0.5.2", + "content-type": "~1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.4", + "qs": "6.5.2", + "range-parser": "~1.2.0", + "safe-buffer": "5.1.2", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "~1.4.0", + "type-is": "~1.6.16", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fastparse": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz", + "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=", + "dev": true + }, + "faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "file-loader": { + "version": "1.1.11", + "resolved": "http://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", + "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==", + "dev": true, + "requires": { + "loader-utils": "^1.0.2", + "schema-utils": "^0.4.5" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fileset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", + "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", + "dev": true, + "requires": { + "glob": "^7.0.3", + "minimatch": "^3.0.3" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "finalhandler": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" + } + }, + "find-cache-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^2.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "flush-write-stream": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", + "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.4" + } + }, + "follow-redirects": { + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.9.tgz", + "integrity": "sha512-Bh65EZI/RU8nx0wbYF9shkFZlqLP+6WT/5FnA3cE/djNSuKNHJEinGGZgu/cQEkeeb2GdFOgenAmn8qaqYke2w==", + "dev": true, + "requires": { + "debug": "=3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "1.0.6", + "mime-types": "^2.1.12" + }, + "dependencies": { + "combined-stream": { + "version": "1.0.6", + "resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + } + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-access": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", + "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", + "dev": true, + "requires": { + "null-check": "^1.0.0" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", + "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.9.2", + "node-pre-gyp": "^0.10.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.21", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": "^2.1.0" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.2.4", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "^5.1.1", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.0", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.1.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.5.1", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.0.5" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.5.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.0.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.2.4", + "minizlib": "^1.1.0", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.1", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true, + "dev": true + } + } + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "dev": true, + "optional": true, + "requires": { + "globule": "^1.0.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + }, + "dependencies": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "dir-glob": "^2.0.0", + "glob": "^7.1.2", + "ignore": "^3.3.5", + "pify": "^3.0.0", + "slash": "^1.0.0" + } + }, + "globule": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", + "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", + "dev": true, + "optional": true, + "requires": { + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "handle-thing": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz", + "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=", + "dev": true + }, + "handlebars": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.12.tgz", + "integrity": "sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA==", + "dev": true, + "requires": { + "async": "^2.5.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + }, + "dependencies": { + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "dev": true, + "requires": { + "lodash": "^4.17.10" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", + "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", + "dev": true, + "requires": { + "ajv": "^5.3.0", + "har-schema": "^2.0.0" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + } + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "dev": true, + "requires": { + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "hash.js": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", + "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "dev": true + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "html-entities": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", + "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", + "dev": true + }, + "html-minifier": { + "version": "3.5.20", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.20.tgz", + "integrity": "sha512-ZmgNLaTp54+HFKkONyLFEfs5dd/ZOtlquKaTnqIWFmx3Av5zG6ZPcV2d0o9XM2fXOTxxIf6eDcwzFFotke/5zA==", + "dev": true, + "requires": { + "camel-case": "3.0.x", + "clean-css": "4.2.x", + "commander": "2.17.x", + "he": "1.1.x", + "param-case": "2.1.x", + "relateurl": "0.2.x", + "uglify-js": "3.4.x" + } + }, + "html-webpack-plugin": { + "version": "3.2.0", + "resolved": "http://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz", + "integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s=", + "dev": true, + "requires": { + "html-minifier": "^3.2.3", + "loader-utils": "^0.2.16", + "lodash": "^4.17.3", + "pretty-error": "^2.0.2", + "tapable": "^1.0.0", + "toposort": "^1.0.0", + "util.promisify": "1.0.0" + }, + "dependencies": { + "loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "dev": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } + } + } + }, + "htmlparser2": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz", + "integrity": "sha1-zHDQWln2VC5D8OaFyYLhTJJKnv4=", + "dev": true, + "requires": { + "domelementtype": "1", + "domhandler": "2.1", + "domutils": "1.1", + "readable-stream": "1.0" + }, + "dependencies": { + "domutils": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.1.6.tgz", + "integrity": "sha1-vdw94Jm5ou+sxRxiPyj0FuzFdIU=", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", + "dev": true + }, + "http-errors": { + "version": "1.6.3", + "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "http-parser-js": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.13.tgz", + "integrity": "sha1-O9bW/ebjFyyTNMOzO2wZPYD+ETc=", + "dev": true + }, + "http-proxy": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", + "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", + "dev": true, + "requires": { + "eventemitter3": "^3.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-middleware": { + "version": "0.18.0", + "resolved": "http://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz", + "integrity": "sha512-Fs25KVMPAIIcgjMZkVHJoKg9VcXcC1C8yb9JUgeDvVXY0S/zgVIhMb+qVswDIgtJe2DfckMSY2d6TuTEutlk6Q==", + "dev": true, + "requires": { + "http-proxy": "^1.16.2", + "is-glob": "^4.0.0", + "lodash": "^4.17.5", + "micromatch": "^3.1.9" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "https-proxy-agent": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", + "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", + "dev": true, + "requires": { + "agent-base": "^4.1.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", + "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", + "dev": true + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + }, + "image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", + "dev": true, + "optional": true + }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=", + "dev": true + }, + "import-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", + "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", + "dev": true, + "requires": { + "import-from": "^2.1.0" + } + }, + "import-from": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", + "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", + "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + } + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "in-publish": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz", + "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=", + "dev": true, + "optional": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "optional": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "internal-ip": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-3.0.1.tgz", + "integrity": "sha512-NXXgESC2nNVtU+pqmC9e6R8B1GpKxzsAQhffvh5AL79qKnodd+L7tnEQmTiUAVngqLalPbSqRA7XGIEL5nCd0Q==", + "dev": true, + "requires": { + "default-gateway": "^2.6.0", + "ipaddr.js": "^1.5.2" + } + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true, + "optional": true + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "dev": true + }, + "ipaddr.js": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", + "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "^2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, + "requires": { + "is-path-inside": "^1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isbinaryfile": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", + "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", + "dev": true, + "requires": { + "buffer-alloc": "^1.2.0" + } + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", + "dev": true, + "requires": { + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, + "istanbul-api": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-2.0.6.tgz", + "integrity": "sha512-8W5oeAGWXhtTJjAyVfvavOLVyZCTNCKsyF6GON/INKlBdO7uJ/bv3qnPj5M6ERKzmMCJS1kntnjjGuJ86fn3rQ==", + "dev": true, + "requires": { + "async": "^2.6.1", + "compare-versions": "^3.2.1", + "fileset": "^2.0.3", + "istanbul-lib-coverage": "^2.0.1", + "istanbul-lib-hook": "^2.0.1", + "istanbul-lib-instrument": "^3.0.0", + "istanbul-lib-report": "^2.0.2", + "istanbul-lib-source-maps": "^2.0.1", + "istanbul-reports": "^2.0.1", + "js-yaml": "^3.12.0", + "make-dir": "^1.3.0", + "once": "^1.4.0" + }, + "dependencies": { + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "dev": true, + "requires": { + "lodash": "^4.17.10" + } + }, + "istanbul-lib-coverage": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", + "integrity": "sha512-nPvSZsVlbG9aLhZYaC3Oi1gT/tpyo3Yt5fNyf6NmcKIayz4VV/txxJFFKAK/gU4dcNn8ehsanBbVHVl0+amOLA==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.0.0.tgz", + "integrity": "sha512-eQY9vN9elYjdgN9Iv6NS/00bptm02EBBk70lRMaVjeA6QYocQgenVrSgC28TJurdnZa80AGO3ASdFN+w/njGiQ==", + "dev": true, + "requires": { + "@babel/generator": "^7.0.0", + "@babel/parser": "^7.0.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "istanbul-lib-coverage": "^2.0.1", + "semver": "^5.5.0" + } + } + } + }, + "istanbul-instrumenter-loader": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz", + "integrity": "sha512-a5SPObZgS0jB/ixaKSMdn6n/gXSrK2S6q/UfRJBT3e6gQmVjwZROTODQsYW5ZNwOu78hG62Y3fWlebaVOL0C+w==", + "dev": true, + "requires": { + "convert-source-map": "^1.5.0", + "istanbul-lib-instrument": "^1.7.3", + "loader-utils": "^1.1.0", + "schema-utils": "^0.3.0" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "schema-utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", + "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", + "dev": true, + "requires": { + "ajv": "^5.0.0" + } + } + } + }, + "istanbul-lib-coverage": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", + "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", + "dev": true + }, + "istanbul-lib-hook": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.1.tgz", + "integrity": "sha512-ufiZoiJ8CxY577JJWEeFuxXZoMqiKpq/RqZtOAYuQLvlkbJWscq9n3gc4xrCGH9n4pW0qnTxOz1oyMmVtk8E1w==", + "dev": true, + "requires": { + "append-transform": "^1.0.0" + } + }, + "istanbul-lib-instrument": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", + "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", + "dev": true, + "requires": { + "babel-generator": "^6.18.0", + "babel-template": "^6.16.0", + "babel-traverse": "^6.18.0", + "babel-types": "^6.18.0", + "babylon": "^6.18.0", + "istanbul-lib-coverage": "^1.2.1", + "semver": "^5.3.0" + } + }, + "istanbul-lib-report": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.2.tgz", + "integrity": "sha512-rJ8uR3peeIrwAxoDEbK4dJ7cqqtxBisZKCuwkMtMv0xYzaAnsAi3AHrHPAAtNXzG/bcCgZZ3OJVqm1DTi9ap2Q==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^2.0.1", + "make-dir": "^1.3.0", + "supports-color": "^5.4.0" + }, + "dependencies": { + "istanbul-lib-coverage": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", + "integrity": "sha512-nPvSZsVlbG9aLhZYaC3Oi1gT/tpyo3Yt5fNyf6NmcKIayz4VV/txxJFFKAK/gU4dcNn8ehsanBbVHVl0+amOLA==", + "dev": true + } + } + }, + "istanbul-lib-source-maps": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-2.0.1.tgz", + "integrity": "sha512-30l40ySg+gvBLcxTrLzR4Z2XTRj3HgRCA/p2rnbs/3OiTaoj054gAbuP5DcLOtwqmy4XW8qXBHzrmP2/bQ9i3A==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "istanbul-lib-coverage": "^2.0.1", + "make-dir": "^1.3.0", + "rimraf": "^2.6.2", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "istanbul-lib-coverage": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", + "integrity": "sha512-nPvSZsVlbG9aLhZYaC3Oi1gT/tpyo3Yt5fNyf6NmcKIayz4VV/txxJFFKAK/gU4dcNn8ehsanBbVHVl0+amOLA==", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.0.1.tgz", + "integrity": "sha512-CT0QgMBJqs6NJLF678ZHcquUAZIoBIUNzdJrRJfpkI9OnzG6MkUfHxbJC3ln981dMswC7/B1mfX3LNkhgJxsuw==", + "dev": true, + "requires": { + "handlebars": "^4.0.11" + } + }, + "jasmine": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz", + "integrity": "sha1-awicChFXax8W3xG4AUbZHU6Lij4=", + "dev": true, + "requires": { + "exit": "^0.1.2", + "glob": "^7.0.6", + "jasmine-core": "~2.8.0" + }, + "dependencies": { + "jasmine-core": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz", + "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=", + "dev": true + } + } + }, + "jasmine-core": { + "version": "2.99.1", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.99.1.tgz", + "integrity": "sha1-5kAN8ea1bhMLYcS80JPap/boyhU=", + "dev": true + }, + "jasmine-diff": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/jasmine-diff/-/jasmine-diff-0.1.3.tgz", + "integrity": "sha1-k8zC3MQQKMXd1GBlWAdIOfLe6qg=", + "dev": true, + "requires": { + "diff": "^3.2.0" + } + }, + "jasmine-spec-reporter": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz", + "integrity": "sha512-FZBoZu7VE5nR7Nilzy+Np8KuVIOxF4oXDPDknehCYBDE080EnlPu0afdZNmpGDBRCUBv3mj5qgqCRmk6W/K8vg==", + "dev": true, + "requires": { + "colors": "1.1.2" + } + }, + "jasminewd2": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-2.2.0.tgz", + "integrity": "sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=", + "dev": true + }, + "js-base64": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.9.tgz", + "integrity": "sha512-xcinL3AuDJk7VSzsHgb9DvvIXayBbadtMZ4HFPx8rUszbW1MuNMlwYVC4zzCZ6e1sqZpnNS5ZFYOhXqA39T7LQ==", + "dev": true, + "optional": true + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + } + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jszip": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.1.5.tgz", + "integrity": "sha512-5W8NUaFRFRqTOL7ZDDrx5qWHJyBXy6velVudIzQUSoqAAYqzSh2Z7/m0Rf1QbmQJccegD0r+YZxBjzqoBiEeJQ==", + "dev": true, + "requires": { + "core-js": "~2.3.0", + "es6-promise": "~3.0.2", + "lie": "~3.1.0", + "pako": "~1.0.2", + "readable-stream": "~2.0.6" + }, + "dependencies": { + "core-js": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz", + "integrity": "sha1-+rg/uwstjchfpjbEudNMdUIMbWU=", + "dev": true + }, + "es6-promise": { + "version": "3.0.2", + "resolved": "http://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz", + "integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "readable-stream": { + "version": "2.0.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "karma": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/karma/-/karma-3.0.0.tgz", + "integrity": "sha512-ZTjyuDXVXhXsvJ1E4CnZzbCjSxD6sEdzEsFYogLuZM0yqvg/mgz+O+R1jb0J7uAQeuzdY8kJgx6hSNXLwFuHIQ==", + "dev": true, + "requires": { + "bluebird": "^3.3.0", + "body-parser": "^1.16.1", + "chokidar": "^2.0.3", + "colors": "^1.1.0", + "combine-lists": "^1.0.0", + "connect": "^3.6.0", + "core-js": "^2.2.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.0", + "expand-braces": "^0.1.1", + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "http-proxy": "^1.13.0", + "isbinaryfile": "^3.0.0", + "lodash": "^4.17.4", + "log4js": "^3.0.0", + "mime": "^2.3.1", + "minimatch": "^3.0.2", + "optimist": "^0.6.1", + "qjobs": "^1.1.4", + "range-parser": "^1.2.0", + "rimraf": "^2.6.0", + "safe-buffer": "^5.0.1", + "socket.io": "2.1.1", + "source-map": "^0.6.1", + "tmp": "0.0.33", + "useragent": "2.2.1" + }, + "dependencies": { + "mime": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", + "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "karma-chrome-launcher": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", + "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", + "dev": true, + "requires": { + "fs-access": "^1.0.0", + "which": "^1.2.1" + } + }, + "karma-coverage-istanbul-reporter": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-2.0.4.tgz", + "integrity": "sha512-xJS7QSQIVU6VK9HuJ/ieE5yynxKhjCCkd96NLY/BX/HXsx0CskU9JJiMQbd4cHALiddMwI4OWh1IIzeWrsavJw==", + "dev": true, + "requires": { + "istanbul-api": "^2.0.5", + "minimatch": "^3.0.4" + } + }, + "karma-jasmine": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-1.1.2.tgz", + "integrity": "sha1-OU8rJf+0pkS5rabyLUQ+L9CIhsM=", + "dev": true + }, + "karma-jasmine-html-reporter": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-0.2.2.tgz", + "integrity": "sha1-SKjl7xiAdhfuK14zwRlMNbQ5Ukw=", + "dev": true, + "requires": { + "karma-jasmine": "^1.0.2" + } + }, + "karma-source-map-support": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.3.0.tgz", + "integrity": "sha512-HcPqdAusNez/ywa+biN4EphGz62MmQyPggUsDfsHqa7tSe4jdsxgvTKuDfIazjL+IOxpVWyT7Pr4dhAV+sxX5Q==", + "dev": true, + "requires": { + "source-map-support": "^0.5.5" + } + }, + "killable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", + "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "optional": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "less": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/less/-/less-3.8.1.tgz", + "integrity": "sha512-8HFGuWmL3FhQR0aH89escFNBQH/nEiYPP2ltDFdQw2chE28Yx2E3lhAIq9Y2saYwLSwa699s4dBVEfCY8Drf7Q==", + "dev": true, + "requires": { + "clone": "^2.1.2", + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "mime": "^1.4.1", + "mkdirp": "^0.5.0", + "promise": "^7.1.1", + "request": "^2.83.0", + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, + "less-loader": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-4.1.0.tgz", + "integrity": "sha512-KNTsgCE9tMOM70+ddxp9yyt9iHqgmSs0yTZc5XH5Wo+g80RWRIYNqE58QJKm/yMud5wZEvz50ugRDuzVIkyahg==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "loader-utils": "^1.1.0", + "pify": "^3.0.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "license-webpack-plugin": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-1.5.0.tgz", + "integrity": "sha512-Of/H79rZqm2aeg4RnP9SMSh19qkKemoLT5VaJV58uH5AxeYWEcBgGFs753JEJ/Hm6BPvQVfIlrrjoBwYj8p7Tw==", + "dev": true, + "requires": { + "ejs": "^2.5.7" + } + }, + "lie": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", + "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=", + "dev": true, + "requires": { + "immediate": "~3.0.5" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "loader-runner": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.1.tgz", + "integrity": "sha512-By6ZFY7ETWOc9RFaAIb23IjJVcM4dvJC/N57nmdz9RSkMXvAXGI7SyVlAw3v8vjtDRlqThgVDVmTnr9fqMlxkw==", + "dev": true + }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", + "dev": true, + "optional": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", + "dev": true + }, + "lodash.mergewith": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", + "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==", + "dev": true, + "optional": true + }, + "lodash.tail": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz", + "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=", + "dev": true + }, + "log4js": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", + "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", + "dev": true, + "requires": { + "circular-json": "^0.5.5", + "date-format": "^1.2.0", + "debug": "^3.1.0", + "rfdc": "^1.1.2", + "streamroller": "0.7.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "loglevel": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.1.tgz", + "integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "optional": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", + "dev": true + }, + "lru-cache": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "make-error": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", + "dev": true + }, + "map-age-cleaner": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.2.tgz", + "integrity": "sha512-UN1dNocxQq44IhJyMI4TU8phc2m9BddacHRPRjKGLYaF0jqd3xLz0jS0skpAU9WgYyoR4gHtUpzytNBS385FWQ==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "math-random": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", + "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", + "dev": true + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "mem": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz", + "integrity": "sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^1.0.0", + "p-is-promise": "^1.1.0" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "optional": true, + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true, + "optional": true + } + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "mime-db": { + "version": "1.36.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", + "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==", + "dev": true + }, + "mime-types": { + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", + "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", + "dev": true, + "requires": { + "mime-db": "~1.36.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "mini-css-extract-plugin": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.4.4.tgz", + "integrity": "sha512-o+Jm+ocb0asEngdM6FsZWtZsRzA8koFUudIDwYUfl94M3PejPHG7Vopw5hN9V8WsMkSFpm3tZP3Fesz89EyrfQ==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "schema-utils": "^1.0.0", + "webpack-sources": "^1.1.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mississippi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", + "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^2.0.1", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mixin-object": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", + "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", + "dev": true, + "requires": { + "for-in": "^0.1.3", + "is-extendable": "^0.1.1" + }, + "dependencies": { + "for-in": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", + "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=", + "dev": true + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dev": true, + "requires": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + } + }, + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "dev": true + }, + "nan": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", + "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "dev": true + }, + "neo-async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", + "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "dev": true, + "requires": { + "lower-case": "^1.1.1" + } + }, + "node-forge": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", + "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==", + "dev": true + }, + "node-gyp": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", + "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", + "dev": true, + "optional": true, + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": "^2.87.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "http://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true, + "optional": true + } + } + }, + "node-libs-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", + "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^1.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.0", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.10.3", + "vm-browserify": "0.0.4" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, + "node-sass": { + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.4.tgz", + "integrity": "sha512-MXyurANsUoE4/6KmfMkwGcBzAnJQ5xJBGW7Ei6ea8KnUKuzHr/SguVBIi3uaUAHtZCPUYkvlJ3Ef5T5VAwVpaA==", + "dev": true, + "optional": true, + "requires": { + "async-foreach": "^0.1.3", + "chalk": "^1.1.1", + "cross-spawn": "^3.0.0", + "gaze": "^1.0.0", + "get-stdin": "^4.0.1", + "glob": "^7.0.3", + "in-publish": "^2.0.0", + "lodash.assign": "^4.2.0", + "lodash.clonedeep": "^4.3.2", + "lodash.mergewith": "^4.6.0", + "meow": "^3.7.0", + "mkdirp": "^0.5.1", + "nan": "^2.10.0", + "node-gyp": "^3.8.0", + "npmlog": "^4.0.0", + "request": "^2.88.0", + "sass-graph": "^2.2.4", + "stdout-stream": "^1.4.0", + "true-case-path": "^1.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true, + "optional": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "optional": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true, + "optional": true + } + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true + }, + "npm-package-arg": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.0.tgz", + "integrity": "sha512-zYbhP2k9DbJhA0Z3HKUePUgdB1x7MfIfKssC+WLPFMKTBZKpZh5m13PgexJjCq6KW7j17r0jHWcCpxEqnnncSA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.6.0", + "osenv": "^0.1.5", + "semver": "^5.5.0", + "validate-npm-package-name": "^3.0.0" + } + }, + "npm-registry-client": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/npm-registry-client/-/npm-registry-client-8.6.0.tgz", + "integrity": "sha512-Qs6P6nnopig+Y8gbzpeN/dkt+n7IyVd8f45NTMotGk6Qo7GfBmzwYx6jRLoOOgKiMnaQfYxsuyQlD8Mc3guBhg==", + "dev": true, + "requires": { + "concat-stream": "^1.5.2", + "graceful-fs": "^4.1.6", + "normalize-package-data": "~1.0.1 || ^2.0.0", + "npm-package-arg": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0", + "npmlog": "2 || ^3.1.0 || ^4.0.0", + "once": "^1.3.3", + "request": "^2.74.0", + "retry": "^0.10.0", + "safe-buffer": "^5.1.1", + "semver": "2 >=2.2.1 || 3.x || 4 || 5", + "slide": "^1.1.3", + "ssri": "^5.2.4" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "nth-check": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", + "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", + "dev": true, + "requires": { + "boolbase": "~1.0.0" + } + }, + "null-check": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", + "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=", + "dev": true + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-keys": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", + "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + }, + "dependencies": { + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + } + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "opn": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.4.0.tgz", + "integrity": "sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "original": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", + "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", + "dev": true, + "requires": { + "url-parse": "^1.4.3" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-locale": { + "version": "1.4.0", + "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "optional": true, + "requires": { + "lcid": "^1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-is-promise": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "dev": true + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "pako": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", + "dev": true + }, + "parallel-transform": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "dev": true, + "requires": { + "cyclist": "~0.2.2", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "dev": true, + "requires": { + "no-case": "^2.2.0" + } + }, + "parse-asn1": { + "version": "5.1.1", + "resolved": "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", + "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", + "dev": true, + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "dev": true + }, + "parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pbkdf2": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", + "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "portfinder": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.17.tgz", + "integrity": "sha512-syFcRIRzVI1BoEFOCaAiizwDolh1S1YXSodsVhncbhjzjZQulhczNRbqnUl9N31Q4dKGOXsNDqxC2BWBgSMqeQ==", + "dev": true, + "requires": { + "async": "^1.5.2", + "debug": "^2.2.0", + "mkdirp": "0.5.x" + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-import": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-11.1.0.tgz", + "integrity": "sha512-5l327iI75POonjxkXgdRCUS+AlzAdBx4pOvMEhTKTCjb1p8IEeVR9yx3cPbmN7LIWJLbfnIXxAhoB4jpD0c/Cw==", + "dev": true, + "requires": { + "postcss": "^6.0.1", + "postcss-value-parser": "^3.2.3", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + } + }, + "postcss-load-config": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.0.0.tgz", + "integrity": "sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ==", + "dev": true, + "requires": { + "cosmiconfig": "^4.0.0", + "import-cwd": "^2.0.0" + } + }, + "postcss-loader": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-2.1.6.tgz", + "integrity": "sha512-hgiWSc13xVQAq25cVw80CH0l49ZKlAnU1hKPOdRrNj89bokRr/bZF2nT+hebPPF9c9xs8c3gw3Fr2nxtmXYnNg==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "postcss": "^6.0.0", + "postcss-load-config": "^2.0.0", + "schema-utils": "^0.4.0" + } + }, + "postcss-url": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/postcss-url/-/postcss-url-7.3.2.tgz", + "integrity": "sha512-QMV5mA+pCYZQcUEPQkmor9vcPQ2MT+Ipuu8qdi1gVxbNiIiErEGft+eny1ak19qALoBkccS5AHaCaCDzh7b9MA==", + "dev": true, + "requires": { + "mime": "^1.4.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.0", + "postcss": "^6.0.1", + "xxhashjs": "^0.2.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "pretty-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", + "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", + "dev": true, + "requires": { + "renderkid": "^2.0.1", + "utila": "~0.4" + } + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "dev": true, + "optional": true, + "requires": { + "asap": "~2.0.3" + } + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "protractor": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/protractor/-/protractor-5.4.1.tgz", + "integrity": "sha512-ORey5ewQMYiXQxcQohsqEiKYOg/r5yJoJbt0tuROmmgajdg/CA3gTOZNIFJncUVMAJIk5YFqBBLUjKVmQO6tfA==", + "dev": true, + "requires": { + "@types/node": "^6.0.46", + "@types/q": "^0.0.32", + "@types/selenium-webdriver": "^3.0.0", + "blocking-proxy": "^1.0.0", + "browserstack": "^1.5.1", + "chalk": "^1.1.3", + "glob": "^7.0.3", + "jasmine": "2.8.0", + "jasminewd2": "^2.1.0", + "optimist": "~0.6.0", + "q": "1.4.1", + "saucelabs": "^1.5.0", + "selenium-webdriver": "3.6.0", + "source-map-support": "~0.4.0", + "webdriver-js-extender": "2.1.0", + "webdriver-manager": "^12.0.6" + }, + "dependencies": { + "@types/node": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-6.14.0.tgz", + "integrity": "sha512-6tQyh4Q4B5pECcXBOQDZ5KjyBIxRZGzrweGPM47sAYTdVG4+7R+2EGMTmp0h6ZwgqHrFRCeg2gdhsG9xXEl2Sg==", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + } + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "^0.5.6" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "webdriver-manager": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.0.tgz", + "integrity": "sha512-oEc5fmkpz6Yh6udhwir5m0eN5mgRPq9P/NU5YWuT3Up5slt6Zz+znhLU7q4+8rwCZz/Qq3Fgpr/4oao7NPCm2A==", + "dev": true, + "requires": { + "adm-zip": "^0.4.9", + "chalk": "^1.1.1", + "del": "^2.2.0", + "glob": "^7.0.3", + "ini": "^1.3.4", + "minimist": "^1.2.0", + "q": "^1.4.1", + "request": "^2.87.0", + "rimraf": "^2.5.2", + "semver": "^5.3.0", + "xml2js": "^0.4.17" + } + } + } + }, + "proxy-addr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", + "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", + "dev": true, + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.8.0" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "psl": { + "version": "1.1.29", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==", + "dev": true + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "q": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", + "dev": true + }, + "qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "querystringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.0.tgz", + "integrity": "sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg==", + "dev": true + }, + "randomatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz", + "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==", + "dev": true, + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "randombytes": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "dev": true + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "dev": true, + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "raw-loader": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz", + "integrity": "sha1-DD0L6u2KAclm2Xh793goElKpeao=", + "dev": true + }, + "read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", + "dev": true, + "requires": { + "pify": "^2.3.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + }, + "dependencies": { + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + } + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "optional": true, + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "reflect-metadata": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.12.tgz", + "integrity": "sha512-n+IyV+nGz3+0q3/Yf1ra12KpCyi001bi4XFxSjbiWWjfqb52iTTtpGXmCCAOWWIAn9KEuFZKGqBERHmrtScZ3A==", + "dev": true + }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "^0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexpu-core": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", + "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", + "dev": true, + "requires": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "dev": true + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "renderkid": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.2.tgz", + "integrity": "sha512-FsygIxevi1jSiPY9h7vZmBFUbAOcbYm9UwyiLNdVsLRs/5We9Ob5NMPbGYUTWiLq5L+ezlVdE0A8bbME5CWTpg==", + "dev": true, + "requires": { + "css-select": "^1.1.0", + "dom-converter": "~0.2", + "htmlparser2": "~3.3.0", + "strip-ansi": "^3.0.0", + "utila": "^0.4.0" + } + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "retry": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", + "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=", + "dev": true + }, + "rfdc": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz", + "integrity": "sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==", + "dev": true + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "^7.0.5" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, + "rxjs": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.2.2.tgz", + "integrity": "sha512-0MI8+mkKAXZUF9vMrEoPnaoHkfzBPP4IGwUYRJhIRJF6/w3uByO1e91bEHn8zd43RdkTMKiooYKmwz7RH6zfOQ==", + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sass-graph": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", + "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=", + "dev": true, + "optional": true, + "requires": { + "glob": "^7.0.0", + "lodash": "^4.0.0", + "scss-tokenizer": "^0.2.3", + "yargs": "^7.0.0" + } + }, + "sass-loader": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.1.0.tgz", + "integrity": "sha512-+G+BKGglmZM2GUSfT9TLuEp6tzehHPjAMoRRItOojWIqIGPloVCMhNIQuG639eJ+y033PaGTSjLaTHts8Kw79w==", + "dev": true, + "requires": { + "clone-deep": "^2.0.1", + "loader-utils": "^1.0.1", + "lodash.tail": "^4.1.1", + "neo-async": "^2.5.0", + "pify": "^3.0.0", + "semver": "^5.5.0" + } + }, + "saucelabs": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.5.0.tgz", + "integrity": "sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==", + "dev": true, + "requires": { + "https-proxy-agent": "^2.2.1" + } + }, + "sax": { + "version": "0.5.8", + "resolved": "http://registry.npmjs.org/sax/-/sax-0.5.8.tgz", + "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=", + "dev": true + }, + "schema-utils": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", + "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0" + } + }, + "scss-tokenizer": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", + "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", + "dev": true, + "optional": true, + "requires": { + "js-base64": "^2.1.8", + "source-map": "^0.4.2" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "optional": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", + "dev": true + }, + "selenium-webdriver": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz", + "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==", + "dev": true, + "requires": { + "jszip": "^3.1.3", + "rimraf": "^2.5.4", + "tmp": "0.0.30", + "xml2js": "^0.4.17" + }, + "dependencies": { + "tmp": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", + "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.1" + } + } + } + }, + "selfsigned": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.4.tgz", + "integrity": "sha512-9AukTiDmHXGXWtWjembZ5NDmVvP2695EtpgbCsxCa68w3c88B+alqbmZ4O3hZ4VWGXeGWzEVdvqgAJD8DQPCDw==", + "dev": true, + "requires": { + "node-forge": "0.7.5" + } + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + }, + "semver-dsl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/semver-dsl/-/semver-dsl-1.0.1.tgz", + "integrity": "sha1-02eN5VVeimH2Ke7QJTZq5fJzQKA=", + "dev": true, + "requires": { + "semver": "^5.3.0" + } + }, + "semver-intersect": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.4.0.tgz", + "integrity": "sha512-d8fvGg5ycKAq0+I6nfWeCx6ffaWJCsBYU0H2Rq56+/zFePYfT8mXkB3tWBSjR5BerkHNZ5eTPIk1/LBYas35xQ==", + "dev": true, + "requires": { + "semver": "^5.0.0" + } + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + }, + "dependencies": { + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "dev": true + } + } + }, + "serialize-javascript": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz", + "integrity": "sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==", + "dev": true + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shallow-clone": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-1.0.0.tgz", + "integrity": "sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==", + "dev": true, + "requires": { + "is-extendable": "^0.1.1", + "kind-of": "^5.0.0", + "mixin-object": "^2.0.1" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "socket.io": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", + "dev": true, + "requires": { + "debug": "~3.1.0", + "engine.io": "~3.2.0", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.1.1", + "socket.io-parser": "~3.2.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "socket.io-adapter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", + "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", + "dev": true + }, + "socket.io-client": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", + "dev": true, + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "engine.io-client": "~3.2.0", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.2.0", + "to-array": "0.1.4" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "socket.io-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "sockjs": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", + "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==", + "dev": true, + "requires": { + "faye-websocket": "^0.10.0", + "uuid": "^3.0.1" + } + }, + "sockjs-client": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.5.tgz", + "integrity": "sha1-G7fA9yIsQPQq3xT0RCy9Eml3GoM=", + "dev": true, + "requires": { + "debug": "^2.6.6", + "eventsource": "0.1.6", + "faye-websocket": "~0.11.0", + "inherits": "^2.0.1", + "json3": "^3.3.2", + "url-parse": "^1.1.8" + }, + "dependencies": { + "faye-websocket": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", + "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + } + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-loader": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-0.2.4.tgz", + "integrity": "sha512-OU6UJUty+i2JDpTItnizPrlpOIBLmQbWMuBg9q5bVtnHACqw1tn9nNwqJLbv0/00JjnJb/Ee5g5WS5vrRv7zIQ==", + "dev": true, + "requires": { + "async": "^2.5.0", + "loader-utils": "^1.1.0" + }, + "dependencies": { + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "dev": true, + "requires": { + "lodash": "^4.17.10" + } + } + } + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", + "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "spdx-correct": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz", + "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz", + "integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w==", + "dev": true + }, + "spdy": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz", + "integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=", + "dev": true, + "requires": { + "debug": "^2.6.8", + "handle-thing": "^1.2.5", + "http-deceiver": "^1.2.7", + "safe-buffer": "^5.0.1", + "select-hose": "^2.0.0", + "spdy-transport": "^2.0.18" + } + }, + "spdy-transport": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.1.0.tgz", + "integrity": "sha512-bpUeGpZcmZ692rrTiqf9/2EUakI6/kXX1Rpe0ib/DyOzbiexVfXkw6GnvI9hVGvIwVaUhkaBojjCZwLNRGQg1g==", + "dev": true, + "requires": { + "debug": "^2.6.8", + "detect-node": "^2.0.3", + "hpack.js": "^2.1.6", + "obuf": "^1.1.1", + "readable-stream": "^2.2.9", + "safe-buffer": "^5.0.1", + "wbuf": "^1.7.2" + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.1.tgz", + "integrity": "sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", + "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.1" + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "stats-webpack-plugin": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/stats-webpack-plugin/-/stats-webpack-plugin-0.6.2.tgz", + "integrity": "sha1-LFlJtTHgf4eojm6k3PrFOqjHWis=", + "dev": true, + "requires": { + "lodash": "^4.17.4" + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "dev": true + }, + "stdout-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", + "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", + "dev": true, + "optional": true, + "requires": { + "readable-stream": "^2.0.1" + } + }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, + "streamroller": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", + "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", + "dev": true, + "requires": { + "date-format": "^1.2.0", + "debug": "^3.1.0", + "mkdirp": "^0.5.1", + "readable-stream": "^2.3.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "optional": true, + "requires": { + "get-stdin": "^4.0.1" + } + }, + "style-loader": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.21.0.tgz", + "integrity": "sha512-T+UNsAcl3Yg+BsPKs1vd22Fr8sVT+CJMtzqc6LEw9bbJZb43lm9GoeIfUcDEefBSWC0BhYbcdupV1GtI4DGzxg==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "schema-utils": "^0.4.5" + } + }, + "stylus": { + "version": "0.54.5", + "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.5.tgz", + "integrity": "sha1-QrlWCTHKcJDOhRWnmLqeaqPW3Hk=", + "dev": true, + "requires": { + "css-parse": "1.7.x", + "debug": "*", + "glob": "7.0.x", + "mkdirp": "0.5.x", + "sax": "0.5.x", + "source-map": "0.1.x" + }, + "dependencies": { + "glob": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", + "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "stylus-loader": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-3.0.2.tgz", + "integrity": "sha512-+VomPdZ6a0razP+zinir61yZgpw2NfljeSsdUF5kJuEzlo3khXhY19Fn6l8QQz1GRJGtMCo8nG5C04ePyV7SUA==", + "dev": true, + "requires": { + "loader-utils": "^1.0.2", + "lodash.clonedeep": "^4.5.0", + "when": "~3.6.x" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", + "dev": true + }, + "tapable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.0.tgz", + "integrity": "sha512-IlqtmLVaZA2qab8epUXbVWRn3aB1imbDMJtjB3nu4X0NqPkcY/JH9ZtCBWKHWPxs8Svi9tyo8w2dBoi07qZbBA==", + "dev": true + }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "dev": true, + "optional": true, + "requires": { + "block-stream": "*", + "fstream": "^1.0.2", + "inherits": "2" + } + }, + "through": { + "version": "2.3.8", + "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + } + }, + "thunky": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.2.tgz", + "integrity": "sha1-qGLgGOP7HqLsP85dVWBc9X8kc3E=", + "dev": true + }, + "timers-browserify": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", + "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", + "dev": true + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "toposort": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz", + "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=", + "dev": true + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "dev": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, + "tree-kill": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.0.tgz", + "integrity": "sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg==", + "dev": true + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true, + "optional": true + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "true-case-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", + "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.2" + } + }, + "ts-node": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", + "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", + "dev": true, + "requires": { + "arrify": "^1.0.0", + "buffer-from": "^1.1.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map-support": "^0.5.6", + "yn": "^2.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "tsickle": { + "version": "0.32.1", + "resolved": "https://registry.npmjs.org/tsickle/-/tsickle-0.32.1.tgz", + "integrity": "sha512-JW9j+W0SaMSZGejIFZBk0AiPfnhljK3oLx5SaqxrJhjlvzFyPml5zqG1/PuScUj6yTe1muEqwk5CnDK0cOZmKw==", + "dev": true, + "requires": { + "jasmine-diff": "^0.1.3", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map": "^0.6.0", + "source-map-support": "^0.5.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + }, + "tslint": { + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.11.0.tgz", + "integrity": "sha1-mPMMAurjzecAYgHkwzywi0hYHu0=", + "dev": true, + "requires": { + "babel-code-frame": "^6.22.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^3.2.0", + "glob": "^7.1.1", + "js-yaml": "^3.7.0", + "minimatch": "^3.0.4", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.27.2" + }, + "dependencies": { + "resolve": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "dev": true, + "requires": { + "path-parse": "^1.0.5" + } + } + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.18" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typescript": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", + "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", + "dev": true + }, + "uglify-js": { + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", + "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", + "dev": true, + "requires": { + "commander": "~2.17.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "uglifyjs-webpack-plugin": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.3.0.tgz", + "integrity": "sha512-ovHIch0AMlxjD/97j9AYovZxG5wnHOPkL7T1GKochBADp/Zwc44pEWNqpKl1Loupp1WhFg7SlYmHZRUfdAacgw==", + "dev": true, + "requires": { + "cacache": "^10.0.4", + "find-cache-dir": "^1.0.0", + "schema-utils": "^0.4.5", + "serialize-javascript": "^1.4.0", + "source-map": "^0.6.1", + "uglify-es": "^3.3.4", + "webpack-sources": "^1.1.0", + "worker-farm": "^1.5.2" + }, + "dependencies": { + "commander": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "uglify-es": { + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", + "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", + "dev": true, + "requires": { + "commander": "~2.13.0", + "source-map": "~0.6.1" + } + } + } + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "dev": true + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" + } + } + } + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.1.tgz", + "integrity": "sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, + "upath": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", + "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", + "dev": true + }, + "upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", + "dev": true + }, + "uri-js": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-3.0.2.tgz", + "integrity": "sha1-+QuFhQf4HepNz7s8TD2/orVX+qo=", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "url-loader": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-1.1.2.tgz", + "integrity": "sha512-dXHkKmw8FhPqu8asTc1puBfe3TehOCo2+RmOOev5suNCIYBcT626kxiWg1NBVkwc4rO8BGa7gP70W7VXuqHrjg==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "mime": "^2.0.3", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "mime": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", + "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "url-parse": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.3.tgz", + "integrity": "sha512-rh+KuAW36YKo0vClhQzLLveoj8FwPJNu65xLb7Mrt+eZht0IPT0IXgSv8gcMegZ6NvjJUALf6Mf25POlMwD1Fw==", + "dev": true, + "requires": { + "querystringify": "^2.0.0", + "requires-port": "^1.0.0" + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "useragent": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.2.1.tgz", + "integrity": "sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4=", + "dev": true, + "requires": { + "lru-cache": "2.2.x", + "tmp": "0.0.x" + }, + "dependencies": { + "lru-cache": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz", + "integrity": "sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0=", + "dev": true + } + } + }, + "util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, + "utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "validate-npm-package-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", + "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "dev": true, + "requires": { + "builtins": "^1.0.3" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true + }, + "watchpack": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", + "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "dev": true, + "requires": { + "chokidar": "^2.0.2", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, + "webdriver-js-extender": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz", + "integrity": "sha512-lcUKrjbBfCK6MNsh7xaY2UAUmZwe+/ib03AjVOpFobX4O7+83BUveSrLfU0Qsyb1DaKJdQRbuU+kM9aZ6QUhiQ==", + "dev": true, + "requires": { + "@types/selenium-webdriver": "^3.0.0", + "selenium-webdriver": "^3.0.1" + } + }, + "webpack": { + "version": "4.20.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.20.2.tgz", + "integrity": "sha512-75WFUMblcWYcocjSLlXCb71QuGyH7egdBZu50FtBGl2Nso8CK3Ej+J7bTZz2FPFq5l6fzCisD9modB7t30ikuA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.8", + "@webassemblyjs/helper-module-context": "1.7.8", + "@webassemblyjs/wasm-edit": "1.7.8", + "@webassemblyjs/wasm-parser": "1.7.8", + "acorn": "^5.6.2", + "acorn-dynamic-import": "^3.0.0", + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0", + "chrome-trace-event": "^1.0.0", + "enhanced-resolve": "^4.1.0", + "eslint-scope": "^4.0.0", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.3.0", + "loader-utils": "^1.1.0", + "memory-fs": "~0.4.1", + "micromatch": "^3.1.8", + "mkdirp": "~0.5.0", + "neo-async": "^2.5.0", + "node-libs-browser": "^2.0.0", + "schema-utils": "^0.4.4", + "tapable": "^1.1.0", + "uglifyjs-webpack-plugin": "^1.2.4", + "watchpack": "^1.5.0", + "webpack-sources": "^1.3.0" + } + }, + "webpack-dev-middleware": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.4.0.tgz", + "integrity": "sha512-Q9Iyc0X9dP9bAsYskAVJ/hmIZZQwf/3Sy4xCAZgL5cUkjZmUZLt4l5HpbST/Pdgjn3u6pE7u5OdGd1apgzRujA==", + "dev": true, + "requires": { + "memory-fs": "~0.4.1", + "mime": "^2.3.1", + "range-parser": "^1.0.3", + "webpack-log": "^2.0.0" + }, + "dependencies": { + "mime": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", + "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==", + "dev": true + } + } + }, + "webpack-dev-server": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.1.9.tgz", + "integrity": "sha512-fqPkuNalLuc/hRC2QMkVYJkgNmRvxZQo7ykA2e1XRg/tMJm3qY7ZaD6d89/Fqjxtj9bOrn5wZzLD2n84lJdvWg==", + "dev": true, + "requires": { + "ansi-html": "0.0.7", + "bonjour": "^3.5.0", + "chokidar": "^2.0.0", + "compression": "^1.5.2", + "connect-history-api-fallback": "^1.3.0", + "debug": "^3.1.0", + "del": "^3.0.0", + "express": "^4.16.2", + "html-entities": "^1.2.0", + "http-proxy-middleware": "~0.18.0", + "import-local": "^2.0.0", + "internal-ip": "^3.0.1", + "ip": "^1.1.5", + "killable": "^1.0.0", + "loglevel": "^1.4.1", + "opn": "^5.1.0", + "portfinder": "^1.0.9", + "schema-utils": "^1.0.0", + "selfsigned": "^1.9.1", + "serve-index": "^1.7.2", + "sockjs": "0.3.19", + "sockjs-client": "1.1.5", + "spdy": "^3.4.1", + "strip-ansi": "^3.0.0", + "supports-color": "^5.1.0", + "webpack-dev-middleware": "3.4.0", + "webpack-log": "^2.0.0", + "yargs": "12.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "decamelize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz", + "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==", + "dev": true, + "requires": { + "xregexp": "4.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "os-locale": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.0.1.tgz", + "integrity": "sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw==", + "dev": true, + "requires": { + "execa": "^0.10.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "p-limit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", + "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "yargs": { + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.2.tgz", + "integrity": "sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^2.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^10.1.0" + } + }, + "yargs-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", + "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + } + }, + "webpack-merge": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.1.4.tgz", + "integrity": "sha512-TmSe1HZKeOPey3oy1Ov2iS3guIZjWvMT2BBJDzzT5jScHTjVC3mpjJofgueEzaEd6ibhxRDD6MIblDr8tzh8iQ==", + "dev": true, + "requires": { + "lodash": "^4.17.5" + } + }, + "webpack-sources": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", + "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "webpack-subresource-integrity": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-1.2.0.tgz", + "integrity": "sha512-bdMR4DRbINUFt+QhNfBFHURnCzT8mtHjXiclQWX/aXBpu2pM4nOb2qViyt84ZSFrVKEXkAbmz7mSoZQH/08xFg==", + "dev": true, + "requires": { + "webpack-sources": "^1.3.0" + } + }, + "websocket-driver": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", + "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", + "dev": true, + "requires": { + "http-parser-js": ">=0.4.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", + "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", + "dev": true + }, + "when": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/when/-/when-3.6.4.tgz", + "integrity": "sha1-RztRfsFZ4rhQBUl6E5g/CVQS404=", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "worker-farm": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", + "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "dev": true, + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + }, + "dependencies": { + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + } + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", + "dev": true + }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", + "dev": true + }, + "xregexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", + "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "xxhashjs": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.2.tgz", + "integrity": "sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==", + "dev": true, + "requires": { + "cuint": "^0.2.2" + } + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "dev": true, + "optional": true, + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true, + "optional": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true, + "optional": true + } + } + }, + "yargs-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "dev": true, + "optional": true, + "requires": { + "camelcase": "^3.0.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true, + "optional": true + } + } + }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", + "dev": true + }, + "yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", + "dev": true + }, + "zone.js": { + "version": "0.8.26", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.8.26.tgz", + "integrity": "sha512-W9Nj+UmBJG251wkCacIkETgra4QgBo/vgoEkb4a2uoLzpQG7qF9nzwoLXWU5xj3Fg2mxGvEDh47mg24vXccYjA==" + } + } +} diff --git "a/angualr/angualr\345\256\230\347\275\221demo/package.json" "b/angualr/angualr\345\256\230\347\275\221demo/package.json" new file mode 100644 index 00000000..8bad785c --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/package.json" @@ -0,0 +1,49 @@ +{ + "name": "demo1", + "version": "0.0.0", + "scripts": { + "ng": "ng", + "start": "ng serve", + "build": "ng build", + "test": "ng test", + "lint": "ng lint", + "e2e": "ng e2e" + }, + "private": true, + "dependencies": { + "@angular/animations": "^6.1.0", + "@angular/common": "^6.1.0", + "@angular/compiler": "^6.1.0", + "@angular/core": "^6.1.0", + "@angular/forms": "^6.1.0", + "@angular/http": "^6.1.0", + "@angular/platform-browser": "^6.1.0", + "@angular/platform-browser-dynamic": "^6.1.0", + "@angular/router": "^6.1.0", + "angular-in-memory-web-api": "^0.6.1", + "core-js": "^2.5.4", + "rxjs": "~6.2.0", + "zone.js": "~0.8.26" + }, + "devDependencies": { + "@angular-devkit/build-angular": "~0.8.0", + "@angular/cli": "~6.2.4", + "@angular/compiler-cli": "^6.1.0", + "@angular/language-service": "^6.1.0", + "@types/jasmine": "~2.8.8", + "@types/jasminewd2": "~2.0.3", + "@types/node": "~8.9.4", + "codelyzer": "~4.3.0", + "jasmine-core": "~2.99.1", + "jasmine-spec-reporter": "~4.2.1", + "karma": "~3.0.0", + "karma-chrome-launcher": "~2.2.0", + "karma-coverage-istanbul-reporter": "~2.0.1", + "karma-jasmine": "~1.1.2", + "karma-jasmine-html-reporter": "^0.2.2", + "protractor": "~5.4.0", + "ts-node": "~7.0.0", + "tslint": "~5.11.0", + "typescript": "~2.9.2" + } +} diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/app-routing.module.spec.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/app-routing.module.spec.ts" new file mode 100644 index 00000000..d68ef067 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/app-routing.module.spec.ts" @@ -0,0 +1,13 @@ +import { AppRoutingModule } from './app-routing.module'; + +describe('AppRoutingModule', () => { + let appRoutingModule: AppRoutingModule; + + beforeEach(() => { + appRoutingModule = new AppRoutingModule(); + }); + + it('should create an instance', () => { + expect(appRoutingModule).toBeTruthy(); + }); +}); diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/app-routing.module.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/app-routing.module.ts" new file mode 100644 index 00000000..6755406f --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/app-routing.module.ts" @@ -0,0 +1,25 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; + +import { HeroesComponent } from './heroes/heroes.component'; +import { DashboardComponent } from './dashboard/dashboard.component'; +import { HeroDetailComponent } from './hero-detail/hero-detail.component'; + + +const routes : Routes = [ + {path : '', redirectTo:'/dashboard', pathMatch:'full'}, + {path : 'heroes', component: HeroesComponent}, + {path : 'detail/:id', component:HeroDetailComponent}, + {path : 'dashboard', component: DashboardComponent} +] + +@NgModule({ + imports: [ + RouterModule.forRoot(routes) + ], + exports: [ + RouterModule + ], + declarations: [] +}) +export class AppRoutingModule { } diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/app.component.css" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/app.component.css" new file mode 100644 index 00000000..25d42851 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/app.component.css" @@ -0,0 +1,29 @@ +/* AppComponent's private CSS styles */ +h1 { + font-size: 1.2em; + color: #999; + margin-bottom: 0; + } + h2 { + font-size: 2em; + margin-top: 0; + padding-top: 0; + } + nav a { + padding: 5px 10px; + text-decoration: none; + margin-top: 10px; + display: inline-block; + background-color: #eee; + border-radius: 4px; + } + nav a:visited, a:link { + color: #607d8b; + } + nav a:hover { + color: #039be5; + background-color: #cfd8dc; + } + nav a.active { + color: #039be5; + } \ No newline at end of file diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/app.component.html" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/app.component.html" new file mode 100644 index 00000000..5f5ec2da --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/app.component.html" @@ -0,0 +1,11 @@ +
+

{{title}}

+ + + + +
\ No newline at end of file diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/app.component.spec.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/app.component.spec.ts" new file mode 100644 index 00000000..153f6f0d --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/app.component.spec.ts" @@ -0,0 +1,31 @@ +import { TestBed, async } from '@angular/core/testing'; +import { AppComponent } from './app.component'; + +describe('AppComponent', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ + AppComponent + ], + }).compileComponents(); + })); + + it('should create the app', () => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.debugElement.componentInstance; + expect(app).toBeTruthy(); + }); + + it(`should have as title 'demo1'`, () => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.debugElement.componentInstance; + expect(app.title).toEqual('demo1'); + }); + + it('should render title in a h1 tag', () => { + const fixture = TestBed.createComponent(AppComponent); + fixture.detectChanges(); + const compiled = fixture.debugElement.nativeElement; + expect(compiled.querySelector('h1').textContent).toContain('Welcome to demo1!'); + }); +}); diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/app.component.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/app.component.ts" new file mode 100644 index 00000000..9ba3e653 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/app.component.ts" @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.css'] +}) +export class AppComponent { + title = 'hello'; +} diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/app.module.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/app.module.ts" new file mode 100644 index 00000000..963ebf85 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/app.module.ts" @@ -0,0 +1,33 @@ +import { BrowserModule } from '@angular/platform-browser'; +import { NgModule } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import {HttpClientModule} from '@angular/common/http'; + +import { AppComponent } from './app.component'; +import { HeroesComponent } from './heroes/heroes.component'; +import { HeroDetailComponent } from './hero-detail/hero-detail.component'; +import { MessageComponent } from './message/message.component'; +import { AppRoutingModule } from './app-routing.module'; +import { DashboardComponent } from './dashboard/dashboard.component'; + +import { HttpClientInMemoryWebApiModule } from 'angular-in-memory-web-api'; +import { InMemoryDataService } from './in-memory-data.service'; + +@NgModule({ + declarations: [ + AppComponent, + HeroesComponent, + HeroDetailComponent, + MessageComponent, + DashboardComponent + ], + imports: [ + BrowserModule, + FormsModule, + AppRoutingModule, + HttpClientModule + ], + providers: [], + bootstrap: [AppComponent] +}) +export class AppModule { } diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/dashboard/dashboard.component.css" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/dashboard/dashboard.component.css" new file mode 100644 index 00000000..a3cfa047 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/dashboard/dashboard.component.css" @@ -0,0 +1,62 @@ +/* DashboardComponent's private CSS styles */ +[class*='col-'] { + float: left; + padding-right: 20px; + padding-bottom: 20px; + } + [class*='col-']:last-of-type { + padding-right: 0; + } + a { + text-decoration: none; + } + *, *:after, *:before { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + h3 { + text-align: center; margin-bottom: 0; + } + h4 { + position: relative; + } + .grid { + margin: 0; + } + .col-1-4 { + width: 25%; + } + .module { + padding: 20px; + text-align: center; + color: #eee; + max-height: 120px; + min-width: 120px; + background-color: #607d8b; + border-radius: 2px; + } + .module:hover { + background-color: #eee; + cursor: pointer; + color: #607d8b; + } + .grid-pad { + padding: 10px 0; + } + .grid-pad > [class*='col-']:last-of-type { + padding-right: 20px; + } + @media (max-width: 600px) { + .module { + font-size: 10px; + max-height: 75px; } + } + @media (max-width: 1024px) { + .grid { + margin: 0; + } + .module { + min-width: 60px; + } + } \ No newline at end of file diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/dashboard/dashboard.component.html" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/dashboard/dashboard.component.html" new file mode 100644 index 00000000..d7fa0a7c --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/dashboard/dashboard.component.html" @@ -0,0 +1,10 @@ +

top heroes

+ \ No newline at end of file diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/dashboard/dashboard.component.spec.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/dashboard/dashboard.component.spec.ts" new file mode 100644 index 00000000..9c996c37 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/dashboard/dashboard.component.spec.ts" @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DashboardComponent } from './dashboard.component'; + +describe('DashboardComponent', () => { + let component: DashboardComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ DashboardComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DashboardComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/dashboard/dashboard.component.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/dashboard/dashboard.component.ts" new file mode 100644 index 00000000..56bc93b0 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/dashboard/dashboard.component.ts" @@ -0,0 +1,22 @@ +import { Component, OnInit } from '@angular/core'; +import { Hero } from '../hero'; +import { HeroService } from '../hero.service'; + +@Component({ + selector: 'app-dashboard', + templateUrl: './dashboard.component.html', + styleUrls: ['./dashboard.component.css'] +}) +export class DashboardComponent implements OnInit { + heroes: Hero[] = []; + constructor(private heroService: HeroService) { } + + ngOnInit() { + this.getHeroes(); + } + + getHeroes(): void{ + this.heroService.getHeroes() + .subscribe(heroes => this.heroes = heroes.slice(1, 5)); + } +} diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/hero-detail/hero-detail.component.css" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/hero-detail/hero-detail.component.css" new file mode 100644 index 00000000..ea85213b --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/hero-detail/hero-detail.component.css" @@ -0,0 +1,30 @@ +/* HeroDetailComponent's private CSS styles */ +label { + display: inline-block; + width: 3em; + margin: .5em 0; + color: #607D8B; + font-weight: bold; + } + input { + height: 2em; + font-size: 1em; + padding-left: .4em; + } + button { + margin-top: 20px; + font-family: Arial; + background-color: #eee; + border: none; + padding: 5px 10px; + border-radius: 4px; + cursor: pointer; cursor: hand; + } + button:hover { + background-color: #cfd8dc; + } + button:disabled { + background-color: #eee; + color: #ccc; + cursor: auto; + } \ No newline at end of file diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/hero-detail/hero-detail.component.html" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/hero-detail/hero-detail.component.html" new file mode 100644 index 00000000..3f1ea04a --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/hero-detail/hero-detail.component.html" @@ -0,0 +1,11 @@ +
+

{{hero.name | uppercase}} details

+
id: {{hero.id}}
+
name: {{hero.name}}
+ + + + +
\ No newline at end of file diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/hero-detail/hero-detail.component.spec.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/hero-detail/hero-detail.component.spec.ts" new file mode 100644 index 00000000..5e34497b --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/hero-detail/hero-detail.component.spec.ts" @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { HeroDetailComponent } from './hero-detail.component'; + +describe('HeroDetailComponent', () => { + let component: HeroDetailComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ HeroDetailComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(HeroDetailComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/hero-detail/hero-detail.component.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/hero-detail/hero-detail.component.ts" new file mode 100644 index 00000000..f2840ff4 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/hero-detail/hero-detail.component.ts" @@ -0,0 +1,37 @@ +import { Component, OnInit, Input } from '@angular/core'; +import { Location } from '@angular/common'; +import { ActivatedRoute } from '@angular/router'; + +import { Hero } from '../hero'; +import { HeroService } from '../hero.service'; + +@Component({ + selector: 'app-hero-detail', + templateUrl: './hero-detail.component.html', + styleUrls: ['./hero-detail.component.css'] +}) +export class HeroDetailComponent implements OnInit { + @Input() hero: Hero; + constructor( + private route : ActivatedRoute, + private heroService: HeroService, + private location: Location + ) { } + + + ngOnInit() { + this.getHero(); + } + + getHero(): void { + const id = +this.route.snapshot.paramMap.get('id'); + this.heroService.getHero(id).subscribe(hero => this.hero = hero); + } + goBack ():void{ + this.location.back(); + } + save():void { + this.heroService.updateHero(this.hero) + .subscribe(()=> this.goBack()) + } +} diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/hero.service.spec.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/hero.service.spec.ts" new file mode 100644 index 00000000..082791a7 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/hero.service.spec.ts" @@ -0,0 +1,12 @@ +import { TestBed } from '@angular/core/testing'; + +import { HeroService } from './hero.service'; + +describe('HeroService', () => { + beforeEach(() => TestBed.configureTestingModule({})); + + it('should be created', () => { + const service: HeroService = TestBed.get(HeroService); + expect(service).toBeTruthy(); + }); +}); diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/hero.service.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/hero.service.ts" new file mode 100644 index 00000000..b4b3df09 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/hero.service.ts" @@ -0,0 +1,62 @@ +import { Injectable } from '@angular/core'; +import { Observable, of } from 'rxjs'; +import { Hero } from './hero'; +import { HEROES } from './mock-heroes'; +import { MessageService } from './message.service'; + +import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { catchError, map, tap } from 'rxjs/operators'; + +const httpOptions = { + headers: new HttpHeaders({ + 'Content-Type': 'application/json' + }) +} +@Injectable({ + providedIn: 'root' +}) + +export class HeroService { + + constructor( + private http: HttpClient, + private messageService : MessageService + ) { } + + private heroesUrl = 'api/heroes'; + private log ( message:string ) { + this.messageService.add(`HeroService: ${message}`) + } + private handleError (operation = 'operation', result?:T){ + return (error:any): Observable =>{ + console.error(error); + this.log(`${operation} failed: ${error.message}`); + return of(result as T) + } + } + + getHeroes(): Observable { + // this.messageService.add('HeroService: fetched heros !'); + // return of(HEROES); + return this.http.get (this.heroesUrl).pipe( + tap(heroes => this.log('fetched heroes')), + catchError(this.handleError('getHeroes', [])) + ) + } + + getHero(id: number): Observable { + const url = `${this.heroesUrl}/${id}` + // this.messageService.add(`HeroService: fetched hero id = ${id}`) + return this.http.get(url).pipe( + tap(_ => this.log(`fetched hero id=${id}`)), + catchError(this.handleError(`getHero id=${id}`)) + ); + } + updateHero(hero:Hero): Observable{ + return this.http.put(this.heroesUrl, hero, httpOptions).pipe( + tap(_=> this.log(`updated hero id=${hero.id}`)), + catchError(this.handleError('updateHero')) + ) + } + +} diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/hero.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/hero.ts" new file mode 100644 index 00000000..a42e2a24 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/hero.ts" @@ -0,0 +1,4 @@ +export class Hero { + id : number; + name : string; +} \ No newline at end of file diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/heroes/heroes.component.css" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/heroes/heroes.component.css" new file mode 100644 index 00000000..90d69067 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/heroes/heroes.component.css" @@ -0,0 +1,51 @@ +/* HeroesComponent's private CSS styles */ +.heroes { + margin: 0 0 2em 0; + list-style-type: none; + padding: 0; + width: 15em; +} +.heroes li { + position: relative; + cursor: pointer; + background-color: #EEE; + margin: .5em; + padding: .3em 0; + height: 1.6em; + border-radius: 4px; +} + +.heroes li:hover { + color: #607D8B; + background-color: #DDD; + left: .1em; +} + +.heroes a { + color: #888; + text-decoration: none; + position: relative; + display: block; + width: 250px; +} + +.heroes a:hover { + color:#607D8B; +} + +.heroes .badge { + display: inline-block; + font-size: small; + color: white; + padding: 0.8em 0.7em 0 0.7em; + background-color: #607D8B; + line-height: 1em; + position: relative; + left: -1px; + top: -4px; + height: 1.8em; + min-width: 16px; + text-align: right; + margin-right: .8em; + border-radius: 4px 0 0 4px; +} \ No newline at end of file diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/heroes/heroes.component.html" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/heroes/heroes.component.html" new file mode 100644 index 00000000..f0bf3763 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/heroes/heroes.component.html" @@ -0,0 +1,10 @@ + + \ No newline at end of file diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/heroes/heroes.component.spec.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/heroes/heroes.component.spec.ts" new file mode 100644 index 00000000..66518e44 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/heroes/heroes.component.spec.ts" @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { HeroesComponent } from './heroes.component'; + +describe('HeroesComponent', () => { + let component: HeroesComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ HeroesComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(HeroesComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/heroes/heroes.component.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/heroes/heroes.component.ts" new file mode 100644 index 00000000..09e60ce3 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/heroes/heroes.component.ts" @@ -0,0 +1,26 @@ +import { Component, OnInit } from '@angular/core'; +import { Hero } from '../hero'; +import { HeroService } from '../hero.service'; + +@Component({ + selector: 'app-heroes', + templateUrl: './heroes.component.html', + styleUrls: ['./heroes.component.css'] +}) +export class HeroesComponent implements OnInit { + // selectedHero : Hero; + heroes : Hero[]; + constructor(private heroService:HeroService) { } + + ngOnInit() { + } + + // onSelect(hero: Hero):void { + // console.log(hero) + // this.selectedHero = hero; + // } + getHeroes():void { + this.heroService.getHeroes().subscribe(heroes => this.heroes = heroes); + } + +} diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/in-memory-data.service.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/in-memory-data.service.ts" new file mode 100644 index 00000000..901faf5c --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/in-memory-data.service.ts" @@ -0,0 +1,19 @@ +import { InMemoryDbService } from 'angular-in-memory-web-api'; + +export class InMemoryDataService implements InMemoryDbService { + createDb() { + const heroes = [ + { id: 11, name: 'Mr. Nice' }, + { id: 12, name: 'Narco' }, + { id: 13, name: 'Bombasto' }, + { id: 14, name: 'Celeritas' }, + { id: 15, name: 'Magneta' }, + { id: 16, name: 'RubberMan' }, + { id: 17, name: 'Dynama' }, + { id: 18, name: 'Dr IQ' }, + { id: 19, name: 'Magma' }, + { id: 20, name: 'Tornado' } + ] + return {heroes}; + } +} \ No newline at end of file diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/message.service.spec.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/message.service.spec.ts" new file mode 100644 index 00000000..24d2d1d3 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/message.service.spec.ts" @@ -0,0 +1,12 @@ +import { TestBed } from '@angular/core/testing'; + +import { MessageService } from './message.service'; + +describe('MessageService', () => { + beforeEach(() => TestBed.configureTestingModule({})); + + it('should be created', () => { + const service: MessageService = TestBed.get(MessageService); + expect(service).toBeTruthy(); + }); +}); diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/message.service.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/message.service.ts" new file mode 100644 index 00000000..f9fb3b22 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/message.service.ts" @@ -0,0 +1,17 @@ +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class MessageService { + messages: string [] = []; + + add (message: string){ + this.messages.push(message) + } + clear (){ + this.messages = []; + } + + constructor() { } +} diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/message/message.component.css" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/message/message.component.css" new file mode 100644 index 00000000..fae80c0c --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/message/message.component.css" @@ -0,0 +1,35 @@ +/* MessagesComponent's private CSS styles */ +h2 { + color: red; + font-family: Arial, Helvetica, sans-serif; + font-weight: lighter; + } + body { + margin: 2em; + } + body, input[text], button { + color: crimson; + font-family: Cambria, Georgia; + } + + button.clear { + font-family: Arial; + background-color: #eee; + border: none; + padding: 5px 10px; + border-radius: 4px; + cursor: pointer; + cursor: hand; + } + button:hover { + background-color: #cfd8dc; + } + button:disabled { + background-color: #eee; + color: #aaa; + cursor: auto; + } + button.clear { + color: #888; + margin-bottom: 12px; + } \ No newline at end of file diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/message/message.component.html" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/message/message.component.html" new file mode 100644 index 00000000..a3b175bb --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/message/message.component.html" @@ -0,0 +1,12 @@ +
+

Messages

+ +
+ {{message}} +
+
\ No newline at end of file diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/message/message.component.spec.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/message/message.component.spec.ts" new file mode 100644 index 00000000..e8601637 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/message/message.component.spec.ts" @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MessageComponent } from './message.component'; + +describe('MessageComponent', () => { + let component: MessageComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ MessageComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MessageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/message/message.component.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/message/message.component.ts" new file mode 100644 index 00000000..0252aa38 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/message/message.component.ts" @@ -0,0 +1,16 @@ +import { Component, OnInit } from '@angular/core'; +import { MessageService } from '../message.service'; + +@Component({ + selector: 'app-message', + templateUrl: './message.component.html', + styleUrls: ['./message.component.css'] +}) +export class MessageComponent implements OnInit { + + constructor(public messageService : MessageService) { } + + ngOnInit() { + } + +} diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/app/mock-heroes.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/app/mock-heroes.ts" new file mode 100644 index 00000000..bf325d1e --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/app/mock-heroes.ts" @@ -0,0 +1,14 @@ +import { Hero } from './hero'; + +export const HEROES: Hero[] = [ + { id: 11, name: 'Mr. Nice' }, + { id: 12, name: 'Narco' }, + { id: 13, name: 'Bombasto' }, + { id: 14, name: 'Celeritas' }, + { id: 15, name: 'Magneta' }, + { id: 16, name: 'RubberMan' }, + { id: 17, name: 'Dynama' }, + { id: 18, name: 'Dr IQ' }, + { id: 19, name: 'Magma' }, + { id: 20, name: 'Tornado' } +] \ No newline at end of file diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/assets/.gitkeep" "b/angualr/angualr\345\256\230\347\275\221demo/src/assets/.gitkeep" new file mode 100644 index 00000000..e69de29b diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/browserslist" "b/angualr/angualr\345\256\230\347\275\221demo/src/browserslist" new file mode 100644 index 00000000..37371cb0 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/browserslist" @@ -0,0 +1,11 @@ +# This file is currently used by autoprefixer to adjust CSS to support the below specified browsers +# For additional information regarding the format and rule options, please see: +# https://github.com/browserslist/browserslist#queries +# +# For IE 9-11 support, please remove 'not' from the last line of the file and adjust as needed + +> 0.5% +last 2 versions +Firefox ESR +not dead +not IE 9-11 \ No newline at end of file diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/environments/environment.prod.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/environments/environment.prod.ts" new file mode 100644 index 00000000..3612073b --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/environments/environment.prod.ts" @@ -0,0 +1,3 @@ +export const environment = { + production: true +}; diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/environments/environment.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/environments/environment.ts" new file mode 100644 index 00000000..7b4f817a --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/environments/environment.ts" @@ -0,0 +1,16 @@ +// This file can be replaced during build by using the `fileReplacements` array. +// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. +// The list of file replacements can be found in `angular.json`. + +export const environment = { + production: false +}; + +/* + * For easier debugging in development mode, you can import the following file + * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. + * + * This import should be commented out in production mode because it will have a negative impact + * on performance if an error is thrown. + */ +// import 'zone.js/dist/zone-error'; // Included with Angular CLI. diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/favicon.ico" "b/angualr/angualr\345\256\230\347\275\221demo/src/favicon.ico" new file mode 100644 index 0000000000000000000000000000000000000000..8081c7ceaf2be08bf59010158c586170d9d2d517 GIT binary patch literal 5430 zcmc(je{54#6vvCoAI3i*G5%$U7!sA3wtMZ$fH6V9C`=eXGJb@R1%(I_{vnZtpD{6n z5Pl{DmxzBDbrB>}`90e12m8T*36WoeDLA&SD_hw{H^wM!cl_RWcVA!I+x87ee975; z@4kD^=bYPn&pmG@(+JZ`rqQEKxW<}RzhW}I!|ulN=fmjVi@x{p$cC`)5$a!)X&U+blKNvN5tg=uLvuLnuqRM;Yc*swiexsoh#XPNu{9F#c`G zQLe{yWA(Y6(;>y|-efAy11k<09(@Oo1B2@0`PtZSkqK&${ zgEY}`W@t{%?9u5rF?}Y7OL{338l*JY#P!%MVQY@oqnItpZ}?s z!r?*kwuR{A@jg2Chlf0^{q*>8n5Ir~YWf*wmsh7B5&EpHfd5@xVaj&gqsdui^spyL zB|kUoblGoO7G(MuKTfa9?pGH0@QP^b#!lM1yHWLh*2iq#`C1TdrnO-d#?Oh@XV2HK zKA{`eo{--^K&MW66Lgsktfvn#cCAc*(}qsfhrvOjMGLE?`dHVipu1J3Kgr%g?cNa8 z)pkmC8DGH~fG+dlrp(5^-QBeEvkOvv#q7MBVLtm2oD^$lJZx--_=K&Ttd=-krx(Bb zcEoKJda@S!%%@`P-##$>*u%T*mh+QjV@)Qa=Mk1?#zLk+M4tIt%}wagT{5J%!tXAE;r{@=bb%nNVxvI+C+$t?!VJ@0d@HIyMJTI{vEw0Ul ze(ha!e&qANbTL1ZneNl45t=#Ot??C0MHjjgY8%*mGisN|S6%g3;Hlx#fMNcL<87MW zZ>6moo1YD?P!fJ#Jb(4)_cc50X5n0KoDYfdPoL^iV`k&o{LPyaoqMqk92wVM#_O0l z09$(A-D+gVIlq4TA&{1T@BsUH`Bm=r#l$Z51J-U&F32+hfUP-iLo=jg7Xmy+WLq6_tWv&`wDlz#`&)Jp~iQf zZP)tu>}pIIJKuw+$&t}GQuqMd%Z>0?t%&BM&Wo^4P^Y z)c6h^f2R>X8*}q|bblAF?@;%?2>$y+cMQbN{X$)^R>vtNq_5AB|0N5U*d^T?X9{xQnJYeU{ zoZL#obI;~Pp95f1`%X3D$Mh*4^?O?IT~7HqlWguezmg?Ybq|7>qQ(@pPHbE9V?f|( z+0xo!#m@Np9PljsyxBY-UA*{U*la#8Wz2sO|48_-5t8%_!n?S$zlGe+NA%?vmxjS- zHE5O3ZarU=X}$7>;Okp(UWXJxI%G_J-@IH;%5#Rt$(WUX?6*Ux!IRd$dLP6+SmPn= z8zjm4jGjN772R{FGkXwcNv8GBcZI#@Y2m{RNF_w8(Z%^A*!bS*!}s6sh*NnURytky humW;*g7R+&|Ledvc- + + + + Demo1 + + + + + + + + + diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/karma.conf.js" "b/angualr/angualr\345\256\230\347\275\221demo/src/karma.conf.js" new file mode 100644 index 00000000..b6e00421 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/karma.conf.js" @@ -0,0 +1,31 @@ +// Karma configuration file, see link for more information +// https://karma-runner.github.io/1.0/config/configuration-file.html + +module.exports = function (config) { + config.set({ + basePath: '', + frameworks: ['jasmine', '@angular-devkit/build-angular'], + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-coverage-istanbul-reporter'), + require('@angular-devkit/build-angular/plugins/karma') + ], + client: { + clearContext: false // leave Jasmine Spec Runner output visible in browser + }, + coverageIstanbulReporter: { + dir: require('path').join(__dirname, '../coverage'), + reports: ['html', 'lcovonly'], + fixWebpackSourcePaths: true + }, + reporters: ['progress', 'kjhtml'], + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: true, + browsers: ['Chrome'], + singleRun: false + }); +}; \ No newline at end of file diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/main.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/main.ts" new file mode 100644 index 00000000..28bfa9e1 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/main.ts" @@ -0,0 +1,13 @@ +import { enableProdMode } from '@angular/core'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; +import { environment } from './environments/environment'; + +if (environment.production) { + enableProdMode(); +} + +platformBrowserDynamic().bootstrapModule(AppModule) + .catch(err => console.error(err)); + diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/polyfills.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/polyfills.ts" new file mode 100644 index 00000000..d310405a --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/polyfills.ts" @@ -0,0 +1,80 @@ +/** + * This file includes polyfills needed by Angular and is loaded before the app. + * You can add your own extra polyfills to this file. + * + * This file is divided into 2 sections: + * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. + * 2. Application imports. Files imported after ZoneJS that should be loaded before your main + * file. + * + * The current setup is for so-called "evergreen" browsers; the last versions of browsers that + * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), + * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. + * + * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html + */ + +/*************************************************************************************************** + * BROWSER POLYFILLS + */ + +/** IE9, IE10 and IE11 requires all of the following polyfills. **/ +// import 'core-js/es6/symbol'; +// import 'core-js/es6/object'; +// import 'core-js/es6/function'; +// import 'core-js/es6/parse-int'; +// import 'core-js/es6/parse-float'; +// import 'core-js/es6/number'; +// import 'core-js/es6/math'; +// import 'core-js/es6/string'; +// import 'core-js/es6/date'; +// import 'core-js/es6/array'; +// import 'core-js/es6/regexp'; +// import 'core-js/es6/map'; +// import 'core-js/es6/weak-map'; +// import 'core-js/es6/set'; + +/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +// import 'classlist.js'; // Run `npm install --save classlist.js`. + +/** IE10 and IE11 requires the following for the Reflect API. */ +// import 'core-js/es6/reflect'; + + +/** Evergreen browsers require these. **/ +// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove. +import 'core-js/es7/reflect'; + + +/** + * Web Animations `@angular/platform-browser/animations` + * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. + * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). + **/ +// import 'web-animations-js'; // Run `npm install --save web-animations-js`. + +/** + * By default, zone.js will patch all possible macroTask and DomEvents + * user can disable parts of macroTask/DomEvents patch by setting following flags + */ + + // (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame + // (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick + // (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames + + /* + * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js + * with the following flag, it will bypass `zone.js` patch for IE/Edge + */ +// (window as any).__Zone_enable_cross_context_check = true; + +/*************************************************************************************************** + * Zone JS is required by default for Angular itself. + */ +import 'zone.js/dist/zone'; // Included with Angular CLI. + + + +/*************************************************************************************************** + * APPLICATION IMPORTS + */ diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/styles.css" "b/angualr/angualr\345\256\230\347\275\221demo/src/styles.css" new file mode 100644 index 00000000..45e4ad78 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/styles.css" @@ -0,0 +1,22 @@ +/* You can add global styles to this file, and also import other style files */ +h1 { + color: #369; + font-family: Arial, Helvetica, sans-serif; + font-size: 250%; +} +h2, h3 { + color: #444; + font-family: Arial, Helvetica, sans-serif; + font-weight: lighter; +} +body { + margin: 2em; +} +body, input[text], button { + color: #888; + font-family: Cambria, Georgia; +} +/* everywhere else */ +* { + font-family: Arial, Helvetica, sans-serif; +} \ No newline at end of file diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/test.ts" "b/angualr/angualr\345\256\230\347\275\221demo/src/test.ts" new file mode 100644 index 00000000..16317897 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/test.ts" @@ -0,0 +1,20 @@ +// This file is required by karma.conf.js and loads recursively all the .spec and framework files + +import 'zone.js/dist/zone-testing'; +import { getTestBed } from '@angular/core/testing'; +import { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting +} from '@angular/platform-browser-dynamic/testing'; + +declare const require: any; + +// First, initialize the Angular testing environment. +getTestBed().initTestEnvironment( + BrowserDynamicTestingModule, + platformBrowserDynamicTesting() +); +// Then we find all the tests. +const context = require.context('./', true, /\.spec\.ts$/); +// And load the modules. +context.keys().map(context); diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/tsconfig.app.json" "b/angualr/angualr\345\256\230\347\275\221demo/src/tsconfig.app.json" new file mode 100644 index 00000000..190fd300 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/tsconfig.app.json" @@ -0,0 +1,11 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "outDir": "../out-tsc/app", + "types": [] + }, + "exclude": [ + "test.ts", + "**/*.spec.ts" + ] +} diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/tsconfig.spec.json" "b/angualr/angualr\345\256\230\347\275\221demo/src/tsconfig.spec.json" new file mode 100644 index 00000000..de773363 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/tsconfig.spec.json" @@ -0,0 +1,18 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "outDir": "../out-tsc/spec", + "types": [ + "jasmine", + "node" + ] + }, + "files": [ + "test.ts", + "polyfills.ts" + ], + "include": [ + "**/*.spec.ts", + "**/*.d.ts" + ] +} diff --git "a/angualr/angualr\345\256\230\347\275\221demo/src/tslint.json" "b/angualr/angualr\345\256\230\347\275\221demo/src/tslint.json" new file mode 100644 index 00000000..52e2c1a5 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/src/tslint.json" @@ -0,0 +1,17 @@ +{ + "extends": "../tslint.json", + "rules": { + "directive-selector": [ + true, + "attribute", + "app", + "camelCase" + ], + "component-selector": [ + true, + "element", + "app", + "kebab-case" + ] + } +} diff --git "a/angualr/angualr\345\256\230\347\275\221demo/tsconfig.json" "b/angualr/angualr\345\256\230\347\275\221demo/tsconfig.json" new file mode 100644 index 00000000..916247e4 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/tsconfig.json" @@ -0,0 +1,21 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "baseUrl": "./", + "outDir": "./dist/out-tsc", + "sourceMap": true, + "declaration": false, + "module": "es2015", + "moduleResolution": "node", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "target": "es5", + "typeRoots": [ + "node_modules/@types" + ], + "lib": [ + "es2017", + "dom" + ] + } +} diff --git "a/angualr/angualr\345\256\230\347\275\221demo/tslint.json" "b/angualr/angualr\345\256\230\347\275\221demo/tslint.json" new file mode 100644 index 00000000..6ddb6b29 --- /dev/null +++ "b/angualr/angualr\345\256\230\347\275\221demo/tslint.json" @@ -0,0 +1,131 @@ +{ + "rulesDirectory": [ + "node_modules/codelyzer" + ], + "rules": { + "arrow-return-shorthand": true, + "callable-types": true, + "class-name": true, + "comment-format": [ + true, + "check-space" + ], + "curly": true, + "deprecation": { + "severity": "warn" + }, + "eofline": true, + "forin": true, + "import-blacklist": [ + true, + "rxjs/Rx" + ], + "import-spacing": true, + "indent": [ + true, + "spaces" + ], + "interface-over-type-literal": true, + "label-position": true, + "max-line-length": [ + true, + 140 + ], + "member-access": false, + "member-ordering": [ + true, + { + "order": [ + "static-field", + "instance-field", + "static-method", + "instance-method" + ] + } + ], + "no-arg": true, + "no-bitwise": true, + "no-console": [ + true, + "debug", + "info", + "time", + "timeEnd", + "trace" + ], + "no-construct": true, + "no-debugger": true, + "no-duplicate-super": true, + "no-empty": false, + "no-empty-interface": true, + "no-eval": true, + "no-inferrable-types": [ + true, + "ignore-params" + ], + "no-misused-new": true, + "no-non-null-assertion": true, + "no-redundant-jsdoc": true, + "no-shadowed-variable": true, + "no-string-literal": false, + "no-string-throw": true, + "no-switch-case-fall-through": true, + "no-trailing-whitespace": true, + "no-unnecessary-initializer": true, + "no-unused-expression": true, + "no-use-before-declare": true, + "no-var-keyword": true, + "object-literal-sort-keys": false, + "one-line": [ + true, + "check-open-brace", + "check-catch", + "check-else", + "check-whitespace" + ], + "prefer-const": true, + "quotemark": [ + true, + "single" + ], + "radix": true, + "semicolon": [ + true, + "always" + ], + "triple-equals": [ + true, + "allow-null-check" + ], + "typedef-whitespace": [ + true, + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + } + ], + "unified-signatures": true, + "variable-name": false, + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type" + ], + "no-output-on-prefix": true, + "use-input-property-decorator": true, + "use-output-property-decorator": true, + "use-host-property-decorator": true, + "no-input-rename": true, + "no-output-rename": true, + "use-life-cycle-interface": true, + "use-pipe-transform-interface": true, + "component-class-suffix": true, + "directive-class-suffix": true + } +} From 8945e286119ae07ede05fe1b1694db33958cf06e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Wed, 17 Oct 2018 23:25:07 +0800 Subject: [PATCH 075/835] 2018.10.17 --- EXEFE-es6book/README.md | 139 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 EXEFE-es6book/README.md diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md new file mode 100644 index 00000000..300a9cb4 --- /dev/null +++ b/EXEFE-es6book/README.md @@ -0,0 +1,139 @@ +**** +- [x] +- [x] Ŀ¼ +- [ ] ES6 +- [ ] ES7 +- [ ] ES8 +- [ ] ES9 +- [ ] ֪ʶ +> 2018.10.17 + +# һ +Ѿиʽ **ECMAScript** 淶Ľܺͷ£׼һݱȽҲȽϾڿŵϡ +ϵ**ES6**οһʦ [ECMAScript6](http://es6.ruanyifeng.com/) ʵõݡ +**ES7/ES8/ES9**ο + +# Ŀ¼ + + +- [һ](#һ) +- [Ŀ¼](#Ŀ¼) +- [](#) + - [1. ES6](#1-es6) + - [let const](#let--const) + - [Ľ⹹ֵ](#Ľ⹹ֵ) + - [ַչ](#ַչ) + - [չ](#չ) + - [ֵչ](#ֵչ) + - [չ](#չ) + - [չ](#չ) + - [2. ES7](#2-es7) + - [3. ES8](#3-es8) + - [4. ES9](#4-es9) + - [5. ֪ʶ](#5-֪ʶ) + - [鼶](#鼶) +- [ġ](#Ľ) + + + +# +## 1. ES6 + +### let const +ES6Уͨʵ `let` ʾ****`const` ʾ**** `let` `const` **鼶**ڵǰЧظ +* **ڱ** +ES6֮ǰ `var` һ****һ****ű⣬ʵʿ̾һЩ߼ϵɻ󣬰һ˼άϰߣҪʹá +```js +// var +console.log(v1); // undefined +var v1 = 2; +// ڱ ʵ +var v1; +console.log(v1) +v1 = 2; + +// let +console.log(v2); // ReferenceError +let v2 = 2; +``` + +* **ظ** +`let` `const` ͬ£**ظͬһ****ں** +```js +// 1. ظͬһ +// +function f1 (){ + let a = 1; + var a = 2; +} +// +function f2 (){ + let a = 1; + let a = 2; +} + +// 2. ں +// +function f3 (a1){ + let a1; +} +// +function f4 (a2){ + { + let a2 + } +} +``` + + +### Ľ⹹ֵ +### ַչ +### չ +### ֵչ +### չ +### չ + +## 2. ES7 + +## 3. ES8 + +## 4. ES9 + +## 5. ֪ʶ +### 鼶 + +ָͨһ**ڲ**һ**ڲ** +磺 +```js +function fun1 () { + // 鼶 + if (true) { + // 鼶 + } +} +``` +**ȱ** +1.ڲ +```js +var a1 = new Date(); +function f1 (){ + console.log(a1); // undefined + if (false) { + var a1 = 'hello' + } +} +``` + `undefined` Ϊ `if` ڵ `a1` ıڲ `a1` ⲿ `a1`Ϊ `undefined` + +2.ȫȾ +```js +var a = 'hello'; +for (var i = 0; i< a.length; i++) { + //... +} +console.log(i); // 5 +``` +ѭ󣬱 `i` ֵȻڣɱȫȾ + + +# ġ \ No newline at end of file From 28244b41a9fa799cba993089afc8a2624b93cd94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Wed, 17 Oct 2018 23:27:08 +0800 Subject: [PATCH 076/835] 2018.10.17 --- EXEFE-es6book/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 300a9cb4..810d7203 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -7,6 +7,7 @@ - [ ] ES9 - [ ] ֪ʶ > 2018.10.17 +> Ҳ˼һϣÿˣջ # һ Ѿиʽ **ECMAScript** 淶Ľܺͷ£׼һݱȽҲȽϾڿŵϡ From f39cd575edfcd5c3279c2d378f4c067422206a23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Thu, 18 Oct 2018 23:04:40 +0800 Subject: [PATCH 077/835] 2018.10.18 --- EXEFE-es6book/README.md | 279 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 278 insertions(+), 1 deletion(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 810d7203..6d3d49a8 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -22,7 +22,15 @@ - [](#) - [1. ES6](#1-es6) - [let const](#let--const) + - [let ](#let-) + - [2.const ](#2const-) - [Ľ⹹ֵ](#Ľ⹹ֵ) + - [1.](#1) + - [2.Ľ⹹ֵ](#2Ľ⹹ֵ) + - [3.ַĽ⹹ֵ](#3ַĽ⹹ֵ) + - [4.ֵͲֵĽ⹹ֵ](#4ֵͲֵĽ⹹ֵ) + - [5.Ľ⹹ֵ](#5Ľ⹹ֵ) + - [6.;](#6;) - [ַչ](#ַչ) - [չ](#չ) - [ֵչ](#ֵչ) @@ -41,7 +49,21 @@ ## 1. ES6 ### let const -ES6Уͨʵ `let` ʾ****`const` ʾ**** `let` `const` **鼶**ڵǰЧظ + +ES6Уͨʵ `let` ʾ****`const` ʾ**** `let` `const` **鼶****ǰЧ**ظ + +#### let +`let` ÷ `var` ƣ `let` ֻڴЧ +÷ +```js +{ + let a = 1; + let b = 2; +} +``` + + `let` ص㣺 + * **ڱ** ES6֮ǰ `var` һ****һ****ű⣬ʵʿ̾һЩ߼ϵɻ󣬰һ˼άϰߣҪʹá ```js @@ -86,8 +108,263 @@ function f4 (a2){ } ``` +#### 2.const +`const` һ**ֻ****** +÷ +```js +const PI = 3.1415926; +console.log(PI); // 3.1415926 + +``` +**ע** +* `const` ޷޸ֵ +```js +const PI = 3.1415926; +PI = 3; +// TypeError: Assignment to constant variable. +``` +* `const` ʱ븳ֵ +```js +const a ; +// SyntaxError: Missing initializer in const declaration. +``` +* `const` ij`let` ظ +```js +const PI = 3.1415926; +let PI = 0; +// Uncaught SyntaxError: Identifier 'PI' has already been declared +``` + ### Ľ⹹ֵ +**⹹ֵ**ES6УֱӴͶȡֵնӦλãֵIJ + +#### 1. +÷ +```js +// ES6 ֮ǰ +let a = 1; +let b = 2; + +// ES6 ֮ +let [a, b] = [1, 2]; +``` + +ϣֻҪȺģʽһ£߱ɻȡұ߶Ӧλõֵ÷ + +```js +let [a, [[b], c]] = [1, [[2], 3]]; +console.log(a, b, c); // 1, 2, 3 + +let [ , , c] = [1, 2, 3]; +console.log(c); // 3 + +let [a, , c] = [1, 2, 3]; +console.log(a,c); // 1, 3 + +let [a, ...b] = [1, 2, 3]; +console.log(a,b); // 1, [2,3] + +let [a, b, ..c.] = [1]; +console.log(a, b, c); // 1, undefined, [] +``` + +**ע** +* ⹹ɹֵ͵`undefined` +```js +let [a] = []; // a => undefined +let [a, b] = [1]; // a => 1 , b => undefined +``` +* ģʽұߣҲԽ⹹ɹ +```js +let [a, b] = [1, 2, 3]; +console.log(a, b); // 1, 2 +``` +* ģʽͬ +```js +let [a] = 1; +let [a] = false; +let [a] = NaN; +let [a] = undefined; +let [a] = null; +let [a] = {}; +``` + +**ָ⹹Ĭֵ** +÷ +```js +let [a = 1] = []; // a => 1 +let [a, b = 2] = [a]; // a => 1 , b => 2 +``` + +```js +let [a = 1] = [undefined]; // a => 1 +let [a = 1] = [null]; // a => null +``` +ұģʽӦֵϸ`undefined`ĬֵЧ`null`ϸ`undefined` + +#### 2.Ľ⹹ֵ +⹹ͬǣ⹹**Ҫϸ˳ȡֵ**ֻҪ****ȥȡӦ****ֵȡӦ****ֵΪ`undefined` + +÷ +```js +let {a, b} = {a:1, b:2}; // a => 1 , b => 2 +let {a, b} = {a:2, b:1}; // a => 2 , b => 1 +let {a} = {a:3, b:2, c:1};// a => 3 +let {a} = {b:2, c:1}; // a => undefined +``` + +**ע** +* ********һ£Ҫ޸ơ +```js +let {a:b} = {a:1, c:2}; +// error: a is not defined +// b => 1 +``` +Ľ⹹ֵڲƣҵͬԣȻٸӦıֵǺߣǰߡ +У`a` ƥģʽ`b`DZֵDZ`b`ģʽ`a` + +* ⹹Ҳ֧**Ƕ׽⹹** +```js +let obj = { + a:[ 1, { b: 2}] +}; +let {a, a: [c, {b}]} = obj; +// a=>[1, {b: 2}], b => 2, c => 1 +``` + +**ָ⹹Ĭֵ** +```js +let {a=1} = {}; // a => 1 +let {a, b=1} = {a:2}; // a => 2, b => 1 + +let {a:b=3} = {}; // b => 3 +let {a:b=3} = {a:4}; // b = >4 +// aģʽbDZ μ + +let {a=1} = {a:undefined}; // a => 1 +let {a=1} = {a:null}; // a => null +// ΪnullundefinedϸȣԸֵЧ +// Ĭֵ1Ч +``` + +#### 3.ַĽ⹹ֵ +ַĽ⹹ֵУַתһ**Ķ** +÷ +```js +const [a, b, c, d, e] = 'hello'; +a // "h" +b // "e" +c // "l" +d // "l" +e // "o" + +let {length:len} = 'hello';// len => 5 +``` + +#### 4.ֵͲֵĽ⹹ֵ +⹹ֵĹǣ**ֻҪȺұߵֵǶ飬ȽתΪ**`undefined``null`**޷תΪ**Զǽн⹹ֵᱨ +```js +// ֵͲֵİװtoString +let {toString: s} = 123; +s === Number.prototype.toString // true +let {toString: s} = true; +s === Boolean.prototype.toString // true + +let { prop: x } = undefined; // TypeError +let { prop: y } = null; // TypeError +``` + +#### 5.Ľ⹹ֵ +÷ +```js +function fun ([a, b]){ + return a + b; +} +fun ([1, 2]); // 3 +``` +**ָĬֵĽ⹹**: +```js +function fun ({a=0, b=0} = {}){ + return [a, b]; +} +fun ({a:1, b:2}); // [1, 2] +fun ({a:1}); // [1, 0] +fun ({}); // [0, 0] +fun (); // [0, 0] + +function fun ({a, b} = {a:0, b:0}){ + return [a, b]; +} +fun ({a:1, b:2}); // [1, 2] +fun ({a:1}); // [1, undefined] +fun ({}); // [undefined, undefined] +fun (); // [0, 0] +``` + +#### 6.; +* **ֵ**: +```js +let a = 1,b = 2; +[a, b] = [b, a]; // a =>2 , b => 1 +``` + +* **ضֵ**: +```js +// һ +function f (){ + return [1, 2, 3]; +} +let [a, b, c] = f(); // a=>1, b=>2, c=>3 + +// һ +function f (){ + return {a:1, b:2}; +} +let {a, b} = f(); // a=>1, b=>2 +``` + +* **ٶӦ**: +ٵĽһӦ +```js +function f([a, b, c]) {...} +f([1, 2, 3]); + +function f({a, b, c}) {...} +f({b:2, c:3, a:1}); +``` + +* **ȡJSON** +```js +let json = { + name : 'leo', + age: 18 +} +let {name, age} = json; +console.log(name,age); // leo, 18 +``` + +* **Mapṹ**: +```js +const m = new Map(); +m.set('a':1); +m.set('b':2); +for ([k, v] of m){ + console.log(k + ' : ' + v); +} +// ȡ +for (let [k] of m){...} +// ȡֵ +for (let [,k] of m){...} +``` + +* **ģָ**: +****ģҪõķ +```js +const {log, sin, cos} = require('math'); + +``` + ### ַչ ### չ ### ֵչ From b926f5ce914ae06917e15480b9476b34b602b9ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Thu, 18 Oct 2018 23:06:26 +0800 Subject: [PATCH 078/835] 2018.10.18 --- EXEFE-es6book/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 6d3d49a8..f8759e19 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -6,7 +6,7 @@ - [ ] ES8 - [ ] ES9 - [ ] ֪ʶ -> 2018.10.17 +> 2018.10.18 > Ҳ˼һϣÿˣջ # һ From 086d7b1fdeb645e9aab7450beb3aa03a87e3f424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Thu, 18 Oct 2018 23:07:36 +0800 Subject: [PATCH 079/835] 2018.10.18 --- EXEFE-es6book/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index f8759e19..c325669e 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -23,7 +23,7 @@ - [1. ES6](#1-es6) - [let const](#let--const) - [let ](#let-) - - [2.const ](#2const-) + - [const ](#const-) - [Ľ⹹ֵ](#Ľ⹹ֵ) - [1.](#1) - [2.Ľ⹹ֵ](#2Ľ⹹ֵ) @@ -108,7 +108,7 @@ function f4 (a2){ } ``` -#### 2.const +#### const `const` һ**ֻ****** ÷ ```js From ac9b66776d18630c065e058aee8ef205bcf3e644 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 19 Oct 2018 07:53:09 +0800 Subject: [PATCH 080/835] 2018.10.19 --- EXEFE-es6book/README.md | 80 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 73 insertions(+), 7 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index c325669e..fb128180 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -32,6 +32,9 @@ - [5.Ľ⹹ֵ](#5Ľ⹹ֵ) - [6.;](#6;) - [ַչ](#ַչ) + - [1.includes(),startsWith(),endsWith()](#1includesstartswithendswith) + - [2.repeat()](#2repeat) + - [3.padStart(),padEnd()](#3padstartpadend) - [չ](#չ) - [ֵչ](#ֵչ) - [չ](#չ) @@ -54,7 +57,7 @@ #### let `let` ÷ `var` ƣ `let` ֻڴЧ -÷ +**÷** ```js { let a = 1; @@ -110,7 +113,7 @@ function f4 (a2){ #### const `const` һ**ֻ****** -÷ +**÷** ```js const PI = 3.1415926; console.log(PI); // 3.1415926 @@ -140,7 +143,7 @@ let PI = 0; **⹹ֵ**ES6УֱӴͶȡֵնӦλãֵIJ #### 1. -÷ +**÷** ```js // ES6 ֮ǰ let a = 1; @@ -191,7 +194,7 @@ let [a] = {}; ``` **ָ⹹Ĭֵ** -÷ +**÷** ```js let [a = 1] = []; // a => 1 let [a, b = 2] = [a]; // a => 1 , b => 2 @@ -206,7 +209,7 @@ let [a = 1] = [null]; // a => null #### 2.Ľ⹹ֵ ⹹ͬǣ⹹**Ҫϸ˳ȡֵ**ֻҪ****ȥȡӦ****ֵȡӦ****ֵΪ`undefined` -÷ +**÷** ```js let {a, b} = {a:1, b:2}; // a => 1 , b => 2 let {a, b} = {a:2, b:1}; // a => 2 , b => 1 @@ -250,7 +253,7 @@ let {a=1} = {a:null}; // a => null #### 3.ַĽ⹹ֵ ַĽ⹹ֵУַתһ**Ķ** -÷ +**÷** ```js const [a, b, c, d, e] = 'hello'; a // "h" @@ -276,7 +279,7 @@ let { prop: y } = null; // TypeError ``` #### 5.Ľ⹹ֵ -÷ +**÷** ```js function fun ([a, b]){ return a + b; @@ -366,6 +369,69 @@ const {log, sin, cos} = require('math'); ``` ### ַչ +#### 1.includes(),startsWith(),endsWith() +жַǷһַʱES6֮ǰֻ`typeof`ES6ֶַ֮ +* **includes()**:**ֵ**ʾ**Ƿҵַ** +* **startsWith()**:**ֵ**ʾַǷԭַ**ͷ** +* **endsWith()**:**ֵ**ʾַǷԭַ**β** +```js +let a = 'hello leo'; +a.startsWith('leo'); // false +a.endsWith('o'); // true +a.includes('lo'); // true +``` +ֵ֧ڶʾʼλá +```js +let a = 'hello leo'; +a.startsWith('leo',1); // false +a.endsWith('o',5); // true +a.includes('lo',6); // false +``` +`endsWith` ǰ `n` ַԴӵ`n`λֱ + +#### 2.repeat() +`repeat`һַʾԭַظ`n`Ρ +**÷** +```js +'ab'.repeat(3); // 'ababab' +'ab'.repeat(0); // '' +``` +**÷**: +* Ϊ`С`ȡ +```js +'ab'.repeat(2.3); // 'abab' +``` +* Ϊ```Infinity`򱨴 +```js +'ab'.repeat(-1); // RangeError +'ab'.repeat(Infinity); // RangeError +``` +* Ϊ`0-1С``NaN`ȡ0 +```js +'ab'.repeat(-0.5); // '' +'ab'.repeat(NaN); // '' +``` +* Ϊ`ַ`ת`` +```js +'ab'.repeat('ab'); // '' +'ab'.repeat('3'); // 'ababab' +``` + +#### 3.padStart(),padEnd() +ڽַ**ͷ****β**ȫȣ`padStart()`Ϊ**ͷȫ**`padEnd()`Ϊ**βȫ** +**2**һָ**ַС**ڶ**ڲȫַ** +**÷** +```js +'x'.padStart(5, 'ab') // 'ababx' +'x'.padEnd(5, 'ab') // 'xabab' +``` +**÷**: +* ԭַȣڻָСȣ򷵻ԭַ +```js +'xyzabc'.padStart(5, 'ab') // 'xyzabc' +``` + + ### չ ### ֵչ ### չ From ec7d7fac8a2451102619766a93b2754ef94f69bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 19 Oct 2018 08:05:27 +0800 Subject: [PATCH 081/835] 2018.10.19 --- EXEFE-es6book/README.md | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index fb128180..85f11b33 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -35,6 +35,7 @@ - [1.includes(),startsWith(),endsWith()](#1includesstartswithendswith) - [2.repeat()](#2repeat) - [3.padStart(),padEnd()](#3padstartpadend) + - [4.ģַ](#4ģַ) - [չ](#չ) - [ֵչ](#ֵչ) - [չ](#չ) @@ -422,15 +423,47 @@ a.includes('lo',6); // false **2**һָ**ַС**ڶ**ڲȫַ** **÷** ```js -'x'.padStart(5, 'ab') // 'ababx' -'x'.padEnd(5, 'ab') // 'xabab' +'x'.padStart(5, 'ab'); // 'ababx' +'x'.padEnd(5, 'ab'); // 'xabab' ``` **÷**: * ԭַȣڻָСȣ򷵻ԭַ ```js -'xyzabc'.padStart(5, 'ab') // 'xyzabc' +'xyzabc'.padStart(5, 'ab'); // 'xyzabc' ``` +* ȫַȺԭַָ֮ͣСȣȥֵIJȫַ +```js +'ab'.padStart(5,'012345'); // "012ab" +``` +* ʡԵڶ`ո`ȫ +```js +'x'.padStart(4); // ' x' +'x'.endStart(4); // 'x ' +``` +#### 4.ģַ +ƴַES6֮ǰ +```js +let a = 'abc' + + 'def' + + 'ghi'; +``` +ES6֮ +```js +let a = ` + abc + def + ghi +` +``` +**ƴӱ**: +**(\`)**ʹ`${}`򷽷 +```js +// ES6֮ǰ +let a = 'abc' + v1 + 'def'; +// ES6֮ +let a = `abc${v1}def` +``` ### չ ### ֵչ From f48652512938b25c7eea6cf7c371682c8fdce95c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sun, 21 Oct 2018 10:44:31 +0800 Subject: [PATCH 082/835] 2018.10.21 --- EXEFE-es6book/README.md | 430 +++++++++++++++++++++++++++++++++------- 1 file changed, 355 insertions(+), 75 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 85f11b33..77f40bcc 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -1,18 +1,18 @@ -**** -- [x] -- [x] Ŀ¼ -- [ ] ES6 -- [ ] ES7 -- [ ] ES8 -- [ ] ES9 -- [ ] ֪ʶ -> 2018.10.18 -> Ҳ˼һϣÿˣջ +**** +- [x] +- [x] Ŀ¼ +- [ ] ES6 +- [ ] ES7 +- [ ] ES8 +- [ ] ES9 +- [ ] ֪ʶ +> 2018.10.18 +> Ҳ˼һϣÿˣջ # һ -Ѿиʽ **ECMAScript** 淶Ľܺͷ£׼һݱȽҲȽϾڿŵϡ -ϵ**ES6**οһʦ [ECMAScript6](http://es6.ruanyifeng.com/) ʵõݡ -**ES7/ES8/ES9**ο +Ѿиʽ **ECMAScript** 淶Ľܺͷ£׼һݱȽҲȽϾڿŵϡ +ϵ**ES6**οһʦ [ECMAScript6](http://es6.ruanyifeng.com/) ʵõݡ +**ES7/ES8/ES9**ο # Ŀ¼ @@ -38,6 +38,11 @@ - [4.ģַ](#4ģַ) - [չ](#չ) - [ֵչ](#ֵչ) + - [1.Number.isFinite(), Number.isNaN()](#1numberisfinite-numberisnan) + - [2.Number.parseInt(), Number.parseFloat()](#2numberparseint-numberparsefloat) + - [3.Number.isInteger()](#3numberisinteger) + - [4.Mathչ](#4mathչ) + - [5.ָ](#5ָ) - [չ](#չ) - [չ](#չ) - [2. ES7](#2-es7) @@ -58,7 +63,7 @@ #### let `let` ÷ `var` ƣ `let` ֻڴЧ -**÷** +**÷** ```js { let a = 1; @@ -68,7 +73,7 @@ `let` ص㣺 -* **ڱ** +* **ڱ** ES6֮ǰ `var` һ****һ****ű⣬ʵʿ̾һЩ߼ϵɻ󣬰һ˼άϰߣҪʹá ```js // var @@ -84,7 +89,7 @@ console.log(v2); // ReferenceError let v2 = 2; ``` -* **ظ** +* **ظ** `let` `const` ͬ£**ظͬһ****ں** ```js // 1. ظͬһ @@ -120,19 +125,19 @@ const PI = 3.1415926; console.log(PI); // 3.1415926 ``` -**ע** -* `const` ޷޸ֵ +**ע** +* `const` ޷޸ֵ ```js const PI = 3.1415926; PI = 3; // TypeError: Assignment to constant variable. ``` -* `const` ʱ븳ֵ +* `const` ʱ븳ֵ ```js const a ; // SyntaxError: Missing initializer in const declaration. ``` -* `const` ij`let` ظ +* `const` ij`let` ظ ```js const PI = 3.1415926; let PI = 0; @@ -141,10 +146,10 @@ let PI = 0; ### Ľ⹹ֵ -**⹹ֵ**ES6УֱӴͶȡֵնӦλãֵIJ +**⹹ֵ**ES6УֱӴͶȡֵնӦλãֵIJ -#### 1. -**÷** +#### 1. +**÷** ```js // ES6 ֮ǰ let a = 1; @@ -154,7 +159,7 @@ let b = 2; let [a, b] = [1, 2]; ``` -ϣֻҪȺģʽһ£߱ɻȡұ߶Ӧλõֵ÷ +ϣֻҪȺģʽһ£߱ɻȡұ߶Ӧλõֵ÷ ```js let [a, [[b], c]] = [1, [[2], 3]]; @@ -173,18 +178,18 @@ let [a, b, ..c.] = [1]; console.log(a, b, c); // 1, undefined, [] ``` -**ע** -* ⹹ɹֵ͵`undefined` +**ע** +* ⹹ɹֵ͵`undefined` ```js let [a] = []; // a => undefined let [a, b] = [1]; // a => 1 , b => undefined ``` -* ģʽұߣҲԽ⹹ɹ +* ģʽұߣҲԽ⹹ɹ ```js let [a, b] = [1, 2, 3]; console.log(a, b); // 1, 2 ``` -* ģʽͬ +* ģʽͬ ```js let [a] = 1; let [a] = false; @@ -194,23 +199,23 @@ let [a] = null; let [a] = {}; ``` -**ָ⹹Ĭֵ** -**÷** +**ָ⹹Ĭֵ** +**÷** ```js let [a = 1] = []; // a => 1 let [a, b = 2] = [a]; // a => 1 , b => 2 ``` - + ```js let [a = 1] = [undefined]; // a => 1 let [a = 1] = [null]; // a => null ``` -ұģʽӦֵϸ`undefined`ĬֵЧ`null`ϸ`undefined` +ұģʽӦֵϸ`undefined`ĬֵЧ`null`ϸ`undefined` #### 2.Ľ⹹ֵ -⹹ͬǣ⹹**Ҫϸ˳ȡֵ**ֻҪ****ȥȡӦ****ֵȡӦ****ֵΪ`undefined` +⹹ͬǣ⹹**Ҫϸ˳ȡֵ**ֻҪ****ȥȡӦ****ֵȡӦ****ֵΪ`undefined` -**÷** +**÷** ```js let {a, b} = {a:1, b:2}; // a => 1 , b => 2 let {a, b} = {a:2, b:1}; // a => 2 , b => 1 @@ -218,17 +223,17 @@ let {a} = {a:3, b:2, c:1};// a => 3 let {a} = {b:2, c:1}; // a => undefined ``` -**ע** +**ע** * ********һ£Ҫ޸ơ ```js let {a:b} = {a:1, c:2}; // error: a is not defined // b => 1 ``` -Ľ⹹ֵڲƣҵͬԣȻٸӦıֵǺߣǰߡ -У`a` ƥģʽ`b`DZֵDZ`b`ģʽ`a` +Ľ⹹ֵڲƣҵͬԣȻٸӦıֵǺߣǰߡ +У`a` ƥģʽ`b`DZֵDZ`b`ģʽ`a` -* ⹹Ҳ֧**Ƕ׽⹹** +* ⹹Ҳ֧**Ƕ׽⹹** ```js let obj = { a:[ 1, { b: 2}] @@ -237,7 +242,7 @@ let {a, a: [c, {b}]} = obj; // a=>[1, {b: 2}], b => 2, c => 1 ``` -**ָ⹹Ĭֵ** +**ָ⹹Ĭֵ** ```js let {a=1} = {}; // a => 1 let {a, b=1} = {a:2}; // a => 2, b => 1 @@ -253,8 +258,8 @@ let {a=1} = {a:null}; // a => null ``` #### 3.ַĽ⹹ֵ -ַĽ⹹ֵУַתһ**Ķ** -**÷** +ַĽ⹹ֵУַתһ**Ķ** +**÷** ```js const [a, b, c, d, e] = 'hello'; a // "h" @@ -267,7 +272,7 @@ let {length:len} = 'hello';// len => 5 ``` #### 4.ֵͲֵĽ⹹ֵ -⹹ֵĹǣ**ֻҪȺұߵֵǶ飬ȽתΪ**`undefined``null`**޷תΪ**Զǽн⹹ֵᱨ +⹹ֵĹǣ**ֻҪȺұߵֵǶ飬ȽתΪ**`undefined``null`**޷תΪ**Զǽн⹹ֵᱨ ```js // ֵͲֵİװtoString let {toString: s} = 123; @@ -280,14 +285,14 @@ let { prop: y } = null; // TypeError ``` #### 5.Ľ⹹ֵ -**÷** +**÷** ```js function fun ([a, b]){ return a + b; } fun ([1, 2]); // 3 ``` -**ָĬֵĽ⹹**: +**ָĬֵĽ⹹**: ```js function fun ({a=0, b=0} = {}){ return [a, b]; @@ -307,13 +312,13 @@ fun (); // [0, 0] ``` #### 6.; -* **ֵ**: +* **ֵ**: ```js let a = 1,b = 2; [a, b] = [b, a]; // a =>2 , b => 1 ``` -* **ضֵ**: +* **ضֵ**: ```js // һ function f (){ @@ -328,8 +333,8 @@ function f (){ let {a, b} = f(); // a=>1, b=>2 ``` -* **ٶӦ**: -ٵĽһӦ +* **ٶӦ**: +ٵĽһӦ ```js function f([a, b, c]) {...} f([1, 2, 3]); @@ -338,7 +343,7 @@ function f({a, b, c}) {...} f({b:2, c:3, a:1}); ``` -* **ȡJSON** +* **ȡJSON** ```js let json = { name : 'leo', @@ -348,7 +353,7 @@ let {name, age} = json; console.log(name,age); // leo, 18 ``` -* **Mapṹ**: +* **Mapṹ**: ```js const m = new Map(); m.set('a':1); @@ -362,8 +367,8 @@ for (let [k] of m){...} for (let [,k] of m){...} ``` -* **ģָ**: -****ģҪõķ +* **ģָ**: +****ģҪõķ ```js const {log, sin, cos} = require('math'); @@ -371,83 +376,83 @@ const {log, sin, cos} = require('math'); ### ַչ #### 1.includes(),startsWith(),endsWith() -жַǷһַʱES6֮ǰֻ`typeof`ES6ֶַ֮ -* **includes()**:**ֵ**ʾ**Ƿҵַ** -* **startsWith()**:**ֵ**ʾַǷԭַ**ͷ** -* **endsWith()**:**ֵ**ʾַǷԭַ**β** +жַǷһַʱES6֮ǰֻ`typeof`ES6ֶַ֮ +* **includes()**:**ֵ**ʾ**Ƿҵַ** +* **startsWith()**:**ֵ**ʾַǷԭַ**ͷ** +* **endsWith()**:**ֵ**ʾַǷԭַ**β** ```js let a = 'hello leo'; a.startsWith('leo'); // false a.endsWith('o'); // true a.includes('lo'); // true ``` -ֵ֧ڶʾʼλá +ֵ֧ڶʾʼλá ```js let a = 'hello leo'; a.startsWith('leo',1); // false a.endsWith('o',5); // true a.includes('lo',6); // false ``` -`endsWith` ǰ `n` ַԴӵ`n`λֱ +`endsWith` ǰ `n` ַԴӵ`n`λֱ #### 2.repeat() -`repeat`һַʾԭַظ`n`Ρ -**÷** +`repeat`һַʾԭַظ`n`Ρ +**÷** ```js 'ab'.repeat(3); // 'ababab' 'ab'.repeat(0); // '' ``` -**÷**: -* Ϊ`С`ȡ +**÷**: +* Ϊ`С`ȡ ```js 'ab'.repeat(2.3); // 'abab' ``` -* Ϊ```Infinity`򱨴 +* Ϊ```Infinity`򱨴 ```js 'ab'.repeat(-1); // RangeError 'ab'.repeat(Infinity); // RangeError ``` -* Ϊ`0-1С``NaN`ȡ0 +* Ϊ`0-1С``NaN`ȡ0 ```js 'ab'.repeat(-0.5); // '' 'ab'.repeat(NaN); // '' ``` -* Ϊ`ַ`ת`` +* Ϊ`ַ`ת`` ```js 'ab'.repeat('ab'); // '' 'ab'.repeat('3'); // 'ababab' ``` #### 3.padStart(),padEnd() -ڽַ**ͷ****β**ȫȣ`padStart()`Ϊ**ͷȫ**`padEnd()`Ϊ**βȫ** -**2**һָ**ַС**ڶ**ڲȫַ** -**÷** +ڽַ**ͷ****β**ȫȣ`padStart()`Ϊ**ͷȫ**`padEnd()`Ϊ**βȫ** +**2**һָ**ַС**ڶ**ڲȫַ** +**÷** ```js 'x'.padStart(5, 'ab'); // 'ababx' 'x'.padEnd(5, 'ab'); // 'xabab' ``` -**÷**: -* ԭַȣڻָСȣ򷵻ԭַ +**÷**: +* ԭַȣڻָСȣ򷵻ԭַ ```js 'xyzabc'.padStart(5, 'ab'); // 'xyzabc' ``` -* ȫַȺԭַָ֮ͣСȣȥֵIJȫַ +* ȫַȺԭַָ֮ͣСȣȥֵIJȫַ ```js 'ab'.padStart(5,'012345'); // "012ab" ``` -* ʡԵڶ`ո`ȫ +* ʡԵڶ`ո`ȫ ```js 'x'.padStart(4); // ' x' 'x'.endStart(4); // 'x ' ``` #### 4.ģַ -ƴַES6֮ǰ +ƴַES6֮ǰ ```js let a = 'abc' + 'def' + 'ghi'; ``` -ES6֮ +ES6֮ ```js let a = ` abc @@ -456,7 +461,7 @@ let a = ` ` ``` **ƴӱ**: -**(\`)**ʹ`${}`򷽷 +**(\`)**ʹ`${}`򷽷 ```js // ES6֮ǰ let a = 'abc' + v1 + 'def'; @@ -466,7 +471,282 @@ let a = `abc${v1}def` ``` ### չ + ### ֵչ +#### 1.Number.isFinite(), Number.isNaN() +`Number.isFinite()` ڼһֵǷ޵ģ`Infinity``Number`ͣһɷ`false` +```js +Number.isFinite(10); // true +Number.isFinite(0.5); // true +Number.isFinite(NaN); // false +Number.isFinite(Infinity); // false +Number.isFinite(-Infinity); // false +Number.isFinite('leo'); // false +Number.isFinite('15'); // false +Number.isFinite(true); // false +Number.isFinite(Math.random()); // true +``` + +`Number.isNaN()`ڼǷ`NaN``NaN`һɷ`false` +```js +Number.isNaN(NaN); // true +Number.isNaN(10); // false +Number.isNaN('10'); // false +Number.isNaN(true); // false +Number.isNaN(5/NaN); // true +Number.isNaN('true' / 0); // true +Number.isNaN('true' / 'true'); // true +``` + +**** +봫ͳȫֵ`isFinite()``isNaN()`𣬴ͳȽת**ֵ**жϡ +ES6ֻ**ֵ**Ч `Number.isFinite()`**ֵ**һɷ`false`,` Number.isNaN()`ֻж`NaN`ŷ`true`һɷ`false` +```js +isFinite(25); // true +isFinite("25"); // true +Number.isFinite(25); // true +Number.isFinite("25"); // false + +isNaN(NaN); // true +isNaN("NaN"); // true +Number.isNaN(NaN); // true +Number.isNaN("NaN"); // false +``` + +#### 2.Number.parseInt(), Number.parseFloat() +ȫַ`parseInt()``parseFloat()`һ£Ŀ**ȫԵķ****Ըģ黯** +```js +parseInt('12.34'); // 12 +parseFloat('123.45#'); // 123.45 + +Number.parseInt('12.34'); // 12 +Number.parseFloat('123.45#'); // 123.45 + +Number.parseInt === parseInt; // true +Number.parseFloat === parseFloat; // true +``` + +#### 3.Number.isInteger() +жһֵǷֵ򷵻`false` +```js +Number.isInteger(10); // true +Number.isInteger(10.0); // true +Number.isInteger(10.1); // false +``` + +#### 4.Mathչ +ES617ѧص**̬**ֻ**Math**ϵá +* **Math.trunc**: +ȥСС֣**** +Ϊ**ֵ****תΪֵ** +Ϊ**ֵ****޷ȡֵ**򷵻**NaN** +```js +// ʹ +Math.trunc(1.1); // 1 +Math.trunc(1.9); // 1 +Math.trunc(-1.1); // -1 +Math.trunc(-1.9); // -1 +Math.trunc(-0.1234); // -0 + +// Ϊֵ +Math.trunc('11.22'); // 11 +Math.trunc(true); // 1 +Math.trunc(false); // 0 +Math.trunc(null); // 0 + +// Ϊպ޷ȡ +Math.trunc(NaN); // NaN +Math.trunc('leo'); // NaN +Math.trunc(); // NaN +Math.trunc(undefined); // NaN +``` +**ES5ʵ** +```js +Math.trunc = Math.trunc || function(x){ + return x < 0 ? Math.ceil(x) : Math.floor(x); +} +``` + +* **Math.sign()**: +жһ************ڷֵת**ֵ** +ֵ +> Ϊ +1 +> Ϊ -1 +> Ϊ0 0 +> Ϊ-0 -0 +> Ϊֵ NaN +```js +Math.sign(-1); // -1 +Math.sign(1); // +1 +Math.sign(0); // 0 +Math.sign(-0); // -0 +Math.sign(NaN); // NaN + +Math.sign(''); // 0 +Math.sign(true); // +1 +Math.sign(false);// 0 +Math.sign(null); // 0 +Math.sign('9'); // +1 +Math.sign('leo');// NaN +Math.sign(); // NaN +Math.sign(undefined); // NaN +``` + +**ES5ʵ** +```js +Math.sign = Math.sign || function (x){ + x = +x; + if (x === 0 || isNaN(x)){ + return x; + } + return x > 0 ? 1: -1; +} +``` + +* **Math.cbrt()**: +һΪֵתֵ +```js +Math.cbrt(-1); // -1 +Math.cbrt(0); // 0 +Math.cbrt(1); // 1 +Math.cbrt(2); // 1.2599210498 + +Math.cbrt('1'); // 1 +Math.cbrt('leo'); // NaN +``` +**ES5ʵ** +```js +Math.cbrt = Math.cbrt || function (x){ + var a = Math.pow(Math.abs(x), 1/3); + return x < 0 ? -y : y; +} +``` + +* **Math.clz32()**: +ڷһ 32 λ޷ʽжٸǰ 0 +```js +Math.clz32(0) // 32 +Math.clz32(1) // 31 +Math.clz32(1000) // 22 +Math.clz32(0b01000000000000000000000000000000) // 1 +Math.clz32(0b00100000000000000000000000000000) // 2 +``` + +* **Math.imul()**: +ڷ 32 λʽ˵ĽصҲһ 32 λĴ +```js +Math.imul(2, 4) // 8 +Math.imul(-1, 8) // -8 +Math.imul(-2, -2) // 4 +``` + +* **Math.fround()**: +һ**2λȸ**ʽ +```js +Math.fround(0) // 0 +Math.fround(1) // 1 +Math.fround(2 ** 24 - 1) // 16777215 +``` + +* **Math.hypot()**: +вƽ͵**ƽ** +```js +Math.hypot(3, 4); // 5 +Math.hypot(3, 4, 5); // 7.0710678118654755 +Math.hypot(); // 0 +Math.hypot(NaN); // NaN +Math.hypot(3, 4, 'foo'); // NaN +Math.hypot(3, 4, '5'); // 7.0710678118654755 +Math.hypot(-3); // 3 +``` + +* **Math.expm1()**: +` ex - 1``Math.exp(x) - 1` +```js +Math.expm1(-1) // -0.6321205588285577 +Math.expm1(0) // 0 +Math.expm1(1) // 1.718281828459045 +``` +**ES5ʵ** +```js +Math.expm1 = Math.expm1 || function(x) { + return Math.exp(x) - 1; +}; +``` + +* **Math.log1p()**: +`1 + x`Ȼ`Math.log(1 + x)`xС`-1``NaN` +```js +Math.log1p(1) // 0.6931471805599453 +Math.log1p(0) // 0 +Math.log1p(-1) // -Infinity +Math.log1p(-2) // NaN +``` +**ES5ʵ** +```js +Math.log1p = Math.log1p || function(x) { + return Math.log(1 + x); +}; +``` + +* **Math.log10()**: + `10 `Ϊ׵`xĶ`xС 0򷵻 `NaN` +```js +Math.log10(2) // 0.3010299956639812 +Math.log10(1) // 0 +Math.log10(0) // -Infinity +Math.log10(-2) // NaN +Math.log10(100000) // 5 +``` +**ES5ʵ** +```js +Math.log10 = Math.log10 || function(x) { + return Math.log(x) / Math.LN10; +}; +``` + +* **Math.log2()**: + `2` Ϊ׵`xĶ``x`С` 0`򷵻 `NaN` +```js +Math.log2(3) // 1.584962500721156 +Math.log2(2) // 1 +Math.log2(1) // 0 +Math.log2(0) // -Infinity +Math.log2(-2) // NaN +Math.log2(1024) // 10 +Math.log2(1 << 29) // 29 +``` +**ES5ʵ** +```js +Math.log2 = Math.log2 || function(x) { + return Math.log(x) / Math.LN2; +}; +``` +* **˫**: +>`Math.sinh(x)` x**˫**hyperbolic sine +>`Math.cosh(x)` x**˫**hyperbolic cosine +>`Math.tanh(x)` x**˫**hyperbolic tangent +>`Math.asinh(x)` x**˫**inverse hyperbolic sine +>`Math.acosh(x)` x**˫**inverse hyperbolic cosine +>`Math.atanh(x)` x**˫**inverse hyperbolic tangent + +#### 5.ָ +ָ(`**`): +```js +2 ** 2; // 4 +2 ** 3; // 8 + +2 ** 3 ** 2; // ൱ 2 ** (3 ** 2); 512 +``` +ָ(`**`)`Math.pow`ʵֲͬر߻ϸ΢IJ졣 +```js +Math.pow(99, 99) +// 3.697296376497263e+197 + +99 ** 99 +// 3.697296376497268e+197 +``` + ### չ ### չ From 5f22746f44b11713109c6c8e221b895747381873 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sun, 21 Oct 2018 14:13:12 +0800 Subject: [PATCH 083/835] 2018.10.21 --- EXEFE-es6book/README.md | 236 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 229 insertions(+), 7 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 77f40bcc..ee1cd75f 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -6,7 +6,7 @@ - [ ] ES8 - [ ] ES9 - [ ] ֪ʶ -> 2018.10.18 +> 2018.10.21 > Ҳ˼һϣÿˣջ # һ @@ -44,6 +44,11 @@ - [4.Mathչ](#4mathչ) - [5.ָ](#5ָ) - [չ](#չ) + - [1.Ĭֵ](#1Ĭֵ) + - [2.rest ](#2rest-) + - [3.name ](#3name-) + - [3.ͷ](#3ͷ) + - [4.˫ð](#4˫ð) - [չ](#չ) - [2. ES7](#2-es7) - [3. ES8](#3-es8) @@ -723,12 +728,12 @@ Math.log2 = Math.log2 || function(x) { }; ``` * **˫**: ->`Math.sinh(x)` x**˫**hyperbolic sine ->`Math.cosh(x)` x**˫**hyperbolic cosine ->`Math.tanh(x)` x**˫**hyperbolic tangent ->`Math.asinh(x)` x**˫**inverse hyperbolic sine ->`Math.acosh(x)` x**˫**inverse hyperbolic cosine ->`Math.atanh(x)` x**˫**inverse hyperbolic tangent +>`Math.sinh(x)` x**˫**hyperbolic sine +>`Math.cosh(x)` x**˫**hyperbolic cosine +>`Math.tanh(x)` x**˫**hyperbolic tangent +>`Math.asinh(x)` x**˫**inverse hyperbolic sine +>`Math.acosh(x)` x**˫**inverse hyperbolic cosine +>`Math.atanh(x)` x**˫**inverse hyperbolic tangent #### 5.ָ ָ(`**`): @@ -748,6 +753,223 @@ Math.pow(99, 99) ``` ### չ +#### 1.Ĭֵ +```js +// ES6 ֮ǰ +function f(a, b){ + b = b || 'leo'; + console.log(a, b); +} + +// ES6 ֮ +function f(a, b='leo'){ + console.log(a, b); +} + +f('hi'); // hi leo +f('hi', 'jack'); // hi jack +f('hi', ''); // hi leo +``` +**ע**: +* Ĭģ`let``const`ٴ +```js +function f (a = 1){ + let a = 2; // error +} +``` +* ʹòĬֵʱͬ +```js +function f (a, a, b){ ... }; // +function f (a, a, b = 1){ ... }; // +``` + +**⹹ֵĬֵʹ** +```js +function f ({a, b=1}){ + console.log(a,b) +}; +f({}); // undefined 1 +f({a:2}); // 2 1 +f({a:2, b:3}); // 2 3 +f(); // + +function f ({a, b = 1} = {}){ + console.log(a, b) +} +f(); // undefined 1 +``` + +**βĬֵ**: +ͨΪĬֵڹ۲ҷβ޷ʡԡ +```js +function f (a=1,b){ + return [a, b]; +} +f(); // [1, undefined] +f(2); // [2, undefined] +f(,2); // + +f(undefined, 2); // [1, 2] + +function f (a, b=1, c){ + return [a, b, c]; +} +f(); // [undefined, 1, undefined] +f(1); // [1,1,undefined] +f(1, ,2); // +f(1,undefined,2); // [1,1,2] +``` +Ĭֵݲ`undefined`ᴥĬֵ`null`ᴥ +```js +function f (a = 1, b = 2){ + console.log(a, b); +} +f(undefined, null); // 1 null +``` + +**length**: +`length`ԽأûָĬֵIJrest`length`ԡ +```js +function f1 (a){...}; +function f2 (a=1){...}; +function f3 (a, b=2){...}; +function f4 (...a){...}; +function f5 (a,b,...c){...}; + +f1.length; // 1 +f2.length; // 0 +f3.length; // 1 +f4.length; // 0 +f5.length; // 2 +``` + +#### 2.rest +`rest`ʽΪ`...`ֵΪһ飬ڻȡ +```js +function f (a, ...b){ + console.log(a, b); +} +f(1,2,3,4); // 1 [2, 3, 4] +``` +**ע** +* `rest`ֻܷһ򱨴 +```js +function f(a, ...b, c){...}; // +``` +* `length`Բ`rest` +```js +function f1 (a){...}; +function f2 (a,...b){...}; +f1(1); // 1 +f2(1,2); // 1 +``` + +#### 3.name +ڷظúĺ +```js +function f (){...}; +f.name; // f + +const f = function g(){...}; +f.name; // g +``` + +#### 3.ͷ +ʹáͷ(`=>`)庯 +**ʹ** +```js +// 1 +let f = v => v; +// ͬ +let f = function (v){return v}; + +// ж +let f = (v, i) => {return v + i}; +// ͬ +let f = function (v, i){return v + i}; + +// û +let f = () => 1; +// ͬ +let f = function (){return 1}; +``` + +**ͷṹʹ** +```js +// д +function f (p) { + return p.a + ':' + p.b; +} + +// ͷд +let f = ({a, b}) => a + ':' + b; +``` + +**򻯻ص** +```js +// д +[1, 2, 3].map(function (x){ + return x * x; +}) + + +// ͷд +[1, 2, 3].map(x => x * x); +``` + +**ͷrest** +```js +let f = (...n) => n; +f(1, 2, 3); // [1, 2, 3] +``` + +**ע** +* 1.ͷڵ`this`****ָ**ʱڵĶ**ǵʱ +* 2.ͷܵ**캯**`new`򱨴 +* 3.ͷ`arguments`󣬼ʹãʹ`rest`档 +* 4.ͷʹ`yield`**Generator** + +**ó** +* 1.ڶ庯Ҹ÷ڲ`this` +```js +const obj = { + a:9, + b: () => { + this.a --; + } +} +``` +`b`**ͨ**ڲ`this`ָ`obj`Ǽͷ`this`ָ**ȫ**Ԥڽ + +* 2.Ҫ̬`this`ʱ +```js +let b = document.getElementById('myID'); +b.addEventListener('click', ()=>{ + this.classList.toggle('on'); +}) +``` +߰ťᱨΪ`b`ļͷУ`this`ȫֶij**ͨ**`this`ͻָ򱻵İť + +#### 4.˫ð +˫ðʱһ᰸ڽһЩõijϣȡ`call``apply``bind`á +˫ð(`::`)һ****ұһ****ԶߵĶΪĻ(`this`)󶨵ұߺϡ +```js +f::b; +// ͬ +b.bind(f); + +f::b(...arguments); +// ͬ +b.apply(f, arguments); +``` +˫ðΪգұһķڽ÷󶨵öϡ +```js +let f = a::a.b; +// ͬ +let f = ::a.b; +``` + + ### չ ## 2. ES7 From 54f7479d06335d28586d8eec945c23c8c08fb487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sun, 21 Oct 2018 22:35:41 +0800 Subject: [PATCH 084/835] 2018.10.21 --- EXEFE-es6book/README.md | 63 +++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 9 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index ee1cd75f..1920bd72 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -22,8 +22,8 @@ - [](#) - [1. ES6](#1-es6) - [let const](#let--const) - - [let ](#let-) - - [const ](#const-) + - [1.let ](#1let-) + - [2.const ](#2const-) - [Ľ⹹ֵ](#Ľ⹹ֵ) - [1.](#1) - [2.Ľ⹹ֵ](#2Ľ⹹ֵ) @@ -47,9 +47,10 @@ - [1.Ĭֵ](#1Ĭֵ) - [2.rest ](#2rest-) - [3.name ](#3name-) - - [3.ͷ](#3ͷ) - - [4.˫ð](#4˫ð) + - [4.ͷ](#4ͷ) + - [5.˫ð](#5˫ð) - [չ](#չ) + - [1.չ](#1չ) - [2. ES7](#2-es7) - [3. ES8](#3-es8) - [4. ES9](#4-es9) @@ -66,7 +67,7 @@ ES6Уͨʵ `let` ʾ****`const` ʾ**** `let` `const` **鼶****ǰЧ**ظ -#### let +#### 1.let `let` ÷ `var` ƣ `let` ֻڴЧ **÷** ```js @@ -122,7 +123,7 @@ function f4 (a2){ } ``` -#### const +#### 2.const `const` һ**ֻ****** **÷** ```js @@ -874,7 +875,7 @@ const f = function g(){...}; f.name; // g ``` -#### 3.ͷ +#### 4.ͷ ʹáͷ(`=>`)庯 **ʹ** ```js @@ -950,7 +951,7 @@ b.addEventListener('click', ()=>{ ``` ߰ťᱨΪ`b`ļͷУ`this`ȫֶij**ͨ**`this`ͻָ򱻵İť -#### 4.˫ð +#### 5.˫ð ˫ðʱһ᰸ڽһЩõijϣȡ`call``apply``bind`á ˫ð(`::`)һ****ұһ****ԶߵĶΪĻ(`this`)󶨵ұߺϡ ```js @@ -969,8 +970,52 @@ let f = a::a.b; let f = ::a.b; ``` - ### չ +#### 1.չ +չʹ(`...`)`rest`㣬תΪ(`,`)ָIJС +```js +console.log(...[1, 2, 3]); // 1 2 3 +console.log(1, ...[2,3], 4); // 1 2 3 4 +``` +չҪʹںá +```js +function f (a, b){ + console.log(a, b); +} +f(...[1, 2]); // 1 2 + +function g (a, b, c, d, e){ + console.log(a, b, c, d, e); +} +g(0, ...[1, 2], 3, ...[4]); // 0 1 2 3 4 +``` +**չǸ飬򲻲Ч** +```js +[...[], 1]; // 1 +``` + +**apply** +```js +// ES6֮ǰ +function f(a, b, c){...}; +var a = [1, 2, 3]; +f.apply(null, a); + +// ES6֮ +function f(a, b, c){...}; +let a = [1, 2, 3]; +f(...a); + +// ES6֮ǰ +Math.max.apply(null, [3,2,6]); + +// ES6֮ +Math.max(...[3,2,6]); +``` + +**չ** + + ## 2. ES7 From 0c9b7af6f3fd978d872f2ab46bd55828fa84c483 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 22 Oct 2018 18:25:53 +0800 Subject: [PATCH 085/835] =?UTF-8?q?2018.10.22=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E4=B8=8D=E9=80=9A=E9=A1=BA=E8=AF=AD=E5=8F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 552 ++++++++++++++++++++-------------------- 1 file changed, 276 insertions(+), 276 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 1920bd72..44ae880b 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -1,75 +1,75 @@ -**** -- [x] -- [x] Ŀ¼ +**整理进度**: +- [x] 介绍 +- [x] 目录 - [ ] ES6 - [ ] ES7 - [ ] ES8 - [ ] ES9 -- [ ] ֪ʶ -> 2018.10.21 -> Ҳ˼һϣÿˣջ +- [ ] 知识补充 +> 最后更新 2018.10.21 +> 也在思考,如何整理好这一份资料,让看的人,都各有收获。 -# һ -Ѿиʽ **ECMAScript** 淶Ľܺͷ£׼һݱȽҲȽϾڿŵϡ -ϵ**ES6**οһʦ [ECMAScript6](http://es6.ruanyifeng.com/) ʵõݡ -**ES7/ES8/ES9**ο +# 一、介绍 +现如今网络上已经有各式各样关于 **ECMAScript** 规范的介绍和分析的文章,而我准备整理一份比较完善也比较精简便于快速入门的资料。 +这份资料的**ES6部分**将会参考阮一峰老师的 [ECMAScript6入门](http://es6.ruanyifeng.com/) ,精简和整理出快速实用的内容。 +另外**ES7/ES8/ES9**则会从网络参考和整理。 -# Ŀ¼ +# 二、目录 -- [һ](#һ) -- [Ŀ¼](#Ŀ¼) -- [](#) +- [一、介绍](#一介绍) +- [二、目录](#二目录) +- [三、正文](#三正文) - [1. ES6](#1-es6) - - [let const](#let--const) - - [1.let ](#1let-) - - [2.const ](#2const-) - - [Ľ⹹ֵ](#Ľ⹹ֵ) - - [1.](#1) - - [2.Ľ⹹ֵ](#2Ľ⹹ֵ) - - [3.ַĽ⹹ֵ](#3ַĽ⹹ֵ) - - [4.ֵͲֵĽ⹹ֵ](#4ֵͲֵĽ⹹ֵ) - - [5.Ľ⹹ֵ](#5Ľ⹹ֵ) - - [6.;](#6;) - - [ַչ](#ַչ) + - [let 和 const命令](#let-和-const命令) + - [1.let 命令](#1let-命令) + - [2.const 命令](#2const-命令) + - [变量的解构赋值](#变量的解构赋值) + - [1.数组](#1数组) + - [2.对象的解构赋值](#2对象的解构赋值) + - [3.字符串的解构赋值](#3字符串的解构赋值) + - [4.数值和布尔值的解构赋值](#4数值和布尔值的解构赋值) + - [5.函数参数的解构赋值](#5函数参数的解构赋值) + - [6.用途](#6用途) + - [字符串的拓展](#字符串的拓展) - [1.includes(),startsWith(),endsWith()](#1includesstartswithendswith) - [2.repeat()](#2repeat) - [3.padStart(),padEnd()](#3padstartpadend) - - [4.ģַ](#4ģַ) - - [չ](#չ) - - [ֵչ](#ֵչ) + - [4.模版字符串](#4模版字符串) + - [正则的拓展](#正则的拓展) + - [数值的拓展](#数值的拓展) - [1.Number.isFinite(), Number.isNaN()](#1numberisfinite-numberisnan) - [2.Number.parseInt(), Number.parseFloat()](#2numberparseint-numberparsefloat) - [3.Number.isInteger()](#3numberisinteger) - - [4.Mathչ](#4mathչ) - - [5.ָ](#5ָ) - - [չ](#չ) - - [1.Ĭֵ](#1Ĭֵ) - - [2.rest ](#2rest-) - - [3.name ](#3name-) - - [4.ͷ](#4ͷ) - - [5.˫ð](#5˫ð) - - [չ](#չ) - - [1.չ](#1չ) + - [4.Math对象的拓展](#4math对象的拓展) + - [5.指数运算符](#5指数运算符) + - [函数的拓展](#函数的拓展) + - [1.参数默认值](#1参数默认值) + - [2.rest 参数](#2rest-参数) + - [3.name 属性](#3name-属性) + - [4.箭头函数](#4箭头函数) + - [5.双冒号运算符](#5双冒号运算符) + - [对象的拓展](#对象的拓展) + - [1.拓展运算符](#1拓展运算符) - [2. ES7](#2-es7) - [3. ES8](#3-es8) - [4. ES9](#4-es9) - - [5. ֪ʶ](#5-֪ʶ) - - [鼶](#鼶) -- [ġ](#Ľ) + - [5. 知识补充](#5-知识补充) + - [块级作用域](#块级作用域) +- [四、结语](#四结语) -# +# 三、正文 ## 1. ES6 -### let const +### let 和 const命令 -ES6Уͨʵ `let` ʾ****`const` ʾ**** `let` `const` **鼶****ǰЧ**ظ +在ES6中,我们通常实用 `let` 表示**变量**,`const` 表示**常量**,并且 `let` 和 `const` 都是**块级作用域**,且在**当前作用域有效**不能重复声明。 -#### 1.let -`let` ÷ `var` ƣ `let` ֻڴЧ -**÷** +#### 1.let 命令 +`let` 命令的用法和 `var` 相似,但是 `let` 只在所在代码块内有效。 +**基础用法**: ```js { let a = 1; @@ -77,15 +77,15 @@ } ``` - `let` ص㣺 +并且 `let` 有以下特点: -* **ڱ** -ES6֮ǰ `var` һ****һ****ű⣬ʵʿ̾һЩ߼ϵɻ󣬰һ˼άϰߣҪʹá +* **不存在变量提升:** +在ES6之前,我们 `var` 声明一个**变量**一个**函数**,都会伴随着变量提升的问题,导致实际开发过程经常出现一些逻辑上的疑惑,按照一般思维习惯,变量都是需要先声明后使用。 ```js // var console.log(v1); // undefined var v1 = 2; -// ڱ ʵ +// 由于变量提升 代码实际如下 var v1; console.log(v1) v1 = 2; @@ -95,27 +95,27 @@ console.log(v2); // ReferenceError let v2 = 2; ``` -* **ظ** -`let` `const` ͬ£**ظͬһ****ں** +* **不允许重复声明:** +`let` 和 `const` 在相同作用域下,都**不能重复声明同一变量**,并且**不能在函数内重新声明参数**。 ```js -// 1. ظͬһ -// +// 1. 不能重复声明同一变量 +// 报错 function f1 (){ let a = 1; var a = 2; } -// +// 报错 function f2 (){ let a = 1; let a = 2; } -// 2. ں -// +// 2. 不能在函数内重新声明参数 +// 报错 function f3 (a1){ let a1; } -// +// 不报错 function f4 (a2){ { let a2 @@ -123,27 +123,27 @@ function f4 (a2){ } ``` -#### 2.const -`const` һ**ֻ****** -**÷** +#### 2.const 命令 +`const` 声明一个**只读**的**常量**。 +**基础用法**: ```js const PI = 3.1415926; console.log(PI); // 3.1415926 ``` -**ע** -* `const` ޷޸ֵ +**注意点**: +* `const` 声明后,无法修改值; ```js const PI = 3.1415926; PI = 3; // TypeError: Assignment to constant variable. ``` -* `const` ʱ븳ֵ +* `const` 声明时,必须赋值; ```js const a ; // SyntaxError: Missing initializer in const declaration. ``` -* `const` ij`let` ظ +* `const` 声明的常量,`let` 不能重复声明; ```js const PI = 3.1415926; let PI = 0; @@ -151,21 +151,21 @@ let PI = 0; ``` -### Ľ⹹ֵ -**⹹ֵ**ES6УֱӴͶȡֵնӦλãֵIJ +### 变量的解构赋值 +**解构赋值概念**:在ES6中,直接从数组和对象中取值,按照对应位置,赋值给变量的操作。 -#### 1. -**÷** +#### 1.数组 +**基础用法**: ```js -// ES6 ֮ǰ +// ES6 之前 let a = 1; let b = 2; -// ES6 ֮ +// ES6 之后 let [a, b] = [1, 2]; ``` -ϣֻҪȺģʽһ£߱ɻȡұ߶Ӧλõֵ÷ +本质上,只要等号两边模式一致,左边变量即可获取右边对应位置的值,更多用法: ```js let [a, [[b], c]] = [1, [[2], 3]]; @@ -184,18 +184,18 @@ let [a, b, ..c.] = [1]; console.log(a, b, c); // 1, undefined, [] ``` -**ע** -* ⹹ɹֵ͵`undefined` +**注意点**: +* 如果解构不成功,变量的值就等于`undefined`。 ```js let [a] = []; // a => undefined let [a, b] = [1]; // a => 1 , b => undefined ``` -* ģʽұߣҲԽ⹹ɹ +* 当左边模式多于右边,也可以解构成功。 ```js let [a, b] = [1, 2, 3]; console.log(a, b); // 1, 2 ``` -* ģʽͬ +* 两边模式不同,报错。 ```js let [a] = 1; let [a] = false; @@ -205,23 +205,23 @@ let [a] = null; let [a] = {}; ``` -**ָ⹹Ĭֵ** -**÷** +**指定解构的默认值**: +**基础用法**: ```js let [a = 1] = []; // a => 1 let [a, b = 2] = [a]; // a => 1 , b => 2 ``` - +特殊情况: ```js let [a = 1] = [undefined]; // a => 1 let [a = 1] = [null]; // a => null ``` -ұģʽӦֵϸ`undefined`ĬֵЧ`null`ϸ`undefined` +右边模式对应的值,必须严格等于`undefined`,默认值才能生效,而`null`不严格等于`undefined`。 -#### 2.Ľ⹹ֵ -⹹ͬǣ⹹**Ҫϸ˳ȡֵ**ֻҪ****ȥȡӦ****ֵȡӦ****ֵΪ`undefined` +#### 2.对象的解构赋值 +与数组解构不同的是,对象解构**不需要严格按照顺序取值**,而只要按照**变量名**去取对应**属性名**的值,若取不到对应**属性名**的值,则为`undefined` 。 -**÷** +**基础用法**: ```js let {a, b} = {a:1, b:2}; // a => 1 , b => 2 let {a, b} = {a:2, b:1}; // a => 2 , b => 1 @@ -229,17 +229,17 @@ let {a} = {a:3, b:2, c:1};// a => 3 let {a} = {b:2, c:1}; // a => undefined ``` -**ע** -* ********һ£Ҫ޸ơ +**注意点**: +* 若**变量名**和**属性名**不一致,则需要修改名称。 ```js let {a:b} = {a:1, c:2}; // error: a is not defined // b => 1 ``` -Ľ⹹ֵڲƣҵͬԣȻٸӦıֵǺߣǰߡ -У`a` ƥģʽ`b`DZֵDZ`b`ģʽ`a` +对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。 +上面代码中,`a` 是匹配的模式,`b`才是变量。真正被赋值的是变量`b`,而不是模式`a`。 -* ⹹Ҳ֧**Ƕ׽⹹** +* 对象解构也支持**嵌套解构**。 ```js let obj = { a:[ 1, { b: 2}] @@ -248,24 +248,24 @@ let {a, a: [c, {b}]} = obj; // a=>[1, {b: 2}], b => 2, c => 1 ``` -**ָ⹹Ĭֵ** +**指定解构的默认值**: ```js let {a=1} = {}; // a => 1 let {a, b=1} = {a:2}; // a => 2, b => 1 let {a:b=3} = {}; // b => 3 let {a:b=3} = {a:4}; // b = >4 -// aģʽbDZ μ +// a是模式,b是变量 牢记 let {a=1} = {a:undefined}; // a => 1 let {a=1} = {a:null}; // a => null -// ΪnullundefinedϸȣԸֵЧ -// Ĭֵ1Ч +// 因为null与undefined不严格相等,所以赋值有效 +// 导致默认值1不会生效。 ``` -#### 3.ַĽ⹹ֵ -ַĽ⹹ֵУַתһ**Ķ** -**÷** +#### 3.字符串的解构赋值 +字符串的解构赋值中,字符串被转换成了一个**类似数组的对象**。 +**基础用法**: ```js const [a, b, c, d, e] = 'hello'; a // "h" @@ -277,10 +277,10 @@ e // "o" let {length:len} = 'hello';// len => 5 ``` -#### 4.ֵͲֵĽ⹹ֵ -⹹ֵĹǣ**ֻҪȺұߵֵǶ飬ȽתΪ**`undefined``null`**޷תΪ**Զǽн⹹ֵᱨ +#### 4.数值和布尔值的解构赋值 +解构赋值的规则是,**只要等号右边的值不是对象或数组,就先将其转为对象**。由于`undefined`和`null`**无法转为对象**,所以对它们进行解构赋值,都会报错。 ```js -// ֵͲֵİװtoString +// 数值和布尔值的包装对象都有toString属性 let {toString: s} = 123; s === Number.prototype.toString // true let {toString: s} = true; @@ -290,15 +290,15 @@ let { prop: x } = undefined; // TypeError let { prop: y } = null; // TypeError ``` -#### 5.Ľ⹹ֵ -**÷** +#### 5.函数参数的解构赋值 +**基础用法**: ```js function fun ([a, b]){ return a + b; } fun ([1, 2]); // 3 ``` -**ָĬֵĽ⹹**: +**指定默认值的解构**: ```js function fun ({a=0, b=0} = {}){ return [a, b]; @@ -317,30 +317,30 @@ fun ({}); // [undefined, undefined] fun (); // [0, 0] ``` -#### 6.; -* **ֵ**: +#### 6.用途 +* **交换变量的值**: ```js let a = 1,b = 2; [a, b] = [b, a]; // a =>2 , b => 1 ``` -* **ضֵ**: +* **函数返回多个值**: ```js -// һ +// 返回一个数组 function f (){ return [1, 2, 3]; } let [a, b, c] = f(); // a=>1, b=>2, c=>3 -// һ +// 返回一个对象 function f (){ return {a:1, b:2}; } let {a, b} = f(); // a=>1, b=>2 ``` -* **ٶӦ**: -ٵĽһӦ +* **快速对应参数**: +快速的将一组参数与变量名对应。 ```js function f([a, b, c]) {...} f([1, 2, 3]); @@ -349,7 +349,7 @@ function f({a, b, c}) {...} f({b:2, c:3, a:1}); ``` -* **ȡJSON** +* **提取JSON数据**: ```js let json = { name : 'leo', @@ -359,7 +359,7 @@ let {name, age} = json; console.log(name,age); // leo, 18 ``` -* **Mapṹ**: +* **遍历Map结构**: ```js const m = new Map(); m.set('a':1); @@ -367,98 +367,98 @@ m.set('b':2); for ([k, v] of m){ console.log(k + ' : ' + v); } -// ȡ +// 获取键名 for (let [k] of m){...} -// ȡֵ +// 获取键值 for (let [,k] of m){...} ``` -* **ģָ**: -****ģҪõķ +* **输入模块的指定方法**: +用于**按需加载**模块中需要用到的方法。 ```js const {log, sin, cos} = require('math'); ``` -### ַչ +### 字符串的拓展 #### 1.includes(),startsWith(),endsWith() -жַǷһַʱES6֮ǰֻ`typeof`ES6ֶַ֮ -* **includes()**:**ֵ**ʾ**Ƿҵַ** -* **startsWith()**:**ֵ**ʾַǷԭַ**ͷ** -* **endsWith()**:**ֵ**ʾַǷԭַ**β** +在我们判断字符串是否包含另一个字符串时,ES6之前,我们只有`typeof`方法,ES6之后我们又多了三种方法: +* **includes()**:返回**布尔值**,表示**是否找到参数字符串**。 +* **startsWith()**:返回**布尔值**,表示参数字符串是否在原字符串的**头部**。 +* **endsWith()**:返回**布尔值**,表示参数字符串是否在原字符串的**尾部**。 ```js let a = 'hello leo'; a.startsWith('leo'); // false a.endsWith('o'); // true a.includes('lo'); // true ``` -ֵ֧ڶʾʼλá +并且这三个方法都支持第二个参数,表示起始搜索的位置。 ```js let a = 'hello leo'; a.startsWith('leo',1); // false a.endsWith('o',5); // true a.includes('lo',6); // false ``` -`endsWith` ǰ `n` ַԴӵ`n`λֱ +`endsWith` 是针对前 `n` 个字符,而其他两个是针对从第`n`个位置直到结束。 #### 2.repeat() -`repeat`һַʾԭַظ`n`Ρ -**÷** +`repeat`方法返回一个新字符串,表示将原字符串重复`n`次。 +**基础用法**: ```js 'ab'.repeat(3); // 'ababab' 'ab'.repeat(0); // '' ``` -**÷**: -* Ϊ`С`ȡ +**特殊用法**: +* 参数为`小数`,则取整 ```js 'ab'.repeat(2.3); // 'abab' ``` -* Ϊ```Infinity`򱨴 +* 参数为`负数`或`Infinity`,则报错 ```js 'ab'.repeat(-1); // RangeError 'ab'.repeat(Infinity); // RangeError ``` -* Ϊ`0-1С``NaN`ȡ0 +* 参数为`0到-1的小数`或`NaN`,则取0 ```js 'ab'.repeat(-0.5); // '' 'ab'.repeat(NaN); // '' ``` -* Ϊ`ַ`ת`` +* 参数为`字符串`,则转成`数字` ```js 'ab'.repeat('ab'); // '' 'ab'.repeat('3'); // 'ababab' ``` #### 3.padStart(),padEnd() -ڽַ**ͷ****β**ȫȣ`padStart()`Ϊ**ͷȫ**`padEnd()`Ϊ**βȫ** -**2**һָ**ַС**ڶ**ڲȫַ** -**÷** +用于将字符串**头部**或**尾部**补全长度,`padStart()`为**头部补全**,`padEnd()`为**尾部补全**。 +这两个方法接收**2个**参数,第一个指定**字符串最小长度**,第二个**用于补全的字符串**。 +**基础用法** : ```js 'x'.padStart(5, 'ab'); // 'ababx' 'x'.padEnd(5, 'ab'); // 'xabab' ``` -**÷**: -* ԭַȣڻָСȣ򷵻ԭַ +**特殊用法**: +* 原字符串长度,大于或等于指定最小长度,则返回原字符串。 ```js 'xyzabc'.padStart(5, 'ab'); // 'xyzabc' ``` -* ȫַȺԭַָ֮ͣСȣȥֵIJȫַ +* 用来补全的字符串长度和原字符串长度之和,超过指定最小长度,则截去超出部分的补全字符串。 ```js 'ab'.padStart(5,'012345'); // "012ab" ``` -* ʡԵڶ`ո`ȫ +* 省略第二个参数,则用`空格`补全。 ```js 'x'.padStart(4); // ' x' 'x'.endStart(4); // 'x ' ``` -#### 4.ģַ -ƴַES6֮ǰ +#### 4.模版字符串 +用于拼接字符串,ES6之前: ```js let a = 'abc' + 'def' + 'ghi'; ``` -ES6֮ +ES6之后: ```js let a = ` abc @@ -466,21 +466,21 @@ let a = ` ghi ` ``` -**ƴӱ**: -**(\`)**ʹ`${}`򷽷 +**拼接变量**: +在**反引号(\`)**中使用`${}`包裹变量或方法。 ```js -// ES6֮ǰ +// ES6之前 let a = 'abc' + v1 + 'def'; -// ES6֮ +// ES6之后 let a = `abc${v1}def` ``` -### չ +### 正则的拓展 -### ֵչ +### 数值的拓展 #### 1.Number.isFinite(), Number.isNaN() -`Number.isFinite()` ڼһֵǷ޵ģ`Infinity``Number`ͣһɷ`false` +`Number.isFinite()` 用于检查一个数值是否是有限的,即不是`Infinity`,若参数不是`Number`类型,则一律返回`false` 。 ```js Number.isFinite(10); // true Number.isFinite(0.5); // true @@ -493,7 +493,7 @@ Number.isFinite(true); // false Number.isFinite(Math.random()); // true ``` -`Number.isNaN()`ڼǷ`NaN``NaN`һɷ`false` +`Number.isNaN()`用于检查是否是`NaN`,若参数不是`NaN`,则一律返回`false`。 ```js Number.isNaN(NaN); // true Number.isNaN(10); // false @@ -504,9 +504,9 @@ Number.isNaN('true' / 0); // true Number.isNaN('true' / 'true'); // true ``` -**** -봫ͳȫֵ`isFinite()``isNaN()`𣬴ͳȽת**ֵ**жϡ -ES6ֻ**ֵ**Ч `Number.isFinite()`**ֵ**һɷ`false`,` Number.isNaN()`ֻж`NaN`ŷ`true`һɷ`false` +**区别**: +与传统全局的`isFinite()`和`isNaN()`方法的区别,传统的这两个方法,是先将参数转换成**数值**,再判断。 +而ES6新增的这两个方法则只对**数值**有效, `Number.isFinite()`对于**非数值**一律返回`false`,` Number.isNaN()`只有对于`NaN`才返回`true`,其他一律返回`false`。 ```js isFinite(25); // true isFinite("25"); // true @@ -520,7 +520,7 @@ Number.isNaN("NaN"); // false ``` #### 2.Number.parseInt(), Number.parseFloat() -ȫַ`parseInt()``parseFloat()`һ£Ŀ**ȫԵķ****Ըģ黯** +这两个方法与全局方法`parseInt()`和`parseFloat()`一致,目的是逐步**减少全局性的方法**,让**语言更模块化**。 ```js parseInt('12.34'); // 12 parseFloat('123.45#'); // 123.45 @@ -533,40 +533,40 @@ Number.parseFloat === parseFloat; // true ``` #### 3.Number.isInteger() -жһֵǷֵ򷵻`false` +用来判断一个数值是否是整数,若参数不是数值,则返回`false`。 ```js Number.isInteger(10); // true Number.isInteger(10.0); // true Number.isInteger(10.1); // false ``` -#### 4.Mathչ -ES617ѧص**̬**ֻ**Math**ϵá +#### 4.Math对象的拓展 +ES6新增17个数学相关的**静态方法**,只能在**Math对象**上调用。 * **Math.trunc**: -ȥСС֣**** -Ϊ**ֵ****תΪֵ** -Ϊ**ֵ****޷ȡֵ**򷵻**NaN** +用来去除小数的小数部分,**返回整数部分**。 +若参数为**非数值**,则**先转为数值**。 +若参数为**空值**或**无法截取整数的值**,则返回**NaN**。 ```js -// ʹ +// 正常使用 Math.trunc(1.1); // 1 Math.trunc(1.9); // 1 Math.trunc(-1.1); // -1 Math.trunc(-1.9); // -1 Math.trunc(-0.1234); // -0 -// Ϊֵ +// 参数为非数值 Math.trunc('11.22'); // 11 Math.trunc(true); // 1 Math.trunc(false); // 0 Math.trunc(null); // 0 -// Ϊպ޷ȡ +// 参数为空和无法取整 Math.trunc(NaN); // NaN Math.trunc('leo'); // NaN Math.trunc(); // NaN Math.trunc(undefined); // NaN ``` -**ES5ʵ** +**ES5实现**: ```js Math.trunc = Math.trunc || function(x){ return x < 0 ? Math.ceil(x) : Math.floor(x); @@ -574,13 +574,13 @@ Math.trunc = Math.trunc || function(x){ ``` * **Math.sign()**: -жһ************ڷֵת**ֵ** -ֵ -> Ϊ +1 -> Ϊ -1 -> Ϊ0 0 -> Ϊ-0 -0 -> Ϊֵ NaN +判断一个数是**正数**、**负数**还**是零**,对于非数值,会先转成**数值**。 +返回值: +> 参数为正数, 返回 +1 +> 参数为负数, 返回 -1 +> 参数为0, 返回 0 +> 参数为-0, 返回 -0 +> 参数为其他值, 返回 NaN ```js Math.sign(-1); // -1 Math.sign(1); // +1 @@ -598,7 +598,7 @@ Math.sign(); // NaN Math.sign(undefined); // NaN ``` -**ES5ʵ** +**ES5实现** ```js Math.sign = Math.sign || function (x){ x = +x; @@ -610,7 +610,7 @@ Math.sign = Math.sign || function (x){ ``` * **Math.cbrt()**: -һΪֵתֵ +用来计算一个数的立方根,若参数为非数值则先转成数值。 ```js Math.cbrt(-1); // -1 Math.cbrt(0); // 0 @@ -620,7 +620,7 @@ Math.cbrt(2); // 1.2599210498 Math.cbrt('1'); // 1 Math.cbrt('leo'); // NaN ``` -**ES5ʵ** +**ES5实现** ```js Math.cbrt = Math.cbrt || function (x){ var a = Math.pow(Math.abs(x), 1/3); @@ -629,7 +629,7 @@ Math.cbrt = Math.cbrt || function (x){ ``` * **Math.clz32()**: -ڷһ 32 λ޷ʽжٸǰ 0 +用于返回一个数的 32 位无符号整数形式有多少个前导 0。 ```js Math.clz32(0) // 32 Math.clz32(1) // 31 @@ -639,7 +639,7 @@ Math.clz32(0b00100000000000000000000000000000) // 2 ``` * **Math.imul()**: -ڷ 32 λʽ˵ĽصҲһ 32 λĴ +用于返回两个数以 32 位带符号整数形式相乘的结果,返回的也是一个 32 位的带符号整数。 ```js Math.imul(2, 4) // 8 Math.imul(-1, 8) // -8 @@ -647,7 +647,7 @@ Math.imul(-2, -2) // 4 ``` * **Math.fround()**: -һ**2λȸ**ʽ +用来返回一个数的**2位单精度浮点数**形式。 ```js Math.fround(0) // 0 Math.fround(1) // 1 @@ -655,7 +655,7 @@ Math.fround(2 ** 24 - 1) // 16777215 ``` * **Math.hypot()**: -вƽ͵**ƽ** +用来返回所有参数的平方和的**平方根**。 ```js Math.hypot(3, 4); // 5 Math.hypot(3, 4, 5); // 7.0710678118654755 @@ -667,13 +667,13 @@ Math.hypot(-3); // 3 ``` * **Math.expm1()**: -` ex - 1``Math.exp(x) - 1` +用来返回` ex - 1`,即`Math.exp(x) - 1`。 ```js Math.expm1(-1) // -0.6321205588285577 Math.expm1(0) // 0 Math.expm1(1) // 1.718281828459045 ``` -**ES5ʵ** +**ES5实现** ```js Math.expm1 = Math.expm1 || function(x) { return Math.exp(x) - 1; @@ -681,14 +681,14 @@ Math.expm1 = Math.expm1 || function(x) { ``` * **Math.log1p()**: -`1 + x`Ȼ`Math.log(1 + x)`xС`-1``NaN` +用来返回`1 + x`的自然对数,即`Math.log(1 + x)`。如果x小于`-1`,返回`NaN`。 ```js Math.log1p(1) // 0.6931471805599453 Math.log1p(0) // 0 Math.log1p(-1) // -Infinity Math.log1p(-2) // NaN ``` -**ES5ʵ** +**ES5实现** ```js Math.log1p = Math.log1p || function(x) { return Math.log(1 + x); @@ -696,7 +696,7 @@ Math.log1p = Math.log1p || function(x) { ``` * **Math.log10()**: - `10 `Ϊ׵`xĶ`xС 0򷵻 `NaN` +用来返回以 `10 `为底的`x的对数`。如果x小于 0,则返回 `NaN`。 ```js Math.log10(2) // 0.3010299956639812 Math.log10(1) // 0 @@ -704,7 +704,7 @@ Math.log10(0) // -Infinity Math.log10(-2) // NaN Math.log10(100000) // 5 ``` -**ES5ʵ** +**ES5实现** ```js Math.log10 = Math.log10 || function(x) { return Math.log(x) / Math.LN10; @@ -712,7 +712,7 @@ Math.log10 = Math.log10 || function(x) { ``` * **Math.log2()**: - `2` Ϊ׵`xĶ``x`С` 0`򷵻 `NaN` +用来返回以 `2` 为底的`x的对数`。如果`x`小于` 0`,则返回 `NaN`。 ```js Math.log2(3) // 1.584962500721156 Math.log2(2) // 1 @@ -722,29 +722,29 @@ Math.log2(-2) // NaN Math.log2(1024) // 10 Math.log2(1 << 29) // 29 ``` -**ES5ʵ** +**ES5实现** ```js Math.log2 = Math.log2 || function(x) { return Math.log(x) / Math.LN2; }; ``` -* **˫**: ->`Math.sinh(x)` x**˫**hyperbolic sine ->`Math.cosh(x)` x**˫**hyperbolic cosine ->`Math.tanh(x)` x**˫**hyperbolic tangent ->`Math.asinh(x)` x**˫**inverse hyperbolic sine ->`Math.acosh(x)` x**˫**inverse hyperbolic cosine ->`Math.atanh(x)` x**˫**inverse hyperbolic tangent +* **双曲函数方法**: +>`Math.sinh(x)` 返回x的**双曲正弦**(hyperbolic sine) +>`Math.cosh(x)` 返回x的**双曲余弦**(hyperbolic cosine) +>`Math.tanh(x)` 返回x的**双曲正切**(hyperbolic tangent) +>`Math.asinh(x)` 返回x的**反双曲正弦**(inverse hyperbolic sine) +>`Math.acosh(x)` 返回x的**反双曲余弦**(inverse hyperbolic cosine) +>`Math.atanh(x)` 返回x的**反双曲正切**(inverse hyperbolic tangent) -#### 5.ָ -ָ(`**`): +#### 5.指数运算符 +新增的指数运算符(`**`): ```js 2 ** 2; // 4 2 ** 3; // 8 -2 ** 3 ** 2; // ൱ 2 ** (3 ** 2); 512 +2 ** 3 ** 2; // 相当于 2 ** (3 ** 2); 返回 512 ``` -ָ(`**`)`Math.pow`ʵֲͬر߻ϸ΢IJ졣 +指数运算符(`**`)与`Math.pow`的实现不相同,对于特别大的运算结果,两者会有细微的差异。 ```js Math.pow(99, 99) // 3.697296376497263e+197 @@ -753,16 +753,16 @@ Math.pow(99, 99) // 3.697296376497268e+197 ``` -### չ -#### 1.Ĭֵ +### 函数的拓展 +#### 1.参数默认值 ```js -// ES6 ֮ǰ +// ES6 之前 function f(a, b){ b = b || 'leo'; console.log(a, b); } -// ES6 ֮ +// ES6 之后 function f(a, b='leo'){ console.log(a, b); } @@ -771,20 +771,20 @@ f('hi'); // hi leo f('hi', 'jack'); // hi jack f('hi', ''); // hi leo ``` -**ע**: -* Ĭģ`let``const`ٴ +**注意**: +* 参数变量是默认声明的,不能用`let`和`const`再次声明: ```js function f (a = 1){ let a = 2; // error } ``` -* ʹòĬֵʱͬ +* 使用参数默认值时,参数名不能相同: ```js -function f (a, a, b){ ... }; // -function f (a, a, b = 1){ ... }; // +function f (a, a, b){ ... }; // 不报错 +function f (a, a, b = 1){ ... }; // 报错 ``` -**⹹ֵĬֵʹ** +**与解构赋值默认值结合使用**: ```js function f ({a, b=1}){ console.log(a,b) @@ -792,7 +792,7 @@ function f ({a, b=1}){ f({}); // undefined 1 f({a:2}); // 2 1 f({a:2, b:3}); // 2 3 -f(); // +f(); // 报错 function f ({a, b = 1} = {}){ console.log(a, b) @@ -800,15 +800,15 @@ function f ({a, b = 1} = {}){ f(); // undefined 1 ``` -**βĬֵ**: -ͨΪĬֵڹ۲ҷβ޷ʡԡ +**尾参数定义默认值**: +通常在尾参数定义默认值,便于观察参数,并且非尾参数无法省略。 ```js function f (a=1,b){ return [a, b]; } f(); // [1, undefined] f(2); // [2, undefined] -f(,2); // +f(,2); // 报错 f(undefined, 2); // [1, 2] @@ -817,10 +817,10 @@ function f (a, b=1, c){ } f(); // [undefined, 1, undefined] f(1); // [1,1,undefined] -f(1, ,2); // +f(1, ,2); // 报错 f(1,undefined,2); // [1,1,2] ``` -Ĭֵݲ`undefined`ᴥĬֵ`null`ᴥ +在给参数传递默认值时,传入`undefined`会触发默认值,传入`null`不会触发。 ```js function f (a = 1, b = 2){ console.log(a, b); @@ -828,8 +828,8 @@ function f (a = 1, b = 2){ f(undefined, null); // 1 null ``` -**length**: -`length`ԽأûָĬֵIJrest`length`ԡ +**函数的length属性**: +`length`属性将返回,没有指定默认值的参数数量,并且rest参数不计入`length`属性。 ```js function f1 (a){...}; function f2 (a=1){...}; @@ -844,20 +844,20 @@ f4.length; // 0 f5.length; // 2 ``` -#### 2.rest -`rest`ʽΪ`...`ֵΪһ飬ڻȡ +#### 2.rest 参数 +`rest`参数形式为(`...变量名`),其值为一个数组,用于获取函数多余参数。 ```js function f (a, ...b){ console.log(a, b); } f(1,2,3,4); // 1 [2, 3, 4] ``` -**ע** -* `rest`ֻܷһ򱨴 +**注意**: +* `rest`参数只能放在最后一个,否则报错: ```js -function f(a, ...b, c){...}; // +function f(a, ...b, c){...}; // 报错 ``` -* `length`Բ`rest` +* 函数的`length`属性不包含`rest`参数。 ```js function f1 (a){...}; function f2 (a,...b){...}; @@ -865,8 +865,8 @@ f1(1); // 1 f2(1,2); // 1 ``` -#### 3.name -ڷظúĺ +#### 3.name 属性 +用于返回该函数的函数名。 ```js function f (){...}; f.name; // f @@ -875,63 +875,63 @@ const f = function g(){...}; f.name; // g ``` -#### 4.ͷ -ʹáͷ(`=>`)庯 -**ʹ** +#### 4.箭头函数 +使用“箭头”(`=>`)定义函数。 +**基础使用**: ```js -// 1 +// 有1个参数 let f = v => v; -// ͬ +// 等同于 let f = function (v){return v}; -// ж +// 有多个参数 let f = (v, i) => {return v + i}; -// ͬ +// 等同于 let f = function (v, i){return v + i}; -// û +// 没参数 let f = () => 1; -// ͬ +// 等同于 let f = function (){return 1}; ``` -**ͷṹʹ** +**箭头函数与变量结构结合使用**: ```js -// д +// 正常函数写法 function f (p) { return p.a + ':' + p.b; } -// ͷд +// 箭头函数写法 let f = ({a, b}) => a + ':' + b; ``` -**򻯻ص** +**简化回调函数**: ```js -// д +// 正常函数写法 [1, 2, 3].map(function (x){ return x * x; }) -// ͷд +// 箭头函数写法 [1, 2, 3].map(x => x * x); ``` -**ͷrest** +**箭头函数与rest参数结合**: ```js let f = (...n) => n; f(1, 2, 3); // [1, 2, 3] ``` -**ע** -* 1.ͷڵ`this`****ָ**ʱڵĶ**ǵʱ -* 2.ͷܵ**캯**`new`򱨴 -* 3.ͷ`arguments`󣬼ʹãʹ`rest`档 -* 4.ͷʹ`yield`**Generator** +**注意点**: +* 1.箭头函数内的`this`**总是**指向**定义时所在的对象**,而不是调用时。 +* 2.箭头函数不能当做**构造函数**,即不能用`new`命令,否则报错。 +* 3.箭头函数不存在`arguments`对象,即不能使用,可以使用`rest`参数代替。 +* 4.箭头函数不能使用`yield`命令,即不能用作**Generator**函数。 -**ó** -* 1.ڶ庯Ҹ÷ڲ`this` +**不适用场景**: +* 1.在定义函数方法,且该方法内部包含`this`。 ```js const obj = { a:9, @@ -940,44 +940,44 @@ const obj = { } } ``` -`b`**ͨ**ڲ`this`ָ`obj`Ǽͷ`this`ָ**ȫ**Ԥڽ +上述`b`如果是**普通函数**,函数内部的`this`指向`obj`,但是如果是箭头函数,则`this`会指向**全局**,不是预期结果。 -* 2.Ҫ̬`this`ʱ +* 2.需要动态`this`时。 ```js let b = document.getElementById('myID'); b.addEventListener('click', ()=>{ this.classList.toggle('on'); }) ``` -߰ťᱨΪ`b`ļͷУ`this`ȫֶij**ͨ**`this`ͻָ򱻵İť +上诉按钮点击会报错,因为`b`监听的箭头函数中,`this`是全局对象,若改成**普通函数**,`this`就会指向被点击的按钮对象。 -#### 5.˫ð -˫ðʱһ᰸ڽһЩõijϣȡ`call``apply``bind`á -˫ð(`::`)һ****ұһ****ԶߵĶΪĻ(`this`)󶨵ұߺϡ +#### 5.双冒号运算符 +双冒号暂时是一个提案,用于解决一些不适用的场合,取代`call`、`apply`、`bind`调用。 +双冒号运算符(`::`)的左边是一个**对象**,右边是一个**函数**。该运算符会自动将左边的对象,作为上下文环境(即`this`对象),绑定到右边函数上。 ```js f::b; -// ͬ +// 等同于 b.bind(f); f::b(...arguments); -// ͬ +// 等同于 b.apply(f, arguments); ``` -˫ðΪգұһķڽ÷󶨵öϡ +若双冒号左边为空,右边是一个对象的方法,则等于将该方法绑定到该对象上。 ```js let f = a::a.b; -// ͬ +// 等同于 let f = ::a.b; ``` -### չ -#### 1.չ -չʹ(`...`)`rest`㣬תΪ(`,`)ָIJС +### 对象的拓展 +#### 1.拓展运算符 +拓展运算符使用(`...`),类似`rest`参数的逆运算,将数组转为用(`,`)分隔的参数序列。 ```js console.log(...[1, 2, 3]); // 1 2 3 console.log(1, ...[2,3], 4); // 1 2 3 4 ``` -չҪʹںá +拓展运算符主要使用在函数调用。 ```js function f (a, b){ console.log(a, b); @@ -989,31 +989,31 @@ function g (a, b, c, d, e){ } g(0, ...[1, 2], 3, ...[4]); // 0 1 2 3 4 ``` -**չǸ飬򲻲Ч** +**若拓展运算符后面是个空数组,则不产生效果**。 ```js [...[], 1]; // 1 ``` -**apply** +**替代apply方法** ```js -// ES6֮ǰ +// ES6之前 function f(a, b, c){...}; var a = [1, 2, 3]; f.apply(null, a); -// ES6֮ +// ES6之后 function f(a, b, c){...}; let a = [1, 2, 3]; f(...a); -// ES6֮ǰ +// ES6之前 Math.max.apply(null, [3,2,6]); -// ES6֮ +// ES6之后 Math.max(...[3,2,6]); ``` -**չ** +**拓展运算符的运用** @@ -1023,21 +1023,21 @@ Math.max(...[3,2,6]); ## 4. ES9 -## 5. ֪ʶ -### 鼶 +## 5. 知识补充 +### 块级作用域 -ָͨһ**ڲ**һ**ڲ** -磺 +通常指一个**函数内部**,或者一个**代码块内部**。 +比如: ```js function fun1 () { - // 鼶 + // 块级作用域 if (true) { - // 鼶 + // 块级作用域 } } ``` -**ȱ** -1.ڲ +**缺点**: +1.导致内层变量覆盖外层变量 ```js var a1 = new Date(); function f1 (){ @@ -1047,9 +1047,9 @@ function f1 (){ } } ``` - `undefined` Ϊ `if` ڵ `a1` ıڲ `a1` ⲿ `a1`Ϊ `undefined` +输出 `undefined` 是因为 `if` 内的 `a1` 变量声明的变量提升,导致内部的 `a1` 覆盖外部的 `a1`,所以输出为 `undefined` 。 -2.ȫȾ +2.变量的全局污染 ```js var a = 'hello'; for (var i = 0; i< a.length; i++) { @@ -1057,7 +1057,7 @@ for (var i = 0; i< a.length; i++) { } console.log(i); // 5 ``` -ѭ󣬱 `i` ֵȻڣɱȫȾ +循环结束后,变量 `i` 的值依然存在,造成变量的全局污染。 -# ġ \ No newline at end of file +# 四、结语 From 7adfae266c63c482f258b6016fdff29836854ddb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 22 Oct 2018 22:30:41 +0800 Subject: [PATCH 086/835] 2018.10.22 --- EXEFE-es6book/README.md | 165 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 163 insertions(+), 2 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 44ae880b..d86e88c8 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -6,7 +6,7 @@ - [ ] ES8 - [ ] ES9 - [ ] 知识补充 -> 最后更新 2018.10.21 +> 最后更新 2018.10.22 > 也在思考,如何整理好这一份资料,让看的人,都各有收获。 # 一、介绍 @@ -51,6 +51,13 @@ - [5.双冒号运算符](#5双冒号运算符) - [对象的拓展](#对象的拓展) - [1.拓展运算符](#1拓展运算符) + - [2.Array.from()](#2arrayfrom) + - [3.Array.of()](#3arrayof) + - [4.find()和findIndex()](#4find和findindex) + - [5.fill()](#5fill) + - [6.entries(),keys(),values()](#6entrieskeysvalues) + - [7.includes()](#7includes) + - [8.flat(),flatMap()](#8flatflatmap) - [2. ES7](#2-es7) - [3. ES8](#3-es8) - [4. ES9](#4-es9) @@ -1014,8 +1021,162 @@ Math.max(...[3,2,6]); ``` **拓展运算符的运用** - +* **(1)复制数组**: +通常我们直接复制数组时,只是浅拷贝,如果要实现深拷贝,可以使用拓展运算符。 +```js +// 通常情况 浅拷贝 +let a1 = [1, 2]; +let a2 = a1; +a2[0] = 3; +console.log(a1,a2); // [3,2] [3,2] + +// 拓展运算符 深拷贝 +let a1 = [1, 2]; +let a2 = [...a1]; +// let [...a2] = a1; // 作用相同 +a2[0] = 3; +console.log(a1,a2); // [1,2] [3,2] +``` +* **(2)合并数组**: +注意,这里合并数组,只是浅拷贝。 +```js +let a1 = [1,2]; +let a2 = [3]; +let a3 = [4,5]; + +// ES5 +let a4 = a1.concat(a2, a3); + +// ES6 +let a5 = [...a1, ...a2, ...a3]; + +a4[0] === a1[0]; // true +a5[0] === a1[0]; // true +``` + +* **(3)与解构赋值结合**: +与解构赋值结合生成数组,但是使用拓展运算符需要放到参数最后一个,否则报错。 +```js +let [a, ...b] = [1, 2, 3, 4]; +// a => 1 b => [2,3,4] + +let [a, ...b] = []; +// a => undefined b => [] + +let [a, ...b] = ["abc"]; +// a => "abc" b => [] +``` +#### 2.Array.from() +将 **类数组对象** 和 **可遍历的对象**,转换成真正的数组。 +```js +// 类数组对象 +let a = { + '0':'a', + '1':'b', + length:2 +} +let arr = Array.from(a); + +// 可遍历的对象 +let a = Array.from([1,2,3]); +let b = Array.from({length: 3}); +let c = Array.from([1,2,3]).map(x => x * x); +let d = Array.from([1,2,3].map(x => x * x)); +``` + +#### 3.Array.of() +将一组数值,转换成**数组**,弥补`Array`方法参数不同导致的差异。 +```js +Array.of(1,2,3); // [1,2,3] +Array.of(1).length; // 1 + +Array(); // [] +Array(2); // [,] 1个参数时,为指定数组长度 +Array(1,2,3); // [1,2,3] 多于2个参数,组成新数组 +``` + +#### 4.find()和findIndex() +`find()`方法用于找出第一个符合条件的数组成员,参数为一个回调函数,所有成员依次执行该回调函数,返回第一个返回值为`true`的成员,如果没有一个符合则返回`undefined`。 +```js +[1,2,3,4,5].find( a => a < 3 ); // 1 +``` +回调函数接收三个参数,当前值、当前位置和原数组。 +```js +[1,2,3,4,5].find((value, index, arr){ + // ... +}); +``` +`findIndex()`方法与`find()`类似,返回第一个符合条件的数组成员的**位置**,如果都不符合则返回`-1`。 +```js +[1,2,3,4].findIndex((v,i,a)=>{ + return v>2; +}); // 2 +``` + +#### 5.fill() +用于用指定值**填充**一个数组,通常用来**初始化空数组**,并抹去数组中已有的元素。 +```js +new Array(3).fill('a'); // ['a','a','a'] +[1,2,3].fill('a'); // ['a','a','a'] +``` +并且`fill()`的第二个和第三个参数指定填充的**起始位置**和**结束位置**。 +```js +[1,2,3].fill('a',1,2); +``` + +#### 6.entries(),keys(),values() +主要用于遍历数组,`entries()`对键值对遍历,`keys()`对键名遍历,`values()`对键值遍历。 +```js +for (let i of ['a', 'b'].keys()){ + console.log(i) +} +// 0 +// 1 + +for (let e of ['a', 'b'].keys()){ + console.log(e) +} +// 'a' +// 'b' + +for (let e of ['a', 'b'].keys()){ + console.log(e) +} +// 0 'a' +// 1 'b' +``` + +#### 7.includes() +用于表示数组是否包含给定的值,与字符串的`includes`方法类似。 +```js +[1,2,3].includes(2); // true +[1,2,3].includes(4); // false +[1,2,NaN].includes(NaN); // true +``` +第二个参数为**起始位置**,默认为`0`,如果负数,则表示倒数的位置,如果大于数组长度,则重置为`0`开始。 +```js +[1,2,3].includes(3,3); // false +[1,2,3].includes(3,4); // false +[1,2,3].includes(3,-1); // true +[1,2,3].includes(3,-4); // true +``` + +#### 8.flat(),flatMap() +`flat()`用于将数组一维化,返回一个新数组,不影响原数组。 +默认一次只一维化一层数组,若需多层,则传入一个整数参数指定层数。 +若要一维化所有层的数组,则传入`Infinity`作为参数。 +```js +[1, 2, [2,3]].flat(); // [1,2,2,3] +[1,2,[3,[4,[5,6]]]].flat(3); // [1,2,3,4,5,6] +[1,2,[3,[4,[5,6]]]].flat('Infinity'); // [1,2,3,4,5,6] +``` +`flatMap()`是将原数组每个对象先执行一个函数,在对返回值组成的数组执行`flat()`方法,返回一个新数组,不改变原数组。 + `flatMap()`只能展开一层。 +```js +[2, 3, 4].flatMap((x) => [x, x * 2]); +// [2, 4, 3, 6, 4, 8] +``` ## 2. ES7 From 7c29f4d6aab666b3bf4648b105265097bfce9370 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 22 Oct 2018 22:50:58 +0800 Subject: [PATCH 087/835] 2018.10.22 --- EXEFE-es6book/README.md | 55 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index d86e88c8..7c6026d2 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -63,6 +63,7 @@ - [4. ES9](#4-es9) - [5. 知识补充](#5-知识补充) - [块级作用域](#块级作用域) + - [ES5/6对数组空位的处理](#es56对数组空位的处理) - [四、结语](#四结语) @@ -1178,6 +1179,7 @@ for (let e of ['a', 'b'].keys()){ // [2, 4, 3, 6, 4, 8] ``` + ## 2. ES7 ## 3. ES8 @@ -1220,5 +1222,58 @@ console.log(i); // 5 ``` 循环结束后,变量 `i` 的值依然存在,造成变量的全局污染。 +### ES5/6对数组空位的处理 + +数组的空位不是`undefined`,而是没有任何值,数组的`undefined`也是有值。 +```js +0 in [undefined,undefined,undefined] // true +0 in [,,,] // false +``` +**ES5对空位的处理**: +* `forEach()`, `filter()`, `reduce()`, `every()` 和`some()`都会跳过空位。 +* `map()`会跳过空位,但会保留这个值。 +* `join()`和`toString()`会将空位视为`undefined`,而`undefined`和`null`会被处理成空字符串。 +```js +[,'a'].forEach((x,i) => console.log(i)); // 1 +['a',,'b'].filter(x => true); // ['a','b'] +[,'a'].every(x => x==='a'); // true +[1,,2].reduce((x,y) => x+y); // 3 +[,'a'].some(x => x !== 'a'); // false +[,'a'].map(x => 1); // [,1] +[,'a',undefined,null].join('#'); // "#a##" +[,'a',undefined,null].toString(); // ",a,," +``` +**ES6对空位的处理**: +将空位视为正常值,转成`undefined`。 +```js +Array.from(['a',,'b']);// [ "a", undefined, "b" ] +[...['a',,'b']]; // [ "a", undefined, "b" ] + +//copyWithin() 会连空位一起拷贝。 +[,'a','b',,].copyWithin(2,0) // [,"a",,"a"] + +//fill()会将空位视为正常的数组位置。 +new Array(3).fill('a') // ["a","a","a"] + +//for...of循环也会遍历空位。 +let arr = [, ,]; +for (let i of arr) { + console.log(1); +} // 1 1 +``` +`entries()`、`keys()`、`values()`、`find()`和`findIndex()`会将空位处理成`undefined`。 +```js +[...[,'a'].entries()] // [[0,undefined], [1,"a"]] + +[...[,'a'].keys()] // [0,1] + +[...[,'a'].values()] // [undefined,"a"] + +[,'a'].find(x => true) // undefined + +[,'a'].findIndex(x => true) // 0 +``` +**由于空位的处理规则非常不统一,所以建议避免出现空位。** + # 四、结语 From a05d5222da233fbdc59f92a561f844d551f72afb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 22 Oct 2018 22:56:51 +0800 Subject: [PATCH 088/835] 2018.10.22 --- EXEFE-es6book/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 7c6026d2..7ae3aebd 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -7,12 +7,12 @@ - [ ] ES9 - [ ] 知识补充 > 最后更新 2018.10.22 -> 也在思考,如何整理好这一份资料,让看的人,都各有收获。 +> 在思考,如何整理好这一份资料,让不同阶段的人,能有不同的收获。 # 一、介绍 -现如今网络上已经有各式各样关于 **ECMAScript** 规范的介绍和分析的文章,而我准备整理一份比较完善也比较精简便于快速入门的资料。 +现如今网络上已经有各式各样关于 **ECMAScript** 规范的介绍和分析的文章,而我准备整理一份比较完善也比较精简适合快速入门的资料,主要内容将涵盖**ES6**、**ES7**、**ES8**、**ES9**,如有异议欢迎指点。 这份资料的**ES6部分**将会参考阮一峰老师的 [ECMAScript6入门](http://es6.ruanyifeng.com/) ,精简和整理出快速实用的内容。 -另外**ES7/ES8/ES9**则会从网络参考和整理。 +另外**ES7/ES8/ES9**则会从网络综合参考和整理。 # 二、目录 From 3d59fc450e5b49a862fb995da66fe0657e61a8e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Tue, 23 Oct 2018 22:41:05 +0800 Subject: [PATCH 089/835] 2018.10.23 --- EXEFE-es6book/README.md | 143 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 140 insertions(+), 3 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 7ae3aebd..47dd6658 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -49,7 +49,7 @@ - [3.name 属性](#3name-属性) - [4.箭头函数](#4箭头函数) - [5.双冒号运算符](#5双冒号运算符) - - [对象的拓展](#对象的拓展) + - [数组的拓展](#数组的拓展) - [1.拓展运算符](#1拓展运算符) - [2.Array.from()](#2arrayfrom) - [3.Array.of()](#3arrayof) @@ -58,7 +58,14 @@ - [6.entries(),keys(),values()](#6entrieskeysvalues) - [7.includes()](#7includes) - [8.flat(),flatMap()](#8flatflatmap) + - [对象的拓展](#对象的拓展) + - [1.属性的简洁表示](#1属性的简洁表示) + - [2.属性名表达式](#2属性名表达式) + - [3.Object.is()](#3objectis) + - [4.Object.assign()](#4objectassign) - [2. ES7](#2-es7) + - [Object.keys(),Object.values(),Object.entries()](#objectkeysobjectvaluesobjectentries) + - [Object.getOwnPropertyDescriptors()](#objectgetownpropertydescriptors) - [3. ES8](#3-es8) - [4. ES9](#4-es9) - [5. 知识补充](#5-知识补充) @@ -978,7 +985,7 @@ let f = a::a.b; let f = ::a.b; ``` -### 对象的拓展 +### 数组的拓展 #### 1.拓展运算符 拓展运算符使用(`...`),类似`rest`参数的逆运算,将数组转为用(`,`)分隔的参数序列。 ```js @@ -1180,7 +1187,137 @@ for (let e of ['a', 'b'].keys()){ ``` +### 对象的拓展 +#### 1.属性的简洁表示 +```js +let a = 'a1'; +let b = { a }; // b => { a : 'a1' } +// 等同于 +let b = { a : a }; + +function f(a, b){ + return {a, b}; +} +// 等同于 +function f (a, b){ + return {a:a ,b:b}; +} + +let a = { + fun () { + return 'leo'; + } +} +// 等同于 +let a = { + fun : function(){ + return 'leo'; + } +} +``` + +#### 2.属性名表达式 +`JavaScript`提供2种方法**定义对象的属性**。 +```js +// 方法1 标识符作为属性名 +a.f = true; + +// 方法2 字符串作为属性名 +a['f' + 'un'] = true; +``` +延伸出来的还有: +```js +let a = 'hi leo'; +let b = { + [a]: true, + ['a'+'bc']: 123, + ['my' + 'fun'] (){ + return 'hi'; + } +}; +// b.a => undefined ; b.abc => 123 ; b.myfun() => 'hi' +// b[a] => 'hi leo' ; b['abc'] => 123 ; b['myfun'] => 'hi' +``` +**注意**: +属性名表达式不能与简介表示法同时使用,否则报错。 +```js +// 报错 +let a1 = 'aa'; +let a2 = 'bb'; +let b1 = {[a1]}; + +// 正确 +let a1 = 'aa'; +let b1 = { [a1] : 'bb'}; +``` + +#### 3.Object.is() +`.Object.is()` 用于比较两个值是否严格相等,在ES5时候只要使用**相等运算符**(`==`)和**严格相等运算符**(`===`)就可以做比较,但是它们都有缺点,前者会**自动转换数据类型**,后者的`NaN`不等于自身,以及`+0`等于`-0`。 +```js +Object.is('a','a'); // true +Object.is({}, {}); // false + +// ES5 ++0 === -0 ; // true +NaN === NaN; // false + +// ES6 +Object.is(+0,-0); // false +Object.is(NaN,NaN); // true +``` + +#### 4.Object.assign() +`Object.assign()`方法用于对象的合并,将原对象的所有可枚举属性复制到目标对象。 +**基础用法**: +第一个参数是**目标对象**,后面参数都是**源对象**。 +```js +let a = {a:1}; +let b = {b:2}; +Object.assign(a,b); // a=> {a:1,b:2} +``` +**注意**: +* 若目标对象与源对象有同名属性,则后面属性会覆盖前面属性。 +```js +let a = {a:1, b:2}; +let b = {b:3, c:4}; +Object.assign(a, b); // a => {a:1, b:3, c:4} +``` +* 若只有**一个**参数,则返回该参数。 +```js +let a = {a:1}; +Object.assign(a) === a; // true +``` +* 若参数**不是对象**,则先转成对象后返回。 +```js +typeof Object.assign(2); // 'object' +``` +* 由于`undefined`或`NaN`无法转成对象,所以做为参数会报错。 +```js +Object.assign(undefined) // 报错 +Object.assign(NaN); // 报错 +``` +* `Object.assign()`实现的是浅拷贝。 + +`Object.assign()`拷贝得到的是这个对象的引用。这个对象的任何变化,都会反映到目标对象上面。 +```js +let a = {a: {b:1}}; +let b = Object.assign({},a); +a.a.b = 2; +console.log(b.a.b); // 2 +``` +* 将数组当做对象处理,键名为数组下标,键值为数组下标对应的值。 +```js +Object.assign([1, 2, 3], [4, 5]); // [4, 5, 3] +``` + + ## 2. ES7 +### Object.keys(),Object.values(),Object.entries() +[对应地址](http://es6.ruanyifeng.com/#docs/object#Object-assign) + +### Object.getOwnPropertyDescriptors() + +[对应地址](http://es6.ruanyifeng.com/#docs/object#Object-assign) ## 3. ES8 @@ -1276,4 +1413,4 @@ for (let i of arr) { **由于空位的处理规则非常不统一,所以建议避免出现空位。** -# 四、结语 +# 四、结语 \ No newline at end of file From b6aa2fd8ed0be621aa4653bb400e71447fe87638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Wed, 24 Oct 2018 09:28:46 +0800 Subject: [PATCH 090/835] =?UTF-8?q?2018.10.24=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E9=94=99=E5=88=AB=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 47dd6658..770ae998 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -1239,7 +1239,7 @@ let b = { // b[a] => 'hi leo' ; b['abc'] => 123 ; b['myfun'] => 'hi' ``` **注意**: -属性名表达式不能与简介表示法同时使用,否则报错。 +属性名表达式不能与简洁表示法同时使用,否则报错。 ```js // 报错 let a1 = 'aa'; @@ -1413,4 +1413,4 @@ for (let i of arr) { **由于空位的处理规则非常不统一,所以建议避免出现空位。** -# 四、结语 \ No newline at end of file +# 四、结语 From 874a4d968341fb1918e6990f4d69fbf3b45ded80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Wed, 24 Oct 2018 23:00:34 +0800 Subject: [PATCH 091/835] =?UTF-8?q?2018.10.24=20=E6=B7=BB=E5=8A=A0**ES6**?= =?UTF-8?q?=E7=AB=A0=E8=8A=82=E3=80=8A**Symbol**=E3=80=8B=E5=92=8C?= =?UTF-8?q?=E3=80=8A**Set=E5=92=8CMap=E6=95=B0=E6=8D=AE=E7=BB=93=E6=9E=84*?= =?UTF-8?q?*=E3=80=8B=E7=9A=84=E6=95=B4=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 316 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 314 insertions(+), 2 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 770ae998..48896a92 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -6,9 +6,12 @@ - [ ] ES8 - [ ] ES9 - [ ] 知识补充 -> 最后更新 2018.10.22 > 在思考,如何整理好这一份资料,让不同阶段的人,能有不同的收获。 +**更新记录**: +...前面几天没有写记录。 +* 2018.10.24 添加**ES6**章节《**Symbol**》和《**Set和Map数据结构**》的整理。 + # 一、介绍 现如今网络上已经有各式各样关于 **ECMAScript** 规范的介绍和分析的文章,而我准备整理一份比较完善也比较精简适合快速入门的资料,主要内容将涵盖**ES6**、**ES7**、**ES8**、**ES9**,如有异议欢迎指点。 这份资料的**ES6部分**将会参考阮一峰老师的 [ECMAScript6入门](http://es6.ruanyifeng.com/) ,精简和整理出快速实用的内容。 @@ -63,6 +66,14 @@ - [2.属性名表达式](#2属性名表达式) - [3.Object.is()](#3objectis) - [4.Object.assign()](#4objectassign) + - [Symbol](#symbol) + - [1.介绍](#1介绍) + - [2.更多介绍](#2更多介绍) + - [Set和Map数据结构](#set和map数据结构) + - [1.Set](#1set) + - [2.Set的应用](#2set的应用) + - [3.Map](#3map) + - [4.Map与其他数据结构互相转换](#4map与其他数据结构互相转换) - [2. ES7](#2-es7) - [Object.keys(),Object.values(),Object.entries()](#objectkeysobjectvaluesobjectentries) - [Object.getOwnPropertyDescriptors()](#objectgetownpropertydescriptors) @@ -1310,6 +1321,307 @@ console.log(b.a.b); // 2 Object.assign([1, 2, 3], [4, 5]); // [4, 5, 3] ``` +### Symbol +#### 1.介绍 +ES6引入`Symbol`作为一种新的**原始数据类型**,表示**独一无二**的值,主要是为了**防止属性名冲突**。 +ES6之后,JavaScript一共有其中数据类型:`Symbol`、`undefined`、`null`、`Boolean`、`String`、`Number`、`Object`。 +简单实用: +```js +let a = Symbol(); +typeof a; // "symbol" +``` +**注意:** +* `Symbol`函数不能用`new`,会报错。由于`Symbol`是一个原始类型,不是对象,所以不能添加属性,它是类似于字符串的数据类型。 +* `Symbol`都是不相等的,即使参数相同。 +```js +let a1 = Symbol(); +let a2 = Symbal(); +a1 === a2; // false + +let a1 = Symbol('abc'); +let a2 = Symbal('abc'); +a1 === a2; // false +``` +* `Symbol`不能与其他类型的值计算,会报错。 +```js +let a = Symbol('hello'); +a + " world!"; // 报错 +`${a} world!`; // 报错 +``` + +#### 2.更多介绍 +详细介绍[参考阮一峰老师的ES6 Symbol介绍](http://es6.ruanyifeng.com/#docs/symbol) + +### Set和Map数据结构 +#### 1.Set +**介绍**: +`Set`数据结构类似数组,但所有成员的值**唯一**。 +`Set`本身为一个构造函数,用来生成`Set`数据结构,使用`add`方法来添加新成员。 +```js +let a = new Set(); +[1,2,2,1,3,4,5,4,5].forEach(x=>a.add(x)); +for(let k of a){ + console.log(k) +}; +// 1 2 3 4 5 +``` +**基础使用**: +```js +let a = new Set([1,2,3,3,4]); +[...a]; // [1,2,3,4] +a.size; // 4 + +// 数组去重 +[...new Set([1,2,3,4,4,4])];// [1,2,3,4] +``` + +**注意**: +* 向`Set`中添加值的时候,不会类型转换,即`5`和`'5'`是不同的。 +```js +[...new Set([5,'5'])]; // [5, "5"] +``` + +**属性和方法**: +* 属性: + * `Set.prototype.constructor`:构造函数,默认就是`Set`函数。 + * `Set.prototype.size`:返回`Set`实例的成员总数。 + +* 操作方法: + * `add(value)`:添加某个值,返回 Set 结构本身。 + * `delete(value)`:删除某个值,返回一个布尔值,表示删除是否成功。 + * `has(value)`:返回一个布尔值,表示该值是否为Set的成员。 + * `clear()`:清除所有成员,没有返回值。 + +```js +let a = new Set(); +a.add(1).add(2); // a => Set(2) {1, 2} +a.has(2); // true +a.has(3); // false +a.delete(2); // true a => Set(1) {1} +a.clear(); // a => Set(0) {} +``` +**数组去重**: +```js +let a = new Set([1,2,3,3,3,3]); +``` +#### 2.Set的应用 +**数组去重**: +```js +// 方法1 +[...new Set([1,2,3,4,4,4])]; // [1,2,3,4] +// 方法2 +Array.from([1,2,3,4,4,4]); // [1,2,3,4] +``` +**遍历和过滤**: +```js +let a = new Set([1,2,3,4]); + +// map 遍历操作 +let b = new Set([...a].map(x =>x*2));// b => Set(4) {2,4,6,8} + +// filter 过滤操作 +let c = new Set([...a].filter(x =>(x%2) == 0)); // b => Set(2) {2,4} +``` +**获取并集、交集和差集**: +```js +let a = new Set([1,2,3]); +let b = new Set([4,3,2]); + +// 并集 +let c1 = new Set([...a, ...b]); // Set {1,2,3,4} + +// 交集 +let c2 = new Set([...a].filter(x => b.has(x))); // set {2,3} + +// 差集 +let c3 = new Set([...a].filter(x => !b.has(x))); // set {1,4} +``` + +* 遍历方法: + * `keys()`:返回**键名**的遍历器。 + * `values()`:返回**键值**的遍历器。 + * `entries()`:返回**键值对**的遍历器。 + * `forEach()`:使用回调函数遍历**每个成员**。 + +`Set`遍历顺序是**插入顺序**,当保存多个回调函数,只需按照顺序调用。但由于`Set`结构**没有键名只有键值**,所以`keys()`和`values()`是返回结果相同。 +```js +let a = new Set(['a','b','c']); +for(let i of a.keys()){console.log(i)}; // 'a' 'b' 'c' +for(let i of a.values()){console.log(i)}; // 'a' 'b' 'c' +for(let i of a.entries()){console.log(i)}; +// ['a','a'] ['b','b'] ['c','c'] +``` +并且 还可以使用`for...of```直接遍历`Set`。 +```js +let a = new Set(['a','b','c']); +for(let k of a){console.log(k)}; // 'a' 'b' 'c' +``` +`forEach`与数组相同,对每个成员执行操作,且无返回值。 +```js +let a = new Set(['a','b','c']); +a.forEach((v,k) => console.log(k + ' : ' + v)); +``` + + +### 3.Map +由于传统的`JavaScript`对象只能用字符串当做键,给开发带来很大限制,ES6增加`Map`数据结构,使得**各种类型的值**(包括对象)都可以作为键。 +`Map`结构提供了“**值—值**”的对应,是一种更完善的 Hash 结构实现。 +**基础使用**: +```js +let a = new Map(); +let b = {name: 'leo' }; +a.set(b,'my name'); // 添加值 +a.get(b); // 获取值 +a.size; // 获取总数 +a.has(b); // 查询是否存在 +a.delete(b); // 删除一个值 +a.clear(); // 清空所有成员 无返回 +``` +**注意**: +* 传入数组作为参数,**指定键值对的数组**。 +```js +let a = new Map([ + ['name','leo'], + ['age',18] +]) +``` +* 如果对同一个键**多次赋值**,后面的值将**覆盖前面的值**。 +```js +let a = new Map(); +a.set(1,'aaa').set(1,'bbb'); +a.get(1); // 'bbb' +``` +* 如果读取一个未知的键,则返回`undefined`。 +```js +new Map().get('abcdef'); // undefined +``` +* **同样的值**的两个实例,在 Map 结构中被视为两个键。 +```js +let a = new Map(); +let a1 = ['aaa']; +let a2 = ['aaa']; +a.set(a1,111).set(a2,222); +a.get(a1); // 111 +a.get(a2); // 222 +``` +**遍历方法**: +Map 的遍历顺序就是插入顺序。 +* `keys()`:返回键名的遍历器。 +* `values()`:返回键值的遍历器。 +* `entries()`:返回所有成员的遍历器。 +* `forEach()`:遍历 Map 的所有成员。 +```js +let a = new Map([ + ['name','leo'], + ['age',18] +]) + +for (let i of a.keys()){...}; +for (let i of a.values()){...}; +for (let i of a.entries()){...}; +a.forEach((v,k,m)=>{ + console.log(`key:${k},value:${v},map:${m}`) +}) +``` +**将Map结构转成数组结构**: +```js +let a = new Map([ + ['name','leo'], + ['age',18] +]) + +let a1 = [...a.keys()]; // a1 => ["name", "age"] +let a2 = [...a.values()]; // a2 =>  ["leo", 18] +let a3 = [...a.entries()];// a3 => [['name','leo'], ['age',18]] +``` + +#### 4.Map与其他数据结构互相转换 +* Map 转 数组 +```js +let a = new Map().set(true,1).set({f:2},['abc']); +[...a]; // [[true:1], [ {f:2},['abc'] ]] +``` +* 数组 转 Map +```js +let a = [ ['name','leo'], [1, 'hi' ]] +let b = new Map(a); +``` +* Map 转 对象 +如果所有 Map 的键都是字符串,它可以无损地转为对象。 +如果有非字符串的键名,那么这个键名会被转成字符串,再作为对象的键名。 +```js +function fun(s) { + let obj = Object.create(null); + for (let [k,v] of s) { + obj[k] = v; + } + return obj; +} + +const a = new Map().set('yes', true).set('no', false); +fun(a) +// { yes: true, no: false } +``` +* 对象 转 Map +```js +function fun(obj) { + let a = new Map(); + for (let k of Object.keys(obj)) { + a.set(k, obj[k]); + } + return a; +} + +fun({yes: true, no: false}) +// Map {"yes" => true, "no" => false} +``` + +* Map 转 JSON +**(1)Map键名都是字符串,转为对象JSON:** +```js +function fun (s) { + let obj = Object.create(null); + for (let [k,v] of s) { + obj[k] = v; + } + return JSON.stringify(obj) +} +let a = new Map().set('yes', true).set('no', false); +fun(a); +// '{"yes":true,"no":false}' +``` +**(2)Map键名有非字符串,转为数组JSON:** +```js +function fun (map) { + return JSON.stringify([...map]); +} + +let a = new Map().set(true, 7).set({foo: 3}, ['abc']); +fun(a) +// '[[true,7],[{"foo":3},["abc"]]]' +``` +* JSON 转 Map +**(1)所有键名都是字符串:** +```js +function fun (s) { + let strMap = new Map(); + for (let k of Object.keys(s)) { + strMap.set(k, s[k]); + } + return strMap; + return JSON.parse(strMap); +} +fun('{"yes": true, "no": false}') +// Map {'yes' => true, 'no' => false} +``` +**(2)整个 JSON 就是一个数组,且每个数组成员本身,又是一个有两个成员的数组**: +```js +function fun2(s) { + return new Map(JSON.parse(s)); +} +fun2('[[true,7],[{"foo":3},["abc"]]]') +// Map {true => 7, Object {foo: 3} => ['abc']} +``` ## 2. ES7 ### Object.keys(),Object.values(),Object.entries() @@ -1413,4 +1725,4 @@ for (let i of arr) { **由于空位的处理规则非常不统一,所以建议避免出现空位。** -# 四、结语 +# 四、结语 \ No newline at end of file From 0510a3a5ecf16e2363d9f1336e8f56f35e90f9b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Wed, 24 Oct 2018 23:03:33 +0800 Subject: [PATCH 092/835] =?UTF-8?q?2018.10.24=20=E6=B7=BB=E5=8A=A0**ES6**?= =?UTF-8?q?=E7=AB=A0=E8=8A=82=E3=80=8A**Symbol**=E3=80=8B=E5=92=8C?= =?UTF-8?q?=E3=80=8A**Set=E5=92=8CMap=E6=95=B0=E6=8D=AE=E7=BB=93=E6=9E=84*?= =?UTF-8?q?*=E3=80=8B=E7=9A=84=E6=95=B4=E7=90=86=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 48896a92..39f69aac 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -72,7 +72,7 @@ - [Set和Map数据结构](#set和map数据结构) - [1.Set](#1set) - [2.Set的应用](#2set的应用) - - [3.Map](#3map) + - [3.Map](#3map) - [4.Map与其他数据结构互相转换](#4map与其他数据结构互相转换) - [2. ES7](#2-es7) - [Object.keys(),Object.values(),Object.entries()](#objectkeysobjectvaluesobjectentries) @@ -1463,7 +1463,7 @@ a.forEach((v,k) => console.log(k + ' : ' + v)); ``` -### 3.Map +#### 3.Map 由于传统的`JavaScript`对象只能用字符串当做键,给开发带来很大限制,ES6增加`Map`数据结构,使得**各种类型的值**(包括对象)都可以作为键。 `Map`结构提供了“**值—值**”的对应,是一种更完善的 Hash 结构实现。 **基础使用**: @@ -1725,4 +1725,6 @@ for (let i of arr) { **由于空位的处理规则非常不统一,所以建议避免出现空位。** -# 四、结语 \ No newline at end of file +# 四、结语 + +[回到顶部](#一介绍) \ No newline at end of file From ec0882db6d8bb08efa33a6a7d2246d63570754a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Wed, 24 Oct 2018 23:10:21 +0800 Subject: [PATCH 093/835] =?UTF-8?q?2018.10.24=20=E6=B7=BB=E5=8A=A0ES6?= =?UTF-8?q?=E7=AB=A0=E8=8A=82=E3=80=8ASymbol=E3=80=8B=E5=92=8C=E3=80=8ASet?= =?UTF-8?q?=E5=92=8CMap=E6=95=B0=E6=8D=AE=E7=BB=93=E6=9E=84=E3=80=8B?= =?UTF-8?q?=E7=9A=84=E6=95=B4=E7=90=86=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 39f69aac..81e81685 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -176,6 +176,7 @@ let PI = 0; // Uncaught SyntaxError: Identifier 'PI' has already been declared ``` +[⬆ 返回目录](#二目录) ### 变量的解构赋值 **解构赋值概念**:在ES6中,直接从数组和对象中取值,按照对应位置,赋值给变量的操作。 @@ -406,6 +407,9 @@ const {log, sin, cos} = require('math'); ``` +[⬆ 返回目录](#二目录) + + ### 字符串的拓展 #### 1.includes(),startsWith(),endsWith() 在我们判断字符串是否包含另一个字符串时,ES6之前,我们只有`typeof`方法,ES6之后我们又多了三种方法: @@ -502,8 +506,14 @@ let a = 'abc' + v1 + 'def'; let a = `abc${v1}def` ``` +[⬆ 返回目录](#二目录) + + ### 正则的拓展 +[⬆ 返回目录](#二目录) + + ### 数值的拓展 #### 1.Number.isFinite(), Number.isNaN() `Number.isFinite()` 用于检查一个数值是否是有限的,即不是`Infinity`,若参数不是`Number`类型,则一律返回`false` 。 @@ -779,6 +789,10 @@ Math.pow(99, 99) // 3.697296376497268e+197 ``` + +[⬆ 返回目录](#二目录) + + ### 函数的拓展 #### 1.参数默认值 ```js @@ -996,6 +1010,9 @@ let f = a::a.b; let f = ::a.b; ``` +[⬆ 返回目录](#二目录) + + ### 数组的拓展 #### 1.拓展运算符 拓展运算符使用(`...`),类似`rest`参数的逆运算,将数组转为用(`,`)分隔的参数序列。 @@ -1197,6 +1214,8 @@ for (let e of ['a', 'b'].keys()){ // [2, 4, 3, 6, 4, 8] ``` +[⬆ 返回目录](#二目录) + ### 对象的拓展 #### 1.属性的简洁表示 @@ -1321,6 +1340,9 @@ console.log(b.a.b); // 2 Object.assign([1, 2, 3], [4, 5]); // [4, 5, 3] ``` +[⬆ 返回目录](#二目录) + + ### Symbol #### 1.介绍 ES6引入`Symbol`作为一种新的**原始数据类型**,表示**独一无二**的值,主要是为了**防止属性名冲突**。 @@ -1352,6 +1374,10 @@ a + " world!"; // 报错 #### 2.更多介绍 详细介绍[参考阮一峰老师的ES6 Symbol介绍](http://es6.ruanyifeng.com/#docs/symbol) + +[⬆ 返回目录](#二目录) + + ### Set和Map数据结构 #### 1.Set **介绍**: @@ -1623,18 +1649,27 @@ fun2('[[true,7],[{"foo":3},["abc"]]]') // Map {true => 7, Object {foo: 3} => ['abc']} ``` +[⬆ 返回目录](#二目录) + + ## 2. ES7 ### Object.keys(),Object.values(),Object.entries() [对应地址](http://es6.ruanyifeng.com/#docs/object#Object-assign) +[⬆ 返回目录](#二目录) + ### Object.getOwnPropertyDescriptors() [对应地址](http://es6.ruanyifeng.com/#docs/object#Object-assign) +[⬆ 返回目录](#二目录) + ## 3. ES8 ## 4. ES9 +[⬆ 返回目录](#二目录) + ## 5. 知识补充 ### 块级作用域 @@ -1671,6 +1706,10 @@ console.log(i); // 5 ``` 循环结束后,变量 `i` 的值依然存在,造成变量的全局污染。 + +[⬆ 返回目录](#二目录) + + ### ES5/6对数组空位的处理 数组的空位不是`undefined`,而是没有任何值,数组的`undefined`也是有值。 From 0dc5caba6683c2042525c27991d51f78c2cad4e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Thu, 25 Oct 2018 15:28:50 +0800 Subject: [PATCH 094/835] =?UTF-8?q?2018.10.25=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E9=94=99=E5=88=AB=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 81e81685..504446d6 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -612,11 +612,11 @@ Math.trunc = Math.trunc || function(x){ * **Math.sign()**: 判断一个数是**正数**、**负数**还**是零**,对于非数值,会先转成**数值**。 返回值: -> 参数为正数, 返回 +1 -> 参数为负数, 返回 -1 -> 参数为0, 返回 0 -> 参数为-0, 返回 -0 -> 参数为其他值, 返回 NaN + * 参数为正数, 返回 +1 + * 参数为负数, 返回 -1 + * 参数为0, 返回 0 + * 参数为-0, 返回 -0 + * 参数为其他值, 返回 NaN ```js Math.sign(-1); // -1 Math.sign(1); // +1 @@ -646,7 +646,7 @@ Math.sign = Math.sign || function (x){ ``` * **Math.cbrt()**: -用来计算一个数的立方根,若参数为非数值则先转成数值。 +用来计算一个数的立方根,若参数为非数值则先转成数值。 ```js Math.cbrt(-1); // -1 Math.cbrt(0); // 0 @@ -665,7 +665,7 @@ Math.cbrt = Math.cbrt || function (x){ ``` * **Math.clz32()**: -用于返回一个数的 32 位无符号整数形式有多少个前导 0。 +用于返回一个数的 32 位无符号整数形式有多少个前导 0。 ```js Math.clz32(0) // 32 Math.clz32(1) // 31 @@ -675,7 +675,7 @@ Math.clz32(0b00100000000000000000000000000000) // 2 ``` * **Math.imul()**: -用于返回两个数以 32 位带符号整数形式相乘的结果,返回的也是一个 32 位的带符号整数。 +用于返回两个数以 32 位带符号整数形式相乘的结果,返回的也是一个 32 位的带符号整数。 ```js Math.imul(2, 4) // 8 Math.imul(-1, 8) // -8 @@ -765,12 +765,12 @@ Math.log2 = Math.log2 || function(x) { }; ``` * **双曲函数方法**: ->`Math.sinh(x)` 返回x的**双曲正弦**(hyperbolic sine) ->`Math.cosh(x)` 返回x的**双曲余弦**(hyperbolic cosine) ->`Math.tanh(x)` 返回x的**双曲正切**(hyperbolic tangent) ->`Math.asinh(x)` 返回x的**反双曲正弦**(inverse hyperbolic sine) ->`Math.acosh(x)` 返回x的**反双曲余弦**(inverse hyperbolic cosine) ->`Math.atanh(x)` 返回x的**反双曲正切**(inverse hyperbolic tangent) + * `Math.sinh(x)` 返回x的**双曲正弦**(hyperbolic sine) + * `Math.cosh(x)` 返回x的**双曲余弦**(hyperbolic cosine) + * `Math.tanh(x)` 返回x的**双曲正切**(hyperbolic tangent) + * `Math.asinh(x)` 返回x的**反双曲正弦**(inverse hyperbolic sine) + * `Math.acosh(x)` 返回x的**反双曲余弦**(inverse hyperbolic cosine) + * `Math.atanh(x)` 返回x的**反双曲正切**(inverse hyperbolic tangent) #### 5.指数运算符 新增的指数运算符(`**`): @@ -1089,7 +1089,6 @@ let a5 = [...a1, ...a2, ...a3]; a4[0] === a1[0]; // true a5[0] === a1[0]; // true ``` - * **(3)与解构赋值结合**: 与解构赋值结合生成数组,但是使用拓展运算符需要放到参数最后一个,否则报错。 ```js @@ -1766,4 +1765,4 @@ for (let i of arr) { # 四、结语 -[回到顶部](#一介绍) \ No newline at end of file +[回到顶部](#一介绍) From 1db4366c772cd7d4508d7433c3bdf589acad8027 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Thu, 25 Oct 2018 23:50:31 +0800 Subject: [PATCH 095/835] =?UTF-8?q?2018.10.25=20=E6=B7=BB=E5=8A=A0Proxy?= =?UTF-8?q?=E7=AB=A0=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 300 ++++++++++++++++++++++++++-------------- 1 file changed, 195 insertions(+), 105 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 504446d6..befa84c6 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -10,7 +10,12 @@ **更新记录**: ...前面几天没有写记录。 -* 2018.10.24 添加**ES6**章节《**Symbol**》和《**Set和Map数据结构**》的整理。 +* 2018.10.24 添加**ES6**《**Symbol**》和《**Set和Map数据结构**》章节。 +* 2018.10.25 添加**ES6**《**Proxy**》章节,还没整理完。 + +**未来规划**: +* 1.将内容按不同模块拆分不同文件,方便README文件的阅读。 +* 2.添加案例项目。 # 一、介绍 现如今网络上已经有各式各样关于 **ECMAScript** 规范的介绍和分析的文章,而我准备整理一份比较完善也比较精简适合快速入门的资料,主要内容将涵盖**ES6**、**ES7**、**ES8**、**ES9**,如有异议欢迎指点。 @@ -24,64 +29,66 @@ - [二、目录](#二目录) - [三、正文](#三正文) - [1. ES6](#1-es6) - - [let 和 const命令](#let-和-const命令) - - [1.let 命令](#1let-命令) - - [2.const 命令](#2const-命令) - - [变量的解构赋值](#变量的解构赋值) - - [1.数组](#1数组) - - [2.对象的解构赋值](#2对象的解构赋值) - - [3.字符串的解构赋值](#3字符串的解构赋值) - - [4.数值和布尔值的解构赋值](#4数值和布尔值的解构赋值) - - [5.函数参数的解构赋值](#5函数参数的解构赋值) - - [6.用途](#6用途) - - [字符串的拓展](#字符串的拓展) - - [1.includes(),startsWith(),endsWith()](#1includesstartswithendswith) - - [2.repeat()](#2repeat) - - [3.padStart(),padEnd()](#3padstartpadend) - - [4.模版字符串](#4模版字符串) - - [正则的拓展](#正则的拓展) - - [数值的拓展](#数值的拓展) - - [1.Number.isFinite(), Number.isNaN()](#1numberisfinite-numberisnan) - - [2.Number.parseInt(), Number.parseFloat()](#2numberparseint-numberparsefloat) - - [3.Number.isInteger()](#3numberisinteger) - - [4.Math对象的拓展](#4math对象的拓展) - - [5.指数运算符](#5指数运算符) - - [函数的拓展](#函数的拓展) - - [1.参数默认值](#1参数默认值) - - [2.rest 参数](#2rest-参数) - - [3.name 属性](#3name-属性) - - [4.箭头函数](#4箭头函数) - - [5.双冒号运算符](#5双冒号运算符) - - [数组的拓展](#数组的拓展) - - [1.拓展运算符](#1拓展运算符) - - [2.Array.from()](#2arrayfrom) - - [3.Array.of()](#3arrayof) - - [4.find()和findIndex()](#4find和findindex) - - [5.fill()](#5fill) - - [6.entries(),keys(),values()](#6entrieskeysvalues) - - [7.includes()](#7includes) - - [8.flat(),flatMap()](#8flatflatmap) - - [对象的拓展](#对象的拓展) - - [1.属性的简洁表示](#1属性的简洁表示) - - [2.属性名表达式](#2属性名表达式) - - [3.Object.is()](#3objectis) - - [4.Object.assign()](#4objectassign) - - [Symbol](#symbol) - - [1.介绍](#1介绍) - - [2.更多介绍](#2更多介绍) - - [Set和Map数据结构](#set和map数据结构) - - [1.Set](#1set) - - [2.Set的应用](#2set的应用) - - [3.Map](#3map) - - [4.Map与其他数据结构互相转换](#4map与其他数据结构互相转换) + - [1.1 let 和 const命令](#11-let-和-const命令) + - [1.1.1 let 命令](#111-let-命令) + - [1.1.2 const 命令](#112-const-命令) + - [1.2 变量的解构赋值](#12-变量的解构赋值) + - [1.2.1 数组](#121-数组) + - [1.2.2 对象的解构赋值](#122-对象的解构赋值) + - [1.2.3 字符串的解构赋值](#123-字符串的解构赋值) + - [1.2.4 数值和布尔值的解构赋值](#124-数值和布尔值的解构赋值) + - [1.2.5 函数参数的解构赋值](#125-函数参数的解构赋值) + - [1.2.6 应用](#126-应用) + - [1.3 字符串的拓展](#13-字符串的拓展) + - [1.3.1 includes(),startsWith(),endsWith()](#131-includesstartswithendswith) + - [1.3.2 repeat()](#132-repeat) + - [1.3.3 padStart(),padEnd()](#133-padstartpadend) + - [1.3.4 模版字符串](#134-模版字符串) + - [1.4 正则的拓展](#14-正则的拓展) + - [1.5 数值的拓展](#15-数值的拓展) + - [1.5.1 Number.isFinite(), Number.isNaN()](#151-numberisfinite-numberisnan) + - [1.5.2 Number.parseInt(), Number.parseFloat()](#152-numberparseint-numberparsefloat) + - [1.5.3 Number.isInteger()](#153-numberisinteger) + - [1.5.4 Math对象的拓展](#154-math对象的拓展) + - [1.5.5 指数运算符](#155-指数运算符) + - [1.6 函数的拓展](#16-函数的拓展) + - [1.6.1 参数默认值](#161-参数默认值) + - [1.6.2 rest 参数](#162-rest-参数) + - [1.6.3 name 属性](#163-name-属性) + - [1.6.4 箭头函数](#164-箭头函数) + - [1.6.5 双冒号运算符](#165-双冒号运算符) + - [1.7 数组的拓展](#17-数组的拓展) + - [1.7.1 拓展运算符](#171-拓展运算符) + - [1.7.2 Array.from()](#172-arrayfrom) + - [1.7.3 Array.of()](#173-arrayof) + - [1.7.4 find()和findIndex()](#174-find和findindex) + - [1.7.5 fill()](#175-fill) + - [1.7.6 entries(),keys(),values()](#176-entrieskeysvalues) + - [1.7.7 includes()](#177-includes) + - [1.7.8 flat(),flatMap()](#178-flatflatmap) + - [1.8 对象的拓展](#18-对象的拓展) + - [1.8.1 属性的简洁表示](#181-属性的简洁表示) + - [1.8.2 属性名表达式](#182-属性名表达式) + - [1.8.3 Object.is()](#183-objectis) + - [1.8.4 Object.assign()](#184-objectassign) + - [1.9 Symbol](#19-symbol) + - [1.9.1 介绍](#191-介绍) + - [1.9.2 更多介绍](#192-更多介绍) + - [1.10 Set和Map数据结构](#110-set和map数据结构) + - [1.10.1 Set](#1101-set) + - [1.10.2 Set的应用](#1102-set的应用) + - [1.10.3 Map](#1103-map) + - [1.10.4 Map与其他数据结构互相转换](#1104-map与其他数据结构互相转换) + - [1.11 Proxy](#111-proxy) + - [1.11.1 基础使用](#1111-基础使用) - [2. ES7](#2-es7) - [Object.keys(),Object.values(),Object.entries()](#objectkeysobjectvaluesobjectentries) - [Object.getOwnPropertyDescriptors()](#objectgetownpropertydescriptors) - [3. ES8](#3-es8) - [4. ES9](#4-es9) - [5. 知识补充](#5-知识补充) - - [块级作用域](#块级作用域) - - [ES5/6对数组空位的处理](#es56对数组空位的处理) + - [5.1 块级作用域](#51-块级作用域) + - [5.2 ES5/6对数组空位的处理](#52-es56对数组空位的处理) - [四、结语](#四结语) @@ -89,11 +96,11 @@ # 三、正文 ## 1. ES6 -### let 和 const命令 +### 1.1 let 和 const命令 在ES6中,我们通常实用 `let` 表示**变量**,`const` 表示**常量**,并且 `let` 和 `const` 都是**块级作用域**,且在**当前作用域有效**不能重复声明。 -#### 1.let 命令 +#### 1.1.1 let 命令 `let` 命令的用法和 `var` 相似,但是 `let` 只在所在代码块内有效。 **基础用法**: ```js @@ -149,7 +156,7 @@ function f4 (a2){ } ``` -#### 2.const 命令 +#### 1.1.2 const 命令 `const` 声明一个**只读**的**常量**。 **基础用法**: ```js @@ -178,10 +185,10 @@ let PI = 0; [⬆ 返回目录](#二目录) -### 变量的解构赋值 +### 1.2 变量的解构赋值 **解构赋值概念**:在ES6中,直接从数组和对象中取值,按照对应位置,赋值给变量的操作。 -#### 1.数组 +#### 1.2.1 数组 **基础用法**: ```js // ES6 之前 @@ -245,7 +252,7 @@ let [a = 1] = [null]; // a => null ``` 右边模式对应的值,必须严格等于`undefined`,默认值才能生效,而`null`不严格等于`undefined`。 -#### 2.对象的解构赋值 +#### 1.2.2 对象的解构赋值 与数组解构不同的是,对象解构**不需要严格按照顺序取值**,而只要按照**变量名**去取对应**属性名**的值,若取不到对应**属性名**的值,则为`undefined` 。 **基础用法**: @@ -290,7 +297,7 @@ let {a=1} = {a:null}; // a => null // 导致默认值1不会生效。 ``` -#### 3.字符串的解构赋值 +#### 1.2.3 字符串的解构赋值 字符串的解构赋值中,字符串被转换成了一个**类似数组的对象**。 **基础用法**: ```js @@ -304,7 +311,7 @@ e // "o" let {length:len} = 'hello';// len => 5 ``` -#### 4.数值和布尔值的解构赋值 +#### 1.2.4 数值和布尔值的解构赋值 解构赋值的规则是,**只要等号右边的值不是对象或数组,就先将其转为对象**。由于`undefined`和`null`**无法转为对象**,所以对它们进行解构赋值,都会报错。 ```js // 数值和布尔值的包装对象都有toString属性 @@ -317,7 +324,7 @@ let { prop: x } = undefined; // TypeError let { prop: y } = null; // TypeError ``` -#### 5.函数参数的解构赋值 +#### 1.2.5 函数参数的解构赋值 **基础用法**: ```js function fun ([a, b]){ @@ -344,7 +351,7 @@ fun ({}); // [undefined, undefined] fun (); // [0, 0] ``` -#### 6.用途 +#### 1.2.6 应用 * **交换变量的值**: ```js let a = 1,b = 2; @@ -410,8 +417,8 @@ const {log, sin, cos} = require('math'); [⬆ 返回目录](#二目录) -### 字符串的拓展 -#### 1.includes(),startsWith(),endsWith() +### 1.3 字符串的拓展 +#### 1.3.1 includes(),startsWith(),endsWith() 在我们判断字符串是否包含另一个字符串时,ES6之前,我们只有`typeof`方法,ES6之后我们又多了三种方法: * **includes()**:返回**布尔值**,表示**是否找到参数字符串**。 * **startsWith()**:返回**布尔值**,表示参数字符串是否在原字符串的**头部**。 @@ -431,7 +438,7 @@ a.includes('lo',6); // false ``` `endsWith` 是针对前 `n` 个字符,而其他两个是针对从第`n`个位置直到结束。 -#### 2.repeat() +#### 1.3.2 repeat() `repeat`方法返回一个新字符串,表示将原字符串重复`n`次。 **基础用法**: ```js @@ -459,7 +466,7 @@ a.includes('lo',6); // false 'ab'.repeat('3'); // 'ababab' ``` -#### 3.padStart(),padEnd() +####1.3.3 padStart(),padEnd() 用于将字符串**头部**或**尾部**补全长度,`padStart()`为**头部补全**,`padEnd()`为**尾部补全**。 这两个方法接收**2个**参数,第一个指定**字符串最小长度**,第二个**用于补全的字符串**。 **基础用法** : @@ -481,7 +488,7 @@ a.includes('lo',6); // false 'x'.padStart(4); // ' x' 'x'.endStart(4); // 'x ' ``` -#### 4.模版字符串 +#### 1.3.4 模版字符串 用于拼接字符串,ES6之前: ```js let a = 'abc' + @@ -509,13 +516,13 @@ let a = `abc${v1}def` [⬆ 返回目录](#二目录) -### 正则的拓展 +### 1.4 正则的拓展 [⬆ 返回目录](#二目录) -### 数值的拓展 -#### 1.Number.isFinite(), Number.isNaN() +### 1.5 数值的拓展 +#### 1.5.1 Number.isFinite(), Number.isNaN() `Number.isFinite()` 用于检查一个数值是否是有限的,即不是`Infinity`,若参数不是`Number`类型,则一律返回`false` 。 ```js Number.isFinite(10); // true @@ -555,7 +562,7 @@ Number.isNaN(NaN); // true Number.isNaN("NaN"); // false ``` -#### 2.Number.parseInt(), Number.parseFloat() +#### 1.5.2 Number.parseInt(), Number.parseFloat() 这两个方法与全局方法`parseInt()`和`parseFloat()`一致,目的是逐步**减少全局性的方法**,让**语言更模块化**。 ```js parseInt('12.34'); // 12 @@ -568,7 +575,7 @@ Number.parseInt === parseInt; // true Number.parseFloat === parseFloat; // true ``` -#### 3.Number.isInteger() +#### 1.5.3 Number.isInteger() 用来判断一个数值是否是整数,若参数不是数值,则返回`false`。 ```js Number.isInteger(10); // true @@ -576,7 +583,7 @@ Number.isInteger(10.0); // true Number.isInteger(10.1); // false ``` -#### 4.Math对象的拓展 +#### 1.5.4 Math对象的拓展 ES6新增17个数学相关的**静态方法**,只能在**Math对象**上调用。 * **Math.trunc**: 用来去除小数的小数部分,**返回整数部分**。 @@ -772,7 +779,7 @@ Math.log2 = Math.log2 || function(x) { * `Math.acosh(x)` 返回x的**反双曲余弦**(inverse hyperbolic cosine) * `Math.atanh(x)` 返回x的**反双曲正切**(inverse hyperbolic tangent) -#### 5.指数运算符 +#### 1.5.5 指数运算符 新增的指数运算符(`**`): ```js 2 ** 2; // 4 @@ -793,8 +800,8 @@ Math.pow(99, 99) [⬆ 返回目录](#二目录) -### 函数的拓展 -#### 1.参数默认值 +### 1.6 函数的拓展 +#### 1.6.1 参数默认值 ```js // ES6 之前 function f(a, b){ @@ -884,7 +891,7 @@ f4.length; // 0 f5.length; // 2 ``` -#### 2.rest 参数 +#### 1.6.2 rest 参数 `rest`参数形式为(`...变量名`),其值为一个数组,用于获取函数多余参数。 ```js function f (a, ...b){ @@ -905,7 +912,7 @@ f1(1); // 1 f2(1,2); // 1 ``` -#### 3.name 属性 +#### 1.6.3 name 属性 用于返回该函数的函数名。 ```js function f (){...}; @@ -915,7 +922,7 @@ const f = function g(){...}; f.name; // g ``` -#### 4.箭头函数 +#### 1.6.4 箭头函数 使用“箭头”(`=>`)定义函数。 **基础使用**: ```js @@ -991,7 +998,7 @@ b.addEventListener('click', ()=>{ ``` 上诉按钮点击会报错,因为`b`监听的箭头函数中,`this`是全局对象,若改成**普通函数**,`this`就会指向被点击的按钮对象。 -#### 5.双冒号运算符 +#### 1.6.5 双冒号运算符 双冒号暂时是一个提案,用于解决一些不适用的场合,取代`call`、`apply`、`bind`调用。 双冒号运算符(`::`)的左边是一个**对象**,右边是一个**函数**。该运算符会自动将左边的对象,作为上下文环境(即`this`对象),绑定到右边函数上。 ```js @@ -1013,8 +1020,8 @@ let f = ::a.b; [⬆ 返回目录](#二目录) -### 数组的拓展 -#### 1.拓展运算符 +### 1.7 数组的拓展 +#### 1.7.1 拓展运算符 拓展运算符使用(`...`),类似`rest`参数的逆运算,将数组转为用(`,`)分隔的参数序列。 ```js console.log(...[1, 2, 3]); // 1 2 3 @@ -1102,7 +1109,7 @@ let [a, ...b] = ["abc"]; // a => "abc" b => [] ``` -#### 2.Array.from() +#### 1.7.2 Array.from() 将 **类数组对象** 和 **可遍历的对象**,转换成真正的数组。 ```js // 类数组对象 @@ -1120,7 +1127,7 @@ let c = Array.from([1,2,3]).map(x => x * x); let d = Array.from([1,2,3].map(x => x * x)); ``` -#### 3.Array.of() +#### 1.7.3 Array.of() 将一组数值,转换成**数组**,弥补`Array`方法参数不同导致的差异。 ```js Array.of(1,2,3); // [1,2,3] @@ -1131,7 +1138,7 @@ Array(2); // [,] 1个参数时,为指定数组长度 Array(1,2,3); // [1,2,3] 多于2个参数,组成新数组 ``` -#### 4.find()和findIndex() +#### 1.7.4 find()和findIndex() `find()`方法用于找出第一个符合条件的数组成员,参数为一个回调函数,所有成员依次执行该回调函数,返回第一个返回值为`true`的成员,如果没有一个符合则返回`undefined`。 ```js [1,2,3,4,5].find( a => a < 3 ); // 1 @@ -1149,7 +1156,7 @@ Array(1,2,3); // [1,2,3] 多于2个参数,组成新数组 }); // 2 ``` -#### 5.fill() +#### 1.7.5 fill() 用于用指定值**填充**一个数组,通常用来**初始化空数组**,并抹去数组中已有的元素。 ```js new Array(3).fill('a'); // ['a','a','a'] @@ -1160,7 +1167,7 @@ new Array(3).fill('a'); // ['a','a','a'] [1,2,3].fill('a',1,2); ``` -#### 6.entries(),keys(),values() +#### 1.7.6 entries(),keys(),values() 主要用于遍历数组,`entries()`对键值对遍历,`keys()`对键名遍历,`values()`对键值遍历。 ```js for (let i of ['a', 'b'].keys()){ @@ -1182,7 +1189,7 @@ for (let e of ['a', 'b'].keys()){ // 1 'b' ``` -#### 7.includes() +#### 1.7.7 includes() 用于表示数组是否包含给定的值,与字符串的`includes`方法类似。 ```js [1,2,3].includes(2); // true @@ -1197,7 +1204,7 @@ for (let e of ['a', 'b'].keys()){ [1,2,3].includes(3,-4); // true ``` -#### 8.flat(),flatMap() +#### 1.7.8 flat(),flatMap() `flat()`用于将数组一维化,返回一个新数组,不影响原数组。 默认一次只一维化一层数组,若需多层,则传入一个整数参数指定层数。 若要一维化所有层的数组,则传入`Infinity`作为参数。 @@ -1216,8 +1223,8 @@ for (let e of ['a', 'b'].keys()){ [⬆ 返回目录](#二目录) -### 对象的拓展 -#### 1.属性的简洁表示 +### 1.8 对象的拓展 +#### 1.8.1 属性的简洁表示 ```js let a = 'a1'; let b = { a }; // b => { a : 'a1' } @@ -1245,7 +1252,7 @@ let a = { } ``` -#### 2.属性名表达式 +#### 1.8.2 属性名表达式 `JavaScript`提供2种方法**定义对象的属性**。 ```js // 方法1 标识符作为属性名 @@ -1280,7 +1287,7 @@ let a1 = 'aa'; let b1 = { [a1] : 'bb'}; ``` -#### 3.Object.is() +#### 1.8.3 Object.is() `.Object.is()` 用于比较两个值是否严格相等,在ES5时候只要使用**相等运算符**(`==`)和**严格相等运算符**(`===`)就可以做比较,但是它们都有缺点,前者会**自动转换数据类型**,后者的`NaN`不等于自身,以及`+0`等于`-0`。 ```js Object.is('a','a'); // true @@ -1295,7 +1302,7 @@ Object.is(+0,-0); // false Object.is(NaN,NaN); // true ``` -#### 4.Object.assign() +#### 1.8.4 Object.assign() `Object.assign()`方法用于对象的合并,将原对象的所有可枚举属性复制到目标对象。 **基础用法**: 第一个参数是**目标对象**,后面参数都是**源对象**。 @@ -1342,8 +1349,8 @@ Object.assign([1, 2, 3], [4, 5]); // [4, 5, 3] [⬆ 返回目录](#二目录) -### Symbol -#### 1.介绍 +### 1.9 Symbol +#### 1.9.1 介绍 ES6引入`Symbol`作为一种新的**原始数据类型**,表示**独一无二**的值,主要是为了**防止属性名冲突**。 ES6之后,JavaScript一共有其中数据类型:`Symbol`、`undefined`、`null`、`Boolean`、`String`、`Number`、`Object`。 简单实用: @@ -1370,15 +1377,15 @@ a + " world!"; // 报错 `${a} world!`; // 报错 ``` -#### 2.更多介绍 +#### 1.9.2 更多介绍 详细介绍[参考阮一峰老师的ES6 Symbol介绍](http://es6.ruanyifeng.com/#docs/symbol) [⬆ 返回目录](#二目录) -### Set和Map数据结构 -#### 1.Set +### 1.10 Set和Map数据结构 +#### 1.10.1 Set **介绍**: `Set`数据结构类似数组,但所有成员的值**唯一**。 `Set`本身为一个构造函数,用来生成`Set`数据结构,使用`add`方法来添加新成员。 @@ -1429,7 +1436,7 @@ a.clear(); // a => Set(0) {} ```js let a = new Set([1,2,3,3,3,3]); ``` -#### 2.Set的应用 +#### 1.10.2 Set的应用 **数组去重**: ```js // 方法1 @@ -1488,7 +1495,7 @@ a.forEach((v,k) => console.log(k + ' : ' + v)); ``` -#### 3.Map +#### 1.10.3 Map 由于传统的`JavaScript`对象只能用字符串当做键,给开发带来很大限制,ES6增加`Map`数据结构,使得**各种类型的值**(包括对象)都可以作为键。 `Map`结构提供了“**值—值**”的对应,是一种更完善的 Hash 结构实现。 **基础使用**: @@ -1560,7 +1567,7 @@ let a2 = [...a.values()]; // a2 =>  ["leo", 18] let a3 = [...a.entries()];// a3 => [['name','leo'], ['age',18]] ``` -#### 4.Map与其他数据结构互相转换 +#### 1.10.4 Map与其他数据结构互相转换 * Map 转 数组 ```js let a = new Map().set(true,1).set({f:2},['abc']); @@ -1651,6 +1658,89 @@ fun2('[[true,7],[{"foo":3},["abc"]]]') [⬆ 返回目录](#二目录) +### 1.11 Proxy +`proxy` 用于修改某些操作的**默认行为**,可以理解为一种拦截外界对目标对象访问的一种机制,从而对外界的访问进行过滤和修改,即代理某些操作,也称“**代理器**”。 +#### 1.11.1 基础使用 +`proxy`实例化需要传入两个参数,`target`参数表示所要拦截的目标对象,`handler`参数也是一个对象,用来定制拦截行为。 +```js +let p = new Proxy(target, handler); + +let a = new Proxy({}, { + get: function (target, handler){ + return 'leo'; + } +}) +a.name; // leo +a.age; // leo +a.abcd; // leo +``` +上述`a`实例中,在第二个参数中定义了`get`方法,来拦截外界访问,并且`get`方法接收两个参数,分别是**目标对象**和**所要访问的属性**,所以不管外部访问对象中任何属性都会执行`get`方法返回`leo`。 +**注意**: +* 只能使用`Proxy`实例的对象才能使用这些操作。 +* 如果`handler`没有设置拦截,则直接返回原对象。 +```js +let target = {}; +let handler = {}; +let p = new Proxy(target, handler); +p.a = 'leo'; +target.a; // 'leo' +``` +**同个拦截器函数,设置多个拦截操作**: +```js +let p = new Proxy(function(a, b){ + return a + b; +},{ + get:function(){ + return 'get方法'; + }, + apply:function(){ + return 'apply方法'; + } +}) +``` + +**`Proxy`支持的13种拦截操作**: +具体每个操作的介绍,下面会介绍。 +* `get(target, propKey, receiver)`: +拦截对象属性的读取,比如proxy.foo和proxy['foo']。 + +* `set(target, propKey, value, receiver)`: +拦截对象属性的设置,比如proxy.foo = v或proxy['foo'] = v,返回一个布尔值。 + +* `has(target, propKey)`: +拦截propKey in proxy的操作,返回一个布尔值。 + +* `deleteProperty(target, propKey)`: +拦截delete proxy[propKey]的操作,返回一个布尔值。 + +* `ownKeys(target)`: +拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。 + +* `getOwnPropertyDescriptor(target, propKey)`: +拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。 + +* `defineProperty(target, propKey, propDesc)`: +拦截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。 + +* `preventExtensions(target)`: +拦截Object.preventExtensions(proxy),返回一个布尔值。 + +* `getPrototypeOf(target)`: +拦截Object.getPrototypeOf(proxy),返回一个对象。 + +* `isExtensible(target)`: +拦截Object.isExtensible(proxy),返回一个布尔值。 + +* `setPrototypeOf(target, proto)`: +拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。 + +* `apply(target, object, args)`: +拦截 Proxy 实例作为函数调用的操作,比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。 + +* `construct(target, args)`: +拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(...args)。 + + ## 2. ES7 ### Object.keys(),Object.values(),Object.entries() [对应地址](http://es6.ruanyifeng.com/#docs/object#Object-assign) @@ -1670,7 +1760,7 @@ fun2('[[true,7],[{"foo":3},["abc"]]]') [⬆ 返回目录](#二目录) ## 5. 知识补充 -### 块级作用域 +### 5.1 块级作用域 通常指一个**函数内部**,或者一个**代码块内部**。 比如: @@ -1709,7 +1799,7 @@ console.log(i); // 5 [⬆ 返回目录](#二目录) -### ES5/6对数组空位的处理 +### 5.2 ES5/6对数组空位的处理 数组的空位不是`undefined`,而是没有任何值,数组的`undefined`也是有值。 ```js From 1aa46121b4da6a2b9f290826934755cc5bc9f2ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 26 Oct 2018 20:00:52 +0800 Subject: [PATCH 096/835] =?UTF-8?q?2018.10.26=20=E6=9B=B4=E6=96=B0Proxy?= =?UTF-8?q?=E7=AB=A0=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 98 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index befa84c6..29e6e4fe 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -81,6 +81,7 @@ - [1.10.4 Map与其他数据结构互相转换](#1104-map与其他数据结构互相转换) - [1.11 Proxy](#111-proxy) - [1.11.1 基础使用](#1111-基础使用) + - [1.11.2 Proxy实例的13种方法](#1112-proxy实例的13种方法) - [2. ES7](#2-es7) - [Object.keys(),Object.values(),Object.entries()](#objectkeysobjectvaluesobjectentries) - [Object.getOwnPropertyDescriptors()](#objectgetownpropertydescriptors) @@ -1740,6 +1741,103 @@ let p = new Proxy(function(a, b){ * `construct(target, args)`: 拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(...args)。 +#### 1.11.2 Proxy实例的13种方法 +**1. get():** +`get()`方法用于拦截某个属性的**读取操作**,三个参数依次是“**目标对象**”、“**属性名**”和“**proxy实例本身(可选)**”。 +```js +let a = { name:'leo '}; +let p = new Proxy(a, { + get :function(target, property){ + if(property in a){ + return a[property]; + }else{ + throw new ReferenceError(` + Property ${property} does not exist. + `) + } + } +}) +p.name; // "leo" +p.age; // Uncaught ReferenceError: Property age does not exist. +``` + +**2. set():** +`set()`方法用于拦截某个属性的**赋值操作**,四个参数依次是“**目标对象**”,“**属性名**”,“**属性值**”和“**Proxy实例本身(可选)**”。 +```js +let a = { + set:function(obj, prop, val){ + if(prop === 'count'){ + if(!Number.isInteger(val)){ + throw new TypeError('The count is not an integer'); + } + if(val > 100) { + throw new RangeError('The count seems invalid'); + } + } + obj[prop] = val; // 满足条件 保存count所有属性 + } +} +let p = new Proxy({}, a); +p.count = 100; +p.count; // 100 +p.count = 'aaa';// 报错 TypeError +p.count = 200; // 报错 RangeError +``` + +**3. apply():** +`apply()`用来拦截函数的调用,`call`和`apply`操作,三个参数依次是“**目标对象**”,“**目标对象的上下文**”和“**目标对象的参数数组**”。 +```js +let a = function(){return 'leo'}; +let b = { + apply:function(){ + return 'I am the proxy!'; + } +} +let c = new Proxy(a,b); +c(); // 'I am the proxy!' +``` + +**4. has():** +`has()`方法用来拦截`HasProperty`操作,即**判断对象是否具有某个属性**时,这个方法会生效。典型的操作就是`in`运算符。 +两个参数依次是“**目标对象**”和“**需查询的属性名**”。 +```js +let a = { + has(target, key){ + if(key[0] === '_'){return false} + return key in target; + } +} +let b = { _prop:'leo', prop:'robin'}; +let c = new Proxy(b,a); +'_prop' in c; // false +``` + +**5. construct():** +`construct()`用于拦截`new`命令,三个参数依次是“**目标对象**”,“**构造函数的参数对象**”和“**new命令作用的构造函数(可选)**”,而且`construct()`必须返回的是对象,否则报错。 +```js +let p = new Proxy(function(){}, { + construct: function (target, args){ + return {value:atgs[0] * 100} + } +}) +let a = new p(1); +a.value; // 100 +``` +**6. deleteProperty():** +`deleteProperty()`方法用于拦截**delete操作**,如果这个方法抛出错误或者返回false,当前属性就无法被delete命令删除。 + + +**7. defineProperty():** +`defineProperty()`方法拦截了**Object.defineProperty**操作。 + + +**8. getOwnPropertyDescriptor():** +**9. getPrototypeOf():** +**10. isExtensible():** +**11. ownKeys():** +**12. preventExtensions():** +**13. setPrototypeOf():** + ## 2. ES7 ### Object.keys(),Object.values(),Object.entries() From 59f624d28f427926e1d5845ed6a215a6d5f0dbd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sun, 28 Oct 2018 23:16:07 +0800 Subject: [PATCH 097/835] =?UTF-8?q?2018.10.28=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E3=80=8AProxy=E3=80=8B=E7=AB=A0=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 115 ++++++++-------------------------------- 1 file changed, 23 insertions(+), 92 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 29e6e4fe..88f600ed 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -81,7 +81,8 @@ - [1.10.4 Map与其他数据结构互相转换](#1104-map与其他数据结构互相转换) - [1.11 Proxy](#111-proxy) - [1.11.1 基础使用](#1111-基础使用) - - [1.11.2 Proxy实例的13种方法](#1112-proxy实例的13种方法) + - [1.11.2 取消Proxy实例](#1112-取消proxy实例) + - [1.11.3 实现 Web服务的客户端](#1113-实现-web服务的客户端) - [2. ES7](#2-es7) - [Object.keys(),Object.values(),Object.entries()](#objectkeysobjectvaluesobjectentries) - [Object.getOwnPropertyDescriptors()](#objectgetownpropertydescriptors) @@ -1701,7 +1702,7 @@ let p = new Proxy(function(a, b){ ``` **`Proxy`支持的13种拦截操作**: -具体每个操作的介绍,下面会介绍。 +13种拦截操作的详细介绍:[打开阮一峰老师的链接](http://es6.ruanyifeng.com/#docs/proxy)。 * `get(target, propKey, receiver)`: 拦截对象属性的读取,比如proxy.foo和proxy['foo']。 @@ -1741,103 +1742,33 @@ let p = new Proxy(function(a, b){ * `construct(target, args)`: 拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(...args)。 -#### 1.11.2 Proxy实例的13种方法 -**1. get():** -`get()`方法用于拦截某个属性的**读取操作**,三个参数依次是“**目标对象**”、“**属性名**”和“**proxy实例本身(可选)**”。 -```js -let a = { name:'leo '}; -let p = new Proxy(a, { - get :function(target, property){ - if(property in a){ - return a[property]; - }else{ - throw new ReferenceError(` - Property ${property} does not exist. - `) - } - } -}) -p.name; // "leo" -p.age; // Uncaught ReferenceError: Property age does not exist. -``` - -**2. set():** -`set()`方法用于拦截某个属性的**赋值操作**,四个参数依次是“**目标对象**”,“**属性名**”,“**属性值**”和“**Proxy实例本身(可选)**”。 +#### 1.11.2 取消Proxy实例 +使用`Proxy.revocale`方法取消`Proxy`实例。 ```js -let a = { - set:function(obj, prop, val){ - if(prop === 'count'){ - if(!Number.isInteger(val)){ - throw new TypeError('The count is not an integer'); - } - if(val > 100) { - throw new RangeError('The count seems invalid'); - } - } - obj[prop] = val; // 满足条件 保存count所有属性 - } -} -let p = new Proxy({}, a); -p.count = 100; -p.count; // 100 -p.count = 'aaa';// 报错 TypeError -p.count = 200; // 报错 RangeError -``` +let a = {}; +let b = {}; +let {proxy, revoke} = Proxy.revocale(a, b); -**3. apply():** -`apply()`用来拦截函数的调用,`call`和`apply`操作,三个参数依次是“**目标对象**”,“**目标对象的上下文**”和“**目标对象的参数数组**”。 -```js -let a = function(){return 'leo'}; -let b = { - apply:function(){ - return 'I am the proxy!'; - } -} -let c = new Proxy(a,b); -c(); // 'I am the proxy!' +proxy.name = 'leo'; // 'leo' +revoeke(); +proxy.name; // TypeError: Revoked ``` -**4. has():** -`has()`方法用来拦截`HasProperty`操作,即**判断对象是否具有某个属性**时,这个方法会生效。典型的操作就是`in`运算符。 -两个参数依次是“**目标对象**”和“**需查询的属性名**”。 +#### 1.11.3 实现 Web服务的客户端 ```js -let a = { - has(target, key){ - if(key[0] === '_'){return false} - return key in target; - } -} -let b = { _prop:'leo', prop:'robin'}; -let c = new Proxy(b,a); -'_prop' in c; // false -``` - -**5. construct():** -`construct()`用于拦截`new`命令,三个参数依次是“**目标对象**”,“**构造函数的参数对象**”和“**new命令作用的构造函数(可选)**”,而且`construct()`必须返回的是对象,否则报错。 -```js -let p = new Proxy(function(){}, { - construct: function (target, args){ - return {value:atgs[0] * 100} - } +const service = createWebService('http://le.com/data'); +service.employees().than(json =>{ + const employees = JSON.parse(json); }) -let a = new p(1); -a.value; // 100 -``` -**6. deleteProperty():** -`deleteProperty()`方法用于拦截**delete操作**,如果这个方法抛出错误或者返回false,当前属性就无法被delete命令删除。 - - -**7. defineProperty():** -`defineProperty()`方法拦截了**Object.defineProperty**操作。 - - -**8. getOwnPropertyDescriptor():** -**9. getPrototypeOf():** -**10. isExtensible():** -**11. ownKeys():** -**12. preventExtensions():** -**13. setPrototypeOf():** +function createWebService(url){ + return new Proxy({}, { + get(target, propKey, receiver{ + return () => httpGet(url+'/'+propKey); + }) + }) +} +``` ## 2. ES7 ### Object.keys(),Object.values(),Object.entries() From f5fc0124136b5257a1bf24b084903a455119b288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 29 Oct 2018 21:41:19 +0800 Subject: [PATCH 098/835] =?UTF-8?q?2018.10.29=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E3=80=8A=E6=AD=A3=E5=88=99=E8=A1=A8=E8=BE=BE=E5=BC=8F=E3=80=8B?= =?UTF-8?q?=E7=AB=A0=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 130 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 129 insertions(+), 1 deletion(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 88f600ed..35a3c9e7 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -11,7 +11,8 @@ **更新记录**: ...前面几天没有写记录。 * 2018.10.24 添加**ES6**《**Symbol**》和《**Set和Map数据结构**》章节。 -* 2018.10.25 添加**ES6**《**Proxy**》章节,还没整理完。 +* 2018.10.26 添加**ES6**《**Proxy**》章节。 +* 2018.10.29 添加**ES6**《**正则表达式**》章节。 **未来规划**: * 1.将内容按不同模块拆分不同文件,方便README文件的阅读。 @@ -45,6 +46,11 @@ - [1.3.3 padStart(),padEnd()](#133-padstartpadend) - [1.3.4 模版字符串](#134-模版字符串) - [1.4 正则的拓展](#14-正则的拓展) + - [1.4.1 介绍](#141-介绍) + - [1.4.2 字符串的正则方法](#142-字符串的正则方法) + - [1.4.3 u修饰符](#143-u修饰符) + - [1.4.4 y修饰符](#144-y修饰符) + - [1.4.5 flags属性](#145-flags属性) - [1.5 数值的拓展](#15-数值的拓展) - [1.5.1 Number.isFinite(), Number.isNaN()](#151-numberisfinite-numberisnan) - [1.5.2 Number.parseInt(), Number.parseFloat()](#152-numberparseint-numberparsefloat) @@ -88,6 +94,7 @@ - [Object.getOwnPropertyDescriptors()](#objectgetownpropertydescriptors) - [3. ES8](#3-es8) - [4. ES9](#4-es9) + - [4.1 正则表达式 s 修饰符](#41-正则表达式-s-修饰符) - [5. 知识补充](#5-知识补充) - [5.1 块级作用域](#51-块级作用域) - [5.2 ES5/6对数组空位的处理](#52-es56对数组空位的处理) @@ -519,6 +526,124 @@ let a = `abc${v1}def` ### 1.4 正则的拓展 +#### 1.4.1 介绍 +在ES5中有两种情况。 +* 参数是**字符串**,则第二个参数为正则表达式的修饰符。 +```js +let a = new RegExp('abc', 'i'); +// 等价于 +let a = /abx/i; +``` +* 参数是**正则表达式**,返回一个原表达式的拷贝,且不能有第二个参数,否则报错。 +```js +let a = new RegExp(/abc/i); +//等价于 +let a = /abx/i; + +let a = new RegExp(/abc/, 'i'); +// Uncaught TypeError +``` +ES6中使用: +第一个参数是正则对象,第二个是指定修饰符,如果第一个参数已经有修饰符,则会被第二个参数覆盖。 +```js +new RegExp(/abc/ig, 'i'); +``` + +#### 1.4.2 字符串的正则方法 +常用的四种方法:`match()`、`replace()`、`search()`和`split()`。 + +#### 1.4.3 u修饰符 +添加`u`修饰符,是为了处理大于`uFFFF`的Unicode字符,即正确处理四个字节的UTF-16编码。 +```js +/^\uD83D/u.test('\uD83D\uDC2A'); // false +/^\uD83D/.test('\uD83D\uDC2A'); // true +``` +由于ES5之前不支持四个字节UTF-16编码,会识别为两个字符,导致第二行输出`true`,加入`u`修饰符后ES6就会识别为一个字符,所以输出`false`。 + +**注意:** +加上`u`修饰符后,会改变下面正则表达式的行为: +* (1)点字符 +点字符(`.`)在正则中表示除了**换行符**以外的任意单个字符。对于码点大于`0xFFFF`的Unicode字符,点字符不能识别,必须加上`u`修饰符。 +```js +var a = "𠮷"; +/^.$/.test(a); // false +/^.$/u.test(a); // true +``` +* (2)Unicode字符表示法 +使用ES6新增的大括号表示Unicode字符时,必须在表达式添加`u`修饰符,才能识别大括号。 +```js +/\u{61}/.test('a'); // false +/\u{61}/u.test('a'); // true +/\u{20BB7}/u.test('𠮷'); // true +``` +* (3)量词 +使用`u`修饰符后,所有量词都会正确识别码点大于`0xFFFF`的 Unicode 字符。 +```js +/a{2}/.test('aa'); // true +/a{2}/u.test('aa'); // true +/𠮷{2}/.test('𠮷𠮷'); // false +/𠮷{2}/u.test('𠮷𠮷'); // true +``` +* (4)i修饰符 +不加`u`修饰符,就无法识别非规范的`K`字符。 +```js +/[a-z]/i.test('\u212A') // false +/[a-z]/iu.test('\u212A') // true +``` + +**检查是否设置`u`修饰符:** +使用`unicode`属性。 +```js +const a = /hello/; +const b = /hello/u; + +a.unicode // false +b.unicode // true +``` + +#### 1.4.4 y修饰符 +`y`修饰符与`g`修饰符类似,也是全局匹配,后一次匹配都是从上一次匹配成功的下一个位置开始。区别在于,`g`修饰符**只要**剩余位置中存在匹配即可,而`y`修饰符是必须从**剩余第一个**开始。 +```js +var s = 'aaa_aa_a'; +var r1 = /a+/g; +var r2 = /a+/y; + +r1.exec(s) // ["aaa"] +r2.exec(s) // ["aaa"] + +r1.exec(s) // ["aa"] 剩余 '_aa_a' +r2.exec(s) // null +``` +**`lastIndex`属性**: +指定匹配的开始位置: +```js +const a = /a/y; +a.lastIndex = 2; // 从2号位置开始匹配 +a.exec('wahaha'); // null +a.lastIndex = 3; // 从3号位置开始匹配 +let c = a.exec('wahaha'); +c.index; // 3 +a.lastIndex; // 4 +``` +**返回多个匹配**: +一个`y`修饰符对`match`方法只能返回第一个匹配,与`g`修饰符搭配能返回所有匹配。 +```js +'a1a2a3'.match(/a\d/y); // ["a1"] +'a1a2a3'.match(/a\d/gy); // ["a1", "a2", "a3"] +``` +**检查是否使用`y`修饰符**: +使用`sticky`属性检查。 +```js +const a = /hello\d/y; +a.sticky; // true +``` + +#### 1.4.5 flags属性 +`flags`属性返回所有正则表达式的修饰符。 +```js +/abc/ig.flags; // 'gi' +``` + [⬆ 返回目录](#二目录) @@ -1785,6 +1910,9 @@ function createWebService(url){ ## 3. ES8 ## 4. ES9 +### 4.1 正则表达式 s 修饰符 +[对应地址](http://es6.ruanyifeng.com/#docs/regex) + [⬆ 返回目录](#二目录) From 1dd88278cc2385513bce4ba7e3c013850eda15a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 29 Oct 2018 23:52:09 +0800 Subject: [PATCH 099/835] =?UTF-8?q?2018.10.29=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E3=80=8APromise=E3=80=8B=E6=95=B4=E7=90=86=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 341 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 341 insertions(+) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 35a3c9e7..5a76c0df 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -89,10 +89,23 @@ - [1.11.1 基础使用](#1111-基础使用) - [1.11.2 取消Proxy实例](#1112-取消proxy实例) - [1.11.3 实现 Web服务的客户端](#1113-实现-web服务的客户端) + - [1.12 Promise对象](#112-promise对象) + - [1.12.1 概念](#1121-概念) + - [1.12.2 基本使用](#1122-基本使用) + - [1.12.3 Promise.prototype.then()](#1123-promiseprototypethen) + - [1.12.4 Promise.prototype.catch()](#1124-promiseprototypecatch) + - [1.12.5 Promise.prototype.finally()](#1125-promiseprototypefinally) + - [1.12.6 Promise.all()](#1126-promiseall) + - [1.13 Iterator和 for...of循环](#113-iterator和-forof循环) + - [1.14 Generator函数和应用](#114-generator函数和应用) + - [1.15 Class语法和继承](#115-class语法和继承) + - [1.16 Module语法和加载实现](#116-module语法和加载实现) - [2. ES7](#2-es7) - [Object.keys(),Object.values(),Object.entries()](#objectkeysobjectvaluesobjectentries) - [Object.getOwnPropertyDescriptors()](#objectgetownpropertydescriptors) - [3. ES8](#3-es8) + - [3.1 async函数](#31-async函数) + - [3.2 Promise.prototype.finally()](#32-promiseprototypefinally) - [4. ES9](#4-es9) - [4.1 正则表达式 s 修饰符](#41-正则表达式-s-修饰符) - [5. 知识补充](#5-知识补充) @@ -1895,6 +1908,329 @@ function createWebService(url){ } ``` +### 1.12 Promise对象 +#### 1.12.1 概念 +主要用途:**解决异步编程带来的回调地狱问题**。 +把`Promise`简单理解一个容器,存放着某个未来才会结束的事件(通常是一个异步操作)的结果。通过`Promise`对象来获取异步操作消息,处理各种异步操作。 + +**Promise对象2特点**: +* **对象的状态不受外界影响**。 +> `Promise`对象代表一个异步操作,有三种状态:**pending(进行中)**、**fulfilled(已成功)**和**rejected(已失败)**。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是`Promise`这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。 + +* **一旦状态改变,就不会再变,任何时候都可以得到这个结果**。 +> Promise对象的状态改变,只有两种可能:从**pending**变为**fulfilled**和从**pending**变为**rejected**。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 **resolved**(已定型)。如果改变已经发生了,你再对**Promise**对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。 + +注意,为了行文方便,本章后面的`resolve`d统一只指`fulfilled`状态,不包含`rejected`状态。 + +**`Promise`缺点** +* **无法取消**Promise,一旦新建它就会立即执行,无法中途取消。 +* 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。 +* 当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。 + +#### 1.12.2 基本使用 +`Promise`为一个构造函数,需要用`new`来实例化。 +```js +let p = new Promise(function (resolve, reject){ + if(/*异步操作成功*/){ + resolve(value); + } else { + reject(error); + } +}) +``` +`Promise`接收一个函数作为参数,该函数两个参数`resolve`和`reject`,有JS引擎提供。 +* `resolve`作用是将`Promise`的状态从pending变成resolved,在异步操作成功时调用,返回异步操作的结果,作为参数传递出去。 +* `reject`作用是将`Promise`的状态从pending变成rejected,在异步操作失败时报错,作为参数传递出去。 + +`Promise`实例生成以后,可以用`then`方法分别指定`resolved`状态和`rejected`状态的回调函数。 +```js +p.then(function(val){ + // success... +},function(err){ + // error... +}) +``` + +**几个例子来理解** : +* 当一段时间过后,`Promise`状态便成为`resolved`触发`then`方法绑定的回调函数。 +```js +function timeout (s){ + return new Promise((resolve, reject){ + setTimeout(result,ms, 'done'); + }) +} +timeout(100).then(val => { + console.log(val); +}) +``` + +* `Promise`新建后立刻执行。 +```js +let p = new Promise(function(resolve, reject){ + console.log(1); + resolve(); +}) +p.then(()=>{ + console.log(2); +}) +console.log(3); +// 1 +// 2 +// 3 +``` + +**异步加载图片**: +```js +function f(url){ + return new Promise(function(resolve, reject){ + const img = new Image (); + img.onload = function(){ + resolve(img); + } + img.onerror = function(){ + reject(new Error( + 'Could not load image at ' + url + )); + } + img.src = url; + }) +} +``` + +**`resolve`函数和`reject`函数的参数为`resolve`函数或`reject`函数**: +`p1`的状态决定了`p2`的状态,所以`p2`要等待`p1`的结果再执行回调函数。 +```js +const p1 = new Promise(function (resolve, reject) { + setTimeout(() => reject(new Error('fail')), 3000) +}) + +const p2 = new Promise(function (resolve, reject) { + setTimeout(() => resolve(p1), 1000) +}) + +p2 + .then(result => console.log(result)) + .catch(error => console.log(error)) +// Error: fail +``` + +**调用`resolve`或`reject`不会结束`Promise`参数函数的执行,除了`return`**: +```js +new Promise((resolve, reject){ + resolve(1); + console.log(2); +}).then(r => { + console.log(3); +}) +// 2 +// 1 + +new Promise((resolve, reject){ + return resolve(1); + console.log(2); +}) +// 1 +``` + +#### 1.12.3 Promise.prototype.then() +作用是为`Promise`添加状态改变时的回调函数,`then`方法的第一个参数是`resolved`状态的回调函数,第二个参数(可选)是`rejected`状态的回调函数。 +`then`方法返回一个新`Promise`实例,与原来`Promise`实例不同,因此可以使用链式写法,上一个`then`的结果作为下一个`then`的参数。 +```js +getJSON("/posts.json").then(function(json) { + return json.post; +}).then(function(post) { + // ... +}); +``` + +#### 1.12.4 Promise.prototype.catch() +`Promise.prototype.catch`方法是`.then(null, rejection)`的别名,用于指定发生错误时的回调函数。 +```js +getJSON('/posts.json').then(function(posts) { + // ... +}).catch(function(error) { + // 处理 getJSON 和 前一个回调函数运行时发生的错误 + console.log('发生错误!', error); +}); +``` +如果 `Promise` 状态已经变成`resolved`,再抛出错误是无效的。 +```js +const p = new Promise(function(resolve, reject) { + resolve('ok'); + throw new Error('test'); +}); +p + .then(function(value) { console.log(value) }) + .catch(function(error) { console.log(error) }); +// ok +``` +当`promise`抛出一个错误,就被`catch`方法指定的回调函数捕获,下面三种写法相同。 +```js +// 写法一 +const p = new Promise(function(resolve, reject) { + throw new Error('test'); +}); +p.catch(function(error) { + console.log(error); +}); +// Error: test + +// 写法二 +const p = new Promise(function(resolve, reject) { + try { + throw new Error('test'); + } catch(e) { + reject(e); + } +}); +p.catch(function(error) { + console.log(error); +}); + +// 写法三 +const p = new Promise(function(resolve, reject) { + reject(new Error('test')); +}); +p.catch(function(error) { + console.log(error); +}); +``` +一般来说,不要在`then`方法里面定义` Reject` 状态的回调函数(即`then`的第二个参数),总是使用`catch`方法。 +```js +// bad +promise + .then(function(data) { + // success + }, function(err) { + // error + }); + +// good +promise + .then(function(data) { //cb + // success + }) + .catch(function(err) { + // error + }); +``` + +#### 1.12.5 Promise.prototype.finally() +`finally`方法用于指定不管 `Promise` 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。 +```js +promise +.then(result => {···}) +.catch(error => {···}) +.finally(() => {···}); +``` +`finally`不接收任何参数,与状态无关,本质上是`then`方法的特例。 +```js +promise +.finally(() => { + // 语句 +}); + +// 等同于 +promise +.then( + result => { + // 语句 + return result; + }, + error => { + // 语句 + throw error; + } +); +``` +上面代码中,如果不使用`finally`方法,同样的语句需要为成功和失败两种情况各写一次。有了`finally`方法,则只需要写一次。 +`finally`方法总是会返回原来的值。 +```js +// resolve 的值是 undefined +Promise.resolve(2).then(() => {}, () => {}) + +// resolve 的值是 2 +Promise.resolve(2).finally(() => {}) + +// reject 的值是 undefined +Promise.reject(3).then(() => {}, () => {}) + +// reject 的值是 3 +Promise.reject(3).finally(() => {}) +``` + +#### 1.12.6 Promise.all() +用于将多个 `Promise` 实例,包装成一个新的 `Promise` 实例,参数可以不是数组,但必须是Iterator接口,且返回的每个成员都是`Promise`实例。 +```js +const p = Promise.all([p1, p2, p3]); +``` +`p`的状态由`p1`、`p2`、`p3`决定,分成**两种**情况。 +1. 只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。 +2. 只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。 + +```js +// 生成一个Promise对象的数组 +const promises = [2, 3, 5, 7, 11, 13].map(function (id) { + return getJSON('/post/' + id + ".json"); +}); + +Promise.all(promises).then(function (posts) { + // ... +}).catch(function(reason){ + // ... +}); +``` +上面代码中,`promises`是包含 6 个 Promise 实例的数组,只有这 6 个实例的状态都变成`fulfilled`,或者其中有一个变为`rejected`,才会调用`Promise.all`方法后面的回调函数。 + +**注意**:如果`Promise`的参数中定义了`catch`方法,则`rejected`后不会触发`Promise.all()`的`catch`方法,因为参数中的`catch`方法执行完后也会变成`resolved`,当`Promise.all()`方法参数的实例都是`resolved`时就会调用`Promise.all()`的`then`方法。 +```js +const p1 = new Promise((resolve, reject) => { + resolve('hello'); +}) +.then(result => result) +.catch(e => e); + +const p2 = new Promise((resolve, reject) => { + throw new Error('报错了'); +}) +.then(result => result) +.catch(e => e); + +Promise.all([p1, p2]) +.then(result => console.log(result)) +.catch(e => console.log(e)); +// ["hello", Error: 报错了] +``` + +**如果参数里面都没有catch方法,就会调用Promise.all()的catch方法。** +```js +const p1 = new Promise((resolve, reject) => { + resolve('hello'); +}) +.then(result => result); + +const p2 = new Promise((resolve, reject) => { + throw new Error('报错了'); +}) +.then(result => result); + +Promise.all([p1, p2]) +.then(result => console.log(result)) +.catch(e => console.log(e)); +// Error: 报错了 +``` + + + +### 1.13 Iterator和 for...of循环 + +### 1.14 Generator函数和应用 + +### 1.15 Class语法和继承 + +### 1.16 Module语法和加载实现 + + ## 2. ES7 ### Object.keys(),Object.values(),Object.entries() [对应地址](http://es6.ruanyifeng.com/#docs/object#Object-assign) @@ -1908,6 +2244,11 @@ function createWebService(url){ [⬆ 返回目录](#二目录) ## 3. ES8 +### 3.1 async函数 +[对应地址](http://es6.ruanyifeng.com/#docs/async) + +### 3.2 Promise.prototype.finally() +[对应地址](http://es6.ruanyifeng.com/#docs/promise) ## 4. ES9 ### 4.1 正则表达式 s 修饰符 From cdb2e2014f8f06a14a4865d2f1331658b40df8c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Tue, 30 Oct 2018 00:12:44 +0800 Subject: [PATCH 100/835] =?UTF-8?q?2018.10.30=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E3=80=8APromise=E3=80=8B=E7=AB=A0=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 54 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 5a76c0df..5c156a6a 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -96,6 +96,9 @@ - [1.12.4 Promise.prototype.catch()](#1124-promiseprototypecatch) - [1.12.5 Promise.prototype.finally()](#1125-promiseprototypefinally) - [1.12.6 Promise.all()](#1126-promiseall) + - [1.12.7 Promise.race()](#1127-promiserace) + - [1.12.8 Promise.resolve()](#1128-promiseresolve) + - [1.12.9 Promise.reject()](#1129-promisereject) - [1.13 Iterator和 for...of循环](#113-iterator和-forof循环) - [1.14 Generator函数和应用](#114-generator函数和应用) - [1.15 Class语法和继承](#115-class语法和继承) @@ -1913,7 +1916,7 @@ function createWebService(url){ 主要用途:**解决异步编程带来的回调地狱问题**。 把`Promise`简单理解一个容器,存放着某个未来才会结束的事件(通常是一个异步操作)的结果。通过`Promise`对象来获取异步操作消息,处理各种异步操作。 -**Promise对象2特点**: +**`Promise`对象2特点**: * **对象的状态不受外界影响**。 > `Promise`对象代表一个异步操作,有三种状态:**pending(进行中)**、**fulfilled(已成功)**和**rejected(已失败)**。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是`Promise`这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。 @@ -2220,16 +2223,65 @@ Promise.all([p1, p2]) // Error: 报错了 ``` +#### 1.12.7 Promise.race() +与`Promise.all`方法类似,也是将多个`Promise`实例包装成一个新的`Promise`实例。 +```js +const p = Promise.race([p1, p2, p3]); +``` +与`Promise.all`方法区别在于,`Promise.race`方法是`p1`, `p2`, `p3`中只要一个参数先改变状态,就会把这个参数的返回值传给`p`的回调函数。 + +#### 1.12.8 Promise.resolve() +将现有对象转换成 `Promise` 对象。 +```js +const p = Promise.resolve($.ajax('/whatever.json')); +``` + +#### 1.12.9 Promise.reject() +返回一个`rejected`状态的`Promise`实例。 +```js +const p = Promise.reject('出错了'); +// 等同于 +const p = new Promise((resolve, reject) => reject('出错了')) +p.then(null, function (s) { + console.log(s) +}); +// 出错了 +``` +注意,`Promise.reject()`方法的参数,会原封不动地作为`reject`的理由,变成后续方法的参数。这一点与`Promise.resolve`方法不一致。 +```js +const thenable = { + then(resolve, reject) { + reject('出错了'); + } +}; + +Promise.reject(thenable) +.catch(e => { + console.log(e === thenable) +}) +// true +``` + + +[⬆ 返回目录](#二目录) ### 1.13 Iterator和 for...of循环 +[⬆ 返回目录](#二目录) + ### 1.14 Generator函数和应用 +[⬆ 返回目录](#二目录) + ### 1.15 Class语法和继承 +[⬆ 返回目录](#二目录) + ### 1.16 Module语法和加载实现 +[⬆ 返回目录](#二目录) + ## 2. ES7 ### Object.keys(),Object.values(),Object.entries() From 155619b8c5be86003d58f6ccb9ef5ed41bbcd368 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Tue, 30 Oct 2018 00:13:37 +0800 Subject: [PATCH 101/835] =?UTF-8?q?2018.10.30=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E3=80=8APromise=E3=80=8B=E7=AB=A0=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 5c156a6a..60bee62b 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -12,7 +12,7 @@ ...前面几天没有写记录。 * 2018.10.24 添加**ES6**《**Symbol**》和《**Set和Map数据结构**》章节。 * 2018.10.26 添加**ES6**《**Proxy**》章节。 -* 2018.10.29 添加**ES6**《**正则表达式**》章节。 +* 2018.10.29 添加**ES6**《**正则表达式**》《**Promise**》章节。 **未来规划**: * 1.将内容按不同模块拆分不同文件,方便README文件的阅读。 From 669555146ccad3abe3c4c70998ddca4e1d84ea61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Tue, 30 Oct 2018 23:16:38 +0800 Subject: [PATCH 102/835] =?UTF-8?q?2018.10.30=20=E6=B7=BB=E5=8A=A0ES6?= =?UTF-8?q?=E3=80=8AIterator=E3=80=8B=E7=AB=A0=E8=8A=82=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 183 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 60bee62b..061d6f5d 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -13,6 +13,7 @@ * 2018.10.24 添加**ES6**《**Symbol**》和《**Set和Map数据结构**》章节。 * 2018.10.26 添加**ES6**《**Proxy**》章节。 * 2018.10.29 添加**ES6**《**正则表达式**》《**Promise**》章节。 +* 2018.10.30 添加**ES6**《**Iterator**》章节。 **未来规划**: * 1.将内容按不同模块拆分不同文件,方便README文件的阅读。 @@ -100,6 +101,12 @@ - [1.12.8 Promise.resolve()](#1128-promiseresolve) - [1.12.9 Promise.reject()](#1129-promisereject) - [1.13 Iterator和 for...of循环](#113-iterator和-forof循环) + - [1.13.1 Iterator遍历器概念](#1131-iterator遍历器概念) + - [1.13.2 Iterator遍历过程](#1132-iterator遍历过程) + - [1.13.3 默认Iterator接口](#1133-默认iterator接口) + - [1.13.4 Iterator使用场景](#1134-iterator使用场景) + - [1.13.5 for...of循环](#1135-forof循环) + - [1.13.6 跳出for...of](#1136-跳出forof) - [1.14 Generator函数和应用](#114-generator函数和应用) - [1.15 Class语法和继承](#115-class语法和继承) - [1.16 Module语法和加载实现](#116-module语法和加载实现) @@ -2267,9 +2274,185 @@ Promise.reject(thenable) [⬆ 返回目录](#二目录) ### 1.13 Iterator和 for...of循环 +#### 1.13.1 Iterator遍历器概念 +> **Iterator**是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 **Iterator** 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。 + +**Iterator三个作用**: +* 为各种数据结构,提供一个**统一**的、**简便**的访问接口; +* 使得数据结构的成员能够按某种次序排列; +* **Iterator** 接口主要供ES6新增的`for...of`消费; + +#### 1.13.2 Iterator遍历过程 +1. 创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。 +2. 第一次调用指针对象的`next`方法,可以将指针指向数据结构的第一个成员。 +3. 第二次调用指针对象的`next`方法,指针就指向数据结构的第二个成员。 +4. 不断调用指针对象的`next`方法,直到它指向数据结构的结束位置。 + +每一次调用`next`方法,都会返回数据结构的当前成员的信息。具体来说,就是返回一个包含`value`和`done`两个属性的对象。 + +* `value`属性是当前成员的值; +* `done`属性是一个布尔值,表示遍历是否结束; + +模拟`next`方法返回值: +```js +let f = function (arr){ + var nextIndex = 0; + return { + next:function(){ + return nextIndex < arr.length ? + {value: arr[nextIndex++], done: false}: + {value: undefined, done: true} + } + } +} + +let a = f(['a', 'b']); +a.next(); // { value: "a", done: false } +a.next(); // { value: "b", done: false } +a.next(); // { value: undefined, done: true } +``` + +#### 1.13.3 默认Iterator接口 +若数据**可遍历**,即一种数据部署了Iterator接口。 +ES6中默认的Iterator接口部署在数据结构的`Symbol.iterator`属性,即如果一个数据结构具有`Symbol.iterator`属性,就可以认为是**可遍历**。 +`Symbol.iterator`属性本身是函数,是当前数据结构默认的遍历器生成函数。执行这个函数,就会返回一个遍历器。至于属性名`Symbol.iterator`,它是一个表达式,返回`Symbol`对象的`iterator`属性,这是一个预定义好的、类型为 Symbol 的特殊值,所以要放在方括号内(参见《Symbol》一章)。 + +**原生具有Iterator接口的数据结构有**: +* Array +* Map +* Set +* String +* TypedArray +* 函数的 arguments 对象 +* NodeList 对象 + +#### 1.13.4 Iterator使用场景 +* **(1)解构赋值** +对数组和 `Set` 结构进行解构赋值时,会默认调用`Symbol.iterator`方法。 +```js +let a = new Set().add('a').add('b').add('c'); +let [x, y] = a; // x = 'a' y = 'b' +let [a1, ...a2] = a; // a1 = 'a' a2 = ['b','c'] +``` + +* **(2)扩展运算符** +扩展运算符(`...`)也会调用默认的 Iterator 接口。 +```js +let a = 'hello'; +[...a]; // ['h','e','l','l','o'] + +let a = ['b', 'c']; +['a', ...a, 'd']; // ['a', 'b', 'c', 'd'] +``` + +* **(2)yield*** +`yield*`后面跟的是一个可遍历的结构,它会调用该结构的遍历器接口。 +```js +let a = function*(){ + yield 1; + yield* [2,3,4]; + yield 5; +} + +let b = a(); +b.next() // { value: 1, done: false } +b.next() // { value: 2, done: false } +b.next() // { value: 3, done: false } +b.next() // { value: 4, done: false } +b.next() // { value: 5, done: false } +b.next() // { value: undefined, done: true } +``` + +* **(4)其他场合** +由于数组的遍历会调用遍历器接口,所以任何接受数组作为参数的场合,其实都调用了遍历器接口。下面是一些例子。 + + * for...of + * Array.from() + * Map(), Set(), WeakMap(), WeakSet()(比如`new Map([['a',1],['b',2]])`) + * Promise.all() + * Promise.race() + +#### 1.13.5 for...of循环 +只要数据结构部署了`Symbol.iterator`属性,即具有 iterator 接口,可以用`for...of`循环遍历它的成员。也就是说,`for...of`循环内部调用的是数据结构的`Symbol.iterato`方法。 +**使用场景**: +`for...of`可以使用在**数组**,`Set`和`Map`结构,**类数组对象**,**Genetator对象**和**字符串**。 + +* **数组** +`for...of`循环可以代替数组实例的`forEach`方法。 +```js +let a = ['a', 'b', 'c']; +for (let k of a){console.log(k)}; // a b c + +a.forEach((ele, index)=>{ + console.log(ele); // a b c + console.log(index); // 0 1 2 +}) +``` +与`for...in`对比,`for...in`只能获取对象键名,不能直接获取键值,而`for...of`允许直接获取键值。 +```js +let a = ['a', 'b', 'c']; +for (let k of a){console.log(k)}; // a b c +for (let k in a){console.log(k)}; // 0 1 2 +``` + +* **Set和Map** +```js +let a = new Set(['a', 'b', 'c']); +for (let k of a){console.log(k)}; // a b c + +let b = new Map(); +b.set('name','leo'); +b.set('age', 18); +b.set('aaa','bbb'); +for (let [k,v] of b){console.log(k + ":" + v)}; +// name:leo +// age:18 +// aaa:bbb +``` + +* **类数组对象** +```js +// 字符串 +let a = 'hello'; +for (let k of a ){console.log(k)}; // h e l l o + +// DOM NodeList对象 +let b = document.querySelectorAll('p'); +for (let k of b ){ + k.classList.add('test'); +} + +// arguments对象 +function f(){ + for (let k of arguments){ + console.log(k); + } +} +f('a','b'); // a b +``` + +* **对象** +普通对象不能直接使用`for...of`会报错,要部署Iterator才能使用。 +```js +let a = {a:'aa',b:'bb',c:'cc'}; +for (let k in a){console.log(k)}; // a b c +for (let k of a){console>log(k)}; // TypeError +``` + +#### 1.13.6 跳出for...of +使用`break`来实现。 +```js +for (let k of a){ + if(k>100) + break; + console.log(k); +} +``` [⬆ 返回目录](#二目录) + + ### 1.14 Generator函数和应用 [⬆ 返回目录](#二目录) From c73d3ad16aecec15d0bef2b5728a9ce80ee25391 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Wed, 31 Oct 2018 22:06:15 +0800 Subject: [PATCH 103/835] =?UTF-8?q?2018.10.31=20=E6=B7=BB=E5=8A=A0ES6?= =?UTF-8?q?=E3=80=8AGenerator=E3=80=8B=E7=AB=A0=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 290 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 289 insertions(+), 1 deletion(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 061d6f5d..68bb5171 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -13,7 +13,8 @@ * 2018.10.24 添加**ES6**《**Symbol**》和《**Set和Map数据结构**》章节。 * 2018.10.26 添加**ES6**《**Proxy**》章节。 * 2018.10.29 添加**ES6**《**正则表达式**》《**Promise**》章节。 -* 2018.10.30 添加**ES6**《**Iterator**》章节。 +* 2018.10.30 添加**ES6**《**Iterator**》章节。 +* 2018.10.31 添加**ES6**《**Generator**》章节。 **未来规划**: * 1.将内容按不同模块拆分不同文件,方便README文件的阅读。 @@ -108,6 +109,15 @@ - [1.13.5 for...of循环](#1135-forof循环) - [1.13.6 跳出for...of](#1136-跳出forof) - [1.14 Generator函数和应用](#114-generator函数和应用) + - [1.14.1 基本概念](#1141-基本概念) + - [1.14.2 yield表达式](#1142-yield表达式) + - [1.14.3 next方法](#1143-next方法) + - [1.14.5 for...of循环](#1145-forof循环) + - [1.14.6 Generator.prototype.throw()](#1146-generatorprototypethrow) + - [1.14.7 Generator.prototype.return()](#1147-generatorprototypereturn) + - [1.14.8 next()/throw()/return()Fon共同点](#1148-nextthrowreturnfon共同点) + - [1.14.9 yield* 表达式](#1149-yield-表达式) + - [1.14.10 应用场景](#11410-应用场景) - [1.15 Class语法和继承](#115-class语法和继承) - [1.16 Module语法和加载实现](#116-module语法和加载实现) - [2. ES7](#2-es7) @@ -2454,9 +2464,287 @@ for (let k of a){ ### 1.14 Generator函数和应用 +#### 1.14.1 基本概念 +`Generator`函数是一种异步编程解决方案。 +**原理**: +执行`Genenrator`函数会返回一个遍历器对象,依次遍历`Generator`函数内部的每一个状态。 +`Generator`函数是一个普通函数,有以下两个特征: +* `function`关键字与函数名之间有个星号; +* 函数体内使用`yield`表达式,定义不同状态; + +通过调用`next`方法,将指针移向下一个状态,直到遇到下一个`yield`表达式(或`return`语句)为止。简单理解,`Generator`函数分段执行,`yield`表达式是暂停执行的标记,而`next`恢复执行。 +```js +function * f (){ + yield 'hi'; + yield 'leo'; + return 'ending'; +} +let a = f(); +a.next(); // {value: 'hi', done : false} +a.next(); // {value: 'leo', done : false} +a.next(); // {value: 'ending', done : true} +a.next(); // {value: undefined, done : false} +``` + +#### 1.14.2 yield表达式 +`yield`表达式是暂停标志,遍历器对象的`next`方法的运行逻辑如下: +* 1. 遇到`yield`就暂停执行,将这个`yield`后的表达式的值,作为返回对象的`value`属性值。 +* 2. 下次调用`next`往下执行,直到遇到下一个`yield`。 +* 3. 直到函数结束或者`return`为止,并返回`return`语句后面表达式的值,作为返回对象的`value`属性值。 +* 4. 如果该函数没有`return`语句,则返回对象的`value`为`undefined` 。 + +**注意:** +* `yield`只能用在`Generator`函数里,其他地方会报错。 +```js +// 错误1 +(function(){ + yiled 1; // SyntaxError: Unexpected number +})() + +// 错误2 forEach参数是个普通函数 +let a = [1, [[2, 3], 4], [5, 6]]; +let f = function * (i){ + i.forEach(function(m){ + if(typeof m !== 'number'){ + yield * f (m); + }else{ + yield m; + } + }) +} +for (let k of f(a)){ + console.log(k) +} +``` + +* `yield`表达式如果用于另一个表达式之中,必须放在**圆括号**内。 +```js +function * a (){ + console.log('a' + yield); // SyntaxErro + console.log('a' + yield 123); // SyntaxErro + console.log('a' + (yield)); // ok + console.log('a' + (yield 123)); // ok +} +``` + +* `yield`表达式用做函数参数或放在表达式右边,可以不加括号。 +```js +function * a (){ + f(yield 'a', yield 'b'); // ok + lei i = yield; // ok +} +``` + +#### 1.14.3 next方法 +`yield`本身没有返回值,或者是总返回`undefined`,`next`方法可带一个参数,作为上一个`yield`表达式的返回值。 +```js +function * f (){ + for (let k = 0; true; k++){ + let a = yield k; + if(a){k = -1}; + } +} +let g =f(); +g.next(); // {value: 0, done: false} +g.next(); // {value: 1, done: false} +g.next(true); // {value: 0, done: false} +``` +这一特点,可以让`Generator`函数开始执行之后,可以从外部向内部注入不同值,从而调整函数行为。 +```js +function * f(x){ + let y = 2 * (yield (x+1)); + let z = yield (y/3); + return (x + y + z); +} +let a = f(5); +a.next(); // {value : 6 ,done : false} +a.next(); // {value : NaN ,done : false} +a.next(); // {value : NaN ,done : true} +// NaN因为yeild返回的是对象 和数字计算会NaN + +let b = f(5); +b.next(); // {value : 6 ,done : false} +b.next(12); // {value : 8 ,done : false} +b.next(13); // {value : 42 ,done : false} +// x 5 y 24 z 13 +``` + +#### 1.14.5 for...of循环 +`for...of`循环会自动遍历,不用调用`next`方法,需要注意的是,`for...of`遇到`next`放回的`done`属性为`true`就会终止,`return`返回的不包括在`for...of`循环中。 +```js +function * f(){ + yield 1; + yield 2; + yield 3; + yield 4; + return 5; +} +for (let k of f()){ + console.log(k); +} +// 1 2 3 4 没有 5 +``` + +#### 1.14.6 Generator.prototype.throw() +`throw`方法用来向函数外抛出错误,并且在Generator函数体内捕获。 +```js +let f = function * (){ + try { yield } + catch (e) { console.log('内部捕获', e) } +} + +let a = f(); +a.next(); + +try{ + a.throw('a'); + a.throw('b'); +}catch(e){ + console.log('外部捕获',e); +} +// 内部捕获 a +// 外部捕获 b +``` + +#### 1.14.7 Generator.prototype.return() +`return`方法用来返回给定的值,并结束遍历Generator函数,如果`return`方法没有参数,则返回值的`value`属性为`undefined`。 +```js +function * f(){ + yield 1; + yield 2; + yield 3; +} +let g = f(); +g.next(); // {value : 1, done : false} +g.return('leo'); // {value : 'leo', done " true} +g.next(); // {value : undefined, done : true} +``` + +#### 1.14.8 next()/throw()/return()Fon共同点 +相同点就是都是用来恢复Generator函数的执行,并且使用不同语句替换`yield`表达式。 +* `next()`将`yield`表达式替换成一个值。 +```js +let f = function * (x,y){ + let r = yield x + y; + return r; +} +let g = f(1, 2); +g.next(); // {value : 3, done : false} +g.next(1); // {value : 1, done : true} +// 相当于把 let r = yield x + y; +// 替换成 let r = 1; +``` +* `throw()`将`yield`表达式替换成一个`throw`语句。 +```js +g.throw(new Error('报错')); // Uncaught Error:报错 +// 相当于将 let r = yield x + y +// 替换成 let r = throw(new Error('报错')); +``` +* `next()`将`yield`表达式替换成一个`return`语句。 +```js +g.return(2); // {value: 2, done: true} +// 相当于将 let r = yield x + y +// 替换成 let r = return 2; +``` + +#### 1.14.9 yield* 表达式 +用于在一个Generator中执行另一个Generator函数,如果没有使用`yield*`会没有效果。 +```js +function * a(){ + yield 1; + yield 2; +} +function * b(){ + yield 3; + yield * a(); + yield 4; +} +// 等同于 +function * b(){ + yield 3; + yield 1; + yield 2; + yield 4; +} +for(let k of b()){console.log(k)} +// 3 +// 1 +// 2 +// 4 +``` + +#### 1.14.10 应用场景 +* 1. **控制流管理** +解决回调地狱: +```js +// 使用前 +f1(function(v1){ + f2(function(v2){ + f3(function(v3){ + // ... more and more + }) + }) +}) + +// 使用Promise +Promise.resolve(f1) + .then(f2) + .then(f3) + .then(function(v4){ + // ... + },function (err){ + // ... + }).done(); + +// 使用Generator +function * f (v1){ + try{ + let v2 = yield f1(v1); + let v3 = yield f1(v2); + let v4 = yield f1(v3); + // ... + }catch(err){ + // console.log(err) + } +} +function g (task){ + let obj = task.next(task.value); + // 如果Generator函数未结束,就继续调用 + if(!obj.done){ + task.value = obj.value; + g(task); + } +} +g( f(initValue) ); +``` + +* 2. **异步编程的使用** +在真实的异步任务封装的情况: +```js +let fetch = require('node-fetch'); +function * f(){ + let url = 'http://www.baidu.com'; + let res = yield fetch(url); + console.log(res.bio); +} +// 执行该函数 +let g = f(); +let result = g.next(); +// 由于fetch返回的是Promise对象,所以用then +result.value.then(function(data){ + return data.json(); +}).then(function(data){ + g.next(data); +}) +``` + + + [⬆ 返回目录](#二目录) + + ### 1.15 Class语法和继承 [⬆ 返回目录](#二目录) From b7434d380c1017772c9c091441a66ca29b200400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Wed, 31 Oct 2018 23:11:25 +0800 Subject: [PATCH 104/835] =?UTF-8?q?2018.10.31=20=E6=B7=BB=E5=8A=A0ES6?= =?UTF-8?q?=E3=80=8AModule=E3=80=8B=E7=AB=A0=E8=8A=82=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 225 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 221 insertions(+), 4 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 68bb5171..c4cbaf34 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -14,7 +14,7 @@ * 2018.10.26 添加**ES6**《**Proxy**》章节。 * 2018.10.29 添加**ES6**《**正则表达式**》《**Promise**》章节。 * 2018.10.30 添加**ES6**《**Iterator**》章节。 -* 2018.10.31 添加**ES6**《**Generator**》章节。 +* 2018.10.31 添加**ES6**《**Generator**,**Module**》章节。 **未来规划**: * 1.将内容按不同模块拆分不同文件,方便README文件的阅读。 @@ -120,6 +120,14 @@ - [1.14.10 应用场景](#11410-应用场景) - [1.15 Class语法和继承](#115-class语法和继承) - [1.16 Module语法和加载实现](#116-module语法和加载实现) + - [1.16.1 介绍](#1161-介绍) + - [1.16.2 严格模式](#1162-严格模式) + - [1.16.3 export命令](#1163-export命令) + - [1.16.4 import命令](#1164-import命令) + - [1.16.5 模块的整体加载](#1165-模块的整体加载) + - [1.16.6 export default 命令](#1166-export-default-命令) + - [1.16.7 export 和 import 复合写法](#1167-export-和-import-复合写法) + - [1.16.8 浏览器中的加载规则](#1168-浏览器中的加载规则) - [2. ES7](#2-es7) - [Object.keys(),Object.values(),Object.entries()](#objectkeysobjectvaluesobjectentries) - [Object.getOwnPropertyDescriptors()](#objectgetownpropertydescriptors) @@ -2738,9 +2746,6 @@ result.value.then(function(data){ }) ``` - - - [⬆ 返回目录](#二目录) @@ -2750,6 +2755,218 @@ result.value.then(function(data){ [⬆ 返回目录](#二目录) ### 1.16 Module语法和加载实现 +#### 1.16.1 介绍 +ES6之前用于JavaScript的模块加载方案,是一些社区提供的,主要有`CommonJS`和`AMD`两种,前者用于**服务器**,后者用于**浏览器**。 +ES6提供了模块的实现,使用`export`命令对外暴露接口,使用`import`命令输入其他模块暴露的接口。 +```js +// CommonJS模块 +let { stat, exists, readFire } = require('fs'); + +// ES6模块 +import { stat, exists, readFire } = from 'fs'; +``` + +#### 1.16.2 严格模式 +ES6模块自动采用严格模式,无论模块头部是否有`"use strict"`。 +**严格模式有以下限制**: +* 变量必须**声明后再使用** +* 函数的参数**不能有同名属性**,否则报错 +* 不能使用`with`语句 +* 不能对只读属性赋值,否则报错 +* 不能使用前缀 0 表示八进制数,否则报错 +* 不能删除不可删除的属性,否则报错 +* 不能删除变量`delete prop`,会报错,只能删除属性`delete * global[prop]` +* `eval`不会在它的外层作用域引入变量 +* `eval`和`arguments`不能被重新赋值 +* `arguments`不会自动反映函数参数的变化 +* 不能使用`arguments.callee` +* 不能使用`arguments.caller` +* 禁止`this`指向全局对象 +* 不能使用`fn.caller`和`fn.arguments`获取函数调用的堆栈 +* 增加了保留字(比如`protected`、`static`和`interface`) + +特别是,ES6中顶层`this`指向`undefined`,即不应该在顶层代码使用`this`。 + +#### 1.16.3 export命令 +使用`export`向模块外暴露接口,可以是方法,也可以是变量。 +```js +// 1. 变量 +export let a = 'leo'; +export let b = 100; + +// 还可以 +let a = 'leo'; +let b = 100; +export {a, b}; + +// 2. 方法 +export function f(a,b){ + return a*b; +} + +// 还可以 +function f1 (){ ... } +function f2 (){ ... } +export { + a1 as f1, + a2 as f2 +} +``` +可以使用`as`重命名函数的对外接口。 +**特别注意**: +`export`暴露的必须是接口,不能是值。 +```js +// 错误 +export 1; // 报错 + +let a = 1; +export a; // 报错 + +// 正确 +export let a = 1; // 正确 + +let a = 1; +export {a}; // 正确 + +let a = 1; +export { a as b}; // 正确 +``` +暴露方法也是一样: +```js +// 错误 +function f(){...}; +export f; + +// 正确 +export function f () {...}; + +function f(){...}; +export {f}; +``` + +#### 1.16.4 import命令 +加载`export`暴露的接口,输出为变量。 +```js +import { a, b } from '/a.js'; +function f(){ + return a + b; +} +``` +`import`后大括号指定变量名,需要与`export`的模块暴露的名称一致。 +也可以使用`as`为输入的变量重命名。 +```js +import { a as leo } from './a.js'; +``` +`import`不能直接修改输入变量的值,因为输入变量只读只是个接口,但是如果是个对象,可以修改它的属性。 +```js +// 错误 +import {a} from './f.js'; +a = {}; // 报错 + +// 正确 +a.foo = 'leo'; // 不报错 +``` +`import`命令具有提升效果,会提升到整个模块头部最先执行,且多次执行相同`import`只会执行一次。 + +#### 1.16.5 模块的整体加载 +当一个模块暴露多个方法和变量,引用时可以用`*`整体加载。 +```js +// a.js +export function f(){...} +export function g(){...} + +// b.js +import * as obj from '/a.js'; +console.log(obj.f()); +console.log(obj.g()); +``` +但是,不允许运行时改变: +```js +import * as obj from '/a.js'; +// 不允许 +obj.a = 'leo'; +obj.b = function(){...}; +``` + +#### 1.16.6 export default 命令 +使用`export default`命令,为模块指定默认输出,引用的时候直接指定任意名称即可。 +```js +// a.js +export default function(){console.log('leo')}; + +// b.js +import leo from './a.js'; +leo(); // 'leo' +``` +`export defualt`暴露有函数名的函数时,在调用时相当于匿名函数。 +```js +// a.js +export default function f(){console.log('leo')}; +// 或者 +function f(){console.log('leo')}; +export default f; + +// b.js +import leo from './a.js'; +``` +`export defualt`其实是输出一个名字叫`default`的变量,所以后面不能跟变量赋值语句。 +```js +// 正确 +export let a= 1; + +let a = 1; +export defualt a; + +// 错误 +export default let a = 1; +``` +`export default`命令的本质是将后面的值,赋给`default`变量,所以可以直接将一个值写在`export default`之后。 +```js +// 正确 +export detault 1; +// 错误 +export 1; +``` + +#### 1.16.7 export 和 import 复合写法 +常常在先输入后输出同一个模块使用,即转发接口,将两者写在一起。 +```js +export {a, b} from './leo.js'; + +// 理解为 +import {a, b} from './leo.js'; +export {a, b} +``` +常见的写法还有: +```js +// 接口改名 +export { a as b} from './leo.js'; + +// 整体输出 +export * from './leo.js'; + +// 默认接口改名 +export { default as a } from './leo.js'; +``` +**常常用在模块继承**。 + +#### 1.16.8 浏览器中的加载规则 +ES6中,可以在浏览器使用` +``` +另外,ES6模块也可以内嵌到网页,语法与外部加载脚本一致: +```html + +``` +**注意点**: +* 代码是在模块作用域之中运行,而不是在全局作用域运行。模块内部的顶层变量,外部不可见。 +* 模块脚本自动采用严格模式,不管有没有声明`use strict`。 +* 模块之中,可以使用`import`命令加载其他模块(`.js`后缀不可省略,需要提供`绝对 UR`L 或`相对 UR`L),也可以使用`export`命令输出对外接口。 +* 模块之中,顶层的`this`关键字返回`undefined`,而不是指向`window`。也就是说,在模块顶层使用`this`关键字,是无意义的。 +* 同一个模块如果加载多次,将只执行一次。 [⬆ 返回目录](#二目录) From 8a9f1c21f3cccc87cf167bf4d3cfb30d44b8e2a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Wed, 31 Oct 2018 23:30:20 +0800 Subject: [PATCH 105/835] 2018.10.31 --- ...37\351\235\242\350\257\225\351\242\230.md" | 469 ++++++++++++++++++ 1 file changed, 469 insertions(+) create mode 100644 "article/62-2018\345\220\204\345\244\247\345\205\254\345\217\270\350\277\221\346\234\237\351\235\242\350\257\225\351\242\230.md" diff --git "a/article/62-2018\345\220\204\345\244\247\345\205\254\345\217\270\350\277\221\346\234\237\351\235\242\350\257\225\351\242\230.md" "b/article/62-2018\345\220\204\345\244\247\345\205\254\345\217\270\350\277\221\346\234\237\351\235\242\350\257\225\351\242\230.md" new file mode 100644 index 00000000..2fadae20 --- /dev/null +++ "b/article/62-2018\345\220\204\345\244\247\345\205\254\345\217\270\350\277\221\346\234\237\351\235\242\350\257\225\351\242\230.md" @@ -0,0 +1,469 @@ +> [ԭĵַ](https://segmentfault.com/a/1190000016789897) + + +## +* ʹùkoa2м +* koa-bodyԭ +* Լдм +* û漰Cluster +* pm2 +* master˵Ļpm2ô +* κMySQLͨ +* ReactڼԼ +* React-Router +* ·ɵĶ̬ģ +* ȾSSR +* ·ɵhistory +* Redux +* Reduxʵֶ֮ͨţʹͬ״̬νй +* ֮βָԵstateÿСԼ״̬֮仹һЩ״̬Ҫά˼ +* ʹùReduxм +* ν +* Httpͷ +* ƶ1px +* flex +* cssʽôֱ +* ΪʲôҪʹtransformΪʲôʹmarginLeft/Top +* ʹùwebpackЩpluginloader +* webpackIJôʵֵ +* dev-serverô +* ĿŻ +* ȡļôõ +* Ŀδȫ +* ôʵthis + +## +* reduxҪʲô +* ļϴϵ +* Կ +* promiseasyncʲô +* δ +* +* ܹ۲ģʽ +* нģʽ +* ۲ߺͶ-𣬸 +* reactŻ +* http2.0 +* ͨʲô +* http1.1ʱθtcp +* service worker +* css3position:sticky +* reduxмδ +* Promise쳣 +* position԰CSS3 +* ¼ +* ¼Լȱ +* Reactô¼ +* React¼ԭ +* this +* ǰôƹ· +* ʹ·ʱν +* Reactôݵļͱ仯 + +## ε +* react-routerôʵ·л +* react-routerǩͱǩʲô +* ǩĬ¼֮ʲôʵת +* ReactŻ +* ǰ·ּ +* import { Button } from 'antd'ʱֻbuttonģأô +* ʹimportʱwebpacknode_modulesʲô +* JS첽ķչԼȱ +* Httpĵм +* cookiecookieʹڵļֵ +* cookietokenheader棬Ϊʲôֻٳǰ +* cookiesessionЩ +* ReactDomṹ仯ڲЩ仯 +* Reactصʱ3textComponentcomposeComponentdomComponent͹ϵDomṹ仯ʱôdataı仯ô£ôȣµʱô +* keyҪǽһ⣬Ϊʲôindexػ棩 +* Redux첽ô +* Reduxмʲôܼ˵Ŀﻯ +* ﻯ˵IJʲô +* мôõstoreactionȻô +* stateôע뵽ģreducerʲôĹ +* koaresponse.sendresponse.roundedresponse.jsonʲô£Ϊʲôʶһjsonṹhtml +* koa-bodyparserôrequest +* webpackڣloaderpluginʲô +* ASTAbstract Syntax Tree﷨ +* ׿Activity֮ôݵ +* ׿4.06.0WebViewjsԵı仯 +* WebViewԭͨ +* ôûʹùApacheȷ + +## ͷ +* asyncawait⣬ڲԭ +* Promiseڲʵ +* +* λ⣨ԶλԶλȣ +* URLҳȫ +* tcp3 +* tcpһ㣨1 -> 2 · -> 3 (ip)-> 4 (tcp) -> 5 Ӧò(http) +* redux˼ +* reduxĹ +* connectĹ +* connectԭ +* webpack +* == ===ʲô== +* bindcallapply +* ˽ +* ԭǼ̳ +* Կ˽ + +## +* Linux 754 +* ðѡðŻ +* transformֱʹlefttopıλʲôȱ +* жǷл +* ܶص +* ʱ +* ES6еmapԭĶʲô +* ۲ߺͷ-ĵ +* react첽Ⱦĸ,Time Slicing Suspense +* 16.Xڵĸı +* 16.Xpropsıĸд +* ܴ +* ǰŻ +* pureComponentFunctionComponent +* JSX +* RNڰ׿IOS˵ +* RNΪʲôԭлƳԭbundle.js +* DOM +* һlocalStorage֤ݵʵЧ +* Promise.all() +* ܸ߽ +* sum(2, 3)ʵsum(2)(3)Ч +* reactŻ +* αȽ + +## ڲ +* JSԭ +* +* callapplybind +* ͽ +* ܸ첽 +* react +* Fiber +* ǰŻ +* DOMԱ +* reactеkey +* ״̬ +* cssxsrf +* http +* ĿӦݽṹ +* nativeṩʲôRN +* ϵŻ +* shouldComponentUpdateΪ˽ʲô +* νprops㼶 +* ǰôԪ +* webpack +* webpack +* õplugins +* pm2ô̹̹ҵô +* pm2ô̹ + +## +* +* ôȥ +* jsonpҪô +* AjaxҪʲôǰˣ +* CORS֮ӷʽɹĹ +* xsrf򹥻İȫô +* ʹAsyncעЩ +* Asyncжawait󣬿ôŻǷ +* PromiseAsyncʧܵʱʲô +* Redux״̬Reactܽ +* Reduxûװ +* reactڣõ +* Ӧʲô +* һĸ +* ôŻ첽... +* дreactЩϸڿŻ +* React¼ƣһ¼һϣ +* ¼Ҫʲô +* ǰ˿õЩģʽ +* React/ReduxЩõЩģʽ +* JSͷΪ֣ʲô +* JSջʲôõ֣ô +* һô֯CSSWebpack + +## ô +* С濪ҳ +* ReactӸ֮δֵ +* Emit¼ôҪʲô +* React߽ͨʲô +* һ飬ÿӶһidnameReactȾȫname +* ĸд +* мnameڣͨ첽ӿڻȡ +* Ⱦʱkeyʲôֵʹindexidûindex +* webpacksassҪЩloader +* cssҪЩloader +* ðjscsshtmlһļ +* divֱˮƽУflexԶλ +* Ԫؿ飬һһңм10 +* ¹̶мʵ +* [1, 2, 3, 4, 5][1, 2, 3, a, b, 5] +* ȡֵES5ES6 +* applycall +* ES5ES6ʲô +* someeveryfindfiltermapforEachʲô +* ȡÿηصֵһ +* 0-595-99 +* ҳ1buttonΰ¼ +* жbutton +* ҳһbuttonҰ¼JSԭDOM +* ѭʱindexǶ٣Ϊʲôô +* ҳһinputһpǩıinputpǩ͸ű仯δ +* inputĸ¼ʲôʱ򴥷 + +## Я +* ReactûһЩ +* ԱհĿΪʲôҪñհ +* дȥغ +* дƽ +* Promise; +* PromiseCallbackʲô +* React +* д㷨 + +## ϲ +* ES6µ +* Promise +* Promiseм״̬ +* ˵һ±հ +* React +* componentWillReceivePropsĴʲô +* React16.3ڵĸı +* ReactFilberܹ +* FilberȾ +* React߽ +* ֮ͨ +* ReduxôʵԴݣԭ +* React-Router汾 +* վSEOô +* HTTP״̬ +* 403301302ʲô +* صHTTPͷ +* HTTPS +* HTTPSôȫͨ +* ǰŻJSԭReact +* ûʲôŻ +* PWAʲô˽ +* ԰ȫʲô˽ +* ǩԭ +* ǰͨʹʲô +* RESTfulõMethod +* ¿ +* Access-Control-Allow-Originڷ +* csrfվô +* ǰ˺ͺô + +## Ұ +* localStoragecookieʲô +* CSSѡЩ +* ģͣԼ׼IEµ +* ʵָ߶Ӧ +* prototype͡proto +* _constructʲô +* newôʵֵ +* promiseľ裬Լȱ +* ʵH5ֻ˵ +* remflexroot em +* empx +* React +* ȥurlе# +* Redux״̬ͱصwindowʲô +* webpackgulpȱ +* ʵ첽 +* ʵַģڣ +* ǰŻ1js css2 ͼƬ3 Ԥأ 4 SSR 5 أ6 ؾ⣩ +* Դޣ6 +* base64Ϊʲôܣȱ +* webpͼƬļʽ +* koa2 +* Promiseʵֵ +* 첽󣬵Ͱ汾fetchεͰ汾 +* ajaxδ +* CORS +* jsonpΪʲô֧post +* ͬԴ +* ReactʹùһЩ +* Immuable +* reduxԭ +* ԭ +* μ̳ + +## ΢ҽ +* JSͣͺ͵ +* ArrayObject +* ͷֱ +* var a = {name: "ǰ˿"}; var b = a; a = nullôbʲô +* var a = {b: 1} +* var a = {b: {c: 1}} +* ջͶѵ +* ʱջͶѵ +* 10ݣȡһԪغ͵10Ԫصʱ +* ջͶѾô洢 +* ܱհԼհΪʲôû +* հʹó +* JSôʵ첽 +* 첽ִ +* Promise״̬ +* Async/Awaitôʵ +* PromisesetTimeoutִȺ +* JSΪʲôҪ΢ͺ +* Promise캯ͬ첽ִУthen +* -ĺ͹۲ģʽ +* JSִйзΪЩ׶ +* ʷthis +* ƽô̳ +* dz +* loadshʵԭ +* ES6letôʵֵ +* ReactsetStateʲô +* setStateΪʲôĬ첽 +* setStateʲôʱͬ +* Ϊʲô3ܳԺͳֺܶnativeRNܣDOM +* DOMҪʲô +* DOMʲôJS +* 304ʲô +* ʱHashôɵ +* ֵһα +* ʹwebpackʱһЩԶ +* webpackʲô +* abťaba˳baaα֤abaPromise.then +* nodeӿתʲôŻ +* nodeα֤ȶԣƽ +* RNûȼ +* RNļ +* RNʵһԭ +* RNԭԭRNʲôͬ +* ʲôǵҳĿ +* ĸҵ񳡾 +* Promise.allʵԭ + +## ¿ +* Promiseԣȱ +* Redux +* RNԭΪʲôͬʱڰ׿IOS +* RNεԭһЩ +* RNȱ +* 㷨Ϳԭ +* Ѻջ +* ܱհ +* հĺʲô +* ģ +* HTTPHTTPS +* HTTPSļܹ +* SSLTLS +* DNS +* JSļ̳з +* +* cookieΪ˽ʲô +* cookielocalStorage +* ν +* ǰŻ + +## +* ʹcanvasͼʱ֯ͨ +* formDataԭajaxʲô +* ±ύformDataʲôϵ +* redux +* ruduxȫֹʲôݿɿءӦ +* RNԭͨ +* MVPô֯ +* 첽 +* promiseʵthen +* koa2мԭ +* õм +* ôͳһ״̬ +* ζ·ýŻ +* nodeļȼ +* npm2npm3+ʲô +* +* knexݿӦص +* 첽 +* δ쳣 +* Ŀιģ +* ǰŻ +* JS̳з +* жһDz +* abν +* ¼ί +*
  • ǩɵDomṹһ +* +* domת +* ܵҳӦúͶҳӦ +* redux״̬Ĺ +* localstorageAPI + +## Ģ +* html廯 +* ͵ +* Ահ +* бհʹó +* thisԭ +* ʹԭĺô +* react˼· +* ΪʲôDOMʵDOMܺ +* reactͨŷʽ +* reduxĹ +* reduxȫֶ֮ +* Reduxݻ˼· +* ۲Ŀʵʳ +* ĿʹóԼ˽ +* ջ + +## +* react +* reactŻ +* ԭ¼ƳΪʲôڴй¶ +* Щطڴй¶ +* setIntervalҪעĵ +* ʱΪʲôDzȷ +* setTimeout(1)setTimeout(2)֮ +* ܺ΢ +* promisethenִʲô +* pureComponet +* Function Component +* React +* propsstate +* react context +* classES5Լ +* ܼͷͨ +* definePropertyʲôʱҪõ +* for..in object.keys +* ܱհʹó +* ʹñհȨʹó +* getpostʲô + +## ٷֵ +* React15/16.x +* ȾrenderЩʲô +* ЩᴥreactȾ +* statepropsµڷֱʲô +* setStateͬ첽 +* ״̬ +* Redux +* ES6Ĺ +* letconstԼvar +* dz +* ܼͷthis +* Promisethen +* ܿ +* 㷨ǰKԪ + +## +* reactȱ +* ʹù⣬ν +* reactʲôúʽҳȾ +* JSʲôʽ(Ǻʽ) +* koaԭΪʲôҪkoa(expresskoaԱ) +* ʹõkoaм +* ES6ʹõ﷨ +* Promise async/await callback +* Promiseûн첽⣨promiseǿĵط +* PromisesetTimeoutEvent Loop +* ̵̺߳һnodeʵһ̣nodeǵ̣߳ͨ¼ѭʵ첽 +* DFS +* ¹۲ģʽ +* ۲ģʽʹõݽṹ(߱˳ һlist) \ No newline at end of file From 68b78c58559022b8bc5f9e81797e8fda0e232646 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Wed, 31 Oct 2018 23:32:12 +0800 Subject: [PATCH 106/835] 2018.10.31 --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7f778287..317af925 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,10 @@ * [11-20个超级常用的正则表达式](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/11-20%E4%B8%AA%E8%B6%85%E7%BA%A7%E5%B8%B8%E7%94%A8%E7%9A%84%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F.md) * [57-ES5ES6正则表达式总结](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/57-ES5ES6%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%80%BB%E7%BB%93.md) -### 9、其他 +### 9、面试题 +* [62-2018各大公司近期面试题](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/62-2018%E5%90%84%E5%A4%A7%E5%85%AC%E5%8F%B8%E8%BF%91%E6%9C%9F%E9%9D%A2%E8%AF%95%E9%A2%98.md) + +### 10、其他 * [2017-全年总结](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/2017-%E5%85%A8%E5%B9%B4%E6%80%BB%E7%BB%93.md) * [2018-全年计划](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/2018-%E5%85%A8%E5%B9%B4%E8%AE%A1%E5%88%92.md) * [★ 27-Markdowm语法整理](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/27-Markdowm%E8%AF%AD%E6%B3%95%E6%95%B4%E7%90%86.md) From 55e0fec06a8c0cb3e2b62516a925dc7e79e7dd74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Thu, 1 Nov 2018 00:04:07 +0800 Subject: [PATCH 107/835] =?UTF-8?q?2018.11.1=20=E4=BF=AE=E6=94=B9=E9=94=99?= =?UTF-8?q?=E5=88=AB=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index c4cbaf34..c1a70794 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -1651,7 +1651,7 @@ for(let i of a.values()){console.log(i)}; // 'a' 'b' 'c' for(let i of a.entries()){console.log(i)}; // ['a','a'] ['b','b'] ['c','c'] ``` -并且 还可以使用`for...of```直接遍历`Set`。 +并且 还可以使用`for...of`直接遍历`Set`。 ```js let a = new Set(['a','b','c']); for(let k of a){console.log(k)}; // 'a' 'b' 'c' @@ -2414,6 +2414,7 @@ for (let k in a){console.log(k)}; // 0 1 2 ``` * **Set和Map** +可以使用数组作为变量,如`for (let [k,v] of b){...}`。 ```js let a = new Set(['a', 'b', 'c']); for (let k of a){console.log(k)}; // a b c From 25e2edf346948ec703b5b779f60eb73ec98808d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Thu, 1 Nov 2018 23:30:03 +0800 Subject: [PATCH 108/835] =?UTF-8?q?2018.11.1=20=E6=9B=B4=E6=96=B0ES6?= =?UTF-8?q?=E3=80=8AClass=E3=80=8B=E7=AB=A0=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 378 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 375 insertions(+), 3 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index c1a70794..4740146e 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -14,7 +14,8 @@ * 2018.10.26 添加**ES6**《**Proxy**》章节。 * 2018.10.29 添加**ES6**《**正则表达式**》《**Promise**》章节。 * 2018.10.30 添加**ES6**《**Iterator**》章节。 -* 2018.10.31 添加**ES6**《**Generator**,**Module**》章节。 +* 2018.10.31 添加**ES6**《**Generator**,**Module**》章节。 +* 2018.11.1 更新**ES6**《**Class**》章节。 **未来规划**: * 1.将内容按不同模块拆分不同文件,方便README文件的阅读。 @@ -115,10 +116,21 @@ - [1.14.5 for...of循环](#1145-forof循环) - [1.14.6 Generator.prototype.throw()](#1146-generatorprototypethrow) - [1.14.7 Generator.prototype.return()](#1147-generatorprototypereturn) - - [1.14.8 next()/throw()/return()Fon共同点](#1148-nextthrowreturnfon共同点) + - [1.14.8 next()/throw()/return()共同点](#1148-nextthrowreturn共同点) - [1.14.9 yield* 表达式](#1149-yield-表达式) - [1.14.10 应用场景](#11410-应用场景) - [1.15 Class语法和继承](#115-class语法和继承) + - [1.15.1 介绍](#1151-介绍) + - [1.15.2 constructor()方法](#1152-constructor方法) + - [1.15.3 类的实例对象](#1153-类的实例对象) + - [1.15.4 Class表达式](#1154-class表达式) + - [1.15.5 私有方法和私有属性](#1155-私有方法和私有属性) + - [1.15.6 this指向问题](#1156-this指向问题) + - [1.15.7 Class的getter和setter](#1157-class的getter和setter) + - [1.15.8 Class的generator方法](#1158-class的generator方法) + - [1.15.9 Class的静态方法](#1159-class的静态方法) + - [1.15.10 Class的静态属性和实例属性](#11510-class的静态属性和实例属性) + - [1.15.11 Class的继承](#11511-class的继承) - [1.16 Module语法和加载实现](#116-module语法和加载实现) - [1.16.1 介绍](#1161-介绍) - [1.16.2 严格模式](#1162-严格模式) @@ -2629,7 +2641,7 @@ g.return('leo'); // {value : 'leo', done " true} g.next(); // {value : undefined, done : true} ``` -#### 1.14.8 next()/throw()/return()Fon共同点 +#### 1.14.8 next()/throw()/return()共同点 相同点就是都是用来恢复Generator函数的执行,并且使用不同语句替换`yield`表达式。 * `next()`将`yield`表达式替换成一个值。 ```js @@ -2752,6 +2764,366 @@ result.value.then(function(data){ ### 1.15 Class语法和继承 +#### 1.15.1 介绍 +ES6中的`class`可以看作只是一个语法糖,绝大部分功能都可以用ES5实现,并且,**类和模块的内部,默认就是严格模式,所以不需要使用use strict指定运行模式**。 +```js +// ES5 +function P (x,y){ + this.x = x; + this.y = y; +} +P.prototype.toString = function () { + return '(' + this.x + ', ' + this.y + ')'; +}; +var a = new P(1, 2); + +// ES6 +class P { + constructor(x, y){ + this.x = x; + this.y = y; + } + toString(){ + return '(' + this.x + ', ' + this.y + ')'; + } +} +let a = new P(1, 2); +``` +**值得注意**: +ES6的**类**的所有方法都是定义在`prototype`属性上,调用类的实例的方法,其实就是调用原型上的方法。 +```js +class P { + constructor(){ ... } + toString(){ ... } + toNumber(){ ... } +} +// 等同于 +P.prototyoe = { + constructor(){ ... }, + toString(){ ... }, + toNumber(){ ... } +} + +let a = new P(); +a.constructor === P.prototype.constructor; // true +``` +类的属性名可以使用**表达式**: +```js +let name = 'leo'; +class P { + constructor (){ ... } + [name](){ ... } +} +``` + +**Class不存在变量提升**: +ES6中的类不存在变量提升,与ES5完全不同: +```js +new P (); // ReferenceError +class P{...}; +``` +**Class的name属性**: +`name`属性总是返回紧跟在`class`后的类名。 +```js +class P {} +P.name; // 'P' +``` + +#### 1.15.2 constructor()方法 +`constructor()`是类的默认方法,通过`new`实例化时自动调用执行,一个类必须有`constructor()`方法,否则一个空的`constructor()`会默认添加。 +`constructor()`方法默认返回实例对象(即`this`)。 +```js +class P { ... } +// 等同于 +class P { + constructor(){ ... } +} +``` + +#### 1.15.3 类的实例对象 +与ES5一样,ES6的类必须使用`new`命令实例化,否则报错。 +```js +class P { ... } +let a = P (1,2); // 报错 +let b = new P(1, 2); // 正确 +``` +与 ES5 一样,实例的属性除非显式定义在其本身(即定义在`this`对象上),否则都是定义在原型上(即定义在`class`上)。 +```js +class P { + constructor(x, y){ + this.x = x; + this.y = y; + } + toString(){ + return '(' + this.x + ', ' + this.y + ')'; + } +} +var point = new Point(2, 3); + +point.toString() // (2, 3) + +point.hasOwnProperty('x') // true +point.hasOwnProperty('y') // true +point.hasOwnProperty('toString') // false +point.__proto__.hasOwnProperty('toString') // true +// toString是原型对象的属性(因为定义在Point类上) +``` + +#### 1.15.4 Class表达式 +与函数一样,类也可以使用表达式来定义,使用表达式来作为类的名字,而`class`后跟的名字,用来指代当前类,只能再Class内部使用。 +```js +let a = class P{ + get(){ + return P.name; + } +} + +let b = new a(); +b.get(); // P +P.name; // ReferenceError: P is not defined +``` +如果类的内部没用到的话,可以省略`P`,也就是可以写成下面的形式。 +```js +let a = class { ... } +``` + +#### 1.15.5 私有方法和私有属性 +由于ES6不提供,只能变通来实现: +* 1.使用命名加以区别,如变量名前添加`_`,但是不保险,外面也可以调用到。 +```js +class P { + // 公有方法 + f1 (x) { + this._x(x); + } + // 私有方法 + _x (x){ + return this.y = x; + } +} +``` +* 2.将私有方法移除模块,再在类内部调用`call`方法。 +```js +class P { + f1 (x){ + f2.call(this, x); + } +} +function f2 (x){ + return this.y = x; +} +``` +* 3.使用`Symbol`为私有方法命名。 +```js +const a1 = Symbol('a1'); +const a2 = Symbol('a2'); +export default class P{ + // 公有方法 + f1 (x){ + this[a1](x); + } + // 私有方法 + [a1](x){ + return this[a2] = x; + } +} +``` + + +#### 1.15.6 this指向问题 +类内部方法的`this`默认指向类的实例,但单独使用该方法可能报错,因为`this`指向的问题。 +```js +class P{ + leoDo(thing = 'any'){ + this.print(`Leo do ${thing}`) + } + print(text){ + console.log(text); + } +} +let a = new P(); +let { leoDo } = a; +leoDo(); // TypeError: Cannot read property 'print' of undefined +// 问题出在 单独使用leoDo时,this指向调用的环境, +// 但是leoDo中的this是指向P类的实例,所以报错 +``` +**解决方法**: +* 1.在类里面绑定`this` +```js +class P { + constructor(){ + this.name = this.name.bind(this); + } +} +``` +* 2.使用箭头函数 +```js +class P{ + constructor(){ + this.name = (name = 'leo' )=>{ + this.print(`my name is ${name}`) + } + } +} +``` + +#### 1.15.7 Class的getter和setter +使用`get`和`set`关键词对属性设置取值函数和存值函数,拦截属性的存取行为。 +```js +class P { + constructor (){ ... } + get f (){ + return 'getter'; + } + set f (val) { + console.log('setter: ' + val); + } +} + +let a = new P(); +a.f == 100; // setter : 100 +a.f; // getter +``` + +#### 1.15.8 Class的generator方法 +只要在方法之前加个(`*`)即可。 +```js +class P { + constructor (...args){ + this.args = args; + } + *[Symbol.iterator](){ + for (let arg of this.args){ + yield arg; + } + } +} +for (let k of new P('aa', 'bb')){ + console.log(k); +} +// 'aa' +// 'bb' +``` + +#### 1.15.9 Class的静态方法 +由于类相当于实例的原型,所有类中定义的方法都会被实例继承,若不想被继承,只要加上`static`关键字,只能通过类来调用,即“**静态方法**”。 +```js +class P (){ + static f1 (){ return 'aaa' }; +} +P.f1(); // 'aa' +let a = new P(); +a.f1(); // TypeError: a.f1 is not a function +``` +如果静态方法包含`this`关键字,则`this`指向类,而不是实例。 +```js +class P { + static f1 (){ + this.f2(); + } + static f2 (){ + console.log('aaa'); + } + f2(){ + console.log('bbb'); + } +} +P.f2(); // 'aaa' +``` +并且静态方法可以被子类继承,或者`super`对象中调用。 +```js +class P{ + static f1(){ return 'leo' }; +} +class Q extends P { ... }; +Q.f1(); // 'leo' + +class R extends P { + static f2(){ + return super.f1() + ',too'; + } +} +R.f2(); // 'leo , too' +``` + +#### 1.15.10 Class的静态属性和实例属性 +ES6中明确规定,Class内部只有静态方法没有静态属性,所以只能通过下面实现。 +```js +// 正确写法 +class P {} +P.a1 = 1; +P.a1; // 1 + +// 无效写法 +class P { + a1: 2, // 无效 + static a1 : 2, // 无效 +} +P.a1; // undefined +``` +**新提案来规定实例属性和静态属性的新写法** +* 1.类的实例属性 +类的实例属性可以用等式,写入类的定义中。 +```js +class P { + prop = 100; // prop为P的实例属性 可直接读取 + constructor(){ + console.log(this.prop); // 100 + } +} +``` +有了新写法后,就可以不再`contructor`方法里定义。 +为了可读性的目的,对于那些在`constructor`里面已经定义的实例属性,新写法允许**直接列出**。 +```js +// 之前写法: +class RouctCounter extends React.Component { + constructor(prop){ + super(prop); + this.state = { + count : 0 + } + } +} + +// 新写法 +class RouctCounter extends React.Component { + state; + constructor(prop){ + super(prop); + this.state = { + count : 0 + } + } + +} +``` +* 2.类的静态属性 +只要在实例属性前面加上`static`关键字就可以。 +```js +class P { + static prop = 100; + constructor(){console.log(this.prop)}; // 100 +} +``` +新写法方便静态属性的表达。 +```js +// old +class P { .... } +P.a = 1; + +// new +class P { + static a = 1; +} +``` + +#### 1.15.11 Class的继承 +主要通过`extends`关键字实现。 +```js +class P { ... } +class Q extends P { ... } +``` + [⬆ 返回目录](#二目录) From 0ca589ab355cf69dc626e0b1caaa7a041f1aa73d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 2 Nov 2018 00:17:57 +0800 Subject: [PATCH 109/835] =?UTF-8?q?2018.11.2=20=E5=AE=8C=E6=88=90ES6?= =?UTF-8?q?=E6=89=80=E6=9C=89=E7=AB=A0=E8=8A=82=E5=86=85=E5=AE=B9=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 116 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 114 insertions(+), 2 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 4740146e..b8aefd47 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -15,7 +15,8 @@ * 2018.10.29 添加**ES6**《**正则表达式**》《**Promise**》章节。 * 2018.10.30 添加**ES6**《**Iterator**》章节。 * 2018.10.31 添加**ES6**《**Generator**,**Module**》章节。 -* 2018.11.1 更新**ES6**《**Class**》章节。 +* 2018.11.1 更新**ES6**《**Class**》章节。 +* 2018.11.2 完成**ES6**所有章节内容。 **未来规划**: * 1.将内容按不同模块拆分不同文件,方便README文件的阅读。 @@ -3118,12 +3119,123 @@ class P { ``` #### 1.15.11 Class的继承 -主要通过`extends`关键字实现。 +主要通过`extends`关键字实现,继承父类的所有属性和方法,通过`super`关键字来新建父类构造函数的`this`对象。 ```js class P { ... } class Q extends P { ... } + +class P { + constructor(x, y){ + // ... + } + f1 (){ ... } +} +class Q extends P { + constructor(a, b, c){ + super(x, y); // 调用父类 constructor(x, y) + this.color = color ; + } + f2 (){ + return this.color + ' ' + super.f1(); + // 调用父类的f1()方法 + } +} +``` +**子类必须在`constructor()`调用`super()`否则报错**,并且只有`super`方法才能调用父类实例,还有就是,**父类的静态方法,子类也可以继承到**。 +```js +class P { + constructor(x, y){ + this.x = x; + this.y = y; + } + static fun(){ + console.log('hello leo') + } +} +// 关键点1 调用super +class Q extends P { + constructor(){ ... } +} +let a = new Q(); // ReferenceError 因为Q没有调用super + +// 关键点2 调用super +class R extends P { + constructor (x, y. z){ + this.z = z; // ReferenceError 没调用super不能使用 + super(x, y); + this.z = z; // 正确 + } +} + +// 关键点3 子类继承父类静态方法 +R.hello(); // 'hello leo' +``` + +**super关键字**: +既可以当函数使用,还可以当对象使用。 +* 1.当函数调用,代表父类的构造函数,但必须执行一次。 +```js +class P {... }; +class R extends P { + constructor(){ + super(); + } +} +``` +* 2.当对象调用,指向原型对象,在静态方法中指向父类。 +```js +class P { + f (){ return 2 }; +} +class R extends P { + constructor (){ + super(); + console.log(super.f()); // 2 + } +} +let a = new R() ``` +**注意**:`super`指向父类原型对象,所以定义在父类实例的方法和属性,是无法通过`super`调用的,但是通过调用`super`方法可以把内部`this`指向当前实例,就可以访问到。 +```js +class P { + constructor(){ + this.a = 1; + } + print(){ + console.log(this.a); + } +} +class R extends P { + get f (){ + return super.a; + } +} +let b = new R(); +b.a; // undefined 因为a是父类P实例的属性 + +// 先调用super就可以访问 +class Q extends P { + constructor(){ + super(); // 将内部this指向当前实例 + return super.a; + } +} +let c = new Q(); +c.a; // 1 +// 情况3 +class J extends P { + constructor(){ + super(); + this.a = 3; + } + g(){ + super.print(); + } +} +let c = new J(); +c.g(); // 3 由于执行了super()后 this指向当前实例 +``` [⬆ 返回目录](#二目录) From f716719cb6d68a605ac8990bf100e5aae1f6a27a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 2 Nov 2018 00:18:25 +0800 Subject: [PATCH 110/835] =?UTF-8?q?2018.11.2=20=E5=AE=8C=E6=88=90ES6?= =?UTF-8?q?=E6=89=80=E6=9C=89=E7=AB=A0=E8=8A=82=E5=86=85=E5=AE=B9=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index b8aefd47..181dc5cf 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -1,7 +1,7 @@ **整理进度**: - [x] 介绍 - [x] 目录 -- [ ] ES6 +- [x] ES6 - [ ] ES7 - [ ] ES8 - [ ] ES9 From 88b7097f8e36d4d8b7be92a0343ad530411b7e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 2 Nov 2018 00:19:35 +0800 Subject: [PATCH 111/835] =?UTF-8?q?2018.11.2=20=E5=AE=8C=E6=88=90ES6?= =?UTF-8?q?=E6=89=80=E6=9C=89=E7=AB=A0=E8=8A=82=E5=86=85=E5=AE=B9=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 181dc5cf..e77acbdf 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -16,7 +16,7 @@ * 2018.10.30 添加**ES6**《**Iterator**》章节。 * 2018.10.31 添加**ES6**《**Generator**,**Module**》章节。 * 2018.11.1 更新**ES6**《**Class**》章节。 -* 2018.11.2 完成**ES6**所有章节内容。 +* 2018.11.2 完成**ES6**所有章节内容。 **未来规划**: * 1.将内容按不同模块拆分不同文件,方便README文件的阅读。 From 10f1161049fe81752ec84414b12a74a04b9f0642 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 2 Nov 2018 07:28:26 +0800 Subject: [PATCH 112/835] =?UTF-8?q?2018.11.2=20=E8=B0=83=E6=95=B4=E8=AF=AD?= =?UTF-8?q?=E5=8F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index e77acbdf..ce67cf3c 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -114,12 +114,12 @@ - [1.14.1 基本概念](#1141-基本概念) - [1.14.2 yield表达式](#1142-yield表达式) - [1.14.3 next方法](#1143-next方法) - - [1.14.5 for...of循环](#1145-forof循环) - - [1.14.6 Generator.prototype.throw()](#1146-generatorprototypethrow) - - [1.14.7 Generator.prototype.return()](#1147-generatorprototypereturn) - - [1.14.8 next()/throw()/return()共同点](#1148-nextthrowreturn共同点) - - [1.14.9 yield* 表达式](#1149-yield-表达式) - - [1.14.10 应用场景](#11410-应用场景) + - [1.14.4 for...of循环](#1144-forof循环) + - [1.14.5 Generator.prototype.throw()](#1145-generatorprototypethrow) + - [1.14.6 Generator.prototype.return()](#1146-generatorprototypereturn) + - [1.14.7 next()/throw()/return()共同点](#1147-nextthrowreturn共同点) + - [1.14.8 yield* 表达式](#1148-yield-表达式) + - [1.14.9 应用场景](#1149-应用场景) - [1.15 Class语法和继承](#115-class语法和继承) - [1.15.1 介绍](#1151-介绍) - [1.15.2 constructor()方法](#1152-constructor方法) @@ -192,7 +192,7 @@ let v2 = 2; ``` * **不允许重复声明:** -`let` 和 `const` 在相同作用域下,都**不能重复声明同一变量**,并且**不能在函数内重新声明参数**。 +`let` 和 `const` 在**相同作用域下**,都**不能重复声明同一变量**,并且**不能在函数内重新声明参数**。 ```js // 1. 不能重复声明同一变量 // 报错 @@ -2510,13 +2510,13 @@ a.next(); // {value: undefined, done : false} #### 1.14.2 yield表达式 `yield`表达式是暂停标志,遍历器对象的`next`方法的运行逻辑如下: -* 1. 遇到`yield`就暂停执行,将这个`yield`后的表达式的值,作为返回对象的`value`属性值。 -* 2. 下次调用`next`往下执行,直到遇到下一个`yield`。 -* 3. 直到函数结束或者`return`为止,并返回`return`语句后面表达式的值,作为返回对象的`value`属性值。 -* 4. 如果该函数没有`return`语句,则返回对象的`value`为`undefined` 。 +1. 遇到`yield`就暂停执行,将这个`yield`后的表达式的值,作为返回对象的`value`属性值。 +2. 下次调用`next`往下执行,直到遇到下一个`yield`。 +3. 直到函数结束或者`return`为止,并返回`return`语句后面表达式的值,作为返回对象的`value`属性值。 +4. 如果该函数没有`return`语句,则返回对象的`value`为`undefined` 。 **注意:** -* `yield`只能用在`Generator`函数里,其他地方会报错。 +* `yield`只能用在`Generator`函数里使用,其他地方使用会报错。 ```js // 错误1 (function(){ @@ -2549,7 +2549,7 @@ function * a (){ } ``` -* `yield`表达式用做函数参数或放在表达式右边,可以不加括号。 +* `yield`表达式用做函数参数或放在表达式右边,可以**不加括号**。 ```js function * a (){ f(yield 'a', yield 'b'); // ok @@ -2591,8 +2591,8 @@ b.next(13); // {value : 42 ,done : false} // x 5 y 24 z 13 ``` -#### 1.14.5 for...of循环 -`for...of`循环会自动遍历,不用调用`next`方法,需要注意的是,`for...of`遇到`next`放回的`done`属性为`true`就会终止,`return`返回的不包括在`for...of`循环中。 +#### 1.14.4 for...of循环 +`for...of`循环会自动遍历,不用调用`next`方法,需要注意的是,`for...of`遇到`next`返回值的`done`属性为`true`就会终止,`return`返回的不包括在`for...of`循环中。 ```js function * f(){ yield 1; @@ -2607,7 +2607,7 @@ for (let k of f()){ // 1 2 3 4 没有 5 ``` -#### 1.14.6 Generator.prototype.throw() +#### 1.14.5 Generator.prototype.throw() `throw`方法用来向函数外抛出错误,并且在Generator函数体内捕获。 ```js let f = function * (){ @@ -2628,7 +2628,7 @@ try{ // 外部捕获 b ``` -#### 1.14.7 Generator.prototype.return() +#### 1.14.6 Generator.prototype.return() `return`方法用来返回给定的值,并结束遍历Generator函数,如果`return`方法没有参数,则返回值的`value`属性为`undefined`。 ```js function * f(){ @@ -2642,7 +2642,7 @@ g.return('leo'); // {value : 'leo', done " true} g.next(); // {value : undefined, done : true} ``` -#### 1.14.8 next()/throw()/return()共同点 +#### 1.14.7 next()/throw()/return()共同点 相同点就是都是用来恢复Generator函数的执行,并且使用不同语句替换`yield`表达式。 * `next()`将`yield`表达式替换成一个值。 ```js @@ -2669,7 +2669,7 @@ g.return(2); // {value: 2, done: true} // 替换成 let r = return 2; ``` -#### 1.14.9 yield* 表达式 +#### 1.14.8 yield* 表达式 用于在一个Generator中执行另一个Generator函数,如果没有使用`yield*`会没有效果。 ```js function * a(){ @@ -2695,7 +2695,7 @@ for(let k of b()){console.log(k)} // 4 ``` -#### 1.14.10 应用场景 +#### 1.14.9 应用场景 * 1. **控制流管理** 解决回调地狱: ```js From f92979b3e8f56619296f802117ccb3356a7ef670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 2 Nov 2018 07:47:34 +0800 Subject: [PATCH 113/835] =?UTF-8?q?2018.11.2=20=E4=BF=AE=E6=94=B9=E8=AF=AD?= =?UTF-8?q?=E5=8F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index ce67cf3c..4c09bd37 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -2696,7 +2696,7 @@ for(let k of b()){console.log(k)} ``` #### 1.14.9 应用场景 -* 1. **控制流管理** +1. **控制流管理** 解决回调地狱: ```js // 使用前 @@ -2740,7 +2740,7 @@ function g (task){ g( f(initValue) ); ``` -* 2. **异步编程的使用** +2. **异步编程的使用** 在真实的异步任务封装的情况: ```js let fetch = require('node-fetch'); @@ -2763,7 +2763,6 @@ result.value.then(function(data){ [⬆ 返回目录](#二目录) - ### 1.15 Class语法和继承 #### 1.15.1 介绍 ES6中的`class`可以看作只是一个语法糖,绝大部分功能都可以用ES5实现,并且,**类和模块的内部,默认就是严格模式,所以不需要使用use strict指定运行模式**。 @@ -2982,7 +2981,7 @@ class P { } let a = new P(); -a.f == 100; // setter : 100 +a.f = 100; // setter : 100 a.f; // getter ``` @@ -3063,7 +3062,7 @@ class P { P.a1; // undefined ``` **新提案来规定实例属性和静态属性的新写法** -* 1.类的实例属性 +* 1.类的实例属性 类的实例属性可以用等式,写入类的定义中。 ```js class P { From f5f9869094d203e4a4844b7e628c871421e4e8ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sat, 3 Nov 2018 21:28:57 +0800 Subject: [PATCH 114/835] =?UTF-8?q?2018.11.3=20=E6=B7=BB=E5=8A=A0ES?= =?UTF-8?q?=E4=BB=8B=E7=BB=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 4c09bd37..4b603b3f 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -27,6 +27,16 @@ 这份资料的**ES6部分**将会参考阮一峰老师的 [ECMAScript6入门](http://es6.ruanyifeng.com/) ,精简和整理出快速实用的内容。 另外**ES7/ES8/ES9**则会从网络综合参考和整理。 +**ES全称ECMAScript**: +目前JavaScript使用的ECMAScript版本为[ECMAScript-262](https://www.ecma-international.org/ecma-262/)。 + +| ECMAScript版本 | 发布时间 | 新增特性 | +| ------ | ------ | ------ | +| ECMAScript 2009(ES5) | 2009年11月 | 扩展了Object、Array、Function的功能等 | +| ECMAScript 2015(ES6) | 2015年6月 | 类,模块化,箭头函数,函数参数默认值等 | +| ECMAScript 2016(ES7) | 2016年3月 | includes,指数操作符 | +| ECMAScript 2017(ES8) | 2017年6月 | sync/await,Object.values(),Object.entries(),String padding等 | + # 二、目录 From ba196499106ab29eb5044da6ae7014ef7990f6ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sun, 4 Nov 2018 20:48:57 +0800 Subject: [PATCH 115/835] =?UTF-8?q?2018.11.4=20=E5=AE=8C=E6=88=90ES7?= =?UTF-8?q?=E7=AB=A0=E8=8A=82=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 63 +++++++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 4b603b3f..9c505f8e 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -17,6 +17,7 @@ * 2018.10.31 添加**ES6**《**Generator**,**Module**》章节。 * 2018.11.1 更新**ES6**《**Class**》章节。 * 2018.11.2 完成**ES6**所有章节内容。 +* 2018.11.4 完成**ES7**章节内容。 **未来规划**: * 1.将内容按不同模块拆分不同文件,方便README文件的阅读。 @@ -3466,6 +3467,60 @@ ES6中,可以在浏览器使用` +``` +另外,ES6模块也可以内嵌到网页,语法与外部加载脚本一致: +```html + +``` +**注意点**: +* 代码是在模块作用域之中运行,而不是在全局作用域运行。模块内部的顶层变量,外部不可见。 +* 模块脚本自动采用严格模式,不管有没有声明`use strict`。 +* 模块之中,可以使用`import`命令加载其他模块(`.js`后缀不可省略,需要提供`绝对 UR`L 或`相对 UR`L),也可以使用`export`命令输出对外接口。 +* 模块之中,顶层的`this`关键字返回`undefined`,而不是指向`window`。也就是说,在模块顶层使用`this`关键字,是无意义的。 +* 同一个模块如果加载多次,将只执行一次。 + +[⬆ 返回目录](#二目录) + diff --git "a/article/64-ES7\346\261\207\346\200\273.md" "b/article/64-ES7\346\261\207\346\200\273.md" new file mode 100644 index 00000000..c2d17715 --- /dev/null +++ "b/article/64-ES7\346\261\207\346\200\273.md" @@ -0,0 +1,44 @@ +## 2. ES7 +### 2.1 Array.prototype.includes()方法 +`includes()`用于查找一个值是否在数组中,如果在返回`true`,否则返回`false`。 +```js +['a', 'b', 'c'].includes('a'); // true +['a', 'b', 'c'].includes('d'); // false +``` +`includes()`方法接收两个参数,**搜索的内容**和**开始搜索的索引**,默认值为**0**,若搜索值在数组中则返回`true`否则返回`false`。 +```js +['a', 'b', 'c', 'd'].includes('b'); // true +['a', 'b', 'c', 'd'].includes('b', 1); // true +['a', 'b', 'c', 'd'].includes('b', 2); // false +``` +与`indexOf`方法对比,下面方法效果相同: +```js +['a', 'b', 'c', 'd'].indexOf('b'); // true +['a', 'b', 'c', 'd'].includes('b') > -1; // true +``` +**includes()与indexOf对比:** +* `includes`相比`indexOf`更具语义化,`includes`返回的是是否存在的具体结果,值为布尔值,而`indexOf`返回的是搜索值的下标。 +* `includes`相比`indexOf`更准确,`includes`认为两个`NaN`相等,而`indexOf`不会。 +```js +let a = [1, NaN, 3]; +a.indexOf(NaN); // -1 +a.includes(NaN); // true +``` +另外在判断`+0`与`-0`时,`includes`和`indexOf`的返回相同。 +```js +[1, +0, 3, 4].includes(-0); // true +[1, +0, 3, 4].indexOf(-0); // 1 +``` + +### 2.2 指数操作符(**) +基本用法: +```js +let a = 3 ** 2 ; // 9 +// 等效于 +Math.pow(3, 2); // 9 +``` +`**`是一个运算符,也可以满足类似假发的操作,如下: +```js +let a = 3; +a **= 2; // 9 +``` \ No newline at end of file diff --git "a/article/65-ES8\346\261\207\346\200\273.md" "b/article/65-ES8\346\261\207\346\200\273.md" new file mode 100644 index 00000000..ac16efe0 --- /dev/null +++ "b/article/65-ES8\346\261\207\346\200\273.md" @@ -0,0 +1,371 @@ + +## 3. ES8 +### 3.1 async函数 +#### 3.1.1 介绍 +ES8引入`async`函数,是为了使异步操作更加方便,其实它就是**Generator**函数的语法糖。 +`async`函数使用起来,只要把**Generator**函数的**(*)**号换成`async`,`yield`换成`await`即可。对比如下: +```js +// Generator写法 +const fs = require('fs'); +const readFile = function (fileName) { + return new Promise(function (resolve, reject) { + fs.readFile(fileName, function(error, data) { + if (error) return reject(error); + resolve(data); + }); + }); +}; +const gen = function* () { + const f1 = yield readFile('/etc/fstab'); + const f2 = yield readFile('/etc/shells'); + console.log(f1.toString()); + console.log(f2.toString()); +}; + +// async await写法 +const asyncReadFile = async function () { + const f1 = await readFile('/etc/fstab'); + const f2 = await readFile('/etc/shells'); + console.log(f1.toString()); + console.log(f2.toString()); +}; +``` +**对比Genenrator有四个优点:** +* (1)内置执行器 +Generator函数执行需要有执行器,而`async`函数自带执行器,即`async`函数与普通函数一模一样: +```js +async f(); +``` +* (2)更好的语义 +`async`和`await`,比起`星号`和`yield`,语义更清楚了。`async`表示函数里有异步操作,`await`表示紧跟在后面的表达式需要等待结果。 +* (3)更广的适用性 +`yield`命令后面只能是 Thunk 函数或 Promise 对象,而`async`函数的`await`命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)。 +* (4)返回值是Promise +`async`函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用`then`方法指定下一步的操作。 + +进一步说,`async`函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而`await`命令就是内部`then`命令的语法糖。 + +#### 3.1.2 基本用法 +`async`函数返回一个Promise对象,可以使用`then`方法添加回调函数,函数执行时,遇到`await`就会先返回,等到异步操作完成,在继续执行。 +```js +async function f(item){ + let a = await g(item); + let b = await h(item); + return b; +} +f('hello').then(res => { + console.log(res); +}) +``` +`async`表明该函数内部有异步操作,调用该函数时,会立即返回一个Promise对象。 +另外还有个定时的案例,指定时间后执行: +```js +function f (ms){ + return new Promise(res => { + setTimeout(res, ms); + }); +} +async function g(val, ms){ + await f(ms); + console.log(val); +} +g('leo', 50); +``` +`async`函数还有很多使用形式: +```js +// 函数声明 +async function f (){...} + +// 函数表达式 +let f = async function (){...} + +// 对象的方法 +let a = { + async f(){...} +} +a.f().then(...) + +// Class的方法 +class c { + constructor(){...} + async f(){...} +} + +// 箭头函数 +let f = async () => {...} +``` + +#### 3.1.3 返回Promise对象 +`async`内部`return`返回的值会作为`then`方法的参数,另外只有`async`函数内部的异步操作执行完,才会执行`then`方法指定的回调函数。 +```js +async function f(){ + return 'leo'; +} +f().then(res => { console.log (res) }); // 'leo' +``` +`async`内部抛出的错误,会被`catch`接收。 +```js +async function f(){ + throw new Error('err'); +} +f().then ( + v => console.log(v), + e => console.log(e) +) +// Error: err +``` + +#### 3.1.4 await命令 +通常`await`后面是一个Promise对象,如果不是就返回对应的值。 +```js +async function f(){ + return await 10; +} +f().then(v => console.log(v)); // 10 +``` +我们常常将`async await`和`try..catch`一起使用,并且可以放多个`await`命令,也是防止异步操作失败因为中断后续异步操作的情况。 +```js +async function f(){ + try{ + await Promise.reject('err'); + }catch(err){ ... } + return await Promise.resolve('leo'); +} +f().then(v => console.log(v)); // 'leo' +``` + +#### 3.1.5 使用注意 +* (1)`await`命令放在`try...catch`代码块中,防止Promise返回`rejected`。 +* (2)若多个`await`后面的异步操作不存在继发关系,最好让他们同时执行。 +```js +// 效率低 +let a = await f(); +let b = await g(); + +// 效率高 +let [a, b] = await Promise.all([f(), g()]); +// 或者 +let a = f(); +let b = g(); +let a1 = await a(); +let b1 = await b(); +``` +* (3)`await`命令只能用在`async`函数之中,如果用在普通函数,就会报错。 +```js +// 错误 +async function f(){ + let a = [{}, {}, {}]; + a.forEach(v =>{ // 报错,forEach是普通函数 + await post(v); + }); +} + +// 正确 +async function f(){ + let a = [{}, {}, {}]; + for(let k of a){ + await post(k); + } +} +``` + +### 3.2 Promise.prototype.finally() +`finally()`是ES8中**Promise**添加的一个新标准,用于指定不管**Promise**对象最后状态(是`fulfilled`还是`rejected`)如何,都会执行此操作,并且`finally`方法必须写在最后面,即在`then`和`catch`方法后面。 +```js +// 写法如下: +promise + .then(res => {...}) + .catch(err => {...}) + .finally(() => {...}) +``` +`finally`方法常用在处理**Promise**请求后关闭服务器连接: +```js +server.listen(port) + .then(() => {..}) + .finally(server.stop); +``` +**本质上,finally方法是then方法的特例:** +```js +promise.finally(() => {...}); + +// 等同于 +promise.then( + result => { + // ... + return result + }, + error => { + // ... + throw error + } +) +``` + +### 3.3 Object.values(),Object.entries() +ES7中新增加的 `Object.values()`和`Object.entries()`与之前的`Object.keys()`类似,返回数组类型。 +回顾下`Object.keys()`: +```js +var a = { f1: 'hi', f2: 'leo'}; +Object.keys(a); // ['f1', 'f2'] +``` +#### 3.3.1 Object.values() +返回一个数组,成员是参数对象自身的(不含继承的)所有**可遍历属性**的键值。 +```js +let a = { f1: 'hi', f2: 'leo'}; +Object.values(a); // ['hi', 'leo'] +``` +如果参数不是对象,则返回空数组: +```js +Object.values(10); // [] +Object.values(true); // [] +``` + +#### 3.3.2 Object.entries() +返回一个数组,成员是参数对象自身的(不含继承的)所有**可遍历属性**的键值对数组。 +```js +let a = { f1: 'hi', f2: 'leo'}; +Object.entries(a); // [['f1','hi'], ['f2', 'leo']] +``` +* **用途1**: +遍历对象属性。 +```js +let a = { f1: 'hi', f2: 'leo'}; +for (let [k, v] of Object.entries(a)){ + console.log( + `${JSON.stringfy(k)}:${JSON.stringfy(v)}` + ) +} +// 'f1':'hi' +// 'f2':'leo' +``` +* **用途2**: +将对象转为真正的Map结构。 +```js +let a = { f1: 'hi', f2: 'leo'}; +let map = new Map(Object.entries(a)); +``` +手动实现`Object.entries()`方法: +```js +// Generator函数实现: +function* entries(obj){ + for (let k of Object.keys(obj)){ + yield [k ,obj[k]]; + } +} + +// 非Generator函数实现: +function entries (obj){ + let arr = []; + for(let k of Object.keys(obj)){ + arr.push([k, obj[k]]); + } + return arr; +} +``` + +### 3.4 Object.getOwnPropertyDescriptors() +之前有`Object.getOwnPropertyDescriptor`方法会返回某个对象属性的描述对象,新增的`Object.getOwnPropertyDescriptors()`方法,返回指定对象所有自身属性(非继承属性)的描述对象,所有原对象的属性名都是该对象的属性名,对应的属性值就是该属性的描述对象 +```js +let a = { + a1:1, + get f1(){ return 100} +} +Object.getOwnPropetyDescriptors(a); +/* +{ + a:{ configurable:true, enumerable:true, value:1, writeable:true} + f1:{ configurable:true, enumerable:true, get:f, set:undefined} +} +*/ +``` +实现原理: +```js +function getOwnPropertyDescriptors(obj) { + const result = {}; + for (let key of Reflect.ownKeys(obj)) { + result[key] = Object.getOwnPropertyDescriptor(obj, key); + } + return result; +} +``` +引入这个方法,主要是为了解决`Object.assign()`无法正确拷贝`get`属性和`set`属性的问题。 +```js +let a = { + set f(v){ + console.log(v) + } +} +let b = {}; +Object.assign(b, a); +Object.a(b, 'f'); +/* +f = { + configurable: true, + enumable: true, + value: undefined, + writeable: true +} +*/ +``` +`value`为`undefined`是因为`Object.assign`方法不会拷贝其中的`get`和`set`方法,使用`getOwnPropertyDescriptors`配合`Object.defineProperties`方法来实现正确的拷贝: +```js +let a = { + set f(v){ + console.log(v) + } +} +let b = {}; +Object.defineProperties(b, Object.getOwnPropertyDescriptors(a)); +Object.getOwnPropertyDescriptor(b, 'f') +/* + configurable: true, + enumable: true, + get: undefined, + set: function(){...} +*/ +``` +`Object.getOwnPropertyDescriptors`方法的配合`Object.create`方法,将对象属性克隆到一个新对象,实现浅拷贝。 +```js +const clone = Object.create(Object.getPrototypeOf(obj), + Object.getOwnPropertyDescriptors(obj)); + +// 或者 +const shallowClone = (obj) => Object.create( + Object.getPrototypeOf(obj), + Object.getOwnPropertyDescriptors(obj) +); +``` + +### 3.5 字符串填充 padStart和padEnd +用来为字符串填充特定字符串,并且都有两个参数:**字符串目标长度**和**填充字段**,第二个参数可选,默认空格。 +```js +'es8'.padStart(2); // 'es8' +'es8'.padStart(5); // ' es8' +'es8'.padStart(6, 'woof'); // 'wooes8' +'es8'.padStart(14, 'wow'); // 'wowwowwowwoes8' +'es8'.padStart(7, '0'); // '0000es8' + +'es8'.padEnd(2); // 'es8' +'es8'.padEnd(5); // 'es8 ' +'es8'.padEnd(6, 'woof'); // 'es8woo' +'es8'.padEnd(14, 'wow'); // 'es8wowwowwowwo' +'es8'.padEnd(7, '6'); // 'es86666' +``` +从上面结果来看,填充函数只有在字符长度小于目标长度时才有效,若字符长度已经等于或小于目标长度时,填充字符不会起作用,而且目标长度如果小于字符串本身长度时,字符串也不会做截断处理,只会原样输出。 + +### 3.6 函数参数列表与调用中的尾部逗号 +该特性允许我们在定义或者调用函数时添加尾部逗号而不报错: +```js +function es8(var1, var2, var3,) { + // ... +} +es8(10, 20, 30,); +``` + +### 3.7 共享内存与原子操作 +当内存被共享时,多个线程可以并发读、写内存中相同的数据。原子操作可以确保那些被读、写的值都是可预期的,即新的事务是在旧的事务结束之后启动的,旧的事务在结束之前并不会被中断。这部分主要介绍了 ES8 中新的构造函数 `SharedArrayBuffer` 以及拥有许多静态方法的命名空间对象 `Atomic` 。 +`Atomic` 对象类似于 `Math` 对象,拥有许多静态方法,所以我们不能把它当做构造函数。 `Atomic` 对象有如下常用的静态方法: + +* add /sub :为某个指定的value值在某个特定的位置增加或者减去某个值 +* and / or /xor :进行位操作 +* load :获取特定位置的值 \ No newline at end of file diff --git "a/article/66-ES9\346\261\207\346\200\273.md" "b/article/66-ES9\346\261\207\346\200\273.md" new file mode 100644 index 00000000..991eb667 --- /dev/null +++ "b/article/66-ES9\346\261\207\346\200\273.md" @@ -0,0 +1,324 @@ +## 4. ES9 +### 4.1 对象的拓展运算符 +#### 4.1.1 介绍 +对象的拓展运算符,即对象的Rest/Spread属性,可将对象解构赋值用于从一个对象取值,搜键值对分配到指定对象上,与数组的拓展运算符类似: +```js +let {x, y, ...z} = {x:1, y:2, a:3, b:4}; +x; // 1 +y; // 2 +z; // {a:3, b:4} +``` +对象的解构赋值要求等号右边必须是个对象,所以如果等号右边是`undefined`或`null`就会报错无法转成对象。 +```js +let {a, ...b} = null; // 运行时报错 +let {a, ...b} = undefined; // 运行时报错 +``` +解构赋值必须是最后一个参数,否则报错。 +```js +let {...a, b, c} = obj; // 语法错误 +let {a, ...b, c} = obj; // 语法错误 +``` +**注意**: +* 1.解构赋值是浅拷贝。 +```js +let a = {a1: {a2: 1}}; +let {...b} = a; +a.a1.a2 = 'leo'; +b.a1.a2 = 'leo'; +``` +* 2.拓展运算符的解构赋值,不能复制继承自原型对象的属性。 +```js +let o1 = { a: 1 }; +let o2 = { b: 2 }; +o2.__proto__ = o1; +let { ...o3 } = o2; +o3; // { b: 2 } +o3.a; // undefined +``` + +#### 4.1.2 使用场景 +* 1.取出参数对象所有可遍历属性,拷贝到当前对象中。 +```js +let a = { a1:1, a2:2 }; +let b = { ...a }; +b; // { a1:1, a2:2 } + +// 类似Object.assign方法 +``` +* 2.合并两个对象。 +```js +let a = { a1:1, a2:2 }; +let b = { b1:11, b2:22 }; +let ab = { ...a, ...b }; // {a1: 1, a2: 2, b1: 11, b2: 22} +// 等同于 +let ab = Object.assign({}, a, b); +``` +* 3.将自定义属性放在拓展运算符后面,覆盖对象原有的同名属性。 +```js +let a = { a1:1, a2:2, a3:3 }; +let r = { ...a, a3:666 }; +// r {a1: 1, a2: 2, a3: 666} + +// 等同于 +let r = { ...a, ...{ a3:666 }}; +// r {a1: 1, a2: 2, a3: 666} + +// 等同于 +let r = Object.assign({}, a, { a3:666 }); +// r {a1: 1, a2: 2, a3: 666} +``` +* 4.将自定义属性放在拓展运算符前面,就会成为设置新对象的默认值。 +```js +let a = { a1:1, a2:2 }; +let r = { a3:666, ...a }; +// r {a3: 666, a1: 1, a2: 2} + +// 等同于 +let r = Object.assign({}, {a3:666}, a); +// r {a3: 666, a1: 1, a2: 2} + +// 等同于 +let r = Object.assign({a3:666}, a); +// r {a3: 666, a1: 1, a2: 2} +``` +* 5.拓展运算符后面可以使用表达式。 +```js +let a = { + ...(x>1? {a:!:{}), + b:2 +} +``` +* 6.拓展运算符后面如果是个空对象,则没有任何效果。 +```js +{...{}, a:1}; // {a:1} +``` +* 7.若参数是`null`或`undefined`则忽略且不报错。 +```js +let a = { ...null, ...undefined }; // 不报错 +``` +* 8.若有取值函数`get`则会执行。 +```js +// 不会打印 因为f属性只是定义 而不没执行 +let a = { + ...a1, + get f(){console.log(1)} +} + +// 会打印 因为f执行了 +let a = { + ...a1, + ...{ + get f(){console.log(1)} + } +} +``` + +### 4.2 正则表达式 s 修饰符 +在正则表达式中,点(`.`)可以表示任意单个字符,除了两个:用`u`修饰符解决**四个字节的UTF-16字符**,另一个是行终止符。 +**终止符**即表示一行的结束,如下四个字符属于“行终止符”: +* U+000A 换行符(\n) +* U+000D 回车符(\r) +* U+2028 行分隔符(line separator) +* U+2029 段分隔符(paragraph separator) +```js +/foo.bar/.test('foo\nbar') +// false +``` +上面代码中,因为`.`不匹配`\n`,所以正则表达式返回`false`。 +换个醒,可以匹配任意单个字符: +```js +/foo[^]bar/.test('foo\nbar') +// true +``` +ES9引入`s`修饰符,使得`.`可以匹配任意单个字符: +```js +/foo.bar/s.test('foo\nbar') // true +``` +这被称为`dotAll`模式,即点(`dot`)代表一切字符。所以,正则表达式还引入了一个`dotAll`属性,返回一个布尔值,表示该正则表达式是否处在`dotAll`模式。 +```js +const re = /foo.bar/s; +// 另一种写法 +// const re = new RegExp('foo.bar', 's'); + +re.test('foo\nbar') // true +re.dotAll // true +re.flags // 's' +``` +`/s`修饰符和多行修饰符`/m`不冲突,两者一起使用的情况下,`.`匹配所有字符,而`^`和`$`匹配每一行的行首和行尾。 + +### 4.3 异步遍历器 +在前面ES6章节中,介绍了Iterator接口,而ES6引入了“异步遍历器”,是为异步操作提供原生的遍历器接口,即`value`和`done`这两个属性都是异步产生的。 + +#### 4.3.1 异步遍历的接口 +通过调用遍历器的`next`方法,返回一个Promise对象。 +```js +a.next().then( + ({value, done}) => { + //... + } +) +``` +上述`a`为异步遍历器,调用`next`后返回一个Promise对象,再调用`then`方法就可以指定Promise对象状态变为`resolve`后执行的回调函数,参数为`value`和`done`两个属性的对象,与同步遍历器一致。 +与同步遍历器一样,异步遍历器接口也是部署在`Symbol.asyncIterator`属性上,只要有这个属性,就都可以异步遍历。 +```js +let a = createAsyncIterable(['a', 'b']); +//createAsyncIterable方法用于构建一个iterator接口 +let b = a[Symbol.asyncInterator](); + +b.next().then( result1 => { + console.log(result1); // {value: 'a', done:false} + return b.next(); +}).then( result2 => { + console.log(result2); // {value: 'b', done:false} + return b.next(); +}).then( result3 => { + console.log(result3); // {value: undefined, done:true} +}) +``` +另外`next`方法返回的是一个Promise对象,所以可以放在`await`命令后。 +```js +async function f(){ + let a = createAsyncIterable(['a', 'b']); + let b = a[Symbol.asyncInterator](); + console.log(await b.next());// {value: 'a', done:false} + console.log(await b.next());// {value: 'b', done:false} + console.log(await b.next());// {value: undefined, done:true} +} +``` +还有一种情况,使用`Promise.all`方法,将所有的`next`按顺序连续调用: +```js +let a = createAsyncIterable(['a', 'b']); +let b = a[Symbol.asyncInterator](); +let {{value:v1}, {value:v2}} = await Promise.all([ + b.next(), b.next() +]) +``` +也可以一次调用所有`next`方法,再用`await`最后一步操作。 +```js +async function f(){ + let write = openFile('aaa.txt'); + write.next('hi'); + write.next('leo'); + await write.return(); +} +f(); +``` +#### 4.3.2 for await...of +`for...of`用于遍历同步的Iterator接口,而ES8引入`for await...of`遍历异步的Iterator接口。 +```js +async function f(){ + for await(let a of createAsyncIterable(['a', 'b'])) { + console.log(x); + } +} +// a +// b +``` +上面代码,`createAsyncIterable()`返回一个拥有异步遍历器接口的对象,`for...of`自动调用这个对象的`next`方法,得到一个Promise对象,`await`用来处理这个Promise,一但`resolve`就把得到的值`x`传到`for...of`里面。 +**用途** +直接把部署了asyncIteable操作的异步接口放入这个循环。 +```js +let a = ''; +async function f(){ + for await (let b of req) { + a += b; + } + let c = JSON.parse(a); + console.log('leo', c); +} +``` +当`next`返回的Promise对象被`reject`,`for await...of`就会保错,用`try...catch`捕获。 +```js +async function f(){ + try{ + for await (let a of iterableObj()){ + console.log(a); + } + }catch(e){ + console.error(e); + } +} +``` +注意,`for await...of`循环也可以用于同步遍历器。 +```js +(async function () { + for await (let a of ['a', 'b']) { + console.log(a); + } +})(); +// a +// b +``` +#### 4.3.3 异步Generator函数 +就像 Generator 函数返回一个同步遍历器对象一样,异步 Generator 函数的作用,是返回一个异步遍历器对象。 +在语法上,异步 Generator 函数就是`async`函数与 Generator 函数的结合。 +```js +async function* f() { + yield 'hi'; +} +const a = f(); +a.next().then(x => console.log(x)); +// { value: 'hello', done: false } +``` +设计异步遍历器的目的之一,就是为了让Generator函数能用同一套接口处理同步和异步操作。 +```js +// 同步Generator函数 +function * f(iterable, fun){ + let a = iterabl[Symbol.iterator](); + while(true){ + let {val, done} = a.next(); + if(done) break; + yield fun(val); + } +} + +// 异步Generator函数 +async function * f(iterable, fun){ + let a = iterabl[Symbol.iterator](); + while(true){ + let {val, done} = await a.next(); + if(done) break; + yield fun(val); + } +} +``` +同步和异步Generator函数相同点:在`yield`时用`next`方法停下,将后面表达式的值作为`next()`返回对象的`value`。 +在异步Generator函数中,同时使用`await`和`yield`,简单样理解,`await`命令用于将外部操作产生的值输入函数内部,`yield`命令用于将函数内部的值输出。 +```js +(async function () { + for await (const line of readLines(filePath)) { + console.log(line); + } +})() +``` +异步 Generator 函数可以与`for await...of`循环结合起来使用。 +```js +async function* f(asyncIterable) { + for await (const line of asyncIterable) { + yield '> ' + line; + } +} +``` + +#### 4.3.4 yield* 语句 +`yield*`语句跟一个异步遍历器。 +```js +async function * f(){ + yield 'a'; + yield 'b'; + return 'leo'; +} +async function * g(){ + const a = yield* f(); // a => 'leo' +} +``` +与同步 Generator 函数一样,`for await...of`循环会展开`yield*`。 +```js +(async function () { + for await (const x of gen2()) { + console.log(x); + } +})(); +// a +// b +``` From b50e62fe8aeca36d622857151b249d498489b570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Tue, 13 Nov 2018 23:38:29 +0800 Subject: [PATCH 126/835] =?UTF-8?q?2018.11.13=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E9=A6=96=E9=A1=B5=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 317af925..b0315f98 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,10 @@ * [★ 34-我眼中的async&await](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/34-%E6%88%91%E7%9C%BC%E4%B8%AD%E7%9A%84async%26await.md) * [35-ES6中的模块导入导出整理](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/35-ES6%E4%B8%AD%E7%9A%84%E6%A8%A1%E5%9D%97%E5%AF%BC%E5%85%A5%E5%AF%BC%E5%87%BA%E6%95%B4%E7%90%86.md) * [41-ES2018(ES9)的新特性](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/41-ES2018%EF%BC%88ES9%EF%BC%89%E7%9A%84%E6%96%B0%E7%89%B9%E6%80%A7.md) +* [63-ES6汇总.md](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/63-ES6%E6%B1%87%E6%80%BB.md) +* [64-ES7汇总.md](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/64-ES7%E6%B1%87%E6%80%BB.md) +* [65-ES8汇总.md](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/65-ES8%E6%B1%87%E6%80%BB.md) +* [66-ES9汇总.md](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/66-ES9%E6%B1%87%E6%80%BB.md) ### 4、Webpack * [25-Webpack入门教程整理(整理中)](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/25-Webpack%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%E6%95%B4%E7%90%86%EF%BC%88%E6%95%B4%E7%90%86%E4%B8%AD%EF%BC%89.md) From c9181a41f86c5a3a9c6156ac41b3d907ac411605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sun, 18 Nov 2018 18:24:55 +0800 Subject: [PATCH 127/835] 2018.11.18 --- ...50\347\232\204\345\234\272\346\231\257.md" | 210 ++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 "article/67-JS\347\256\255\345\244\264\345\207\275\346\225\260\347\232\204\351\200\202\347\224\250\345\222\214\344\270\215\351\200\202\347\224\250\347\232\204\345\234\272\346\231\257.md" diff --git "a/article/67-JS\347\256\255\345\244\264\345\207\275\346\225\260\347\232\204\351\200\202\347\224\250\345\222\214\344\270\215\351\200\202\347\224\250\347\232\204\345\234\272\346\231\257.md" "b/article/67-JS\347\256\255\345\244\264\345\207\275\346\225\260\347\232\204\351\200\202\347\224\250\345\222\214\344\270\215\351\200\202\347\224\250\347\232\204\345\234\272\346\231\257.md" new file mode 100644 index 00000000..700beac8 --- /dev/null +++ "b/article/67-JS\347\256\255\345\244\264\345\207\275\346\225\260\347\232\204\351\200\202\347\224\250\345\222\214\344\270\215\351\200\202\347\224\250\347\232\204\345\234\272\346\231\257.md" @@ -0,0 +1,210 @@ +## JavaScript 箭头函数究竟是什么? +JavaScript 箭头函数大致相当于 `python` 中的 `lambda` 函数 或 `Ruby` 中的` blocks`。 + +这些是匿名函数,它们有自己的特殊语法,接受一定数量的参数,并在其封闭的作用域的上下文(即定义它们的函数或其他代码)中操作。 + +让我们依次分解这些部分。 + +### 箭头函数语法 +箭头函数具有单一的总体结构,然后在特殊情况下可以通过多种方式简化它们。 核心结构如下所示: +```js +(argument1, argument2, ... argumentN) => { + // function body +} +``` +括号内的是参数列表,后跟“胖箭头”(`=>`),最后是函数体。 + +这与传统函数非常相似,我们只是省略 `function` 关键字并在参数后添加一个胖箭头(`=>`)。 + +然而,有许多方法可以简化箭头函数。 + +首先,如果函数体是单个表达式,则可以不使用花括号并将其置于内联中(省略大括号直接将表达式写在一行中)。 表达式的结果将由函数返回。 例如: +```js +const add = (a, b) => a + b; +``` +其次,如果只有一个参数,你甚至可以省略参数的括号。例如: +```js +const getFirst = array => array[0]; +``` +正如您所看到的,这是一些非常简洁的语法,我们将重点介绍后面的好处。 + +### 高级语法 +有一些高级语法可以了解一下。 + +首先,如果您尝试使用内联单行表达式语法,但您返回的值是对象字面量。您可能会认为这看起来应该是这样的: +```js +(name, description) => {name: name, description: description}; +``` +问题是这种语法比较含糊不清,容易引起歧义 : 看起来好像你正试图创建一个传统的函数体。 如果你碰巧想要一个对象的单个表达式,请用括号包裹该对象: +```js +(name, description) => ({name: name, description: description}); +``` + +### 封闭的上下文作用域 +与其他形式的函数不同,箭头函数没有自己的 [执行期上下文](https://blog.bitsrc.io/understanding-execution-context-and-execution-stack-in-javascript-1c9ea8642dd0)。 + +实际上,这意味着 this 和 arguments 都是从它们的父函数继承而来的。 + +例如,使用和不使用箭头函数比较以下代码: +```js +const test = { + name: 'test object', + createAnonFunction: function() { + return function() { + console.log(this.name); + console.log(arguments); + }; + }, + + createArrowFunction: function() { + return () => { + console.log(this.name); + console.log(arguments); + }; + } +}; +``` +我们有一个简单的 `test` 对象,有两个方法 – 每个方法都返回一个匿名函数。 + +不同之处在于第一个方法使用传统函数表达式,而后者中使用箭头函数。 + +如果我们使用相同参数,在控制台中运行它们,我们会得到完全不一样的结果。 +```js +const anon = test.createAnonFunction('hello', 'world'); +const arrow = test.createArrowFunction('hello', 'world'); +anon(); // undefined {} +arrow(); //test object { '0': 'hello', '1': 'world' } +``` +第一个匿名函数有自己的函数上下文,因此当您调用它时,`test` 对象的 `this.name` 没有可用的引用,也没有创建它时调用的参数。 + +另一个,箭头函数具有与创建它的函数完全相同的函数上下文,使其可以访问 `argumetns` 和 `test` 对象。 + +### 使用箭头函数改进您的代码 +传统 `lambda` 函数的主要用例之一,就是用于遍历列表中的项,现在用 `JavaScript` 箭头函数实现。 + +比如你有一个有值的数组,你想去 `map` 遍历每一项,这时使用箭头函数非常理想: +```js +const words = ['hello', 'WORLD', 'Whatever']; +const downcasedWords = words.map(word => word.toLowerCase()); +``` +一个非常常见的例子是提取对象中的某个特定值: +```js +const names = objects.map(object => object.name); +``` +类似地,当用现代迭代样式取代传统的 for 循环,一般我们使用 forEach 循环,箭头函数能够保持 `this` 来自于父级,让他们非常直观 + +类似的,当用 forEach 来替换传统 for循环的时候,实际上箭头函数会直观的保持 `this`来自于父一级 + +```js +this.examples.forEach(example => { + this.runExample(example); +}); +``` + +### Promises 和 Promise 链 +箭头函数的另一个可以使代码更清晰,更直观的地方是管理异步代码。 + +[Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises) 使得管理异步代码变得容易很多(即使你很欢快地使用 `async` / `await`,你仍然应该理解 [`async` / `await` 是建立在 Promises 之上的](https://medium.com/@bluepnume/learn-about-promises-before-you-start-using-async-await-eb148164a9c8) !) + +但是,虽然使用 `promises`仍然需要定义在异步代码或调用完成后运行的函数。 + +这是箭头函数的理想位置,特别是如果您生成的函数是有状态的,同时想引用对象中的某些内容。 例如: +```js +this.doSomethingAsync().then((result) => { + this.storeResult(result); +}); +``` + +### 对象转换 +箭头函数的另一个常见且极其强大的用途是封装对象转换。 + +例如,在 Vue.js 中,有一种通用模式,用于使用 `mapState` 将 Vuex 存储的各个部分直接包含到 Vue 组件中。 + +这涉及定义一组 “`mappers`” ,这些 “`mappers`” 将从原始的完整的 `state` 对象转换为提取所涉及组件所需的内容。 + +这些简单的转换使用箭头函数再合适不过了。比如: +```js +export default { + computed: { + ...mapState({ + results: state => state.results, + users: state => state.users, + }); + } +} +``` + +### 你不应该使用箭头函数的情景 +在许多情况下,使用箭头函数不是一个好主意。 他们不仅不会帮助你,而且会给你带来一些不必要的麻烦。 + +第一个是对象的方法。 这是一个函数上下文的例子,这对于我们理解很有帮助。 + +有一段时间使用 Class(类)属性语法和箭头函数的组合,作为创建“自动绑定方法”的方式,例如, 事件处理程序可以使用,但仍然绑定到类的方法。 + +这看起来像是这样的: + +```js +class Counter { + counter = 0; + + handleClick = () => { + this.counter++; + } +} +``` +这样,即使 `handleClick` 由事件处理程序调用,而不是在 `Counter` 实例的上下文中调用,它仍然可以访问实例的数据。 + +这种方法的缺点很多,在本文中很好地记录。 + +虽然使用这种方法确实为您提供了具有绑定函数的快捷方式,但该函数以多种不直观的方式运行,如果您尝试将此对象作为原型进行子类化/使用,则会不利于测试,同时也会产生很多问题。 + +相反,使用常规函数,如果需要,将其绑定到构造函数中的实例: + +```js +class Counter { + counter = 0; + + handleClick() { + this.counter++; + } + + constructor() { + this.handleClick = this.handleClick.bind(this); + } +} +``` + +### 深层的调用链 +箭头函数可能让你遇到麻烦的另一个地方是,它们被用于许多不同的组合,特别是在函数深层调用链中。 + +核心原因与匿名函数相同 – 它们给出了非常糟糕的堆栈跟踪。 + +如果你的函数只是向下一级,比如在迭代器里面,那也不是太糟糕,但是如果你把所有的函数定义为箭头函数,并在它们之间来回调用,你就会陷入困境 遇到一个错误的时候,只是收到错误消息,如: + +```js +{anonymous}() +{anonymous}() +{anonymous}() +{anonymous}() +{anonymous}() +``` + +### 有动态上下文的函数 +箭头函数可能让您遇到麻烦的最后一种情况就是吗, this 是动态绑定的时候。 + +如果您在这些位置使用箭头函数,那么动态绑定将不起作用,并且你(或稍后使用你的代码的其他人)可能会对事情未按预期执行的原因感到困惑。 + +一些典型的例子: + +* 事件处理程序是通过将 this 设置为事件的 currentTarget 属性来调用。 +* 如果您仍在使用 jQuery ,则大多数 jQuery 方法将 this 设置为已选择的 dom 元素。 +* 如果您正在使用 Vue.js ,则方法和计算函数通常将 this 设置为 Vue 组件。 +当然你可以故意使用箭头函数来覆盖这种行为,但特别是在 jQuery 和 Vue 的情况下,这通常会干扰正常运行,让你感到困惑的是为什么看起来与附近其他代码相同的代码不起作用。 + +## 总结 +箭头函数是 JavaScript 语言的一个非常有必要的补充,并且在许多情况下使代码更符合人们的阅读习惯。 + +然而,像所有其他特性一样,它们有优点和缺点。 我们应该将它们作为我们工具箱中的另一个工具,而不是作为所有函数的全面替代品。 + +英文原文:https://zendev.com/2018/10/01/javascript-arrow-functions-how-why-when.html +中文地址:https://www.css88.com/archives/10033 \ No newline at end of file From ed463ec79f67209b5361d8605ac9d5d757a44069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sun, 18 Nov 2018 18:27:15 +0800 Subject: [PATCH 128/835] 2018.11.18 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b0315f98..453f2c37 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ * [64-ES7汇总.md](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/64-ES7%E6%B1%87%E6%80%BB.md) * [65-ES8汇总.md](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/65-ES8%E6%B1%87%E6%80%BB.md) * [66-ES9汇总.md](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/66-ES9%E6%B1%87%E6%80%BB.md) +* [67-JS箭头函数的适用和不适用的场景.md](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/67-JS%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0%E7%9A%84%E9%80%82%E7%94%A8%E5%92%8C%E4%B8%8D%E9%80%82%E7%94%A8%E7%9A%84%E5%9C%BA%E6%99%AF.md) ### 4、Webpack * [25-Webpack入门教程整理(整理中)](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/25-Webpack%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%E6%95%B4%E7%90%86%EF%BC%88%E6%95%B4%E7%90%86%E4%B8%AD%EF%BC%89.md) From 597c87443ce79156b0df98d4204f4d2a39da869b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sun, 25 Nov 2018 21:33:09 +0800 Subject: [PATCH 129/835] 2018.11.25 --- ...03\347\247\215\346\226\271\345\274\217.md" | 212 ++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 "article/68-\345\210\233\345\273\272\345\257\271\350\261\241\347\232\204\344\270\203\347\247\215\346\226\271\345\274\217.md" diff --git "a/article/68-\345\210\233\345\273\272\345\257\271\350\261\241\347\232\204\344\270\203\347\247\215\346\226\271\345\274\217.md" "b/article/68-\345\210\233\345\273\272\345\257\271\350\261\241\347\232\204\344\270\203\347\247\215\346\226\271\345\274\217.md" new file mode 100644 index 00000000..548e09f3 --- /dev/null +++ "b/article/68-\345\210\233\345\273\272\345\257\271\350\261\241\347\232\204\344\270\203\347\247\215\346\226\271\345\274\217.md" @@ -0,0 +1,212 @@ +JavaScript创建对象的方式有很多,通过Object构造函数或对象字面量的方式也可以创建单个对象,显然这两种方式会产生大量的重复代码,并不适合量产。接下来介绍七种非常经典的创建对象的方式,他们也各有优缺点。 + +## 1.工厂模式 +```js +function f(a, b) { + let a1 = new Object(); + a1.a = a; + a1.b = b; + a1.fun = function(){ + console.log(this.a); + } + return a1; +} + +let f1 = f('Leo','good'); +let f2 = f('Robin','nice'); +``` +可以无数次调用这个工厂函数,每次都会返回一个包含两个属性和一个方法的对象。 + +工厂模式虽然解决了**创建多个相似对象**的问题,但是没有解决对象识别问题,即不能知道一个对象的类型。 + +## 2.构造函数模式 +```js +function f (a, b){ + this.a = a; + this.b = b; + this.fun = function (){ + console.log(this.a) + } +} + +let f1 = new f('Leo','good'); +let f2 = new f('Robin','nice'); +``` +没有显示的创建对象,使用`new`来调用这个构造函数,使用`new`后会自动执行如下操作: +* 创建一个新对象 +* 这个新对象会被执行[[prototype]]链接 +* 这个新对象会绑定到函数调用的`this` +* 返回这个对象 + +使用这个方式创建对象可以检测对象类型 +```js +f1 instanceof Object; // true +f1 instanceof f; // true +``` +但是使用构造函数创建对象,每个方法都要在每个实例上**重新创建**一次。 + +## 3.原型模式 +```js +function f (){ + +} +f.prototype.a = 'Leo'; +f.prototype.b = 'good'; +f.prototype.fun = function (){ + console.log(this.a); +} +let f1 = new f(); +``` +将信息直接添加到原型对象上。使用原型的好处是可以让所有的实例对象共享它所包含的属性和方法,不必在构造函数中定义对象实例信息。 + +**更简单的写法** : +```js +function f (){ + +} +f.prototype = { + a : 'Leo'; + b : 'good'; + fun : function (){ + console.log(this.a); + } +} +let f1 = new f(); +``` +将`f.prototype`设置为等于一个以对象字面量形式创建的对象,但是会导致`.constructor`不在指向`f`了。 + +使用这种方式,完全重写了默认的`f.prototype`对象,因此 `.constructor`也不会存在这里。 +```js +f.prototype.constructor === f // false +``` +如果需要这个属性的话,可以手动添加: +```js +function f (){ + +} +f.prototype = { + constructor : f, + a : 'Leo'; + b : 'good'; + fun : function (){ + console.log(this.a); + } +} +let f1 = new f(); +``` +不过这种方式还是不够好,应为`constructor`属性默认是**不可枚举**的,这样直接设置,它将是可枚举的。所以可以时候,`Object.defineProperty`方法: +```js +Object.defineProperty(f.prototype, 'constructor', { + enumerable: false, + value: f +}) +``` +**缺点** + +使用原型,所有的属性都将被共享,这是个很大的优点,同样会带来一些缺点。 + +原型中所有属性实例是被很多实例共享的,这种共享对于函数非常合适。对于那些包含基本值的属性也勉强可以,毕竟实例属性可以屏蔽原型属性。但是引用类型值,就会出现问题了。 +```js +function f() { +} +f.prototype = { + a: 'leo', + b: ['good', 'nice'] +} +var f1 = new f() +var f2 = new f() +f1.b.push('hi') +console.log(f1.b) //["good", "nice", "hi"] +console.log(f2.b) //["good", "nice", "hi"] +console.log(f1.b === f2.b) // true +``` +`b`存在与原型中,实例f1和f2指向同一个原型,f1修改了引用的数组,也会反应到实例f2中。 + +## 4.组合使用构造函数模式和原型模式 +这是使用最为广泛、认同度最高的一种创建自定义类型的方法。它可以解决上面那些模式的缺点。 + +使用此模式可以让每个实例都会有自己的一份实例属性副本,但同时又共享着对方法的引用。 + +这样的话,即使实例属性修改引用类型的值,也不会影响其他实例的属性值了。 +```js +function f(a) { + this.a = a + this.friends = ['good', 'nice'] +} +f.prototype.fun = function() { + console.log(this.a) +} +var f1 = new f() +var f2 = new f() +f1.friends.push('hi') +console.log(f1.friends) //["good", "nice", "hi"] +console.log(f2.friends) // ["good", "nice"] +console.log(f1.friends === f2.friends) //false +``` + +## 5.动态原型模式 +动态原型模式将所有信息都封装在了构造函数中,初始化的时候,通过检测某个应该存在的方法时候有效,来决定是否需要初始化原型。 +```js +function f(a, b) { + // 属性 + this.a = a + this.b = b + + // 方法 + if(typeof this.fun !== 'function') { + f.prototype.fun = function() { + console.log(this.a) + } + } + +} +var f1 = new f('good', 'nice') +f1.fun() +``` +只有在`fun`方法不存在的时候,才会将它添加到原型中。这段代码只会初次调用构造函数的时候才会执行。 + +此后原型已经完成初始化,不需要在做什么修改了。 + +这里对原型所做的修改,能够立即在所有实例中得到反映。 + +其次,if语句检查的可以是初始化之后应该存在的任何属性或方法,所以不必用一大堆的if语句检查每一个属性和方法,只要检查一个就行。 + +## 6.寄生构造函数模式 +这种模式的基本思想就是创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后再返回新建的对象 +```js +function f(a, b) { + var o = new Object() + o.a = a + o.b = b + o.fun = function() { + console.log(this.a) + } + return o +} +var f1 = new f('good', 'nice') +f1.fun() +``` +这个模式,除了使用`new`操作符并把使用的包装函数叫做构造函数之外,和工厂模式几乎一样。 + +构造函数如果不返回对象,默认也会返回一个新的对象,通过在构造函数的末尾添加一个`return`语句,可以重写调用构造函数时返回的值。 + +## 7.稳妥构造函数模式 +首先明白稳妥对象指的是没有公共属性,而且其方法也不引用`this`。 + +稳妥对象最适合在一些安全环境中(这些环境会禁止使用`this`和`new`),或防止数据被其他应用程序改动时使用。 + +稳妥构造函数模式和寄生模式类似,有两点不同:一是创建对象的实例方法不引用this,而是不使用new操作符调用构造函数。 +```js +function f(a, b) { + var o = new Object() + o.a = a + o.b = b + o.fun = function() { + console.log(a) + } + return o +} +var f1 = f('good', 'nice') +f1.fun() +``` +和寄生构造函数模式一样,这样创建出来的对象与构造函数之间没有什么关系,instanceof操作符对他们没有意义。 \ No newline at end of file From a8d212b95a4520112931c206c6182f6ee0994fad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sun, 25 Nov 2018 21:37:35 +0800 Subject: [PATCH 130/835] 2018.11.25 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 453f2c37..fc0a77d9 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ * [65-ES8汇总.md](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/65-ES8%E6%B1%87%E6%80%BB.md) * [66-ES9汇总.md](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/66-ES9%E6%B1%87%E6%80%BB.md) * [67-JS箭头函数的适用和不适用的场景.md](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/67-JS%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0%E7%9A%84%E9%80%82%E7%94%A8%E5%92%8C%E4%B8%8D%E9%80%82%E7%94%A8%E7%9A%84%E5%9C%BA%E6%99%AF.md) +* [68-创建对象的七种方式](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/68-%E5%88%9B%E5%BB%BA%E5%AF%B9%E8%B1%A1%E7%9A%84%E4%B8%83%E7%A7%8D%E6%96%B9%E5%BC%8F.md) ### 4、Webpack * [25-Webpack入门教程整理(整理中)](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/25-Webpack%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%E6%95%B4%E7%90%86%EF%BC%88%E6%95%B4%E7%90%86%E4%B8%AD%EF%BC%89.md) From 50a862f8a0c95e20797274cedd1332013316ae1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 26 Nov 2018 22:40:00 +0800 Subject: [PATCH 131/835] 2018.11.26 --- ...10\345\222\214\351\230\237\345\210\227.js" | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 "demo\347\211\207\346\256\265/4-\346\240\210\345\222\214\351\230\237\345\210\227.js" diff --git "a/demo\347\211\207\346\256\265/4-\346\240\210\345\222\214\351\230\237\345\210\227.js" "b/demo\347\211\207\346\256\265/4-\346\240\210\345\222\214\351\230\237\345\210\227.js" new file mode 100644 index 00000000..36e11627 --- /dev/null +++ "b/demo\347\211\207\346\256\265/4-\346\240\210\345\222\214\351\230\237\345\210\227.js" @@ -0,0 +1,60 @@ +// 实现栈和队列的方法 + +// 1. 栈 LIFO +class Stack { + constructor ( arr ){ + this.arr = arr; + } + // 1. 添加一个(或几个)新元素到栈顶。 + push( ele ){ + this.arr.push( ele ); + } + // 2. 移除栈顶的元素,同时返回被移除的元素 + pop ( ele ){ + return this.arr.pop(); + } + // 3. 返回栈顶的元素,不对栈做任何修改 + peek () { + return this.arr[0]; + } + // 4. 如果栈里没有任何元素就返回true,否则返回false + isEmpty () { + return this.arr.length > 0 ? false : true; + } + // 5. 移除栈里的所有元素。 + clear () { + this.arr = []; + } + // 6. 返回栈里的元素个数。 + size () { + return this.arr.size; + } +} + +// 2. 队列 FIFO +class Queue { + constructor ( arr ){ + this.arr = arr; + } + // 1. 向队列尾部添加一个(或多个)新的项。 + enqueue ( ele ) { + this.arr.unshift( ele ); + } + // 2. 移除队列的第一(即排在队列最前面的)项,并返回被移除的元素。 + dequeue () { + return this.arr.shift(); + } + // 3. 返回队列中第一个元素——最先被添加,也将是最先被移除的元素。 + // 队列不做任何变动(不移除元素,只返回元素信息——与Stack类的peek方法非常类似)。 + front () { + return this.arr[0]; + } + // 4. 如果队列中不包含任何元素,返回true,否则返回false。 + isEmpty () { + return this.arr.length > 0 ? false : true; + } + // 5. 返回队列包含的元素个数,与数组的length属性类似。 + size () { + return this.arr.length; + } +} \ No newline at end of file From a412737442dd33c26487d617338a889b127c566d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Tue, 27 Nov 2018 22:52:13 +0800 Subject: [PATCH 132/835] 2018.11.27 --- "article/69-\347\247\222\346\207\202this.md" | 317 +++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 "article/69-\347\247\222\346\207\202this.md" diff --git "a/article/69-\347\247\222\346\207\202this.md" "b/article/69-\347\247\222\346\207\202this.md" new file mode 100644 index 00000000..79002c6e --- /dev/null +++ "b/article/69-\347\247\222\346\207\202this.md" @@ -0,0 +1,317 @@ +> [打开原文](segmentfault.com/a/1190000017075730) + +日常开发中经常会遇到 `this` 指向的 bug,郁闷好久才猛然醒悟,痛定思痛,将 `this` 做个汇总,以便在日后的开发工作中少走弯路。 +注意:本文讲述只针对浏览器环境。 + +# 一:全局执行 +```js +console.log(this); +// Window +``` +可以看出在全局作用域中 `this` 指向当前的全局对象 `Window`。 + +# 二:函数中执行 +## 1. 非严格模式中 +```js +function func () { + console.log(this); +} +func(); +// Window +``` + +## 2. 严格模式中 +```js +"use strict"; +function func () { + console.log(this); +} +func(); +// undefined +``` + +# 三:作为对象的方法调用 +当一个函数被当作一个对象的方法调用的时候,`this` 指向当前的对象 `obj`: +```js +var obj = { + name: 'kk', + func: function () { + console.log(this.name); + } +} +obj.func(); +// kk +``` +如果把对象的方法赋值给一个变量,调用该方法时,`this` 指向` Window`: +```js +var obj = { + name: 'kk', + func: function () { + console.log(this); + } +} +var test = obj.func; +test(); +// Window +``` +# 四:作为一个构造函数使用 +在 JS 中,为了实现类,我们需要定义一些构造函数,在调用一个构造函数的时候加上 `new `这个关键字: +```js +function Person (name) { + this.name = name; + console.log(this); +} +var p1 = new Person('kk'); +// Person +``` +此时,`this` 指向这个构造函数调用的时候实例化出来的对象。 + +当然了,构造函数其实也是一个函数,若将构造函数当做普通函数来调用,`this` 指向 `Window`: +```js +function Person (name) { + this.name = name; + console.log(this); +} +var p2 = Person('MM'); +// Window +``` + +# 五:在定时器中使用 +```js +setInterval(function () { + console.log(this); +}, 2000) +// Window +setTimeout(function () { + console.log(this); +}, 0) +// Window +``` +如果没有特殊指向(指向更改请看下方:怎么改变 `this` 的指向),`setInterval` 和`setTimeout` 的回调函数中 `this` 的指向都是 `Window` 。这是因为 JS 的定时器方法是定义在` Window` 下的。 + +# 六:箭头函数 +在全局环境中调用: +```js +var func = () => { + console.log(this); +} +func(); +// Window +``` +作为对象的一个函数调用: +```js +var obj = { + name: 'hh', + func: function () { + console.log(this); + } +} +obj.func(); +// obj +var obj = { + name: 'hh', + func: () => { + console.log(this); + } +} +obj.func(); +// Window +``` +不难发现,普通函数作为对象的一个函数被调用,`this` 指向 `obj`,箭头函数作为对象的一个函数被调用,`this` 指向 `Window`。 + +特殊情况:结合定时器调用: +```js +var obj = { + name: 'hh', + func: function () { + setTimeout(function () { + console.log(this); + }, 0) + } +} +obj.func(); +// Window +var obj = { + name: 'hh', + func: function () { + setTimeout(() => { + console.log(this); + }, 0) + } +} +obj.func(); +// obj +``` +若在对象的函数中,普通函数作为定时器延时执行的函数调用,`this` 指向 `Window`;箭头函数作为定时器延时执行的函数调用, `this` 指向定义时所在的对象,也就是 `func `中的 `this`,即` obj`。 + +箭头函数中 `this `的值取决于该函数外部非箭头函数的`this `的值,且不能通过 `call()` 、` apply()` 和 `bind()` 方法来改变 `this` 的值。 +# 七:call、apply、bind +**1.call**: +```js +fun.call(thisArg[, arg1[, arg2[, ...]]]) +``` +它会立即执行函数,第一个参数是指定执行函数中 `this` 的上下文,后面的参数是执行函数需要传入的参数; + +**apply**: +```js +fun.apply(thisArg, [argsArray]) +``` +它也会立即执行函数,第一个参数是指定执行函数中 `this` 的上下文,第二个参数是一个数组,是传给执行函数的参数(与 `call` 的区别); + +**bind**: +```js +var foo = fun.bind(thisArg[, arg1[, arg2[, ...]]]); +``` +它不会执行函数,而是返回一个新的函数,这个新的函数被指定了 `this` 的上下文,后面的参数是执行函数需要传入的参数; + +我们来看个示例: +```js +function Person(name, age) { + this.name = name; + this.age = age; + console.log(this); +} +var obj = { + name: 'kk', + age: 6 +}; +Person.call(obj, 'mm', 10); +// obj,{name: "mm", age: 10} + +Person.apply(obj, ['mm', 10]); +// obj,{name: "mm", age: 10} + +var p1 = Person.bind(obj, 'mm', 10) +var p2 = new p1(); +// Person {name: "mm", age: 10} +``` +在这个示例中,`call`、`apply` 和 `bind` 的 `this` 都指向了` obj`,都能正常运行;`call`、`apply `会立即执行函数,`call` 和 `apply` 的区别就在于传递的参数,`call` 接收多个参数列表,`apply` 接收一个包含多个参数的数组;`bind` 不是立即执行函数,它返回一个函数,需要执行 `p2` 才能返回结果,`bind` 接收多个参数列表。 + +## 应用:怎么改变 this 的指向 +为什么讲这个模块呢,为了便于大家更加透彻的理解上面所讲述的 `this` 指向问题,以及更加彻底的理解 JS 函数中重要的三种方法:`call`、`apply`、`bind` 的使用;并且在实际的项目开发中,我们经常会遇到需要改变 this 指向的情况。 + +我们来看下都有哪些方法: + +## 1. 使用 es6 的箭头函数 +```js +var name = "hh"; +var obj = { + name : "kk", + func1: function () { + console.log(this.name) + }, + func2: function () { + setTimeout(function () { + this.func1() + }, 1000); + } +}; + +obj.func2(); +// Uncaught TypeError: this.func1 is not a function +``` +这时会报错,因为 `setTimeout` 里函数的 `thi`s 指向 `Window`,而 `Window` 对象上是没有 `func1` 这个函数的。下面我们来修改成箭头函数: +```js +var name = "hh"; +var obj = { + name : "kk", + func1: function () { + console.log(this.name) + }, + func2: function () { + setTimeout(() => { + this.func1() + }, 1000); + } +}; + +obj.func2(); +// kk +``` +这时候,没有报错,因为箭头函数的` this` 的值取决于该函数外部非箭头函数的 `this` 的值,也就是 `func2` 的 `this `的值, 即` obj`。 + +## 2. 在函数内部使用 _this = this +```js +var name = "hh"; +var obj = { + name : "kk", + func1: function () { + console.log(this.name) + }, + func2: function () { + let _this = this; + setTimeout(function () { + _this.func1() + }, 1000); + } +}; + +obj.func2(); +// kk +``` +此时,`func2` 也能正常运行。在` func`2 中,首先设置 `var _this = this`,这里的 `this` 是指向 `func2` 的对象 `obj`,为了防止在 `func2` 中的 `setTimeout` 被 `window` 调用而导致的在 `setTimeout` 中的 `this` 为 window。我们将 `this` (指向变量 `obj`) 赋值给一个变量 `_this`,这样,在 `func2` 中我们使用 `_this` 就是指向对象 `obj` 了。 + +## 3. 使用 call、apply、bind + +**call**: +```js +var name = "hh"; +var obj = { + name : "kk", + func1: function () {s + console.log(this.name) + }, + func2: function () { + setTimeout(function () { + this.func1() + }.call(obj), 1000); + } +}; + +obj.func2(); +// kk +``` + +**apply**: +```js +var name = "hh"; +var obj = { + name : "kk", + func1: function () { + console.log(this.name) + }, + func2: function () { + setTimeout(function () { + this.func1() + }.apply(obj), 1000); + } +}; + +obj.func2(); +// kk +``` + +**bind**: +```js +var name = "hh"; +var obj = { + name : "kk", + func1: function () { + console.log(this.name) + }, + func2: function () { + setTimeout(function () { + this.func1() + }.bind(obj)(), 1000); + } +}; + +obj.func2(); +// kk +``` +`call`、`apply`、`bind` 都能改变` this` 的上下文对象,所以也没有报错,可以正常执行。 + +具体原因可看上述第七点,`call`、`apply`、`bind`。 + +## 4. new 实例化一个对象 +如上:第四点,作为一个构造函数使用。 \ No newline at end of file From 1cc09cdd80db7160c977fc4c1714b2c29cf84235 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Tue, 27 Nov 2018 22:57:08 +0800 Subject: [PATCH 133/835] 2018.11.27 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index fc0a77d9..cacc41cf 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ * [66-ES9汇总.md](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/66-ES9%E6%B1%87%E6%80%BB.md) * [67-JS箭头函数的适用和不适用的场景.md](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/67-JS%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0%E7%9A%84%E9%80%82%E7%94%A8%E5%92%8C%E4%B8%8D%E9%80%82%E7%94%A8%E7%9A%84%E5%9C%BA%E6%99%AF.md) * [68-创建对象的七种方式](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/68-%E5%88%9B%E5%BB%BA%E5%AF%B9%E8%B1%A1%E7%9A%84%E4%B8%83%E7%A7%8D%E6%96%B9%E5%BC%8F.md) +* [69-秒懂this](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/69-秒懂this.md) ### 4、Webpack * [25-Webpack入门教程整理(整理中)](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/25-Webpack%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%E6%95%B4%E7%90%86%EF%BC%88%E6%95%B4%E7%90%86%E4%B8%AD%EF%BC%89.md) From 8fe68cd29bfb9ea8faeffc0e3db036bec871018f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Wed, 28 Nov 2018 22:18:13 +0800 Subject: [PATCH 134/835] 2018.11.28 --- ...30\351\233\205\345\206\231\346\263\225.md" | 303 ++++++++++++++++++ 1 file changed, 303 insertions(+) create mode 100644 "article/70-JS\345\244\215\346\235\202\345\210\244\346\226\255\347\232\204\346\233\264\344\274\230\351\233\205\345\206\231\346\263\225.md" diff --git "a/article/70-JS\345\244\215\346\235\202\345\210\244\346\226\255\347\232\204\346\233\264\344\274\230\351\233\205\345\206\231\346\263\225.md" "b/article/70-JS\345\244\215\346\235\202\345\210\244\346\226\255\347\232\204\346\233\264\344\274\230\351\233\205\345\206\231\346\263\225.md" new file mode 100644 index 00000000..84ec490e --- /dev/null +++ "b/article/70-JS\345\244\215\346\235\202\345\210\244\346\226\255\347\232\204\346\233\264\344\274\230\351\233\205\345\206\231\346\263\225.md" @@ -0,0 +1,303 @@ +> [阅读原文](https://juejin.im/post/5bdfef86e51d453bf8051bf8) + + +## 前提 +我们编写js代码时经常遇到复杂逻辑判断的情况,通常大家可以用`if/else`或者`switch`来实现多个条件判断,但这样会有个问题,随着逻辑复杂度的增加,代码中的`if/else/switch`会变得越来越臃肿,越来越看不懂,那么如何更优雅的写判断逻辑,本文带你试一下。 + +## 举个例子 +先看一段代码: +```js +/** + * 按钮点击事件 + * @param {number} status + * 活动状态:1 开团进行中 2 开团失败 3 商品售罄 4 开团成功 5 系统取消 + */ +const onButtonClick = (status)=>{ + if(status == 1){ + sendLog('processing') + jumpTo('IndexPage') + }else if(status == 2){ + sendLog('fail') + jumpTo('FailPage') + }else if(status == 3){ + sendLog('fail') + jumpTo('FailPage') + }else if(status == 4){ + sendLog('success') + jumpTo('SuccessPage') + }else if(status == 5){ + sendLog('cancel') + jumpTo('CancelPage') + }else { + sendLog('other') + jumpTo('Index') + } +} +``` +通过代码可以看到这个按钮的点击逻辑:根据不同活动状态做两件事情,发送日志埋点和跳转到对应页面,大家可以很轻易的提出这段代码的改写方案,`switch`出场: +```js +/** + * 按钮点击事件 + * @param {number} status + * 活动状态:1 开团进行中 2 开团失败 3 商品售罄 4 开团成功 5 系统取消 + */ +const onButtonClick = (status)=>{ + switch (status){ + case 1: + sendLog('processing') + jumpTo('IndexPage') + break + case 2: + case 3: + sendLog('fail') + jumpTo('FailPage') + break + case 4: + sendLog('success') + jumpTo('SuccessPage') + break + case 5: + sendLog('cancel') + jumpTo('CancelPage') + break + default: + sendLog('other') + jumpTo('Index') + break + } +} +``` +嗯,这样看起来比`if/else`清晰多了,细心的同学也发现了小技巧,`case 2`和`case 3`逻辑一样的时候,可以省去执行语句和`break`,则`case 2`的情况自动执行`case 3`的逻辑。 +这时有同学会说,还有更简单的写法: +```js +const actions = { + '1': ['processing','IndexPage'], + '2': ['fail','FailPage'], + '3': ['fail','FailPage'], + '4': ['success','SuccessPage'], + '5': ['cancel','CancelPage'], + 'default': ['other','Index'], +} +/** + * 按钮点击事件 + * @param {number} status + * 活动状态:1开团进行中 2开团失败 3 商品售罄 4 开团成功 5 系统取消 + */ +const onButtonClick = (status)=>{ + let action = actions[status] || actions['default'], + logName = action[0], + pageName = action[1] + sendLog(logName) + jumpTo(pageName) +} +``` +上面代码确实看起来更清爽了,这种方法的聪明之处在于:将判断条件作为对象的属性名,将处理逻辑作为对象的属性值,在按钮点击的时候,通过对象属性查找的方式来进行逻辑判断,这种写法特别适合一元条件判断的情况。 +是不是还有其他写法呢?有的: +```js +const actions = new Map([ + [1, ['processing','IndexPage']], + [2, ['fail','FailPage']], + [3, ['fail','FailPage']], + [4, ['success','SuccessPage']], + [5, ['cancel','CancelPage']], + ['default', ['other','Index']] +]) +/** + * 按钮点击事件 + * @param {number} status + * 活动状态:1 开团进行中 2 开团失败 3 商品售罄 4 开团成功 5 系统取消 + */ +const onButtonClick = (status)=>{ + let action = actions.get(status) || actions.get('default') + sendLog(action[0]) + jumpTo(action[1]) +} +``` +这样写用到了`es6`里的`Map`对象,是不是更爽了?`Map`对象和`Object`对象有什么区别呢? + +* 一个对象通常都有自己的原型,所以一个对象总有一个"`prototype`"键。 +* 一个对象的键只能是**字符串**或者**Symbols**,但一个`Map`的键可以是任意值。 +你可以通过`size`属性很容易地得到一个`Map`的键值对个数,而对象的键值对个数只能手动确认。 + +我们需要把问题升级一下,以前按钮点击时候只需要判断`status`,现在还需要判断用户的身份: +```js +/** + * 按钮点击事件 + * @param {number} status + * 活动状态:1开团进行中 2开团失败 3 开团成功 4 商品售罄 5 有库存未开团 + * @param {string} identity + * 身份标识:guest客态 master主态 + */ +const onButtonClick = (status,identity)=>{ + if(identity == 'guest'){ + if(status == 1){ + //do sth + }else if(status == 2){ + //do sth + }else if(status == 3){ + //do sth + }else if(status == 4){ + //do sth + }else if(status == 5){ + //do sth + }else { + //do sth + } + }else if(identity == 'master') { + if(status == 1){ + //do sth + }else if(status == 2){ + //do sth + }else if(status == 3){ + //do sth + }else if(status == 4){ + //do sth + }else if(status == 5){ + //do sth + }else { + //do sth + } + } +} +``` +原谅我不写每个判断里的具体逻辑了,因为代码太冗长了。 +原谅我又用了`if/else`,因为我看到很多人依然在用`if/else`写这种大段的逻辑判断。 +从上面的例子我们可以看到,当你的逻辑升级为二元判断时,你的判断量会加倍,你的代码量也会加倍,这时怎么写更清爽呢? +```js +const actions = new Map([ + ['guest_1', ()=>{/*do sth*/}], + ['guest_2', ()=>{/*do sth*/}], + ['guest_3', ()=>{/*do sth*/}], + ['guest_4', ()=>{/*do sth*/}], + ['guest_5', ()=>{/*do sth*/}], + ['master_1', ()=>{/*do sth*/}], + ['master_2', ()=>{/*do sth*/}], + ['master_3', ()=>{/*do sth*/}], + ['master_4', ()=>{/*do sth*/}], + ['master_5', ()=>{/*do sth*/}], + ['default', ()=>{/*do sth*/}], +]) + +/** + * 按钮点击事件 + * @param {string} identity 身份标识:guest客态 master主态 + * @param {number} status 活动状态:1 开团进行中 2 开团失败 3 开团成功 4 商品售罄 5 有库存未开团 + */ +const onButtonClick = (identity,status)=>{ + let action = actions.get(`${identity}_${status}`) || actions.get('default') + action.call(this) +} +``` +上述代码核心逻辑是:把两个条件拼接成字符串,并通过以条件拼接字符串作为键,以处理函数作为值的Map对象进行查找并执行,这种写法在多元条件判断时候尤其好用。 +当然上述代码如果用`Object`对象来实现也是类似的: +```js +const actions = { + 'guest_1':()=>{/*do sth*/}, + 'guest_2':()=>{/*do sth*/}, + //.... +} + +const onButtonClick = (identity,status)=>{ + let action = actions[`${identity}_${status}`] || actions['default'] + action.call(this) +} +``` +如果有些同学觉得把查询条件拼成字符串有点别扭,那还有一种方案,就是用`Map`对象,以`Object`对象作为`key`: +```js +const actions = new Map([ + [{identity:'guest',status:1},()=>{/*do sth*/}], + [{identity:'guest',status:2},()=>{/*do sth*/}], + //... +]) + +const onButtonClick = (identity,status)=>{ + let action = [...actions].filter(([key,value])=>(key.identity == identity && key.status == status)) + action.forEach(([key,value])=>value.call(this)) +} +``` +是不是又高级了一点点? +这里也看出来`Map`与`Object`的区别,`Map`可以用任何类型的数据作为`key`。 +我们现在再将难度升级一点点,假如`guest`情况下,`status1-4`的处理逻辑都一样怎么办,最差的情况是这样: +```js +const actions = new Map([ + [{identity:'guest',status:1},()=>{/* functionA */}], + [{identity:'guest',status:2},()=>{/* functionA */}], + [{identity:'guest',status:3},()=>{/* functionA */}], + [{identity:'guest',status:4},()=>{/* functionA */}], + [{identity:'guest',status:5},()=>{/* functionB */}], + //... +]) +``` +好一点的写法是将处理逻辑函数进行缓存: +```js +const actions = ()=>{ + const functionA = ()=>{/*do sth*/} + const functionB = ()=>{/*do sth*/} + return new Map([ + [{identity:'guest',status:1},functionA], + [{identity:'guest',status:2},functionA], + [{identity:'guest',status:3},functionA], + [{identity:'guest',status:4},functionA], + [{identity:'guest',status:5},functionB], + //... + ]) +} + +const onButtonClick = (identity,status)=>{ + let action = [...actions()].filter(([key,value])=>(key.identity == identity && key.status == status)) + action.forEach(([key,value])=>value.call(this)) +} +``` +这样写已经能满足日常需求了,但认真一点讲,上面重写了4次`functionA`还是有点不爽,假如判断条件变得特别复杂,比如`identity`有3种状态,`status`有10种状态,那你需要定义30条处理逻辑,而往往这些逻辑里面很多都是相同的,这似乎也是笔者不想接受的,那可以这样实现: +```js +const actions = ()=>{ + const functionA = ()=>{/*do sth*/} + const functionB = ()=>{/*do sth*/} + return new Map([ + [/^guest_[1-4]$/,functionA], + [/^guest_5$/,functionB], + //... + ]) +} + +const onButtonClick = (identity,status)=>{ + let action = [...actions()].filter(([key,value])=>(key.test(`${identity}_${status}`))) + action.forEach(([key,value])=>value.call(this)) + +} +``` +这里Map的优势更加凸显,可以用正则类型作为`key`了,这样就有了无限可能,假如需求变成,凡是`guest`情况都要发送一个日志埋点,不同`status`情况也需要单独的逻辑处理,那我们可以这样写: +```js +const actions = ()=>{ + const functionA = ()=>{/*do sth*/} + const functionB = ()=>{/*do sth*/} + const functionC = ()=>{/*send log*/} + return new Map([ + [/^guest_[1-4]$/,functionA], + [/^guest_5$/,functionB], + [/^guest_.*$/,functionC], + //... + ]) +} + +const onButtonClick = (identity,status)=>{ + let action = [...actions()].filter(([key,value])=>(key.test(`${identity}_${status}`))) + action.forEach(([key,value])=>value.call(this)) +} +``` +也就是说利用数组循环的特性,符合正则条件的逻辑都会被执行,那就可以同时执行公共逻辑和单独逻辑,因为正则的存在,你可以打开想象力解锁更多的玩法,本文就不赘述了。 + +## 总结 +本文已经教你了8种逻辑判断写法,包括: + +* `if/else` +* `switch` +* 一元判断时:存到`Object`里 +* 一元判断时:存到`Map`里 +* 多元判断时:将`condition`拼接成字符串存到`Object`里 +* 多元判断时:将`condition`拼接成字符串存到`Map`里 +* 多元判断时:将`condition`存为`Object`存到`Map`里 +* 多元判断时:将`condition`写作正则存到`Map`里 + +至此,本文也将告一段落,愿你未来的人生里,不只是有`if/else/switch`。 +如果你对本文感兴趣,请关注作者微信公众号:“大转转fe” \ No newline at end of file From 0cdfabb51fe4299b288317822259202f5dad74f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Wed, 28 Nov 2018 22:19:11 +0800 Subject: [PATCH 135/835] 2018.11.28 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index cacc41cf..9f5814cd 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ * [67-JS箭头函数的适用和不适用的场景.md](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/67-JS%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0%E7%9A%84%E9%80%82%E7%94%A8%E5%92%8C%E4%B8%8D%E9%80%82%E7%94%A8%E7%9A%84%E5%9C%BA%E6%99%AF.md) * [68-创建对象的七种方式](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/68-%E5%88%9B%E5%BB%BA%E5%AF%B9%E8%B1%A1%E7%9A%84%E4%B8%83%E7%A7%8D%E6%96%B9%E5%BC%8F.md) * [69-秒懂this](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/69-秒懂this.md) +* [70-JS复杂判断的更优雅写法](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/70-JS复杂判断的更优雅写法.md) ### 4、Webpack * [25-Webpack入门教程整理(整理中)](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/25-Webpack%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%E6%95%B4%E7%90%86%EF%BC%88%E6%95%B4%E7%90%86%E4%B8%AD%EF%BC%89.md) From 76b8fb7c925d834ac156e2d7801585a7413c433e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Wed, 28 Nov 2018 22:20:31 +0800 Subject: [PATCH 136/835] 2018.11.28 --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9f5814cd..01965ae8 100644 --- a/README.md +++ b/README.md @@ -40,10 +40,6 @@ * [64-ES7汇总.md](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/64-ES7%E6%B1%87%E6%80%BB.md) * [65-ES8汇总.md](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/65-ES8%E6%B1%87%E6%80%BB.md) * [66-ES9汇总.md](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/66-ES9%E6%B1%87%E6%80%BB.md) -* [67-JS箭头函数的适用和不适用的场景.md](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/67-JS%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0%E7%9A%84%E9%80%82%E7%94%A8%E5%92%8C%E4%B8%8D%E9%80%82%E7%94%A8%E7%9A%84%E5%9C%BA%E6%99%AF.md) -* [68-创建对象的七种方式](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/68-%E5%88%9B%E5%BB%BA%E5%AF%B9%E8%B1%A1%E7%9A%84%E4%B8%83%E7%A7%8D%E6%96%B9%E5%BC%8F.md) -* [69-秒懂this](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/69-秒懂this.md) -* [70-JS复杂判断的更优雅写法](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/70-JS复杂判断的更优雅写法.md) ### 4、Webpack * [25-Webpack入门教程整理(整理中)](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/25-Webpack%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%E6%95%B4%E7%90%86%EF%BC%88%E6%95%B4%E7%90%86%E4%B8%AD%EF%BC%89.md) @@ -83,6 +79,10 @@ * [59-前端HTML5几种存储方式的总结](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/59-%E5%89%8D%E7%AB%AFHTML5%E5%87%A0%E7%A7%8D%E5%AD%98%E5%82%A8%E6%96%B9%E5%BC%8F%E7%9A%84%E6%80%BB%E7%BB%93.md) * [60-懒加载和预加载](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/60-%E6%87%92%E5%8A%A0%E8%BD%BD%E5%92%8C%E9%A2%84%E5%8A%A0%E8%BD%BD.md) * [61-JS中this的4种绑定规则](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/61-JS%E4%B8%ADthis%E7%9A%844%E7%A7%8D%E7%BB%91%E5%AE%9A%E8%A7%84%E5%88%99.md) +* [67-JS箭头函数的适用和不适用的场景.md](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/67-JS%E7%AE%AD%E5%A4%B4%E5%87%BD%E6%95%B0%E7%9A%84%E9%80%82%E7%94%A8%E5%92%8C%E4%B8%8D%E9%80%82%E7%94%A8%E7%9A%84%E5%9C%BA%E6%99%AF.md) +* [68-创建对象的七种方式](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/68-%E5%88%9B%E5%BB%BA%E5%AF%B9%E8%B1%A1%E7%9A%84%E4%B8%83%E7%A7%8D%E6%96%B9%E5%BC%8F.md) +* [69-秒懂this](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/69-秒懂this.md) +* [70-JS复杂判断的更优雅写法](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/70-JS复杂判断的更优雅写法.md) ### 7、HTTP * [47-http请求头与响应头的应用](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/47-http%E8%AF%B7%E6%B1%82%E5%A4%B4%E4%B8%8E%E5%93%8D%E5%BA%94%E5%A4%B4%E7%9A%84%E5%BA%94%E7%94%A8.md) From ce63083548033cda83dd6528daec6ac144bfe48d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Thu, 29 Nov 2018 07:49:15 +0800 Subject: [PATCH 137/835] =?UTF-8?q?2018.11.29=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E3=80=8ASet=E5=92=8CMap=E6=95=B0=E6=8D=AE=E7=BB=93=E6=9E=84?= =?UTF-8?q?=E3=80=8B=E7=AB=A0=E8=8A=82=E9=94=99=E8=AF=AF=20=E4=B9=A6?= =?UTF-8?q?=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 161 ++-------------------------------------- 1 file changed, 7 insertions(+), 154 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 898ee6c4..739c9fcb 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -23,10 +23,11 @@ * 2018.11.7 更新**ES9**《**正则表达式s修饰符**》章节。 * 2018.11.8 更新**ES9**《**异步遍历器**》章节。 * 2018.11.9 更新**ES9**完毕,转战vuepress整理一套。 +* 2018.11.29 修改《**Set和Map数据结构**》章节错误 书写。 **未来规划**: -* 1.将内容按不同模块拆分不同文件,方便README文件的阅读。 -* 2.添加案例项目。 +* [x] 1.将内容按不同模块拆分不同文件,方便README文件的阅读。 +* [ ] 2.添加案例项目。 # 一、介绍 现在的网络上已经有各样关于 **ECMAScript** 规范介绍和分析的文章,而我自己重新学习一遍这些规范,整理出这么一份笔记,比较精简,主要内容涵盖**ES6**、**ES7**、**ES8**、**ES9**,后续会增加**面试题**,**框架入门**等笔记,欢迎吐槽交流。 @@ -49,155 +50,7 @@ > 掘金主页 [LeoCoding](https://juejin.im/user/586fc337a22b9d0058807d53) # 二、目录 - - -- [一、介绍](#一介绍) -- [二、目录](#二目录) -- [三、正文](#三正文) - - [1. ES6](#1-es6) - - [1.1 let 和 const命令](#11-let-和-const命令) - - [1.1.1 let 命令](#111-let-命令) - - [1.1.2 const 命令](#112-const-命令) - - [1.2 变量的解构赋值](#12-变量的解构赋值) - - [1.2.1 数组](#121-数组) - - [1.2.2 对象的解构赋值](#122-对象的解构赋值) - - [1.2.3 字符串的解构赋值](#123-字符串的解构赋值) - - [1.2.4 数值和布尔值的解构赋值](#124-数值和布尔值的解构赋值) - - [1.2.5 函数参数的解构赋值](#125-函数参数的解构赋值) - - [1.2.6 应用](#126-应用) - - [1.3 字符串的拓展](#13-字符串的拓展) - - [1.3.1 includes(),startsWith(),endsWith()](#131-includesstartswithendswith) - - [1.3.2 repeat()](#132-repeat) - - [1.3.3 padStart(),padEnd()](#133-padstartpadend) - - [1.3.4 模版字符串](#134-模版字符串) - - [1.4 正则的拓展](#14-正则的拓展) - - [1.4.1 介绍](#141-介绍) - - [1.4.2 字符串的正则方法](#142-字符串的正则方法) - - [1.4.3 u修饰符](#143-u修饰符) - - [1.4.4 y修饰符](#144-y修饰符) - - [1.4.5 flags属性](#145-flags属性) - - [1.5 数值的拓展](#15-数值的拓展) - - [1.5.1 Number.isFinite(), Number.isNaN()](#151-numberisfinite-numberisnan) - - [1.5.2 Number.parseInt(), Number.parseFloat()](#152-numberparseint-numberparsefloat) - - [1.5.3 Number.isInteger()](#153-numberisinteger) - - [1.5.4 Math对象的拓展](#154-math对象的拓展) - - [1.5.5 指数运算符](#155-指数运算符) - - [1.6 函数的拓展](#16-函数的拓展) - - [1.6.1 参数默认值](#161-参数默认值) - - [1.6.2 rest 参数](#162-rest-参数) - - [1.6.3 name 属性](#163-name-属性) - - [1.6.4 箭头函数](#164-箭头函数) - - [1.6.5 双冒号运算符](#165-双冒号运算符) - - [1.7 数组的拓展](#17-数组的拓展) - - [1.7.1 拓展运算符](#171-拓展运算符) - - [1.7.2 Array.from()](#172-arrayfrom) - - [1.7.3 Array.of()](#173-arrayof) - - [1.7.4 find()和findIndex()](#174-find和findindex) - - [1.7.5 fill()](#175-fill) - - [1.7.6 entries(),keys(),values()](#176-entrieskeysvalues) - - [1.7.7 includes()](#177-includes) - - [1.7.8 flat(),flatMap()](#178-flatflatmap) - - [1.8 对象的拓展](#18-对象的拓展) - - [1.8.1 属性的简洁表示](#181-属性的简洁表示) - - [1.8.2 属性名表达式](#182-属性名表达式) - - [1.8.3 Object.is()](#183-objectis) - - [1.8.4 Object.assign()](#184-objectassign) - - [1.9 Symbol](#19-symbol) - - [1.9.1 介绍](#191-介绍) - - [1.9.2 更多介绍](#192-更多介绍) - - [1.10 Set和Map数据结构](#110-set和map数据结构) - - [1.10.1 Set](#1101-set) - - [1.10.2 Set的应用](#1102-set的应用) - - [1.10.3 Map](#1103-map) - - [1.10.4 Map与其他数据结构互相转换](#1104-map与其他数据结构互相转换) - - [1.11 Proxy](#111-proxy) - - [1.11.1 基础使用](#1111-基础使用) - - [1.11.2 取消Proxy实例](#1112-取消proxy实例) - - [1.11.3 实现 Web服务的客户端](#1113-实现-web服务的客户端) - - [1.12 Promise对象](#112-promise对象) - - [1.12.1 概念](#1121-概念) - - [1.12.2 基本使用](#1122-基本使用) - - [1.12.3 Promise.prototype.then()](#1123-promiseprototypethen) - - [1.12.4 Promise.prototype.catch()](#1124-promiseprototypecatch) - - [1.12.5 Promise.prototype.finally()](#1125-promiseprototypefinally) - - [1.12.6 Promise.all()](#1126-promiseall) - - [1.12.7 Promise.race()](#1127-promiserace) - - [1.12.8 Promise.resolve()](#1128-promiseresolve) - - [1.12.9 Promise.reject()](#1129-promisereject) - - [1.13 Iterator和 for...of循环](#113-iterator和-forof循环) - - [1.13.1 Iterator遍历器概念](#1131-iterator遍历器概念) - - [1.13.2 Iterator遍历过程](#1132-iterator遍历过程) - - [1.13.3 默认Iterator接口](#1133-默认iterator接口) - - [1.13.4 Iterator使用场景](#1134-iterator使用场景) - - [1.13.5 for...of循环](#1135-forof循环) - - [1.13.6 跳出for...of](#1136-跳出forof) - - [1.14 Generator函数和应用](#114-generator函数和应用) - - [1.14.1 基本概念](#1141-基本概念) - - [1.14.2 yield表达式](#1142-yield表达式) - - [1.14.3 next方法](#1143-next方法) - - [1.14.4 for...of循环](#1144-forof循环) - - [1.14.5 Generator.prototype.throw()](#1145-generatorprototypethrow) - - [1.14.6 Generator.prototype.return()](#1146-generatorprototypereturn) - - [1.14.7 next()/throw()/return()共同点](#1147-nextthrowreturn共同点) - - [1.14.8 yield* 表达式](#1148-yield-表达式) - - [1.14.9 应用场景](#1149-应用场景) - - [1.15 Class语法和继承](#115-class语法和继承) - - [1.15.1 介绍](#1151-介绍) - - [1.15.2 constructor()方法](#1152-constructor方法) - - [1.15.3 类的实例对象](#1153-类的实例对象) - - [1.15.4 Class表达式](#1154-class表达式) - - [1.15.5 私有方法和私有属性](#1155-私有方法和私有属性) - - [1.15.6 this指向问题](#1156-this指向问题) - - [1.15.7 Class的getter和setter](#1157-class的getter和setter) - - [1.15.8 Class的generator方法](#1158-class的generator方法) - - [1.15.9 Class的静态方法](#1159-class的静态方法) - - [1.15.10 Class的静态属性和实例属性](#11510-class的静态属性和实例属性) - - [1.15.11 Class的继承](#11511-class的继承) - - [1.16 Module语法和加载实现](#116-module语法和加载实现) - - [1.16.1 介绍](#1161-介绍) - - [1.16.2 严格模式](#1162-严格模式) - - [1.16.3 export命令](#1163-export命令) - - [1.16.4 import命令](#1164-import命令) - - [1.16.5 模块的整体加载](#1165-模块的整体加载) - - [1.16.6 export default 命令](#1166-export-default-命令) - - [1.16.7 export 和 import 复合写法](#1167-export-和-import-复合写法) - - [1.16.8 浏览器中的加载规则](#1168-浏览器中的加载规则) - - [2. ES7](#2-es7) - - [2.1 Array.prototype.includes()方法](#21-arrayprototypeincludes方法) - - [2.2 指数操作符(**)](#22-指数操作符) - - [3. ES8](#3-es8) - - [3.1 async函数](#31-async函数) - - [3.1.1 介绍](#311-介绍) - - [3.1.2 基本用法](#312-基本用法) - - [3.1.3 返回Promise对象](#313-返回promise对象) - - [3.1.4 await命令](#314-await命令) - - [3.1.5 使用注意](#315-使用注意) - - [3.2 Promise.prototype.finally()](#32-promiseprototypefinally) - - [3.3 Object.values(),Object.entries()](#33-objectvaluesobjectentries) - - [3.3.1 Object.values()](#331-objectvalues) - - [3.3.2 Object.entries()](#332-objectentries) - - [3.4 Object.getOwnPropertyDescriptors()](#34-objectgetownpropertydescriptors) - - [3.5 字符串填充 padStart和padEnd](#35-字符串填充-padstart和padend) - - [3.6 函数参数列表与调用中的尾部逗号](#36-函数参数列表与调用中的尾部逗号) - - [3.7 共享内存与原子操作](#37-共享内存与原子操作) - - [4. ES9](#4-es9) - - [4.1 对象的拓展运算符](#41-对象的拓展运算符) - - [4.1.1 介绍](#411-介绍) - - [4.1.2 使用场景](#412-使用场景) - - [4.2 正则表达式 s 修饰符](#42-正则表达式-s-修饰符) - - [4.3 异步遍历器](#43-异步遍历器) - - [4.3.1 异步遍历的接口](#431-异步遍历的接口) - - [4.3.2 for await...of](#432-for-awaitof) - - [4.3.3 异步Generator函数](#433-异步generator函数) - - [4.3.4 yield* 语句](#434-yield-语句) - - [5. 知识补充](#5-知识补充) - - [5.1 块级作用域](#51-块级作用域) - - [5.2 ES5/6对数组空位的处理](#52-es56对数组空位的处理) -- [四、结语](#四结语) - - [参考文章](#参考文章) - - [推荐文章](#推荐文章) - - +autoauto- [一、介绍](#一介绍)auto- [二、目录](#二目录)auto- [三、正文](#三正文)auto - [1. ES6](#1-es6)auto - [1.1 let 和 const命令](#11-let-和-const命令)auto - [1.1.1 let 命令](#111-let-命令)auto - [1.1.2 const 命令](#112-const-命令)auto - [1.2 变量的解构赋值](#12-变量的解构赋值)auto - [1.2.1 数组](#121-数组)auto - [1.2.2 对象的解构赋值](#122-对象的解构赋值)auto - [1.2.3 字符串的解构赋值](#123-字符串的解构赋值)auto - [1.2.4 数值和布尔值的解构赋值](#124-数值和布尔值的解构赋值)auto - [1.2.5 函数参数的解构赋值](#125-函数参数的解构赋值)auto - [1.2.6 应用](#126-应用)auto - [1.3 字符串的拓展](#13-字符串的拓展)auto - [1.3.1 includes(),startsWith(),endsWith()](#131-includesstartswithendswith)auto - [1.3.2 repeat()](#132-repeat)auto - [1.3.3 padStart(),padEnd()](#133-padstartpadend)auto - [1.3.4 模版字符串](#134-模版字符串)auto - [1.4 正则的拓展](#14-正则的拓展)auto - [1.4.1 介绍](#141-介绍)auto - [1.4.2 字符串的正则方法](#142-字符串的正则方法)auto - [1.4.3 u修饰符](#143-u修饰符)auto - [1.4.4 y修饰符](#144-y修饰符)auto - [1.4.5 flags属性](#145-flags属性)auto - [1.5 数值的拓展](#15-数值的拓展)auto - [1.5.1 Number.isFinite(), Number.isNaN()](#151-numberisfinite-numberisnan)auto - [1.5.2 Number.parseInt(), Number.parseFloat()](#152-numberparseint-numberparsefloat)auto - [1.5.3 Number.isInteger()](#153-numberisinteger)auto - [1.5.4 Math对象的拓展](#154-math对象的拓展)auto - [1.5.5 指数运算符](#155-指数运算符)auto - [1.6 函数的拓展](#16-函数的拓展)auto - [1.6.1 参数默认值](#161-参数默认值)auto - [1.6.2 rest 参数](#162-rest-参数)auto - [1.6.3 name 属性](#163-name-属性)auto - [1.6.4 箭头函数](#164-箭头函数)auto - [1.6.5 双冒号运算符](#165-双冒号运算符)auto - [1.7 数组的拓展](#17-数组的拓展)auto - [1.7.1 拓展运算符](#171-拓展运算符)auto - [1.7.2 Array.from()](#172-arrayfrom)auto - [1.7.3 Array.of()](#173-arrayof)auto - [1.7.4 find()和findIndex()](#174-find和findindex)auto - [1.7.5 fill()](#175-fill)auto - [1.7.6 entries(),keys(),values()](#176-entrieskeysvalues)auto - [1.7.7 includes()](#177-includes)auto - [1.7.8 flat(),flatMap()](#178-flatflatmap)auto - [1.8 对象的拓展](#18-对象的拓展)auto - [1.8.1 属性的简洁表示](#181-属性的简洁表示)auto - [1.8.2 属性名表达式](#182-属性名表达式)auto - [1.8.3 Object.is()](#183-objectis)auto - [1.8.4 Object.assign()](#184-objectassign)auto - [1.9 Symbol](#19-symbol)auto - [1.9.1 介绍](#191-介绍)auto - [1.9.2 更多介绍](#192-更多介绍)auto - [1.10 Set和Map数据结构](#110-set和map数据结构)auto - [1.10.1 Set](#1101-set)auto - [1.10.2 Set的应用](#1102-set的应用)auto - [1.10.3 Map](#1103-map)auto - [1.10.4 Map与其他数据结构互相转换](#1104-map与其他数据结构互相转换)auto - [1.11 Proxy](#111-proxy)auto - [1.11.1 基础使用](#1111-基础使用)auto - [1.11.2 取消Proxy实例](#1112-取消proxy实例)auto - [1.11.3 实现 Web服务的客户端](#1113-实现-web服务的客户端)auto - [1.12 Promise对象](#112-promise对象)auto - [1.12.1 概念](#1121-概念)auto - [1.12.2 基本使用](#1122-基本使用)auto - [1.12.3 Promise.prototype.then()](#1123-promiseprototypethen)auto - [1.12.4 Promise.prototype.catch()](#1124-promiseprototypecatch)auto - [1.12.5 Promise.prototype.finally()](#1125-promiseprototypefinally)auto - [1.12.6 Promise.all()](#1126-promiseall)auto - [1.12.7 Promise.race()](#1127-promiserace)auto - [1.12.8 Promise.resolve()](#1128-promiseresolve)auto - [1.12.9 Promise.reject()](#1129-promisereject)auto - [1.13 Iterator和 for...of循环](#113-iterator和-forof循环)auto - [1.13.1 Iterator遍历器概念](#1131-iterator遍历器概念)auto - [1.13.2 Iterator遍历过程](#1132-iterator遍历过程)auto - [1.13.3 默认Iterator接口](#1133-默认iterator接口)auto - [1.13.4 Iterator使用场景](#1134-iterator使用场景)auto - [1.13.5 for...of循环](#1135-forof循环)auto - [1.13.6 跳出for...of](#1136-跳出forof)auto - [1.14 Generator函数和应用](#114-generator函数和应用)auto - [1.14.1 基本概念](#1141-基本概念)auto - [1.14.2 yield表达式](#1142-yield表达式)auto - [1.14.3 next方法](#1143-next方法)auto - [1.14.4 for...of循环](#1144-forof循环)auto - [1.14.5 Generator.prototype.throw()](#1145-generatorprototypethrow)auto - [1.14.6 Generator.prototype.return()](#1146-generatorprototypereturn)auto - [1.14.7 next()/throw()/return()共同点](#1147-nextthrowreturn共同点)auto - [1.14.8 yield* 表达式](#1148-yield-表达式)auto - [1.14.9 应用场景](#1149-应用场景)auto - [1.15 Class语法和继承](#115-class语法和继承)auto - [1.15.1 介绍](#1151-介绍)auto - [1.15.2 constructor()方法](#1152-constructor方法)auto - [1.15.3 类的实例对象](#1153-类的实例对象)auto - [1.15.4 Class表达式](#1154-class表达式)auto - [1.15.5 私有方法和私有属性](#1155-私有方法和私有属性)auto - [1.15.6 this指向问题](#1156-this指向问题)auto - [1.15.7 Class的getter和setter](#1157-class的getter和setter)auto - [1.15.8 Class的generator方法](#1158-class的generator方法)auto - [1.15.9 Class的静态方法](#1159-class的静态方法)auto - [1.15.10 Class的静态属性和实例属性](#11510-class的静态属性和实例属性)auto - [1.15.11 Class的继承](#11511-class的继承)auto - [1.16 Module语法和加载实现](#116-module语法和加载实现)auto - [1.16.1 介绍](#1161-介绍)auto - [1.16.2 严格模式](#1162-严格模式)auto - [1.16.3 export命令](#1163-export命令)auto - [1.16.4 import命令](#1164-import命令)auto - [1.16.5 模块的整体加载](#1165-模块的整体加载)auto - [1.16.6 export default 命令](#1166-export-default-命令)auto - [1.16.7 export 和 import 复合写法](#1167-export-和-import-复合写法)auto - [1.16.8 浏览器中的加载规则](#1168-浏览器中的加载规则)auto - [2. ES7](#2-es7)auto - [2.1 Array.prototype.includes()方法](#21-arrayprototypeincludes方法)auto - [2.2 指数操作符(**)](#22-指数操作符)auto - [3. ES8](#3-es8)auto - [3.1 async函数](#31-async函数)auto - [3.1.1 介绍](#311-介绍)auto - [3.1.2 基本用法](#312-基本用法)auto - [3.1.3 返回Promise对象](#313-返回promise对象)auto - [3.1.4 await命令](#314-await命令)auto - [3.1.5 使用注意](#315-使用注意)auto - [3.2 Promise.prototype.finally()](#32-promiseprototypefinally)auto - [3.3 Object.values(),Object.entries()](#33-objectvaluesobjectentries)auto - [3.3.1 Object.values()](#331-objectvalues)auto - [3.3.2 Object.entries()](#332-objectentries)auto - [3.4 Object.getOwnPropertyDescriptors()](#34-objectgetownpropertydescriptors)auto - [3.5 字符串填充 padStart和padEnd](#35-字符串填充-padstart和padend)auto - [3.6 函数参数列表与调用中的尾部逗号](#36-函数参数列表与调用中的尾部逗号)auto - [3.7 共享内存与原子操作](#37-共享内存与原子操作)auto - [4. ES9](#4-es9)auto - [4.1 对象的拓展运算符](#41-对象的拓展运算符)auto - [4.1.1 介绍](#411-介绍)auto - [4.1.2 使用场景](#412-使用场景)auto - [4.2 正则表达式 s 修饰符](#42-正则表达式-s-修饰符)auto - [4.3 异步遍历器](#43-异步遍历器)auto - [4.3.1 异步遍历的接口](#431-异步遍历的接口)auto - [4.3.2 for await...of](#432-for-awaitof)auto - [4.3.3 异步Generator函数](#433-异步generator函数)auto - [4.3.4 yield* 语句](#434-yield-语句)auto - [5. 知识补充](#5-知识补充)auto - [5.1 块级作用域](#51-块级作用域)auto - [5.2 ES5/6对数组空位的处理](#52-es56对数组空位的处理)auto- [四、结语](#四结语)auto - [参考文章](#参考文章)auto - [推荐文章](#推荐文章)autoauto # 三、正文 ## 1. ES6 @@ -1512,7 +1365,7 @@ let b1 = { [a1] : 'bb'}; ``` #### 1.8.3 Object.is() -`.Object.is()` 用于比较两个值是否严格相等,在ES5时候只要使用**相等运算符**(`==`)和**严格相等运算符**(`===`)就可以做比较,但是它们都有缺点,前者会**自动转换数据类型**,后者的`NaN`不等于自身,以及`+0`等于`-0`。 +`Object.is()` 用于比较两个值是否严格相等,在ES5时候只要使用**相等运算符**(`==`)和**严格相等运算符**(`===`)就可以做比较,但是它们都有缺点,前者会**自动转换数据类型**,后者的`NaN`不等于自身,以及`+0`等于`-0`。 ```js Object.is('a','a'); // true Object.is({}, {}); // false @@ -1666,7 +1519,7 @@ let a = new Set([1,2,3,3,3,3]); // 方法1 [...new Set([1,2,3,4,4,4])]; // [1,2,3,4] // 方法2 -Array.from([1,2,3,4,4,4]); // [1,2,3,4] +Array.from(new Set([1,2,3,4,4,4])); // [1,2,3,4] ``` **遍历和过滤**: ```js @@ -1690,7 +1543,7 @@ let c1 = new Set([...a, ...b]); // Set {1,2,3,4} let c2 = new Set([...a].filter(x => b.has(x))); // set {2,3} // 差集 -let c3 = new Set([...a].filter(x => !b.has(x))); // set {1,4} +let c3 = new Set([...a].filter(x => !b.has(x))); // set {1} ``` * 遍历方法: From 07fbbd1c276189a936e64429dc69814708b1a43e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Thu, 29 Nov 2018 07:50:29 +0800 Subject: [PATCH 138/835] =?UTF-8?q?2018.11.29=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=9C=AC=E6=96=87=E5=AF=B9=E5=BA=94=E5=8D=9A=E5=AE=A2=E5=9C=B0?= =?UTF-8?q?=E5=9D=80=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 739c9fcb..6c0e827c 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -44,6 +44,7 @@ | ECMAScript 2016(ES7) | 2016年3月 | includes,指数操作符 | | ECMAScript 2017(ES8) | 2017年6月 | sync/await,Object.values(),Object.entries(),String padding等 | +> 本文博客 [CuteECMAScript](http://es.pingan8787.com) > 本文开源地址 [CuteECMAScript](https://github.com/pingan8787/Leo-JavaScript/tree/master/EXEFE-es6book) > 个人博客 [ping'anの博客](http://www.pingan8787.com) > Github地址 [pingan8787的github](https://github.com/pingan8787) From 2f541e5f6e0f30f6ff016195fecbfe11cc596971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Thu, 29 Nov 2018 23:21:26 +0800 Subject: [PATCH 139/835] =?UTF-8?q?2018.11.29=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E3=80=8ASymbol=E3=80=8B=E7=AB=A0=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 222 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 219 insertions(+), 3 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 6c0e827c..55557ad7 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -23,7 +23,7 @@ * 2018.11.7 更新**ES9**《**正则表达式s修饰符**》章节。 * 2018.11.8 更新**ES9**《**异步遍历器**》章节。 * 2018.11.9 更新**ES9**完毕,转战vuepress整理一套。 -* 2018.11.29 修改《**Set和Map数据结构**》章节错误 书写。 +* 2018.11.29 修改《**Set和Map数据结构**》章节错误 书写,更新《Symbol》章节。 **未来规划**: * [x] 1.将内容按不同模块拆分不同文件,方便README文件的阅读。 @@ -1440,10 +1440,12 @@ typeof a; // "symbol" * `Symbol`函数不能用`new`,会报错。由于`Symbol`是一个原始类型,不是对象,所以不能添加属性,它是类似于字符串的数据类型。 * `Symbol`都是不相等的,即使参数相同。 ```js +// 没有参数 let a1 = Symbol(); let a2 = Symbal(); a1 === a2; // false +// 有参数 let a1 = Symbol('abc'); let a2 = Symbal('abc'); a1 === a2; // false @@ -1454,9 +1456,223 @@ let a = Symbol('hello'); a + " world!"; // 报错 `${a} world!`; // 报错 ``` +Symbol可以显式转换为字符串: +```js +let a1 = Symbol('hello'); + +String(a1); // "Symbol(hello)" +a1.toString(); // "Symbol(hello)" +``` +Symbol可以转换为布尔值,但不能转为数值: +```js +let a1 = Symbol(); +Boolean(a1); +!a1; // false + +Number(a1); // TypeError +a1 + 1 ; // TypeError +``` + +#### 1.9.2 Symbol作为属性名 +好处:防止同名属性,还有防止键被改写或覆盖。 +```js +let a1 = Symbol(); + +// 写法1 +let b = {}; +b[a1] = 'hello'; + +// 写法2 +let b = { + [a1] : 'hello' +} + +// 写法3 +let b = {}; +Object.defineProperty(b, a1, {value : 'hello' }); + +// 3种写法 结果相同 +b[a1]; // 'hello' +``` +**需要注意:** Symbol作为对象属性名时,不能用点运算符,并且必须放在方括号内。 +```js +let a = Symbol(); +let b = {}; + +// 不能用点运算 +b.a = 'hello'; +b[a] ; // undefined +b['a'] ; // 'hello' + +// 必须放在方括号内 +let c = { + [a] : function (text){ + console.log(text); + } +} +c[a]('leo'); // 'leo' + +// 上面等价于 更简洁 +let c = { + [a](text){ + console.log(text); + } +} +``` + +**常常还用于创建一组常量,保证所有值不相等:** +```js +let a = {}; +a.a1 = { + AAA: Symbol('aaa'), + BBB: Symbol('bbb'), + CCC: Symbol('ccc') +} +``` + +#### 1.9.3 应用:消除魔术字符串 +魔术字符串:指代码中多次出现,强耦合的字符串或数值,应该避免,而使用含义清晰的变量代替。 +```js +function f(a){ + if(a == 'leo') { + console.log('hello'); + } +} +f('leo'); // 'leo' 为魔术字符串 +``` +常使用变量,消除魔术字符串: +```js +let obj = { + name: 'leo' +}; +function f (a){ + if(a == obj.name){ + console.log('hello'); + } +} +f(obj.name); // 'leo' +``` +使用Symbol消除强耦合,使得不需关系具体的值: +```js +let obj = { + name: Symbol() +}; +function f (a){ + if(a == obj.name){ + console.log('hello'); + } +} +f(obj.name); +``` + +#### 1.9.4 属性名遍历 +Symbol作为属性名遍历,不出现在`for...in`、`for...of`循环,也不被`Object.keys()`、`Object.getOwnPropertyNames()`、`JSON.stringify()`返回。 +```js +let a = Symbol('aa'),b= Symbol('bb'); +let obj = { + [a]:'11', [b]:'22' +} +for(let k of Object.values(obj)){console.log(k)} +// 无输出 + +let obj = {}; +let aa = Symbol('leo'); +Object.defineProperty(obj, aa, {value: 'hi'}); + +for(let k in obj){ + console.log(k); // 无输出 +} + +Object.getOwnPropertyNames(obj); // [] +Object.getOwnPropertySymbols(obj); // [Symbol(leo)] +``` + +`Object.getOwnPropertySymbols`方法返回一个数组,包含当前对象所有用做属性名的Symbol值。 +```js +let a = {}; +let a1 = Symbol('a'); +let a2 = Symbol('b'); +a[a1] = 'hi'; +a[a2] = 'oi'; + +let obj = Object.getOwnPropertySymbols(a); +obj; //  [Symbol(a), Symbol(b)] +``` + +另外可以使用`Reflect.ownKeys`方法可以返回所有类型的键名,包括常规键名和 Symbol 键名。 +```js +let a = { + [Symbol('leo')]: 1, + aa : 2, + bb : 3, +} +Reflect.ownKeys(a); // ['aa', 'bb',Symbol('leo')] +``` + +由于Symbol值作为名称的属性不被常规方法遍历获取,因此常用于定义对象的一些非私有,且内部使用的方法。 + +#### 1.9.5 Symbol.for()、Symbol.keyFor() +* Symbol.for() +**用于重复使用一个Symbol值**,接收一个**字符串**作为参数,若存在用此参数作为名称的Symbol值,返回这个Symbol,否则新建并返回以这个参数为名称的Symbol值。 +```js +let a = Symbol.for('aaa'); +let b = Symbol.for('aaa'); + +a === b; // true +``` +`Symbol()` 和 `Symbol.for()`区别: +```js +Symbol.for('aa') === Symbol.for('aa'); // true +Symbol('aa') === Symbol('aa'); // false +``` + +* Symbol.keyFor() +**用于返回一个已使用的Symbol类型的key**: +```js +let a = Symbol.for('aa'); +Symbol.keyFor(a); // 'aa' + +let b = Symbol('aa'); +Symbol.keyFor(b); // undefined +``` + +#### 1.9.6 内置的Symbol值 +ES6提供11个内置的Symbol值,指向语言内部使用的方法: +* **1.Symbol.hasInstance** +当其他对象使用`instanceof`运算符,判断是否为该对象的实例时,会调用这个方法。比如,`foo instanceof Foo`在语言内部,实际调用的是`Foo[Symbol.hasInstance](foo)`。 +```js +class P { + [Symbol.hasInstance](a){ + return a instanceof Array; + } +} +[1, 2, 3] instanceof new P(); // true +``` +P是一个类,new P()会返回一个实例,该实例的`Symbol.hasInstance`方法,会在进行`instanceof`运算时自动调用,判断左侧的运算子是否为`Array`的实例。 + +* **2.Symbol.isConcatSpreadable** +值为布尔值,表示该对象用于`Array.prototype.concat()`时,是否可以展开。 +```js +let a = ['aa','bb']; +['cc','dd'].concat(a, 'ee'); +// ['cc', 'dd', 'aa', 'bb', 'ee'] +a[Symbol.isConcatSpreadable]; // undefined + +let b = ['aa','bb']; +b[Symbol.isConcatSpreadable] = false; +['cc','dd'].concat(b, 'ee'); +// ['cc', 'dd',[ 'aa', 'bb'], 'ee'] +``` -#### 1.9.2 更多介绍 -详细介绍[参考阮一峰老师的ES6 Symbol介绍](http://es6.ruanyifeng.com/#docs/symbol) +* **3.Symbol.hasInstance** +* **4.Symbol.hasInstance** +* **5.Symbol.hasInstance** +* **6.Symbol.hasInstance** +* **7.Symbol.hasInstance** +* **8.Symbol.hasInstance** +* **9.Symbol.hasInstance** +* **10.Symbol.hasInstance** +* **11.Symbol.hasInstance** [⬆ 返回目录](#二目录) From 5673143f990dc466202ad6587c8be06d458dc994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 30 Nov 2018 22:27:50 +0800 Subject: [PATCH 140/835] 2018.11.30 --- EXEFE-es6book/README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 55557ad7..18721d55 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -51,7 +51,7 @@ > 掘金主页 [LeoCoding](https://juejin.im/user/586fc337a22b9d0058807d53) # 二、目录 -autoauto- [一、介绍](#一介绍)auto- [二、目录](#二目录)auto- [三、正文](#三正文)auto - [1. ES6](#1-es6)auto - [1.1 let 和 const命令](#11-let-和-const命令)auto - [1.1.1 let 命令](#111-let-命令)auto - [1.1.2 const 命令](#112-const-命令)auto - [1.2 变量的解构赋值](#12-变量的解构赋值)auto - [1.2.1 数组](#121-数组)auto - [1.2.2 对象的解构赋值](#122-对象的解构赋值)auto - [1.2.3 字符串的解构赋值](#123-字符串的解构赋值)auto - [1.2.4 数值和布尔值的解构赋值](#124-数值和布尔值的解构赋值)auto - [1.2.5 函数参数的解构赋值](#125-函数参数的解构赋值)auto - [1.2.6 应用](#126-应用)auto - [1.3 字符串的拓展](#13-字符串的拓展)auto - [1.3.1 includes(),startsWith(),endsWith()](#131-includesstartswithendswith)auto - [1.3.2 repeat()](#132-repeat)auto - [1.3.3 padStart(),padEnd()](#133-padstartpadend)auto - [1.3.4 模版字符串](#134-模版字符串)auto - [1.4 正则的拓展](#14-正则的拓展)auto - [1.4.1 介绍](#141-介绍)auto - [1.4.2 字符串的正则方法](#142-字符串的正则方法)auto - [1.4.3 u修饰符](#143-u修饰符)auto - [1.4.4 y修饰符](#144-y修饰符)auto - [1.4.5 flags属性](#145-flags属性)auto - [1.5 数值的拓展](#15-数值的拓展)auto - [1.5.1 Number.isFinite(), Number.isNaN()](#151-numberisfinite-numberisnan)auto - [1.5.2 Number.parseInt(), Number.parseFloat()](#152-numberparseint-numberparsefloat)auto - [1.5.3 Number.isInteger()](#153-numberisinteger)auto - [1.5.4 Math对象的拓展](#154-math对象的拓展)auto - [1.5.5 指数运算符](#155-指数运算符)auto - [1.6 函数的拓展](#16-函数的拓展)auto - [1.6.1 参数默认值](#161-参数默认值)auto - [1.6.2 rest 参数](#162-rest-参数)auto - [1.6.3 name 属性](#163-name-属性)auto - [1.6.4 箭头函数](#164-箭头函数)auto - [1.6.5 双冒号运算符](#165-双冒号运算符)auto - [1.7 数组的拓展](#17-数组的拓展)auto - [1.7.1 拓展运算符](#171-拓展运算符)auto - [1.7.2 Array.from()](#172-arrayfrom)auto - [1.7.3 Array.of()](#173-arrayof)auto - [1.7.4 find()和findIndex()](#174-find和findindex)auto - [1.7.5 fill()](#175-fill)auto - [1.7.6 entries(),keys(),values()](#176-entrieskeysvalues)auto - [1.7.7 includes()](#177-includes)auto - [1.7.8 flat(),flatMap()](#178-flatflatmap)auto - [1.8 对象的拓展](#18-对象的拓展)auto - [1.8.1 属性的简洁表示](#181-属性的简洁表示)auto - [1.8.2 属性名表达式](#182-属性名表达式)auto - [1.8.3 Object.is()](#183-objectis)auto - [1.8.4 Object.assign()](#184-objectassign)auto - [1.9 Symbol](#19-symbol)auto - [1.9.1 介绍](#191-介绍)auto - [1.9.2 更多介绍](#192-更多介绍)auto - [1.10 Set和Map数据结构](#110-set和map数据结构)auto - [1.10.1 Set](#1101-set)auto - [1.10.2 Set的应用](#1102-set的应用)auto - [1.10.3 Map](#1103-map)auto - [1.10.4 Map与其他数据结构互相转换](#1104-map与其他数据结构互相转换)auto - [1.11 Proxy](#111-proxy)auto - [1.11.1 基础使用](#1111-基础使用)auto - [1.11.2 取消Proxy实例](#1112-取消proxy实例)auto - [1.11.3 实现 Web服务的客户端](#1113-实现-web服务的客户端)auto - [1.12 Promise对象](#112-promise对象)auto - [1.12.1 概念](#1121-概念)auto - [1.12.2 基本使用](#1122-基本使用)auto - [1.12.3 Promise.prototype.then()](#1123-promiseprototypethen)auto - [1.12.4 Promise.prototype.catch()](#1124-promiseprototypecatch)auto - [1.12.5 Promise.prototype.finally()](#1125-promiseprototypefinally)auto - [1.12.6 Promise.all()](#1126-promiseall)auto - [1.12.7 Promise.race()](#1127-promiserace)auto - [1.12.8 Promise.resolve()](#1128-promiseresolve)auto - [1.12.9 Promise.reject()](#1129-promisereject)auto - [1.13 Iterator和 for...of循环](#113-iterator和-forof循环)auto - [1.13.1 Iterator遍历器概念](#1131-iterator遍历器概念)auto - [1.13.2 Iterator遍历过程](#1132-iterator遍历过程)auto - [1.13.3 默认Iterator接口](#1133-默认iterator接口)auto - [1.13.4 Iterator使用场景](#1134-iterator使用场景)auto - [1.13.5 for...of循环](#1135-forof循环)auto - [1.13.6 跳出for...of](#1136-跳出forof)auto - [1.14 Generator函数和应用](#114-generator函数和应用)auto - [1.14.1 基本概念](#1141-基本概念)auto - [1.14.2 yield表达式](#1142-yield表达式)auto - [1.14.3 next方法](#1143-next方法)auto - [1.14.4 for...of循环](#1144-forof循环)auto - [1.14.5 Generator.prototype.throw()](#1145-generatorprototypethrow)auto - [1.14.6 Generator.prototype.return()](#1146-generatorprototypereturn)auto - [1.14.7 next()/throw()/return()共同点](#1147-nextthrowreturn共同点)auto - [1.14.8 yield* 表达式](#1148-yield-表达式)auto - [1.14.9 应用场景](#1149-应用场景)auto - [1.15 Class语法和继承](#115-class语法和继承)auto - [1.15.1 介绍](#1151-介绍)auto - [1.15.2 constructor()方法](#1152-constructor方法)auto - [1.15.3 类的实例对象](#1153-类的实例对象)auto - [1.15.4 Class表达式](#1154-class表达式)auto - [1.15.5 私有方法和私有属性](#1155-私有方法和私有属性)auto - [1.15.6 this指向问题](#1156-this指向问题)auto - [1.15.7 Class的getter和setter](#1157-class的getter和setter)auto - [1.15.8 Class的generator方法](#1158-class的generator方法)auto - [1.15.9 Class的静态方法](#1159-class的静态方法)auto - [1.15.10 Class的静态属性和实例属性](#11510-class的静态属性和实例属性)auto - [1.15.11 Class的继承](#11511-class的继承)auto - [1.16 Module语法和加载实现](#116-module语法和加载实现)auto - [1.16.1 介绍](#1161-介绍)auto - [1.16.2 严格模式](#1162-严格模式)auto - [1.16.3 export命令](#1163-export命令)auto - [1.16.4 import命令](#1164-import命令)auto - [1.16.5 模块的整体加载](#1165-模块的整体加载)auto - [1.16.6 export default 命令](#1166-export-default-命令)auto - [1.16.7 export 和 import 复合写法](#1167-export-和-import-复合写法)auto - [1.16.8 浏览器中的加载规则](#1168-浏览器中的加载规则)auto - [2. ES7](#2-es7)auto - [2.1 Array.prototype.includes()方法](#21-arrayprototypeincludes方法)auto - [2.2 指数操作符(**)](#22-指数操作符)auto - [3. ES8](#3-es8)auto - [3.1 async函数](#31-async函数)auto - [3.1.1 介绍](#311-介绍)auto - [3.1.2 基本用法](#312-基本用法)auto - [3.1.3 返回Promise对象](#313-返回promise对象)auto - [3.1.4 await命令](#314-await命令)auto - [3.1.5 使用注意](#315-使用注意)auto - [3.2 Promise.prototype.finally()](#32-promiseprototypefinally)auto - [3.3 Object.values(),Object.entries()](#33-objectvaluesobjectentries)auto - [3.3.1 Object.values()](#331-objectvalues)auto - [3.3.2 Object.entries()](#332-objectentries)auto - [3.4 Object.getOwnPropertyDescriptors()](#34-objectgetownpropertydescriptors)auto - [3.5 字符串填充 padStart和padEnd](#35-字符串填充-padstart和padend)auto - [3.6 函数参数列表与调用中的尾部逗号](#36-函数参数列表与调用中的尾部逗号)auto - [3.7 共享内存与原子操作](#37-共享内存与原子操作)auto - [4. ES9](#4-es9)auto - [4.1 对象的拓展运算符](#41-对象的拓展运算符)auto - [4.1.1 介绍](#411-介绍)auto - [4.1.2 使用场景](#412-使用场景)auto - [4.2 正则表达式 s 修饰符](#42-正则表达式-s-修饰符)auto - [4.3 异步遍历器](#43-异步遍历器)auto - [4.3.1 异步遍历的接口](#431-异步遍历的接口)auto - [4.3.2 for await...of](#432-for-awaitof)auto - [4.3.3 异步Generator函数](#433-异步generator函数)auto - [4.3.4 yield* 语句](#434-yield-语句)auto - [5. 知识补充](#5-知识补充)auto - [5.1 块级作用域](#51-块级作用域)auto - [5.2 ES5/6对数组空位的处理](#52-es56对数组空位的处理)auto- [四、结语](#四结语)auto - [参考文章](#参考文章)auto - [推荐文章](#推荐文章)autoauto + # 三、正文 ## 1. ES6 @@ -426,7 +426,7 @@ a.includes('lo',6); // false 'ab'.repeat('3'); // 'ababab' ``` -####1.3.3 padStart(),padEnd() +#### 1.3.3 padStart(),padEnd() 用于将字符串**头部**或**尾部**补全长度,`padStart()`为**头部补全**,`padEnd()`为**尾部补全**。 这两个方法接收**2个**参数,第一个指定**字符串最小长度**,第二个**用于补全的字符串**。 **基础用法** : @@ -874,7 +874,6 @@ Math.pow(99, 99) // 3.697296376497268e+197 ``` - [⬆ 返回目录](#二目录) From 2bef8fb51781b8bcd28565e7238ec96c667f9ff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 30 Nov 2018 22:34:10 +0800 Subject: [PATCH 141/835] =?UTF-8?q?2018.11.30=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E7=9B=AE=E5=BD=95=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 154 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 153 insertions(+), 1 deletion(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 18721d55..686694ed 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -51,7 +51,159 @@ > 掘金主页 [LeoCoding](https://juejin.im/user/586fc337a22b9d0058807d53) # 二、目录 - + + +- [一、介绍](#一介绍) +- [二、目录](#二目录) +- [三、正文](#三正文) + - [1. ES6](#1-es6) + - [1.1 let 和 const命令](#11-let-和-const命令) + - [1.1.1 let 命令](#111-let-命令) + - [1.1.2 const 命令](#112-const-命令) + - [1.2 变量的解构赋值](#12-变量的解构赋值) + - [1.2.1 数组](#121-数组) + - [1.2.2 对象的解构赋值](#122-对象的解构赋值) + - [1.2.3 字符串的解构赋值](#123-字符串的解构赋值) + - [1.2.4 数值和布尔值的解构赋值](#124-数值和布尔值的解构赋值) + - [1.2.5 函数参数的解构赋值](#125-函数参数的解构赋值) + - [1.2.6 应用](#126-应用) + - [1.3 字符串的拓展](#13-字符串的拓展) + - [1.3.1 includes(),startsWith(),endsWith()](#131-includesstartswithendswith) + - [1.3.2 repeat()](#132-repeat) + - [1.3.3 padStart(),padEnd()](#133-padstartpadend) + - [1.3.4 模版字符串](#134-模版字符串) + - [1.4 正则的拓展](#14-正则的拓展) + - [1.4.1 介绍](#141-介绍) + - [1.4.2 字符串的正则方法](#142-字符串的正则方法) + - [1.4.3 u修饰符](#143-u修饰符) + - [1.4.4 y修饰符](#144-y修饰符) + - [1.4.5 flags属性](#145-flags属性) + - [1.5 数值的拓展](#15-数值的拓展) + - [1.5.1 Number.isFinite(), Number.isNaN()](#151-numberisfinite-numberisnan) + - [1.5.2 Number.parseInt(), Number.parseFloat()](#152-numberparseint-numberparsefloat) + - [1.5.3 Number.isInteger()](#153-numberisinteger) + - [1.5.4 Math对象的拓展](#154-math对象的拓展) + - [1.5.5 指数运算符](#155-指数运算符) + - [1.6 函数的拓展](#16-函数的拓展) + - [1.6.1 参数默认值](#161-参数默认值) + - [1.6.2 rest 参数](#162-rest-参数) + - [1.6.3 name 属性](#163-name-属性) + - [1.6.4 箭头函数](#164-箭头函数) + - [1.6.5 双冒号运算符](#165-双冒号运算符) + - [1.7 数组的拓展](#17-数组的拓展) + - [1.7.1 拓展运算符](#171-拓展运算符) + - [1.7.2 Array.from()](#172-arrayfrom) + - [1.7.3 Array.of()](#173-arrayof) + - [1.7.4 find()和findIndex()](#174-find和findindex) + - [1.7.5 fill()](#175-fill) + - [1.7.6 entries(),keys(),values()](#176-entrieskeysvalues) + - [1.7.7 includes()](#177-includes) + - [1.7.8 flat(),flatMap()](#178-flatflatmap) + - [1.8 对象的拓展](#18-对象的拓展) + - [1.8.1 属性的简洁表示](#181-属性的简洁表示) + - [1.8.2 属性名表达式](#182-属性名表达式) + - [1.8.3 Object.is()](#183-objectis) + - [1.8.4 Object.assign()](#184-objectassign) + - [1.9 Symbol](#19-symbol) + - [1.9.1 介绍](#191-介绍) + - [1.9.2 Symbol作为属性名](#192-symbol作为属性名) + - [1.9.3 应用:消除魔术字符串](#193-应用消除魔术字符串) + - [1.9.4 属性名遍历](#194-属性名遍历) + - [1.9.5 Symbol.for()、Symbol.keyFor()](#195-symbolforsymbolkeyfor) + - [1.9.6 内置的Symbol值](#196-内置的symbol值) + - [1.10 Set和Map数据结构](#110-set和map数据结构) + - [1.10.1 Set](#1101-set) + - [1.10.2 Set的应用](#1102-set的应用) + - [1.10.3 Map](#1103-map) + - [1.10.4 Map与其他数据结构互相转换](#1104-map与其他数据结构互相转换) + - [1.11 Proxy](#111-proxy) + - [1.11.1 基础使用](#1111-基础使用) + - [1.11.2 取消Proxy实例](#1112-取消proxy实例) + - [1.11.3 实现 Web服务的客户端](#1113-实现-web服务的客户端) + - [1.12 Promise对象](#112-promise对象) + - [1.12.1 概念](#1121-概念) + - [1.12.2 基本使用](#1122-基本使用) + - [1.12.3 Promise.prototype.then()](#1123-promiseprototypethen) + - [1.12.4 Promise.prototype.catch()](#1124-promiseprototypecatch) + - [1.12.5 Promise.prototype.finally()](#1125-promiseprototypefinally) + - [1.12.6 Promise.all()](#1126-promiseall) + - [1.12.7 Promise.race()](#1127-promiserace) + - [1.12.8 Promise.resolve()](#1128-promiseresolve) + - [1.12.9 Promise.reject()](#1129-promisereject) + - [1.13 Iterator和 for...of循环](#113-iterator和-forof循环) + - [1.13.1 Iterator遍历器概念](#1131-iterator遍历器概念) + - [1.13.2 Iterator遍历过程](#1132-iterator遍历过程) + - [1.13.3 默认Iterator接口](#1133-默认iterator接口) + - [1.13.4 Iterator使用场景](#1134-iterator使用场景) + - [1.13.5 for...of循环](#1135-forof循环) + - [1.13.6 跳出for...of](#1136-跳出forof) + - [1.14 Generator函数和应用](#114-generator函数和应用) + - [1.14.1 基本概念](#1141-基本概念) + - [1.14.2 yield表达式](#1142-yield表达式) + - [1.14.3 next方法](#1143-next方法) + - [1.14.4 for...of循环](#1144-forof循环) + - [1.14.5 Generator.prototype.throw()](#1145-generatorprototypethrow) + - [1.14.6 Generator.prototype.return()](#1146-generatorprototypereturn) + - [1.14.7 next()/throw()/return()共同点](#1147-nextthrowreturn共同点) + - [1.14.8 yield* 表达式](#1148-yield-表达式) + - [1.14.9 应用场景](#1149-应用场景) + - [1.15 Class语法和继承](#115-class语法和继承) + - [1.15.1 介绍](#1151-介绍) + - [1.15.2 constructor()方法](#1152-constructor方法) + - [1.15.3 类的实例对象](#1153-类的实例对象) + - [1.15.4 Class表达式](#1154-class表达式) + - [1.15.5 私有方法和私有属性](#1155-私有方法和私有属性) + - [1.15.6 this指向问题](#1156-this指向问题) + - [1.15.7 Class的getter和setter](#1157-class的getter和setter) + - [1.15.8 Class的generator方法](#1158-class的generator方法) + - [1.15.9 Class的静态方法](#1159-class的静态方法) + - [1.15.10 Class的静态属性和实例属性](#11510-class的静态属性和实例属性) + - [1.15.11 Class的继承](#11511-class的继承) + - [1.16 Module语法和加载实现](#116-module语法和加载实现) + - [1.16.1 介绍](#1161-介绍) + - [1.16.2 严格模式](#1162-严格模式) + - [1.16.3 export命令](#1163-export命令) + - [1.16.4 import命令](#1164-import命令) + - [1.16.5 模块的整体加载](#1165-模块的整体加载) + - [1.16.6 export default 命令](#1166-export-default-命令) + - [1.16.7 export 和 import 复合写法](#1167-export-和-import-复合写法) + - [1.16.8 浏览器中的加载规则](#1168-浏览器中的加载规则) + - [2. ES7](#2-es7) + - [2.1 Array.prototype.includes()方法](#21-arrayprototypeincludes方法) + - [2.2 指数操作符(**)](#22-指数操作符) + - [3. ES8](#3-es8) + - [3.1 async函数](#31-async函数) + - [3.1.1 介绍](#311-介绍) + - [3.1.2 基本用法](#312-基本用法) + - [3.1.3 返回Promise对象](#313-返回promise对象) + - [3.1.4 await命令](#314-await命令) + - [3.1.5 使用注意](#315-使用注意) + - [3.2 Promise.prototype.finally()](#32-promiseprototypefinally) + - [3.3 Object.values(),Object.entries()](#33-objectvaluesobjectentries) + - [3.3.1 Object.values()](#331-objectvalues) + - [3.3.2 Object.entries()](#332-objectentries) + - [3.4 Object.getOwnPropertyDescriptors()](#34-objectgetownpropertydescriptors) + - [3.5 字符串填充 padStart和padEnd](#35-字符串填充-padstart和padend) + - [3.6 函数参数列表与调用中的尾部逗号](#36-函数参数列表与调用中的尾部逗号) + - [3.7 共享内存与原子操作](#37-共享内存与原子操作) + - [4. ES9](#4-es9) + - [4.1 对象的拓展运算符](#41-对象的拓展运算符) + - [4.1.1 介绍](#411-介绍) + - [4.1.2 使用场景](#412-使用场景) + - [4.2 正则表达式 s 修饰符](#42-正则表达式-s-修饰符) + - [4.3 异步遍历器](#43-异步遍历器) + - [4.3.1 异步遍历的接口](#431-异步遍历的接口) + - [4.3.2 for await...of](#432-for-awaitof) + - [4.3.3 异步Generator函数](#433-异步generator函数) + - [4.3.4 yield* 语句](#434-yield-语句) + - [5. 知识补充](#5-知识补充) + - [5.1 块级作用域](#51-块级作用域) + - [5.2 ES5/6对数组空位的处理](#52-es56对数组空位的处理) +- [四、结语](#四结语) + - [参考文章](#参考文章) + - [推荐文章](#推荐文章) + + # 三、正文 ## 1. ES6 From 365e0057c9ccd5e5811214d157bd02844529be49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Fri, 30 Nov 2018 23:26:49 +0800 Subject: [PATCH 142/835] =?UTF-8?q?2018.11.30=20=E8=A1=A5=E5=85=85?= =?UTF-8?q?=E3=80=8ASymbol=E3=80=8B=E7=AB=A0=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 188 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 180 insertions(+), 8 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 686694ed..ee344d55 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -24,6 +24,7 @@ * 2018.11.8 更新**ES9**《**异步遍历器**》章节。 * 2018.11.9 更新**ES9**完毕,转战vuepress整理一套。 * 2018.11.29 修改《**Set和Map数据结构**》章节错误 书写,更新《Symbol》章节。 +* 2018.11.30 完成《Symbol》章节。 **未来规划**: * [x] 1.将内容按不同模块拆分不同文件,方便README文件的阅读。 @@ -1815,15 +1816,186 @@ b[Symbol.isConcatSpreadable] = false; // ['cc', 'dd',[ 'aa', 'bb'], 'ee'] ``` -* **3.Symbol.hasInstance** -* **4.Symbol.hasInstance** -* **5.Symbol.hasInstance** +* **3.Symbol.species** +指向一个构造函数,在创建衍生对象时会使用,使用时需要用`get`取值器。 +```js +class P extends Array { + static get [Symbol.species](){ + return this; + } +} +``` +解决下面问题: +```js +// 问题: b应该是 Array 的实例,实际上是 P 的实例 +class P extends Array{} + +let a = new P(1,2,3); +let b = a.map(x => x); + +b instanceof Array; // true +b instanceof P; // true + +// 解决: 通过使用 Symbol.species +class P extends Array { + static get [Symbol.species]() { return Array; } +} +let a = new P(); +let b = a.map(x => x); +b instanceof P; // false +b instanceof Array; // true +``` + +* **4.Symbol.match** +当执行`str.match(myObject)`,传入的属性存在时会调用,并返回该方法的返回值。 +```js +class P { + [Symbol.match](string){ + return 'hello world'.indexOf(string); + } +} +'h'.match(new P()); // 0 +``` + +* **5.Symbol.replace** +当该对象被`String.prototype.replace`方法调用时,会返回该方法的返回值。 +```js +let a = {}; +a[Symbol.replace] = (...s) => console.log(s); +'Hello'.replace(a , 'World') // ["Hello", "World"] +``` + * **6.Symbol.hasInstance** -* **7.Symbol.hasInstance** -* **8.Symbol.hasInstance** -* **9.Symbol.hasInstance** -* **10.Symbol.hasInstance** -* **11.Symbol.hasInstance** +当该对象被`String.prototype.search`方法调用时,会返回该方法的返回值。 +```js +class P { + constructor(val) { + this.val = val; + } + [Symbol.search](s){ + return s.indexOf(this.val); + } +} +'hileo'.search(new P('leo')); // 2 +``` + +* **7.Symbol.split** +当该对象被`String.prototype.split`方法调用时,会返回该方法的返回值。 +```js +// 重新定义了字符串对象的split方法的行为 +class P { + constructor(val) { + this.val = val; + } + [Symbol.split](s) { + let i = s.indexOf(this.val); + if(i == -1) return s; + return [ + s.substr(0, i), + s.substr(i + this.val.length) + ] + } +} + +'helloworld'.split(new P('hello')); // ["hello", ""] +'helloworld'.split(new P('world')); // ["", "world"] +'helloworld'.split(new P('leo')); // "helloworld" +``` + +* **8.Symbol.iterator** +对象进行`for...of`循环时,会调用`Symbol.iterator`方法,返回该对象的默认遍历器。 +```js +class P { + *[Symbol.interator]() { + let i = 0; + while(this[i] !== undefined ) { + yield this[i]; + ++i; + } + } +} +let a = new P(); +a[0] = 1; +a[1] = 2; + +for (let k of a){ + console.log(k); +} +``` + +* **9.Symbol.toPrimitive** +该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。调用时,需要接收一个字符串参数,表示当前运算模式,运算模式有: + * Number : 此时需要转换成数值 + * String : 此时需要转换成字符串 + * Default : 此时可以转换成数值或字符串 +```js +let obj = { + [Symbol.toPrimitive](hint) { + switch (hint) { + case 'number': + return 123; + case 'string': + return 'str'; + case 'default': + return 'default'; + default: + throw new Error(); + } + } +}; + +2 * obj // 246 +3 + obj // '3default' +obj == 'default' // true +String(obj) // 'str' +``` + +* **10.Symbol.toStringTag** +在该对象上面调用`Object.prototype.toString`方法时,如果这个属性存在,它的返回值会出现在`toString`方法返回的字符串之中,表示对象的类型。也就是说,这个属性可以用来定制`[object Object`]或`[object Array]`中`object`后面的那个字符串。 +```js +// 例一 +({[Symbol.toStringTag]: 'Foo'}.toString()) +// "[object Foo]" + +// 例二 +class Collection { + get [Symbol.toStringTag]() { + return 'xxx'; + } +} +let x = new Collection(); +Object.prototype.toString.call(x) // "[object xxx]" +``` + +* **11.Symbol.unscopables** +该对象指定了使用with关键字时,哪些属性会被with环境排除。 +```js +// 没有 unscopables 时 +class MyClass { + foo() { return 1; } +} + +var foo = function () { return 2; }; + +with (MyClass.prototype) { + foo(); // 1 +} + +// 有 unscopables 时 +class MyClass { + foo() { return 1; } + get [Symbol.unscopables]() { + return { foo: true }; + } +} + +var foo = function () { return 2; }; + +with (MyClass.prototype) { + foo(); // 2 +} +``` +上面代码通过指定`Symbol.unscopables`属性,使得`with`语法块不会在当前作用域寻找`foo`属性,即`foo`将指向外层作用域的变量。 [⬆ 返回目录](#二目录) From 08250ba9d58e2fc178f13e77053160470e316bd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sat, 1 Dec 2018 23:38:31 +0800 Subject: [PATCH 143/835] 2018.12.1 --- ...of\350\277\220\347\256\227\347\254\246.md" | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 "article/71-\345\244\215\344\271\240instanceof\350\277\220\347\256\227\347\254\246.md" diff --git "a/article/71-\345\244\215\344\271\240instanceof\350\277\220\347\256\227\347\254\246.md" "b/article/71-\345\244\215\344\271\240instanceof\350\277\220\347\256\227\347\254\246.md" new file mode 100644 index 00000000..28c506fa --- /dev/null +++ "b/article/71-\345\244\215\344\271\240instanceof\350\277\220\347\256\227\347\254\246.md" @@ -0,0 +1,142 @@ +最近开始在整理`ES6/ES7/ES8/ES9`的知识点(已经上传到 [我的博客](http://es.pingan8787.com) 上),碰到一些知识点是自己已经忘记(用得少的知识点),于是也重新复习了一遍。 +这篇文章要复习的 `instanceof` 是我在整理过程中遇到的,那就整理下来吧,不然容易忘记。 +要是哪里写得不妥,欢迎各位大佬指点。 + + +## 1.定义 +> `instanceof`运算符用于测试构造函数的`prototype`属性是否出现在对象的原型链中的任何位置。 —— MDN + +简单理解为:`instanceof`可以检测一个实例是否属于某种类型。 +比如: +```js +function F (){ + // ... +} +let a = new F (); + +a instanceof F; // true +a instanceof Object; // true 后面介绍原因 +``` +还可以在**继承关系**中用来判断一个实例是否属于它的父类型。 +比如: +```js +function F (){}; +function G (){}; +function Q (){}; +G.prototype = new F(); // 继承 + +let a = new G(); +a instanceof F; // true +a instanceof G; // true +a instanceof Q; // false +``` + +## 2.使用方法 +语法为: `object instanceof constructor`。 +* `object` : 需要测试的函数 +* `constructor` : 构造函数 + +即:用`instanceof`运算符来检测`constructor.prototype` 是否存在参数`object`的原型链。 +```js +function F (){}; +function G (){}; +let a = new F (); + +a instanceof F; // true 因为:Object.getPrototypeOf(a) === F.prototype +a instanceof Q; // false 因为:F.prototype不在a的原型链上 +a instanceof Object; // true 因为:Object.prototype.isPrototypeOf(a)返回true +F.prototype instanceof Object; // true,同上 +``` +**注意**: +1. `a instanceof F` 返回 `true` 以后,不一定永远都都返回为`true`,`F.prototype`属性的值有可能会改变。 +2. 原表达式`a`的值也会改变,比如 `a.__proto__ = {}`之后,`a instanceof F`就会返回`false`了。 + +**检测对象是不是特定构造函数的实例:** +```js +// 正确 +if (!(obj instanceof F)) { + // ... +} + +// 错误 因为 +if (!obj instanceof F); // 永远返回false +// 因为 !obj 在instanceof之前被处理 , 即一直使用一个布尔值检测是否是F的实例 +``` + +## 3.实现instanceof +```js +/** +* 实现instanceof +* @param obj{Object} 需要测试的对象 +* @param fun{Function} 构造函数 +*/ +function _instanceof(obj, fun) { + let f = fun.prototype; // 取B的显示原型 + obj = obj.__proto__; // 取A的隐式原型 + while (true) { + //Object.prototype.__proto__ === null + if (obj === null) + return false; + if (f === obj) // 这里重点:当 f 严格等于 obj 时,返回 true + return true; + obj = obj.__proto__; + } +} +``` + +## 4.instanceof 与 typeof 对比 +**相同**: +`instanceof`和`typeof`都能用来判断一个变量的类型。 + +**区别**: +`instanceof` 只能用来判断对象、函数和数组,不能用来判断字符串和数字等: +```js +let a = {}; +let b = function () {}; +let c = []; +let d = 'hi'; +let e = 123; + +a instanceof Object; // true +b instanceof Object; // true +c instanceof Array; // true +d instanceof String; // false +e instanceof Number; // false +``` + +`typeof` :用于判断一个表达式的原始值,返回一个字符串。 +```js +typeof 42; // "number" +typeof 'blubber'; // "string" +typeof true; // "boolean" +typeof aa; // "undefined" +``` +一般返回结果有: +* number +* boolean +* string +* function(函数) +* object(NULL,数组,对象) +* undefined。 + +**判断变量是否存在**: +不能使用: +```js +if(a){ + //变量存在 +} +// Uncaught ReferenceError: a is not defined +``` +原因是如果变量未定义,就会报**未定义**的错,而应该使用: +```js +if(typeof a != 'undefined'){ + //变量存在 +} +``` + +## 5.参考资料 +1. [MDN instanceof](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/instanceof) + +2. [IBM instanceof](https://www.ibm.com/developerworks/cn/web/1306_jiangjj_jsinstanceof/index.html) + +3. [js中typeof和instanceof用法区别](https://blog.csdn.net/qq_27626333/article/details/76146078) \ No newline at end of file From 56911d0b3191406215818859eb85befabc39df9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sun, 2 Dec 2018 00:07:52 +0800 Subject: [PATCH 144/835] 2018.12.2 --- EXEFE-es6book/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index ee344d55..14e63229 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -49,9 +49,10 @@ > 本文开源地址 [CuteECMAScript](https://github.com/pingan8787/Leo-JavaScript/tree/master/EXEFE-es6book) > 个人博客 [ping'anの博客](http://www.pingan8787.com) > Github地址 [pingan8787的github](https://github.com/pingan8787) -> 掘金主页 [LeoCoding](https://juejin.im/user/586fc337a22b9d0058807d53) +> 掘金主页 [pingan8787](https://juejin.im/user/586fc337a22b9d0058807d53) # 二、目录 + - [一、介绍](#一介绍) From a094e965baf8cec457970098be2e00f4e003b588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 3 Dec 2018 21:15:51 +0800 Subject: [PATCH 145/835] =?UTF-8?q?2018.12.03=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 14e63229..394a2778 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -2453,8 +2453,8 @@ p.then(()=>{ }) console.log(3); // 1 +// 3 // 2 -// 3 ``` **异步加载图片**: From fab1a4098d6f24e643efeb8b2125a48913e4b79f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Tue, 4 Dec 2018 21:57:48 +0800 Subject: [PATCH 146/835] =?UTF-8?q?2018.12.04=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 394a2778..1ebcd34a 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -53,6 +53,7 @@ # 二、目录 + - [一、介绍](#一介绍) @@ -510,9 +511,9 @@ console.log(name,age); // leo, 18 * **遍历Map结构**: ```js const m = new Map(); -m.set('a':1); -m.set('b':2); -for ([k, v] of m){ +m.set('a', 1); +m.set('b', 2); +for (let [k, v] of m){ console.log(k + ' : ' + v); } // 获取键名 @@ -600,7 +601,7 @@ a.includes('lo',6); // false * 省略第二个参数,则用`空格`补全。 ```js 'x'.padStart(4); // ' x' -'x'.endStart(4); // 'x ' +'x'.padEnd(4); // 'x ' ``` #### 1.3.4 模版字符串 用于拼接字符串,ES6之前: @@ -1407,13 +1408,13 @@ for (let i of ['a', 'b'].keys()){ // 0 // 1 -for (let e of ['a', 'b'].keys()){ +for (let e of ['a', 'b'].values()){ console.log(e) } // 'a' // 'b' -for (let e of ['a', 'b'].keys()){ +for (let e of ['a', 'b'].entries()){ console.log(e) } // 0 'a' From f925dcab1424b893684904e503d89a0e74fbc786 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Wed, 5 Dec 2018 00:33:49 +0800 Subject: [PATCH 147/835] 2018.12.05 --- ...30\351\230\266\345\207\275\346\225\260.md" | 206 ++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 "article/72-\343\200\220\351\207\215\346\270\251\345\237\272\347\241\200\343\200\221JS\344\270\255\347\232\204\351\253\230\351\230\266\345\207\275\346\225\260.md" diff --git "a/article/72-\343\200\220\351\207\215\346\270\251\345\237\272\347\241\200\343\200\221JS\344\270\255\347\232\204\351\253\230\351\230\266\345\207\275\346\225\260.md" "b/article/72-\343\200\220\351\207\215\346\270\251\345\237\272\347\241\200\343\200\221JS\344\270\255\347\232\204\351\253\230\351\230\266\345\207\275\346\225\260.md" new file mode 100644 index 00000000..85a5c9f9 --- /dev/null +++ "b/article/72-\343\200\220\351\207\215\346\270\251\345\237\272\347\241\200\343\200\221JS\344\270\255\347\232\204\351\253\230\351\230\266\345\207\275\346\225\260.md" @@ -0,0 +1,206 @@ +Ps. 晚上加班到快十点,回来赶紧整理整理这篇文章,今天老大给我推荐了一篇文章,[我从写技术博客中收获到了什么?- J_Knight_](https://juejin.im/post/5c02b2bce51d4533253f2f43),感受也是很多,自己也需要慢慢养成记录博客的习惯,即使起步艰难,难以坚持,但还是要让自己加油加油。 +前两天把我整理的[【复习资料】ES6/ES7/ES8/ES9资料整理(个人整理)](https://juejin.im/post/5c02b106f265da61764aa0c1)要分享给大家啦。 + +正文内容开始: + +# 1.介绍 +个人简单理解为,一个函数可以接收其他函数作为参数,这种函数便称为**高阶函数**,而主要目的就是为了能接收其他函数作为参数。 +> Q: 为什么可以接收一个函数作为参数? +> A: 因为函数可以接收变量作为参数,而变量可以声明一个方法。 + +**简单实例:** +```js +function a (x){ + return 'hi ' + x; +} +function f (a, b){ + return a(b); +} +f(a, 'leo'); // "hi leo" +``` +也可以直接调用JS内置方法: +```js +let a = 3, b = -2; +function my_abs (val, fun){ + return fun(val); +} +my_abs(a, Math.abs); // 3 +my_abs(b, Math.abs); // 2 +``` + +**这段代码的意思**:定义方法`f`,接收两个参数,方法`a`和变量`b`,在方法`a`中返回一段字符串,当执行方法`f`并传入参数方法`a`和参数`b`的时候,返回`"hi leo"`。 + +# 2.常用高阶函数 + +## 2.1 map() +`map()`方法的作用是:接收一个函数作为参数,对数组中每个元素按顺序调用一次传入的函数并返回结果,**不改变原数组,返回一个新数组**。 +通常使用方式:`arr.map(callback())`,更多详细介绍可以参考 [MDN Array.map()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/map)。 +**参数**: +* `arr` : 需要操作的数组; +* `callback(currentValue, index, array, thisArg)` : 处理的方法,四个参数; + * 1. `currentValue` 当前处理的元素的**值** + * 2. `index` 当前处理的元素的**索引**,可选 + * 3. `array` 调用`map()`方法的**数组**,可选 + * 4. `currentVthisArgalue` 执行 `callback` 函数时使用的 `this` 值,可选 + +**返回值**: +返回一个处理后的新数组。 + +**实例**: +```js +let arr = [1, 3, -5]; +let a1 = arr.map(Math.abs); +// a1 => [1, 3, 5]; + +let a2 = arr.map(String); +// a2 => ["1", "3", "-5"] + +let a3 = arr.map(function (x){ + return x + 1; +}) +// 等价于 a3=arr.map(x => x+1) +// a3 => [2, 4, -4] +``` +对比 `for...in` 循环,`map()`书写起来更加简洁: +```js +let arr = [1, 3, -5]; +let a1 = []; +for (var i=0; i [2, 4, -4] +``` +`map()`作为高阶函数,事实上它把运算规则抽象了。 + +## 2.2 reduce() +`reduce()`方法的作用是:接收一个函数,对数组进行累加操作,把累计结果和下一个值进行操作,最后返回最终的单个结果值。 + +通常使用方式:`arr.reduce(callback(), initValue)`,更多详细介绍可以参考 [MDN Array.reduce()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) + +**参数**: +* `callback(returnValue, currentValue, currentIndex, array)` : 累记器的方法,四个参数: + * 1. `returnValue` 上一次处理的返回值,或者初始值 + * 2. `currentValue` 当前处理的元素的**值**,可选 + * 3. `currentIndex` 当前处理的元素的**索引**,可选 + * 4. `array` 调用`reduce()`方法的**数组**,可选 +* `initValue` 初次调用`callback()`时候`returnValue`参数的初始值,默认数组第一个元素,可选 + +**返回值**: +返回一个最终的累计值。 + +**实例**: +1. 数组求和 +```js +let arr = [1, 3, -5]; +let sum1 = arr.reduce((res, cur) => res + cur); +// sum1 => -1 + +let sum2 = arr.reduce((res, cur) => res + cur , 1); +// sum1 => 0 +``` +2. 二维数组转化为一维 +```js +let arr = [[1, 2], [3, 4], [5, 6]]; +let con = arr.reduce((res, cur) => res.concat(cur)); +// con => [1, 2, 3, 4, 5, 6] +``` + +## 2.3 filter() +`filter()`方法的作用是:接收一个函数,依次作用数组每个元素,并过滤符合函数条件的元素,将剩下的数组作为一个新数组返回。 + +通常使用方式:`arr.filter(callback(), thisArg)`,更多详细介绍可以参考 [MDN Array.filter()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) + +**参数**: +* `callback(ele, index, array)` : 过滤条件的方法,当返回`true`则保存该元素,反之不保留,三个参数: + * 1. `ele` 当前处理的元素 + * 2. `index` 当前处理的元素的**索引**,可选 + * 3. `array` 调用`filter()`方法的**数组**,可选 +* `thisArg` 执行 `callback` 时的用于 `this` 的值,可选 + +**返回值**: +返回一个过滤剩下的元素组成的新数组。 + +**实例**: +1. 过滤奇数值 +```js +let arr = [1, 2, 3, 4, 5, 6]; +let res = arr.filter(x => x % 2 != 0); +// res => [1, 3, 5] +``` +2. 过滤不满足条件的值 +```js +let arr = [1, 2, 3, 4, 5, 6]; +let res = arr.filter(x => x > 3); +// res => [4, 5, 6] +``` +3. 过滤空字符串 +```js +let arr = ['a', '', null, undefined, 'b', '']; +let tri = arr.filter(x => x && x.trim()); +// tri => ["a", "b"] +``` +总结下: `filter()`主要作为**筛选功能**,因此核心就是正确实现一个“筛选”函数。 + +## 2.4 sort() +`sort()`方法的作用是:接收一个函数,对数组的元素进行排序,并返回排序后的新数组。**默认排序顺序是根据字符串Unicode码点**。 + +通常使用方式:`arr.sort(fun())`,更多详细介绍可以参考 [MDN Array.sort()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) +compareFunction 可选 +用来指定按某种顺序进行排列的函数。如果省略,元素按照转换为的字符串的各个字符的Unicode位点进行排序。 +**参数**: +* `fun(a, b)` : 指定按某种顺序进行排列的函数,若省略则按照转换为的字符串的各个字符的Unicode位点进行排序,两个可选参数: +`fun()` 返回 `a`和`b`两个值的大小的比较结果,`sort()`根据返回结果进行排序: +* 若 `fun(a, b)` 小于 0 ,则 `a` 排在 `b` 前面; +* 若 `fun(a, b)` 等于 0 ,则 `a` `b` 位置不变; +* 若 `fun(a, b)` 大于 0 ,则 `a` 排在 `b` 后面; + + +**返回值**: +返回排序后的新数组,并**修改原数组**。 + +**实例**: +1. 升序降序数组 +```js +let arr = [1,5,2,3]; +let sort1 = arr.sort(); +// 等同于 let sort1 = arr.sort((a, b) => a - b); +// sort1 => [1, 2, 3, 5] + +let sort2 = arr.sort((a, b) => b - a); +// sort2 => [5, 3, 2, 1] +``` +2. 字符串排序 +```js +let arr1 = ['AA', 'CC', 'BB']; +let sort1 = arr1.sort(); +// sort1 => ["AA", "BB", "CC"] + +let arr2 = ['AA', 'aa', 'BB']; +let sort2 = arr2.sort(); +// sort2 => ["AA", "BB", "aa"] + +let arr3 = ['AA', 'aa', 'BB']; +let sort3 = arr3.sort((a, b) => a.toLowerCase() > b.toLowerCase()); +// sort3 => ["AA", "aa", "BB"] +// 也可以写成: +let sort3 = arr3.sort((a, b) => { + let s1 = a.toLowerCase(); + let s2 = b.toLowerCase(); + return s1 > s2 ? 1 : s1 < s2 ? -1 : 0; +}) +``` +总结下: `sort()`主要作为**排序功能**,因此核心就是正确实现一个“排序”函数。 + +# 3. 参考文章 +* [阮一峰 JS高阶函数](https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/001434499355829ead974e550644e2ebd9fd8bb1b0dd721000) + +分享的内容比较简单,但是还是希望能帮助到需要的人哈。~~感谢 + + +|Author|王平安| +|---|---| +|E-mail|pingan8787@qq.com| +|博 客|www.pingan8787.com| +|微 信|pingan8787| +|每日文章推荐|https://github.com/pingan8787/Leo_Reading/issues| +|ES小册|es.pingan8787.com| From 5f3a3bafa30103a0a02de4606f4f053ed2a5464d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Wed, 5 Dec 2018 00:36:42 +0800 Subject: [PATCH 148/835] 2018.12.05 --- README.md | 2 ++ ...\232\204\351\253\230\351\230\266\345\207\275\346\225\260.md" | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 01965ae8..b9c16346 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,8 @@ * [68-创建对象的七种方式](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/68-%E5%88%9B%E5%BB%BA%E5%AF%B9%E8%B1%A1%E7%9A%84%E4%B8%83%E7%A7%8D%E6%96%B9%E5%BC%8F.md) * [69-秒懂this](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/69-秒懂this.md) * [70-JS复杂判断的更优雅写法](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/70-JS复杂判断的更优雅写法.md) +* [71-复习instanceof运算符](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/71-%E5%A4%8D%E4%B9%A0instanceof%E8%BF%90%E7%AE%97%E7%AC%A6.md) +* [70-JS复杂判断的更优雅写法](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/70-JS复杂判断的更优雅写法.md) ### 7、HTTP * [47-http请求头与响应头的应用](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/47-http%E8%AF%B7%E6%B1%82%E5%A4%B4%E4%B8%8E%E5%93%8D%E5%BA%94%E5%A4%B4%E7%9A%84%E5%BA%94%E7%94%A8.md) diff --git "a/article/72-\343\200\220\351\207\215\346\270\251\345\237\272\347\241\200\343\200\221JS\344\270\255\347\232\204\351\253\230\351\230\266\345\207\275\346\225\260.md" "b/article/72-\343\200\220\351\207\215\346\270\251\345\237\272\347\241\200\343\200\221JS\344\270\255\347\232\204\351\253\230\351\230\266\345\207\275\346\225\260.md" index 85a5c9f9..29d60679 100644 --- "a/article/72-\343\200\220\351\207\215\346\270\251\345\237\272\347\241\200\343\200\221JS\344\270\255\347\232\204\351\253\230\351\230\266\345\207\275\346\225\260.md" +++ "b/article/72-\343\200\220\351\207\215\346\270\251\345\237\272\347\241\200\343\200\221JS\344\270\255\347\232\204\351\253\230\351\230\266\345\207\275\346\225\260.md" @@ -25,7 +25,7 @@ function my_abs (val, fun){ return fun(val); } my_abs(a, Math.abs); // 3 -my_abs(b, Math.abs); // 2 +my_abs(b, Math.abs); // 2 ``` **这段代码的意思**:定义方法`f`,接收两个参数,方法`a`和变量`b`,在方法`a`中返回一段字符串,当执行方法`f`并传入参数方法`a`和参数`b`的时候,返回`"hi leo"`。 From c9003674d5552812a42b9da4695c0cd632e179c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Wed, 5 Dec 2018 00:37:38 +0800 Subject: [PATCH 149/835] 2018.12.05 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b9c16346..d23d4cd7 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ * [69-秒懂this](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/69-秒懂this.md) * [70-JS复杂判断的更优雅写法](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/70-JS复杂判断的更优雅写法.md) * [71-复习instanceof运算符](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/71-%E5%A4%8D%E4%B9%A0instanceof%E8%BF%90%E7%AE%97%E7%AC%A6.md) -* [70-JS复杂判断的更优雅写法](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/70-JS复杂判断的更优雅写法.md) +* [72-【重温基础】JS中的高阶函数](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/72-%E3%80%90%E9%87%8D%E6%B8%A9%E5%9F%BA%E7%A1%80%E3%80%91JS%E4%B8%AD%E7%9A%84%E9%AB%98%E9%98%B6%E5%87%BD%E6%95%B0.md) ### 7、HTTP * [47-http请求头与响应头的应用](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/47-http%E8%AF%B7%E6%B1%82%E5%A4%B4%E4%B8%8E%E5%93%8D%E5%BA%94%E5%A4%B4%E7%9A%84%E5%BA%94%E7%94%A8.md) From 7cbcbf02fc147212d2340651348c82bbe4c12e40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Wed, 5 Dec 2018 08:43:59 +0800 Subject: [PATCH 150/835] 2018.12.05 --- ...\204\351\253\230\351\230\266\345\207\275\346\225\260.md" | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git "a/article/72-\343\200\220\351\207\215\346\270\251\345\237\272\347\241\200\343\200\221JS\344\270\255\347\232\204\351\253\230\351\230\266\345\207\275\346\225\260.md" "b/article/72-\343\200\220\351\207\215\346\270\251\345\237\272\347\241\200\343\200\221JS\344\270\255\347\232\204\351\253\230\351\230\266\345\207\275\346\225\260.md" index 29d60679..561f355f 100644 --- "a/article/72-\343\200\220\351\207\215\346\270\251\345\237\272\347\241\200\343\200\221JS\344\270\255\347\232\204\351\253\230\351\230\266\345\207\275\346\225\260.md" +++ "b/article/72-\343\200\220\351\207\215\346\270\251\345\237\272\347\241\200\343\200\221JS\344\270\255\347\232\204\351\253\230\351\230\266\345\207\275\346\225\260.md" @@ -18,6 +18,8 @@ function f (a, b){ } f(a, 'leo'); // "hi leo" ``` +**这段代码的意思**:定义方法`f`,接收两个参数,方法`a`和变量`b`,在方法`a`中返回一段字符串,当执行方法`f`并传入参数方法`a`和参数`b`的时候,返回`"hi leo"`。 + 也可以直接调用JS内置方法: ```js let a = 3, b = -2; @@ -26,9 +28,7 @@ function my_abs (val, fun){ } my_abs(a, Math.abs); // 3 my_abs(b, Math.abs); // 2 -``` - -**这段代码的意思**:定义方法`f`,接收两个参数,方法`a`和变量`b`,在方法`a`中返回一段字符串,当执行方法`f`并传入参数方法`a`和参数`b`的时候,返回`"hi leo"`。 +``` # 2.常用高阶函数 From ce207668f508c890663533596fcb57f2d802a5b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sat, 8 Dec 2018 22:19:14 +0800 Subject: [PATCH 151/835] =?UTF-8?q?2018.12.08=20=E4=BF=AE=E8=AE=A2?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 1ebcd34a..9146e0ab 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -1273,7 +1273,7 @@ g(0, ...[1, 2], 3, ...[4]); // 0 1 2 3 4 ``` **若拓展运算符后面是个空数组,则不产生效果**。 ```js -[...[], 1]; // 1 +[...[], 1]; // [1] ``` **替代apply方法** @@ -1377,7 +1377,7 @@ Array(1,2,3); // [1,2,3] 多于2个参数,组成新数组 ``` 回调函数接收三个参数,当前值、当前位置和原数组。 ```js -[1,2,3,4,5].find((value, index, arr){ +[1,2,3,4,5].find((value, index, arr) => { // ... }); ``` @@ -1396,7 +1396,7 @@ new Array(3).fill('a'); // ['a','a','a'] ``` 并且`fill()`的第二个和第三个参数指定填充的**起始位置**和**结束位置**。 ```js -[1,2,3].fill('a',1,2); +[1,2,3].fill('a',1,2);// [1, "a", 3] ``` #### 1.7.6 entries(),keys(),values() @@ -1504,7 +1504,7 @@ let b = { } }; // b.a => undefined ; b.abc => 123 ; b.myfun() => 'hi' -// b[a] => 'hi leo' ; b['abc'] => 123 ; b['myfun'] => 'hi' +// b[a] => true ; b['abc'] => 123 ; b['myfun'] => ƒ ['my' + 'fun'] (){ return 'hi'; } ``` **注意**: 属性名表达式不能与简洁表示法同时使用,否则报错。 @@ -1596,12 +1596,12 @@ typeof a; // "symbol" ```js // 没有参数 let a1 = Symbol(); -let a2 = Symbal(); +let a2 = Symbol(); a1 === a2; // false // 有参数 let a1 = Symbol('abc'); -let a2 = Symbal('abc'); +let a2 = Symbol('abc'); a1 === a2; // false ``` * `Symbol`不能与其他类型的值计算,会报错。 From d24058ef0f1cb71ae18fdd768f996c7c61fd3f06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sat, 8 Dec 2018 22:27:35 +0800 Subject: [PATCH 152/835] =?UTF-8?q?2018.12.08=20=E4=BF=AE=E8=AE=A2?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXEFE-es6book/README.md | 164 ++-------------------------------------- 1 file changed, 6 insertions(+), 158 deletions(-) diff --git a/EXEFE-es6book/README.md b/EXEFE-es6book/README.md index 9146e0ab..244b4a11 100644 --- a/EXEFE-es6book/README.md +++ b/EXEFE-es6book/README.md @@ -54,159 +54,7 @@ # 二、目录 - - -- [一、介绍](#一介绍) -- [二、目录](#二目录) -- [三、正文](#三正文) - - [1. ES6](#1-es6) - - [1.1 let 和 const命令](#11-let-和-const命令) - - [1.1.1 let 命令](#111-let-命令) - - [1.1.2 const 命令](#112-const-命令) - - [1.2 变量的解构赋值](#12-变量的解构赋值) - - [1.2.1 数组](#121-数组) - - [1.2.2 对象的解构赋值](#122-对象的解构赋值) - - [1.2.3 字符串的解构赋值](#123-字符串的解构赋值) - - [1.2.4 数值和布尔值的解构赋值](#124-数值和布尔值的解构赋值) - - [1.2.5 函数参数的解构赋值](#125-函数参数的解构赋值) - - [1.2.6 应用](#126-应用) - - [1.3 字符串的拓展](#13-字符串的拓展) - - [1.3.1 includes(),startsWith(),endsWith()](#131-includesstartswithendswith) - - [1.3.2 repeat()](#132-repeat) - - [1.3.3 padStart(),padEnd()](#133-padstartpadend) - - [1.3.4 模版字符串](#134-模版字符串) - - [1.4 正则的拓展](#14-正则的拓展) - - [1.4.1 介绍](#141-介绍) - - [1.4.2 字符串的正则方法](#142-字符串的正则方法) - - [1.4.3 u修饰符](#143-u修饰符) - - [1.4.4 y修饰符](#144-y修饰符) - - [1.4.5 flags属性](#145-flags属性) - - [1.5 数值的拓展](#15-数值的拓展) - - [1.5.1 Number.isFinite(), Number.isNaN()](#151-numberisfinite-numberisnan) - - [1.5.2 Number.parseInt(), Number.parseFloat()](#152-numberparseint-numberparsefloat) - - [1.5.3 Number.isInteger()](#153-numberisinteger) - - [1.5.4 Math对象的拓展](#154-math对象的拓展) - - [1.5.5 指数运算符](#155-指数运算符) - - [1.6 函数的拓展](#16-函数的拓展) - - [1.6.1 参数默认值](#161-参数默认值) - - [1.6.2 rest 参数](#162-rest-参数) - - [1.6.3 name 属性](#163-name-属性) - - [1.6.4 箭头函数](#164-箭头函数) - - [1.6.5 双冒号运算符](#165-双冒号运算符) - - [1.7 数组的拓展](#17-数组的拓展) - - [1.7.1 拓展运算符](#171-拓展运算符) - - [1.7.2 Array.from()](#172-arrayfrom) - - [1.7.3 Array.of()](#173-arrayof) - - [1.7.4 find()和findIndex()](#174-find和findindex) - - [1.7.5 fill()](#175-fill) - - [1.7.6 entries(),keys(),values()](#176-entrieskeysvalues) - - [1.7.7 includes()](#177-includes) - - [1.7.8 flat(),flatMap()](#178-flatflatmap) - - [1.8 对象的拓展](#18-对象的拓展) - - [1.8.1 属性的简洁表示](#181-属性的简洁表示) - - [1.8.2 属性名表达式](#182-属性名表达式) - - [1.8.3 Object.is()](#183-objectis) - - [1.8.4 Object.assign()](#184-objectassign) - - [1.9 Symbol](#19-symbol) - - [1.9.1 介绍](#191-介绍) - - [1.9.2 Symbol作为属性名](#192-symbol作为属性名) - - [1.9.3 应用:消除魔术字符串](#193-应用消除魔术字符串) - - [1.9.4 属性名遍历](#194-属性名遍历) - - [1.9.5 Symbol.for()、Symbol.keyFor()](#195-symbolforsymbolkeyfor) - - [1.9.6 内置的Symbol值](#196-内置的symbol值) - - [1.10 Set和Map数据结构](#110-set和map数据结构) - - [1.10.1 Set](#1101-set) - - [1.10.2 Set的应用](#1102-set的应用) - - [1.10.3 Map](#1103-map) - - [1.10.4 Map与其他数据结构互相转换](#1104-map与其他数据结构互相转换) - - [1.11 Proxy](#111-proxy) - - [1.11.1 基础使用](#1111-基础使用) - - [1.11.2 取消Proxy实例](#1112-取消proxy实例) - - [1.11.3 实现 Web服务的客户端](#1113-实现-web服务的客户端) - - [1.12 Promise对象](#112-promise对象) - - [1.12.1 概念](#1121-概念) - - [1.12.2 基本使用](#1122-基本使用) - - [1.12.3 Promise.prototype.then()](#1123-promiseprototypethen) - - [1.12.4 Promise.prototype.catch()](#1124-promiseprototypecatch) - - [1.12.5 Promise.prototype.finally()](#1125-promiseprototypefinally) - - [1.12.6 Promise.all()](#1126-promiseall) - - [1.12.7 Promise.race()](#1127-promiserace) - - [1.12.8 Promise.resolve()](#1128-promiseresolve) - - [1.12.9 Promise.reject()](#1129-promisereject) - - [1.13 Iterator和 for...of循环](#113-iterator和-forof循环) - - [1.13.1 Iterator遍历器概念](#1131-iterator遍历器概念) - - [1.13.2 Iterator遍历过程](#1132-iterator遍历过程) - - [1.13.3 默认Iterator接口](#1133-默认iterator接口) - - [1.13.4 Iterator使用场景](#1134-iterator使用场景) - - [1.13.5 for...of循环](#1135-forof循环) - - [1.13.6 跳出for...of](#1136-跳出forof) - - [1.14 Generator函数和应用](#114-generator函数和应用) - - [1.14.1 基本概念](#1141-基本概念) - - [1.14.2 yield表达式](#1142-yield表达式) - - [1.14.3 next方法](#1143-next方法) - - [1.14.4 for...of循环](#1144-forof循环) - - [1.14.5 Generator.prototype.throw()](#1145-generatorprototypethrow) - - [1.14.6 Generator.prototype.return()](#1146-generatorprototypereturn) - - [1.14.7 next()/throw()/return()共同点](#1147-nextthrowreturn共同点) - - [1.14.8 yield* 表达式](#1148-yield-表达式) - - [1.14.9 应用场景](#1149-应用场景) - - [1.15 Class语法和继承](#115-class语法和继承) - - [1.15.1 介绍](#1151-介绍) - - [1.15.2 constructor()方法](#1152-constructor方法) - - [1.15.3 类的实例对象](#1153-类的实例对象) - - [1.15.4 Class表达式](#1154-class表达式) - - [1.15.5 私有方法和私有属性](#1155-私有方法和私有属性) - - [1.15.6 this指向问题](#1156-this指向问题) - - [1.15.7 Class的getter和setter](#1157-class的getter和setter) - - [1.15.8 Class的generator方法](#1158-class的generator方法) - - [1.15.9 Class的静态方法](#1159-class的静态方法) - - [1.15.10 Class的静态属性和实例属性](#11510-class的静态属性和实例属性) - - [1.15.11 Class的继承](#11511-class的继承) - - [1.16 Module语法和加载实现](#116-module语法和加载实现) - - [1.16.1 介绍](#1161-介绍) - - [1.16.2 严格模式](#1162-严格模式) - - [1.16.3 export命令](#1163-export命令) - - [1.16.4 import命令](#1164-import命令) - - [1.16.5 模块的整体加载](#1165-模块的整体加载) - - [1.16.6 export default 命令](#1166-export-default-命令) - - [1.16.7 export 和 import 复合写法](#1167-export-和-import-复合写法) - - [1.16.8 浏览器中的加载规则](#1168-浏览器中的加载规则) - - [2. ES7](#2-es7) - - [2.1 Array.prototype.includes()方法](#21-arrayprototypeincludes方法) - - [2.2 指数操作符(**)](#22-指数操作符) - - [3. ES8](#3-es8) - - [3.1 async函数](#31-async函数) - - [3.1.1 介绍](#311-介绍) - - [3.1.2 基本用法](#312-基本用法) - - [3.1.3 返回Promise对象](#313-返回promise对象) - - [3.1.4 await命令](#314-await命令) - - [3.1.5 使用注意](#315-使用注意) - - [3.2 Promise.prototype.finally()](#32-promiseprototypefinally) - - [3.3 Object.values(),Object.entries()](#33-objectvaluesobjectentries) - - [3.3.1 Object.values()](#331-objectvalues) - - [3.3.2 Object.entries()](#332-objectentries) - - [3.4 Object.getOwnPropertyDescriptors()](#34-objectgetownpropertydescriptors) - - [3.5 字符串填充 padStart和padEnd](#35-字符串填充-padstart和padend) - - [3.6 函数参数列表与调用中的尾部逗号](#36-函数参数列表与调用中的尾部逗号) - - [3.7 共享内存与原子操作](#37-共享内存与原子操作) - - [4. ES9](#4-es9) - - [4.1 对象的拓展运算符](#41-对象的拓展运算符) - - [4.1.1 介绍](#411-介绍) - - [4.1.2 使用场景](#412-使用场景) - - [4.2 正则表达式 s 修饰符](#42-正则表达式-s-修饰符) - - [4.3 异步遍历器](#43-异步遍历器) - - [4.3.1 异步遍历的接口](#431-异步遍历的接口) - - [4.3.2 for await...of](#432-for-awaitof) - - [4.3.3 异步Generator函数](#433-异步generator函数) - - [4.3.4 yield* 语句](#434-yield-语句) - - [5. 知识补充](#5-知识补充) - - [5.1 块级作用域](#51-块级作用域) - - [5.2 ES5/6对数组空位的处理](#52-es56对数组空位的处理) -- [四、结语](#四结语) - - [参考文章](#参考文章) - - [推荐文章](#推荐文章) - - +autoauto- [一、介绍](#一介绍)auto- [二、目录](#二目录)auto- [三、正文](#三正文)auto - [1. ES6](#1-es6)auto - [1.1 let 和 const命令](#11-let-和-const命令)auto - [1.1.1 let 命令](#111-let-命令)auto - [1.1.2 const 命令](#112-const-命令)auto - [1.2 变量的解构赋值](#12-变量的解构赋值)auto - [1.2.1 数组](#121-数组)auto - [1.2.2 对象的解构赋值](#122-对象的解构赋值)auto - [1.2.3 字符串的解构赋值](#123-字符串的解构赋值)auto - [1.2.4 数值和布尔值的解构赋值](#124-数值和布尔值的解构赋值)auto - [1.2.5 函数参数的解构赋值](#125-函数参数的解构赋值)auto - [1.2.6 应用](#126-应用)auto - [1.3 字符串的拓展](#13-字符串的拓展)auto - [1.3.1 includes(),startsWith(),endsWith()](#131-includesstartswithendswith)auto - [1.3.2 repeat()](#132-repeat)auto - [1.3.3 padStart(),padEnd()](#133-padstartpadend)auto - [1.3.4 模版字符串](#134-模版字符串)auto - [1.4 正则的拓展](#14-正则的拓展)auto - [1.4.1 介绍](#141-介绍)auto - [1.4.2 字符串的正则方法](#142-字符串的正则方法)auto - [1.4.3 u修饰符](#143-u修饰符)auto - [1.4.4 y修饰符](#144-y修饰符)auto - [1.4.5 flags属性](#145-flags属性)auto - [1.5 数值的拓展](#15-数值的拓展)auto - [1.5.1 Number.isFinite(), Number.isNaN()](#151-numberisfinite-numberisnan)auto - [1.5.2 Number.parseInt(), Number.parseFloat()](#152-numberparseint-numberparsefloat)auto - [1.5.3 Number.isInteger()](#153-numberisinteger)auto - [1.5.4 Math对象的拓展](#154-math对象的拓展)auto - [1.5.5 指数运算符](#155-指数运算符)auto - [1.6 函数的拓展](#16-函数的拓展)auto - [1.6.1 参数默认值](#161-参数默认值)auto - [1.6.2 rest 参数](#162-rest-参数)auto - [1.6.3 name 属性](#163-name-属性)auto - [1.6.4 箭头函数](#164-箭头函数)auto - [1.6.5 双冒号运算符](#165-双冒号运算符)auto - [1.7 数组的拓展](#17-数组的拓展)auto - [1.7.1 拓展运算符](#171-拓展运算符)auto - [1.7.2 Array.from()](#172-arrayfrom)auto - [1.7.3 Array.of()](#173-arrayof)auto - [1.7.4 find()和findIndex()](#174-find和findindex)auto - [1.7.5 fill()](#175-fill)auto - [1.7.6 entries(),keys(),values()](#176-entrieskeysvalues)auto - [1.7.7 includes()](#177-includes)auto - [1.7.8 flat(),flatMap()](#178-flatflatmap)auto - [1.8 对象的拓展](#18-对象的拓展)auto - [1.8.1 属性的简洁表示](#181-属性的简洁表示)auto - [1.8.2 属性名表达式](#182-属性名表达式)auto - [1.8.3 Object.is()](#183-objectis)auto - [1.8.4 Object.assign()](#184-objectassign)auto - [1.9 Symbol](#19-symbol)auto - [1.9.1 介绍](#191-介绍)auto - [1.9.2 Symbol作为属性名](#192-symbol作为属性名)auto - [1.9.3 应用:消除魔术字符串](#193-应用消除魔术字符串)auto - [1.9.4 属性名遍历](#194-属性名遍历)auto - [1.9.5 Symbol.for()、Symbol.keyFor()](#195-symbolforsymbolkeyfor)auto - [1.9.6 内置的Symbol值](#196-内置的symbol值)auto - [1.10 Set和Map数据结构](#110-set和map数据结构)auto - [1.10.1 Set](#1101-set)auto - [1.10.2 Set的应用](#1102-set的应用)auto - [1.10.3 Map](#1103-map)auto - [1.10.4 Map与其他数据结构互相转换](#1104-map与其他数据结构互相转换)auto - [1.11 Proxy](#111-proxy)auto - [1.11.1 基础使用](#1111-基础使用)auto - [1.11.2 取消Proxy实例](#1112-取消proxy实例)auto - [1.11.3 实现 Web服务的客户端](#1113-实现-web服务的客户端)auto - [1.12 Promise对象](#112-promise对象)auto - [1.12.1 概念](#1121-概念)auto - [1.12.2 基本使用](#1122-基本使用)auto - [1.12.3 Promise.prototype.then()](#1123-promiseprototypethen)auto - [1.12.4 Promise.prototype.catch()](#1124-promiseprototypecatch)auto - [1.12.5 Promise.prototype.finally()](#1125-promiseprototypefinally)auto - [1.12.6 Promise.all()](#1126-promiseall)auto - [1.12.7 Promise.race()](#1127-promiserace)auto - [1.12.8 Promise.resolve()](#1128-promiseresolve)auto - [1.12.9 Promise.reject()](#1129-promisereject)auto - [1.13 Iterator和 for...of循环](#113-iterator和-forof循环)auto - [1.13.1 Iterator遍历器概念](#1131-iterator遍历器概念)auto - [1.13.2 Iterator遍历过程](#1132-iterator遍历过程)auto - [1.13.3 默认Iterator接口](#1133-默认iterator接口)auto - [1.13.4 Iterator使用场景](#1134-iterator使用场景)auto - [1.13.5 for...of循环](#1135-forof循环)auto - [1.13.6 跳出for...of](#1136-跳出forof)auto - [1.14 Generator函数和应用](#114-generator函数和应用)auto - [1.14.1 基本概念](#1141-基本概念)auto - [1.14.2 yield表达式](#1142-yield表达式)auto - [1.14.3 next方法](#1143-next方法)auto - [1.14.4 for...of循环](#1144-forof循环)auto - [1.14.5 Generator.prototype.throw()](#1145-generatorprototypethrow)auto - [1.14.6 Generator.prototype.return()](#1146-generatorprototypereturn)auto - [1.14.7 next()/throw()/return()共同点](#1147-nextthrowreturn共同点)auto - [1.14.8 yield* 表达式](#1148-yield-表达式)auto - [1.14.9 应用场景](#1149-应用场景)auto - [1.15 Class语法和继承](#115-class语法和继承)auto - [1.15.1 介绍](#1151-介绍)auto - [1.15.2 constructor()方法](#1152-constructor方法)auto - [1.15.3 类的实例对象](#1153-类的实例对象)auto - [1.15.4 Class表达式](#1154-class表达式)auto - [1.15.5 私有方法和私有属性](#1155-私有方法和私有属性)auto - [1.15.6 this指向问题](#1156-this指向问题)auto - [1.15.7 Class的getter和setter](#1157-class的getter和setter)auto - [1.15.8 Class的generator方法](#1158-class的generator方法)auto - [1.15.9 Class的静态方法](#1159-class的静态方法)auto - [1.15.10 Class的静态属性和实例属性](#11510-class的静态属性和实例属性)auto - [1.15.11 Class的继承](#11511-class的继承)auto - [1.16 Module语法和加载实现](#116-module语法和加载实现)auto - [1.16.1 介绍](#1161-介绍)auto - [1.16.2 严格模式](#1162-严格模式)auto - [1.16.3 export命令](#1163-export命令)auto - [1.16.4 import命令](#1164-import命令)auto - [1.16.5 模块的整体加载](#1165-模块的整体加载)auto - [1.16.6 export default 命令](#1166-export-default-命令)auto - [1.16.7 export 和 import 复合写法](#1167-export-和-import-复合写法)auto - [1.16.8 浏览器中的加载规则](#1168-浏览器中的加载规则)auto - [2. ES7](#2-es7)auto - [2.1 Array.prototype.includes()方法](#21-arrayprototypeincludes方法)auto - [2.2 指数操作符(**)](#22-指数操作符)auto - [3. ES8](#3-es8)auto - [3.1 async函数](#31-async函数)auto - [3.1.1 介绍](#311-介绍)auto - [3.1.2 基本用法](#312-基本用法)auto - [3.1.3 返回Promise对象](#313-返回promise对象)auto - [3.1.4 await命令](#314-await命令)auto - [3.1.5 使用注意](#315-使用注意)auto - [3.2 Promise.prototype.finally()](#32-promiseprototypefinally)auto - [3.3 Object.values(),Object.entries()](#33-objectvaluesobjectentries)auto - [3.3.1 Object.values()](#331-objectvalues)auto - [3.3.2 Object.entries()](#332-objectentries)auto - [3.4 Object.getOwnPropertyDescriptors()](#34-objectgetownpropertydescriptors)auto - [3.5 字符串填充 padStart和padEnd](#35-字符串填充-padstart和padend)auto - [3.6 函数参数列表与调用中的尾部逗号](#36-函数参数列表与调用中的尾部逗号)auto - [3.7 共享内存与原子操作](#37-共享内存与原子操作)auto - [4. ES9](#4-es9)auto - [4.1 对象的拓展运算符](#41-对象的拓展运算符)auto - [4.1.1 介绍](#411-介绍)auto - [4.1.2 使用场景](#412-使用场景)auto - [4.2 正则表达式 s 修饰符](#42-正则表达式-s-修饰符)auto - [4.3 异步遍历器](#43-异步遍历器)auto - [4.3.1 异步遍历的接口](#431-异步遍历的接口)auto - [4.3.2 for await...of](#432-for-awaitof)auto - [4.3.3 异步Generator函数](#433-异步generator函数)auto - [4.3.4 yield* 语句](#434-yield-语句)auto - [5. 知识补充](#5-知识补充)auto - [5.1 块级作用域](#51-块级作用域)auto - [5.2 ES5/6对数组空位的处理](#52-es56对数组空位的处理)auto- [四、结语](#四结语)auto - [参考文章](#参考文章)auto - [推荐文章](#推荐文章)autoauto # 三、正文 ## 1. ES6 @@ -3820,7 +3668,7 @@ export default function(){console.log('leo')}; import leo from './a.js'; leo(); // 'leo' ``` -`export defualt`暴露有函数名的函数时,在调用时相当于匿名函数。 +`export default`暴露有函数名的函数时,在调用时相当于匿名函数。 ```js // a.js export default function f(){console.log('leo')}; @@ -3831,13 +3679,13 @@ export default f; // b.js import leo from './a.js'; ``` -`export defualt`其实是输出一个名字叫`default`的变量,所以后面不能跟变量赋值语句。 +`export default`其实是输出一个名字叫`default`的变量,所以后面不能跟变量赋值语句。 ```js // 正确 export let a= 1; let a = 1; -export defualt a; +export default a; // 错误 export default let a = 1; @@ -3908,8 +3756,8 @@ ES6中,可以在浏览器使用` +``` +另外,ES6模块也可以内嵌到网页,语法与外部加载脚本一致: +```html + +``` +**注意点**: +* 代码是在模块作用域之中运行,而不是在全局作用域运行。模块内部的顶层变量,外部不可见。 +* 模块脚本自动采用严格模式,不管有没有声明`use strict`。 +* 模块之中,可以使用`import`命令加载其他模块(`.js`后缀不可省略,需要提供`绝对 UR`L 或`相对 UR`L),也可以使用`export`命令输出对外接口。 +* 模块之中,顶层的`this`关键字返回`undefined`,而不是指向`window`。也就是说,在模块顶层使用`this`关键字,是无意义的。 +* 同一个模块如果加载多次,将只执行一次。 + +[⬆ 返回目录](#二目录) + + +## 2. ES7 +### 2.1 Array.prototype.includes()方法 +`includes()`用于查找一个值是否在数组中,如果在返回`true`,否则返回`false`。 +```js +['a', 'b', 'c'].includes('a'); // true +['a', 'b', 'c'].includes('d'); // false +``` +`includes()`方法接收两个参数,**搜索的内容**和**开始搜索的索引**,默认值为**0**,若搜索值在数组中则返回`true`否则返回`false`。 +```js +['a', 'b', 'c', 'd'].includes('b'); // true +['a', 'b', 'c', 'd'].includes('b', 1); // true +['a', 'b', 'c', 'd'].includes('b', 2); // false +``` +与`indexOf`方法对比,下面方法效果相同: +```js +['a', 'b', 'c', 'd'].indexOf('b') > -1; // true +['a', 'b', 'c', 'd'].includes('b'); // true +``` +**includes()与indexOf对比:** +* `includes`相比`indexOf`更具语义化,`includes`返回的是是否存在的具体结果,值为布尔值,而`indexOf`返回的是搜索值的下标。 +* `includes`相比`indexOf`更准确,`includes`认为两个`NaN`相等,而`indexOf`不会。 +```js +let a = [1, NaN, 3]; +a.indexOf(NaN); // -1 +a.includes(NaN); // true +``` +另外在判断`+0`与`-0`时,`includes`和`indexOf`的返回相同。 +```js +[1, +0, 3, 4].includes(-0); // true +[1, +0, 3, 4].indexOf(-0); // 1 +``` + +### 2.2 指数操作符(**) +基本用法: +```js +let a = 3 ** 2 ; // 9 +// 等效于 +Math.pow(3, 2); // 9 +``` +`**`是一个运算符,也可以满足类似假发的操作,如下: +```js +let a = 3; +a **= 2; // 9 +``` + +[⬆ 返回目录](#二目录) + + +## 3. ES8 +### 3.1 async函数 +#### 3.1.1 介绍 +ES8引入`async`函数,是为了使异步操作更加方便,其实它就是**Generator**函数的语法糖。 +`async`函数使用起来,只要把**Generator**函数的(*)号换成`async`,`yield`换成`await`即可。对比如下: +```js +// Generator写法 +const fs = require('fs'); +const readFile = function (fileName) { + return new Promise(function (resolve, reject) { + fs.readFile(fileName, function(error, data) { + if (error) return reject(error); + resolve(data); + }); + }); +}; +const gen = function* () { + const f1 = yield readFile('/etc/fstab'); + const f2 = yield readFile('/etc/shells'); + console.log(f1.toString()); + console.log(f2.toString()); +}; + +// async await写法 +const asyncReadFile = async function () { + const f1 = await readFile('/etc/fstab'); + const f2 = await readFile('/etc/shells'); + console.log(f1.toString()); + console.log(f2.toString()); +}; +``` +**对比Genenrator有四个优点:** +* (1)内置执行器 +Generator函数执行需要有执行器,而`async`函数自带执行器,即`async`函数与普通函数一模一样: +```js +async f(); +``` +* (2)更好的语义 +`async`和`await`,比起`星号`和`yield`,语义更清楚了。`async`表示函数里有异步操作,`await`表示紧跟在后面的表达式需要等待结果。 +* (3)更广的适用性 +`yield`命令后面只能是 Thunk 函数或 Promise 对象,而`async`函数的`await`命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)。 +* (4)返回值是Promise +`async`函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用`then`方法指定下一步的操作。 + +进一步说,`async`函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而`await`命令就是内部`then`命令的语法糖。 + +#### 3.1.2 基本用法 +`async`函数返回一个Promise对象,可以使用`then`方法添加回调函数,函数执行时,遇到`await`就会先返回,等到异步操作完成,在继续执行。 +```js +async function f(item){ + let a = await g(item); + let b = await h(item); + return b; +} +f('hello').then(res => { + console.log(res); +}) +``` +`async`表明该函数内部有异步操作,调用该函数时,会立即返回一个Promise对象。 +另外还有个定时的案例,指定时间后执行: +```js +function f (ms){ + return new Promise(res => { + setTimeout(res, ms); + }); +} +async function g(val, ms){ + await f(ms); + console.log(val); +} +g('leo', 50); +``` +`async`函数还有很多使用形式: +```js +// 函数声明 +async function f (){...} + +// 函数表达式 +let f = async function (){...} + +// 对象的方法 +let a = { + async f(){...} +} +a.f().then(...) + +// Class的方法 +class c { + constructor(){...} + async f(){...} +} + +// 箭头函数 +let f = async () => {...} +``` + +#### 3.1.3 返回Promise对象 +`async`内部`return`返回的值会作为`then`方法的参数,另外只有`async`函数内部的异步操作执行完,才会执行`then`方法指定的回调函数。 +```js +async function f(){ + return 'leo'; +} +f().then(res => { console.log (res) }); // 'leo' +``` +`async`内部抛出的错误,会被`catch`接收。 +```js +async function f(){ + throw new Error('err'); +} +f().then ( + v => console.log(v), + e => console.log(e) +) +// Error: err +``` + +#### 3.1.4 await命令 +通常`await`后面是一个Promise对象,如果不是就返回对应的值。 +```js +async function f(){ + return await 10; +} +f().then(v => console.log(v)); // 10 +``` +我们常常将`async await`和`try..catch`一起使用,并且可以放多个`await`命令,也是防止异步操作失败因为中断后续异步操作的情况。 +```js +async function f(){ + try{ + await Promise.reject('err'); + }catch(err){ ... } + return await Promise.resolve('leo'); +} +f().then(v => console.log(v)); // 'leo' +``` + +#### 3.1.5 使用注意 +* (1)`await`命令放在`try...catch`代码块中,防止Promise返回`rejected`。 +* (2)若多个`await`后面的异步操作不存在继发关系,最好让他们同时执行。 +```js +// 效率低 +let a = await f(); +let b = await g(); + +// 效率高 +let [a, b] = await Promise.all([f(), g()]); +// 或者 +let a = f(); +let b = g(); +let a1 = await a(); +let b1 = await b(); +``` +* (3)`await`命令只能用在`async`函数之中,如果用在普通函数,就会报错。 +```js +// 错误 +async function f(){ + let a = [{}, {}, {}]; + a.forEach(v =>{ // 报错,forEach是普通函数 + await post(v); + }); +} + +// 正确 +async function f(){ + let a = [{}, {}, {}]; + for(let k of a){ + await post(k); + } +} +``` + +[⬆ 返回目录](#二目录) + +### 3.2 Promise.prototype.finally() +`finally()`是ES8中**Promise**添加的一个新标准,用于指定不管**Promise**对象最后状态(是`fulfilled`还是`rejected`)如何,都会执行此操作,并且`finally`方法必须写在最后面,即在`then`和`catch`方法后面。 +```js +// 写法如下: +promise + .then(res => {...}) + .catch(err => {...}) + .finally(() => {...}) +``` +`finally`方法常用在处理**Promise**请求后关闭服务器连接: +```js +server.listen(port) + .then(() => {..}) + .finally(server.stop); +``` +**本质上,finally方法是then方法的特例:** +```js +promise.finally(() => {...}); + +// 等同于 +promise.then( + result => { + // ... + return result + }, + error => { + // ... + throw error + } +) +``` +[⬆ 返回目录](#二目录) + +### 3.3 Object.values(),Object.entries() +ES7中新增加的 `Object.values()`和`Object.entries()`与之前的`Object.keys()`类似,返回数组类型。 +回顾下`Object.keys()`: +```js +var a = { f1: 'hi', f2: 'leo'}; +Object.keys(a); // ['f1', 'f2'] +``` +#### 3.3.1 Object.values() +返回一个数组,成员是参数对象自身的(不含继承的)所有**可遍历属性**的键值。 +```js +let a = { f1: 'hi', f2: 'leo'}; +Object.values(a); // ['hi', 'leo'] +``` +如果参数不是对象,则返回空数组: +```js +Object.values(10); // [] +Object.values(true); // [] +``` + +#### 3.3.2 Object.entries() +返回一个数组,成员是参数对象自身的(不含继承的)所有**可遍历属性**的键值对数组。 +```js +let a = { f1: 'hi', f2: 'leo'}; +Object.entries(a); // [['f1','hi'], ['f2', 'leo']] +``` +* **用途1**: +遍历对象属性。 +```js +let a = { f1: 'hi', f2: 'leo'}; +for (let [k, v] of Object.entries(a)){ + console.log( + `${JSON.stringfy(k)}:${JSON.stringfy(v)}` + ) +} +// 'f1':'hi' +// 'f2':'leo' +``` +* **用途2**: +将对象转为真正的Map结构。 +```js +let a = { f1: 'hi', f2: 'leo'}; +let map = new Map(Object.entries(a)); +``` +手动实现`Object.entries()`方法: +```js +// Generator函数实现: +function* entries(obj){ + for (let k of Object.keys(obj)){ + yield [k ,obj[k]]; + } +} + +// 非Generator函数实现: +function entries (obj){ + let arr = []; + for(let k of Object.keys(obj)){ + arr.push([k, obj[k]]); + } + return arr; +} +``` + +[⬆ 返回目录](#二目录) + +### 3.4 Object.getOwnPropertyDescriptors() +之前有`Object.getOwnPropertyDescriptor`方法会返回某个对象属性的描述对象,新增的`Object.getOwnPropertyDescriptors()`方法,返回指定对象所有自身属性(非继承属性)的描述对象,所有原对象的属性名都是该对象的属性名,对应的属性值就是该属性的描述对象 +```js +let a = { + a1:1, + get f1(){ return 100} +} +Object.getOwnPropetyDescriptors(a); +/* +{ + a:{ configurable:true, enumerable:true, value:1, writeable:true} + f1:{ configurable:true, enumerable:true, get:f, set:undefined} +} +*/ +``` +实现原理: +```js +function getOwnPropertyDescriptors(obj) { + const result = {}; + for (let key of Reflect.ownKeys(obj)) { + result[key] = Object.getOwnPropertyDescriptor(obj, key); + } + return result; +} +``` +引入这个方法,主要是为了解决`Object.assign()`无法正确拷贝`get`属性和`set`属性的问题。 +```js +let a = { + set f(v){ + console.log(v) + } +} +let b = {}; +Object.assign(b, a); +Object.a(b, 'f'); +/* +f = { + configurable: true, + enumable: true, + value: undefined, + writeable: true +} +*/ +``` +`value`为`undefined`是因为`Object.assign`方法不会拷贝其中的`get`和`set`方法,使用`getOwnPropertyDescriptors`配合`Object.defineProperties`方法来实现正确的拷贝: +```js +let a = { + set f(v){ + console.log(v) + } +} +let b = {}; +Object.defineProperties(b, Object.getOwnPropertyDescriptors(a)); +Object.getOwnPropertyDescriptor(b, 'f') +/* + configurable: true, + enumable: true, + get: undefined, + set: function(){...} +*/ +``` +`Object.getOwnPropertyDescriptors`方法的配合`Object.create`方法,将对象属性克隆到一个新对象,实现浅拷贝。 +```js +const clone = Object.create(Object.getPrototypeOf(obj), + Object.getOwnPropertyDescriptors(obj)); + +// 或者 +const shallowClone = (obj) => Object.create( + Object.getPrototypeOf(obj), + Object.getOwnPropertyDescriptors(obj) +); +``` + +[⬆ 返回目录](#二目录) + +### 3.5 字符串填充 padStart和padEnd +用来为字符串填充特定字符串,并且都有两个参数:**字符串目标长度**和**填充字段**,第二个参数可选,默认空格。 +```js +'es8'.padStart(2); // 'es8' +'es8'.padStart(5); // ' es8' +'es8'.padStart(6, 'woof'); // 'wooes8' +'es8'.padStart(14, 'wow'); // 'wowwowwowwoes8' +'es8'.padStart(7, '0'); // '0000es8' + +'es8'.padEnd(2); // 'es8' +'es8'.padEnd(5); // 'es8 ' +'es8'.padEnd(6, 'woof'); // 'es8woo' +'es8'.padEnd(14, 'wow'); // 'es8wowwowwowwo' +'es8'.padEnd(7, '6'); // 'es86666' +``` +从上面结果来看,填充函数只有在字符长度小于目标长度时才有效,若字符长度已经等于或小于目标长度时,填充字符不会起作用,而且目标长度如果小于字符串本身长度时,字符串也不会做截断处理,只会原样输出。 + +### 3.6 函数参数列表与调用中的尾部逗号 +该特性允许我们在定义或者调用函数时添加尾部逗号而不报错: +```js +function es8(var1, var2, var3,) { + // ... +} +es8(10, 20, 30,); +``` + +### 3.7 共享内存与原子操作 +当内存被共享时,多个线程可以并发读、写内存中相同的数据。原子操作可以确保那些被读、写的值都是可预期的,即新的事务是在旧的事务结束之后启动的,旧的事务在结束之前并不会被中断。这部分主要介绍了 ES8 中新的构造函数 `SharedArrayBuffer` 以及拥有许多静态方法的命名空间对象 `Atomic` 。 +`Atomic` 对象类似于 `Math` 对象,拥有许多静态方法,所以我们不能把它当做构造函数。 `Atomic` 对象有如下常用的静态方法: + +* add /sub :为某个指定的value值在某个特定的位置增加或者减去某个值 +* and / or /xor :进行位操作 +* load :获取特定位置的值 + +[⬆ 返回目录](#二目录) + +## 4. ES9 +### 4.1 对象的拓展运算符 +#### 4.1.1 介绍 +对象的拓展运算符,即对象的Rest/Spread属性,可将对象解构赋值用于从一个对象取值,搜键值对分配到指定对象上,与数组的拓展运算符类似: +```js +let {x, y, ...z} = {x:1, y:2, a:3, b:4}; +x; // 1 +y; // 2 +z; // {a:3, b:4} +``` +对象的解构赋值要求等号右边必须是个对象,所以如果等号右边是`undefined`或`null`就会报错无法转成对象。 +```js +let {a, ...b} = null; // 运行时报错 +let {a, ...b} = undefined; // 运行时报错 +``` +解构赋值必须是最后一个参数,否则报错。 +```js +let {...a, b, c} = obj; // 语法错误 +let {a, ...b, c} = obj; // 语法错误 +``` +**注意**: +* 1.解构赋值是浅拷贝。 +```js +let a = {a1: {a2: 'leo'}}; +let {...b} = a; +a.a1.a2 = 'leo'; +b.a1.a2 = 'leo'; +``` +* 2.拓展运算符的解构赋值,不能复制继承自原型对象的属性。 +```js +let o1 = { a: 1 }; +let o2 = { b: 2 }; +o2.__proto__ = o1; +let { ...o3 } = o2; +o3; // { b: 2 } +o3.a; // undefined +``` + +#### 4.1.2 使用场景 +* 1.取出参数对象所有可遍历属性,拷贝到当前对象中。 +```js +let a = { a1:1, a2:2 }; +let b = { ...a }; +b; // { a1:1, a2:2 } + +// 类似Object.assign方法 +``` +* 2.合并两个对象。 +```js +let a = { a1:1, a2:2 }; +let b = { b1:11, b2:22 }; +let ab = { ...a, ...b }; // {a1: 1, a2: 2, b1: 11, b2: 22} +// 等同于 +let ab = Object.assign({}, a, b); +``` +* 3.将自定义属性放在拓展运算符后面,覆盖对象原有的同名属性。 +```js +let a = { a1:1, a2:2, a3:3 }; +let r = { ...a, a3:666 }; +// r {a1: 1, a2: 2, a3: 666} + +// 等同于 +let r = { ...a, ...{ a3:666 }}; +// r {a1: 1, a2: 2, a3: 666} + +// 等同于 +let r = Object.assign({}, a, { a3:666 }); +// r {a1: 1, a2: 2, a3: 666} +``` +* 4.将自定义属性放在拓展运算符前面,就会成为设置新对象的默认值。 +```js +let a = { a1:1, a2:2 }; +let r = { a3:666, ...a }; +// r {a3: 666, a1: 1, a2: 2} + +// 等同于 +let r = Object.assign({}, {a3:666}, a); +// r {a3: 666, a1: 1, a2: 2} + +// 等同于 +let r = Object.assign({a3:666}, a); +// r {a3: 666, a1: 1, a2: 2} +``` +* 5.拓展运算符后面可以使用表达式。 +```js +let a = { + ...(x>1? {a:!:{}), + b:2 +} +``` +* 6.拓展运算符后面如果是个空对象,则没有任何效果。 +```js +{...{}, a:1}; // {a:1} +``` +* 7.若参数是`null`或`undefined`则忽略且不报错。 +```js +let a = { ...null, ...undefined }; // 不报错 +``` +* 8.若有取值函数`get`则会执行。 +```js +// 不会打印 因为f属性只是定义 而不没执行 +let a = { + ...a1, + get f(){console.log(1)} +} + +// 会打印 因为f执行了 +let a = { + ...a1, + ...{ + get f(){console.log(1)} + } +} +``` + +[⬆ 返回目录](#二目录) + + +### 4.2 正则表达式 s 修饰符 +在正则表达式中,点(`.`)可以表示任意单个字符,除了两个:用`u`修饰符解决**四个字节的UTF-16字符**,另一个是行终止符。 +**终止符**即表示一行的结束,如下四个字符属于“行终止符”: +* U+000A 换行符(\n) +* U+000D 回车符(\r) +* U+2028 行分隔符(line separator) +* U+2029 段分隔符(paragraph separator) +```js +/foo.bar/.test('foo\nbar') +// false +``` +上面代码中,因为`.`不匹配`\n`,所以正则表达式返回`false`。 +换个醒,可以匹配任意单个字符: +```js +/foo[^]bar/.test('foo\nbar') +// true +``` +ES9引入`s`修饰符,使得`.`可以匹配任意单个字符: +```js +/foo.bar/s.test('foo\nbar') // true +``` +这被称为`dotAll`模式,即点(`dot`)代表一切字符。所以,正则表达式还引入了一个`dotAll`属性,返回一个布尔值,表示该正则表达式是否处在`dotAll`模式。 +```js +const re = /foo.bar/s; +// 另一种写法 +// const re = new RegExp('foo.bar', 's'); + +re.test('foo\nbar') // true +re.dotAll // true +re.flags // 's' +``` +`/s`修饰符和多行修饰符`/m`不冲突,两者一起使用的情况下,`.`匹配所有字符,而`^`和`$`匹配每一行的行首和行尾。 + +[⬆ 返回目录](#二目录) + + +### 4.3 异步遍历器 +在前面ES6章节中,介绍了Iterator接口,而ES6引入了“异步遍历器”,是为异步操作提供原生的遍历器接口,即`value`和`done`这两个属性都是异步产生的。 + +#### 4.3.1 异步遍历的接口 +通过调用遍历器的`next`方法,返回一个Promise对象。 +```js +a.next().then( + ({value, done}) => { + //... + } +) +``` +上述`a`为异步遍历器,调用`next`后返回一个Promise对象,再调用`then`方法就可以指定Promise对象状态变为`resolve`后执行的回调函数,参数为`value`和`done`两个属性的对象,与同步遍历器一致。 +与同步遍历器一样,异步遍历器接口也是部署在`Symbol.asyncIterator`属性上,只要有这个属性,就都可以异步遍历。 +```js +let a = createAsyncIterable(['a', 'b']); +//createAsyncIterable方法用于构建一个iterator接口 +let b = a[Symbol.asyncInterator](); + +b.next().then( result1 => { + console.log(result1); // {value: 'a', done:false} + return b.next(); +}).then( result2 => { + console.log(result2); // {value: 'b', done:false} + return b.next(); +}).then( result3 => { + console.log(result3); // {value: undefined, done:true} +}) +``` +另外`next`方法返回的是一个Promise对象,所以可以放在`await`命令后。 +```js +async function f(){ + let a = createAsyncIterable(['a', 'b']); + let b = a[Symbol.asyncInterator](); + console.log(await b.next());// {value: 'a', done:false} + console.log(await b.next());// {value: 'b', done:false} + console.log(await b.next());// {value: undefined, done:true} +} +``` +还有一种情况,使用`Promise.all`方法,将所有的`next`按顺序连续调用: +```js +let a = createAsyncIterable(['a', 'b']); +let b = a[Symbol.asyncInterator](); +let {{value:v1}, {value:v2}} = await Promise.all([ + b.next(), b.next() +]) +``` +也可以一次调用所有`next`方法,再用`await`最后一步操作。 +```js +async function f(){ + let write = openFile('aaa.txt'); + write.next('hi'); + write.next('leo'); + await write.return(); +} +f(); +``` +#### 4.3.2 for await...of +`for...of`用于遍历同步的Iterator接口,而ES8引入`for await...of`遍历异步的Iterator接口。 +```js +async function f(){ + for await(let a of createAsyncIterable(['a', 'b'])) { + console.log(x); + } +} +// a +// b +``` +上面代码,`createAsyncIterable()`返回一个拥有异步遍历器接口的对象,`for...of`自动调用这个对象的`next`方法,得到一个Promise对象,`await`用来处理这个Promise,一但`resolve`就把得到的值`x`传到`for...of`里面。 +**用途** +直接把部署了asyncIteable操作的异步接口放入这个循环。 +```js +let a = ''; +async function f(){ + for await (let b of req) { + a += b; + } + let c = JSON.parse(a); + console.log('leo', c); +} +``` +当`next`返回的Promise对象被`reject`,`for await...of`就会保错,用`try...catch`捕获。 +```js +async function f(){ + try{ + for await (let a of iterableObj()){ + console.log(a); + } + }catch(e){ + console.error(e); + } +} +``` +注意,`for await...of`循环也可以用于同步遍历器。 +```js +(async function () { + for await (let a of ['a', 'b']) { + console.log(a); + } +})(); +// a +// b +``` +#### 4.3.3 异步Generator函数 +就像 Generator 函数返回一个同步遍历器对象一样,异步 Generator 函数的作用,是返回一个异步遍历器对象。 +在语法上,异步 Generator 函数就是`async`函数与 Generator 函数的结合。 +```js +async function* f() { + yield 'hi'; +} +const a = f(); +a.next().then(x => console.log(x)); +// { value: 'hello', done: false } +``` +设计异步遍历器的目的之一,就是为了让Generator函数能用同一套接口处理同步和异步操作。 +```js +// 同步Generator函数 +function * f(iterable, fun){ + let a = iterabl[Symbol.iterator](); + while(true){ + let {val, done} = a.next(); + if(done) break; + yield fun(val); + } +} + +// 异步Generator函数 +async function * f(iterable, fun){ + let a = iterabl[Symbol.iterator](); + while(true){ + let {val, done} = await a.next(); + if(done) break; + yield fun(val); + } +} +``` +同步和异步Generator函数相同点:在`yield`时用`next`方法停下,将后面表达式的值作为`next()`返回对象的`value`。 +在异步Generator函数中,同时使用`await`和`yield`,简单样理解,`await`命令用于将外部操作产生的值输入函数内部,`yield`命令用于将函数内部的值输出。 +```js +(async function () { + for await (const line of readLines(filePath)) { + console.log(line); + } +})() +``` +异步 Generator 函数可以与`for await...of`循环结合起来使用。 +```js +async function* f(asyncIterable) { + for await (const line of asyncIterable) { + yield '> ' + line; + } +} +``` + +#### 4.3.4 yield* 语句 +`yield*`语句跟一个异步遍历器。 +```js +async function * f(){ + yield 'a'; + yield 'b'; + return 'leo'; +} +async function * g(){ + const a = yield* f(); // a => 'leo' +} +``` +与同步 Generator 函数一样,`for await...of`循环会展开`yield*`。 +```js +(async function () { + for await (const x of gen2()) { + console.log(x); + } +})(); +// a +// b +``` + +[⬆ 返回目录](#二目录) + +## 5. 知识补充 +### 5.1 块级作用域 + +通常指一个**函数内部**,或者一个**代码块内部**。 +比如: +```js +function fun1 () { + // 块级作用域 + if (true) { + // 块级作用域 + } +} +``` +**缺点**: +1.导致内层变量覆盖外层变量 +```js +var a1 = new Date(); +function f1 (){ + console.log(a1); // undefined + if (false) { + var a1 = 'hello' + } +} +``` +输出 `undefined` 是因为 `if` 内的 `a1` 变量声明的变量提升,导致内部的 `a1` 覆盖外部的 `a1`,所以输出为 `undefined` 。 + +2.变量的全局污染 +```js +var a = 'hello'; +for (var i = 0; i< a.length; i++) { + //... +} +console.log(i); // 5 +``` +循环结束后,变量 `i` 的值依然存在,造成变量的全局污染。 + + +[⬆ 返回目录](#二目录) + + +### 5.2 ES5/6对数组空位的处理 + +数组的空位不是`undefined`,而是没有任何值,数组的`undefined`也是有值。 +```js +0 in [undefined,undefined,undefined] // true +0 in [,,,] // false +``` +**ES5对空位的处理**: +* `forEach()`, `filter()`, `reduce()`, `every()` 和`some()`都会跳过空位。 +* `map()`会跳过空位,但会保留这个值。 +* `join()`和`toString()`会将空位视为`undefined`,而`undefined`和`null`会被处理成空字符串。 +```js +[,'a'].forEach((x,i) => console.log(i)); // 1 +['a',,'b'].filter(x => true); // ['a','b'] +[,'a'].every(x => x==='a'); // true +[1,,2].reduce((x,y) => x+y); // 3 +[,'a'].some(x => x !== 'a'); // false +[,'a'].map(x => 1); // [,1] +[,'a',undefined,null].join('#'); // "#a##" +[,'a',undefined,null].toString(); // ",a,," +``` +**ES6对空位的处理**: +将空位视为正常值,转成`undefined`。 +```js +Array.from(['a',,'b']);// [ "a", undefined, "b" ] +[...['a',,'b']]; // [ "a", undefined, "b" ] + +//copyWithin() 会连空位一起拷贝。 +[,'a','b',,].copyWithin(2,0) // [,"a",,"a"] + +//fill()会将空位视为正常的数组位置。 +new Array(3).fill('a') // ["a","a","a"] + +//for...of循环也会遍历空位。 +let arr = [, ,]; +for (let i of arr) { + console.log(1); +} // 1 1 +``` +`entries()`、`keys()`、`values()`、`find()`和`findIndex()`会将空位处理成`undefined`。 +```js +[...[,'a'].entries()] // [[0,undefined], [1,"a"]] + +[...[,'a'].keys()] // [0,1] + +[...[,'a'].values()] // [undefined,"a"] + +[,'a'].find(x => true) // undefined + +[,'a'].findIndex(x => true) // 0 +``` +**由于空位的处理规则非常不统一,所以建议避免出现空位。** + + +# 四、结语 + +[回到顶部](#一介绍) + +### 参考文章 +* [ECMAScript 6 入门](http://es6.ruanyifeng.com/) +* [ES8 新特性一览](https://github.com/xitu/gold-miner/blob/master/TODO/es8-was-released-and-here-are-its-main-new-features.md) +* [ECMAScript 2017(ES8)特性概述](https://zhuanlan.zhihu.com/p/27844393) +* [ECMAScript 2018(ES2018)有哪些新功能?](https://www.imooc.com/article/44423) + +### 推荐文章 +* [ECMAScript 2018 标准导读](https://zhuanlan.zhihu.com/p/27537439) \ No newline at end of file diff --git a/Cute-JavaScript/Cute-JS/README.md b/Cute-JavaScript/Cute-JS/README.md new file mode 100644 index 00000000..ebb3f19d --- /dev/null +++ b/Cute-JavaScript/Cute-JS/README.md @@ -0,0 +1,46 @@ +最近开始把精力放在重新复习JavaScript的基础知识上面,不再太追求各种花枝招展的前端框架,框架再多,适合实际项目才是最重要。 + + +上星期在掘金发布了几篇文章,其中最大块算是 [【复习资料】ES6/ES7/ES8/ES9资料整理(个人整理)](https://juejin.im/post/5c02b106f265da61764aa0c1),也是让我好好把这些规范复习了一遍,虽然不是完全的原创,而是自己的一些复习笔记,但是还是让我感觉还是挺有用的,在项目开发过程中,有有意识的去使用到这些新的规范。 + + +这次开始复习 [MDN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide) 这个系列的文章,巩固好自己的基础,也让自己养成记录学习的习惯,当然这些文章我也会同步到自己的博客。 + +# 本文目录 +## JavaScript初级 +1. [语法和数据类型](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/1.%E8%AF%AD%E6%B3%95%E5%92%8C%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B.md) +2. [流程控制和错误处理](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/2.%E6%B5%81%E7%A8%8B%E6%8E%A7%E5%88%B6%E5%92%8C%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86.md) +3. [循环和迭代](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/3.%E5%BE%AA%E7%8E%AF%E5%92%8C%E8%BF%AD%E4%BB%A3.md) +4. [函数](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/4.%E5%87%BD%E6%95%B0.md) +5. [表达式和运算符](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/5.%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%92%8C%E8%BF%90%E7%AE%97%E7%AC%A6.md) +6. [数字](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/6.数字.md) +7. [时间对象](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/7.时间对象.md) +8. [字符串](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/8.字符串.md) +9. [正则表达式](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/9.正则表达式.md) +10. [数组](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/10.数组.md) +11. [Map和Set对象](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/11.Map和Set对象.md) +12. [使用对象](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/12.使用对象.md) +13. [迭代器和生成器](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/13.迭代器和生成器.md) +14. [元编程](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/14.元编程.md) + +## JavaScript中级 +待补充 + +## JavaScript高级 +待补充 + +## 其他细节知识 +1. [JS中的高阶函数](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/other/1-JS中的高阶函数.md) +2. [instanceof运算符](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/other/2-instanceof运算符.md) + + +希望自己的文章会对各位有所帮助,也欢迎各位大佬指点。 + + +|Author|王平安| +|---|---| +|E-mail|pingan8787@qq.com| +|博 客|www.pingan8787.com| +|微 信|pingan8787| +|每日文章推荐|https://github.com/pingan8787/Leo_Reading/issues| +|ES小册|js.pingan8787.com| \ No newline at end of file diff --git "a/Cute-JavaScript/Cute-JS/level1/1.\350\257\255\346\263\225\345\222\214\346\225\260\346\215\256\347\261\273\345\236\213.md" "b/Cute-JavaScript/Cute-JS/level1/1.\350\257\255\346\263\225\345\222\214\346\225\260\346\215\256\347\261\273\345\236\213.md" new file mode 100644 index 00000000..70b85c6b --- /dev/null +++ "b/Cute-JavaScript/Cute-JS/level1/1.\350\257\255\346\263\225\345\222\214\346\225\260\346\215\256\347\261\273\345\236\213.md" @@ -0,0 +1,330 @@ +最近开始把精力放在重新复习JavaScript的基础知识上面,不再太追求各种花枝招展的前端框架,框架再多,适合实际项目才是最重要。 +上星期在掘金发布了几篇文章,其中最大块算是 [【复习资料】ES6/ES7/ES8/ES9资料整理(个人整理)](https://juejin.im/post/5c02b106f265da61764aa0c1),也是让我好好把这些规范复习了一遍,虽然不是完全的原创,而是自己的一些复习笔记,但是还是让我感觉还是挺有用的,在项目开发过程中,有有意识的去使用到这些新的规范。 +这次开始复习 [MDN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide) 这个系列的文章,巩固好自己的基础,也让自己养成记录学习的习惯,当然这些文章我也会同步到自己的博客。 +希望自己的文章会对各位有所帮助,也欢迎各位大佬指点。 + + +---- +正文开始 + +**本章节复习的是JS中的基本语法,变量声明,数据类型和字面量。** + +首先要记住:JavaScript 对大小写敏感,即`var att;` 和 `var Att` 是两个不同变量。 + +# 1.注释 +```js +// 单行注释 +/* + 多行注释 +*/ +``` + +# 2. 声明 +JavaScript有三种声明方式: +* `var` 声明一个变量,可赋一个初始值。 +* `let` 声明一个块作用域的局部变量,可赋一个初始值。 +* `const` 声明一个块作用域的只读命名的常量。 + +## 声明变量 +变量的名字又叫做“**标识符**”,必须以字母、下划线(`_`)或者美元符号(`$`)开头,并且区分大小写。 +变量声明有三种方式: +* 如`var a = 1`,声明局部变量和全局变量。 +* 如`a = 1`,声明一个全局变量,且在严格模式报错,不应该使用。 +* 如`let a = 1`,声明一个块作用域的局部变量。 + +**注意**: +* 若没有为变量赋初始值,则值默认为`undefined`; +```js +let a; +console.log(a); // undefined +``` +* 若没有声明变量而直接使用,会抛出`ReferenceError`错误; +```js +console.log(b); // Uncaught ReferenceError: b is not defined +``` +* 当变量值为`undefined`时,布尔值环境会当做`false`,数值环境会当做`NaN`; +```js +var a; +if(!a){ + console.log('a为undefined'); // a为undefined +} +a + 1; // NaN +``` +* 当变量值为`null`时,布尔值环境会当做`false`,数值环境会当做`0`; +```js +let a = null; +if(!a){ + console.log('a为unll'); // a为unll +} +a + 1; // 1 +``` + +## 变量作用域 +**全局变量**:即声明在函数之外,当前文档所有地方都可以访问; +**局部遍历**:即声明在函数内部,仅在当前函数内可以访问; +在ES5之前没有语句**块作用域**的概念,并只能使用`var`进行声明,用`var`声明的变量,在函数内和全局都可以访问,而在ES6开始,将只能在声明的作用域中使用: +```js +if(true){ + var a = 1; +} +a; // 1 + +if(true){ + let b = 2; +} +b; // ReferenceError: b is not defined +``` + +## 变量声明提前 +即将变量的声明提升到函数或语句的顶部,并返回`undefined`直到变量被初始化操作。 +**千万注意**: +ES5以及之前,才有变量声明提前,在ES6开始就不存在变量提升。 +```js +// ES5及之前 +console.log(a); // undefined +var a = 1; +console.log(a); // 1 + +// ES6开始 +console.log(b); // Uncaught ReferenceError: b1 is not defined +let b = 2; +console.log(b); // 2 +``` + +## 函数提升 +函数声明有两种方式:**函数声明**和**函数表达式**两种方式: +```js +// 函数声明 +f(); // 'hi leo' +function(){ + console.log('hi leo'); +}; + +// 函数表达式 +g(); // Uncaught TypeError: g is not a function +var g = function(){ // 换成 let 声明也一样 + console.log('hi leo'); +} +``` + +## 全局变量 +全局变量默认是全局对象(`window`)的属性,常常使用`window.variable`语法来设置和访问全局变量。 +这边还需要记住: +* **ES5之中**,顶层对象的属性等价于全局变量(浏览器环境中顶层对象是`window`,Node中是`global`对象); +* **ES6之中**,`var`/`function`声明的全局变量,依然是顶层对象的属性,但是`let`/`const`/`class`声明的全局变量不属于顶层对象的属性,即ES6开始,全局变量和顶层对象的属性是分开的。 +```js +// ES5 +var a = 'leo'; +window.a; // 'leo' + +// ES6 +let b = 'leo'; +window.b; // undefined +``` + +## 常量 +ES6之后我们可以使用`const`来声明一个只读的常量,并且在**声明时必须赋值**,之后在相同作用域中**不能赋值**也**不能重新声明**,否则报错。 +```js +const a; +// Uncaught SyntaxError: Missing initializer in const declaration + +const b = 'leo'; +b = 'hi'; +// Uncaught TypeError: Assignment to constant variable. + +function f(){ + const a1 = 'hi'; + console.log(a1); +} +f(); // 'hi' +const a1 = 'hi leo'; +a1; // "hi leo" +``` +尽管`const`声明的变量不能直接修改值,但是对于对象和数组,却是不受保护可以修改的: +```js +const a = {name:'leo',age:25}; +a.name = 'pingan'; // a => {name: "pingan", age: 25} + +const b = ['hi', 'leo']; +b[1] = 'pingan'; // b => ["hi", "pingan"] +``` + +# 3.数据结构和类型 +## 数据类型 +JavaScript中一共分为**7**中不同类型: +* 六种**原型**数据类型: + * 1.Boolean : 布尔值,true和false; + * 2.null : 对大小写敏感(即`null`/`Null`/`NULL`完全不同); + * 3.undefined : 空类型,变量未定义时候的值; + * 4.Number : 数值类型,如`100`; + * 5.String : 字符串类型,如'hi pingan'; + * 6.Symbol(ES6新增) : 表示一种唯一且不可变的数据; +* 以及Object对象类型 + +## 数据类型转换 +由于JavaScript是门动态类型语言,因此在开发过程可以不需要指定数据类型,在执行时会自动转换: +```js +var a = 100; +a = 'hi leo'; // 这样不报错 +``` +另外还有: +```js +let a1 = '10'; +let b1 = 20; +a1 + b1; // 30 + +let a2 = 'leo ' + 10 + ' age'; // 'leo 10 age' + +'10' - 5; // 5 +'10' + 5; // 105 +``` +**转换字符串为数字小技巧** +小技巧很多,这里说个最简单的: +```js +// 这样不会使两个数字计算总和: +'1.1' + '1.2'; // '1.11.2' + +// 实际上要这样: ++'1.1' + +'1.2'; // 2.3 +``` + +# 4.字面量 +字面量是用来表示**如何表达这个值**,简单理解就是**变量赋值时右边的都是字面量**。比如: +```js +let a = 'hi leo'; +``` +`hi leo`为字符串字面量,`a`为变量名。 +字面量分为七种: +* 1.数组字面量 +* 2.布尔字面量 +* 3.浮点数字面量 +* 4.整数字面量 +* 5.对象字面量 +* 6.正则字面量 +* 7.字符串字面量 + +## 数组字面量 +使用数组字面量创建数组的时,指定元素的值,并作为数组的初始化,从而确定数组长度。 +```js +let a = ['hi','leo','hello','pingan']; +a[1]; // 'leo' +a.length; // 4 +``` +若使用多余逗号,作为数组字面量,则值为`undefined`,并且数组长度也会正常计算: +```js +let a = ['hi', ,'leo']; +a[0]; // 'hi' +a[1]; // undefined +a.length; // 3 +``` + +## 布尔字面量 +只有`true`和`false`: +```js +let a = true; +``` + +## 整数字面量 +整数可以用十进制(基数为10)、十六进制(基数为16)、八进制(基数为8)以及二进制(基数为2)表示。 + +## 浮点数字面量 +浮点数字面量组成: +* 一个十进制的整数,可以带正负号; +* 小数点 +* 小数部分(只能十进制) +* 指数部分 +```js +let a = 3.14; // 3.14 +let b = -.001; // -0.001 +let c = -3.14e+12; // -3.14*1012 +let d = .1e-23;// 0.1*10 - 23 = 10-24 = 1e-24 +``` + +## 对象字面量 +对象字面量是由`{}`包含一个或多个 `键:值` 对的列表: +```js +let a1 = 'hi leo'; +let a2 = function(){ return 'my name is pingan' }; + +let obj = { + n1 : 'pingan', + n2 : a1, + n3 : a2() +} +obj; // {n1: "pingan", n2: "hi leo", n3: "my name is pingan"} +``` +也可以使用任意数字或字符串作为对象属性的名字,但必须用`''`引号包裹: +```js +let obj = { + "" : "hi leo", + "!" : "hi pingan", + 2 : 'hi number' +} +obj; // {2: "hi number", "": "hi leo", !: "hi pingan"} +obj[""]; // "hi leo" +obj[2]; // "hi number" +``` + +## 正则字面量 +使用字符被正斜杠“`/`”围起来的表达式: +```js +var a = /ab+c/; +``` + +## 字符串字面量 +使用单引号(`''`)或者双引号(`""`)括起来的字符串: +```js +let a = 'leo'; +a.length; // 3 +``` +ES6中新增了**模板字符串**,作用于: +* 方便拼接字符串 +* 有效实现字符串换行 +* 防止注入攻击 +* 建立基于字符串的高级数据抽象 +```js +// 拼接字符串 +let name = 'leo'; +let a = ` + hi ${name} +`; +a; // 'hi leo' + +// 换行 +let b = ` + hi + leo +`; +b; +// " +// hi +// leo +// " +``` +**常用特殊字符**: +|字符|含义| +|---|---| +|\b|退格符| +|\f|换页符| +|\n|换行符| +|\r|回车符| +|\t|Tab (制表符)| +|\v|垂直制表符| +|\'|单引号| +|\"|双引号| +|\\|反斜杠字符(\)| + + +--- +# 参考文章: +[1.MDN 语法和数据类型](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Grammar_and_Types) + +**本部分内容到这结束** + +|Author|王平安| +|---|---| +|E-mail|pingan8787@qq.com| +|博 客|www.pingan8787.com| +|微 信|pingan8787| +|每日文章推荐|https://github.com/pingan8787/Leo_Reading/issues| +|ES小册|js.pingan8787.com| \ No newline at end of file diff --git "a/Cute-JavaScript/Cute-JS/level1/10.\346\225\260\347\273\204.md" "b/Cute-JavaScript/Cute-JS/level1/10.\346\225\260\347\273\204.md" new file mode 100644 index 00000000..2d150c32 --- /dev/null +++ "b/Cute-JavaScript/Cute-JS/level1/10.\346\225\260\347\273\204.md" @@ -0,0 +1,657 @@ +本文是 **重温基础** 系列文章的第十篇。 +今日感受:平安夜,多棒。 + +**本章节复习的是JS中的数组,以索引进行排序。** + +前置知识: +数组是一个有序的数据集合,使用数组名称和索引进行访问。 +```js +let arr = [1,2,3]; +arr[0] = 1; +``` +在JavaScript中数组没有明确数据类型。 +```js +let arr = [1, 'hi', undefined, fun()]; +``` + +# 1.创建数组 +创建数组方法有3种: +```js +let arr = new Array(ele1, ele2, ele3, ..., eleN); +let arr = Array(ele1, ele2, ele3, ..., eleN); +let arr = [ele1, ele2, ele3, ..., eleN]; +``` +上面是已知数组元素,另外一种还有**创建一个长度不为0,且有没有任何元素的数组**: +```js +let len = 5; + +let arr = new Array(len); // 方法1 +let arr = Array(len); // 方法2 +let arr = []; // 方法3 +arr.length = len; +``` +若传入的数组长度不是整数,则报错: +```js +let arr = new Array(3.5); +let arr = Array(3.5); +let arr = []; +arr.length = 3.5; +//Uncaught RangeError: Invalid array length +``` +其中要注意这两种创建方法是不同的: +```js +let arr1 = new Array(4); // [empty × 4] +let arr2 = [4]; // [4] +for(let k in arr1){ + console.log(k); +} // undefined +for(let k in arr2){ + console.log(k); +} // 0 +``` + +# 2.使用数组 +## 2.1 简单使用 +获取数组指定位置的值: +```js +let a = [1,2,5]; +a[0]; // 1 +a[2]; // 5 +a[3]; // undefined +``` + +获取数组长度: +```js +let a = [1,2,5]; +a.length; // 3 +a["length"]; // 3 +``` +设置数组指定位置的值: +```js +let a = [1,2,5]; +a[0] = 9; +a[2] = 99; +a[3] = 999; +``` + +## 2.2 理解数组length +* 数组的索引值是从`0`开始,即上面数组索引`0`的是`1`,索引`1`的值是`2`,依次下去。 +* 数组`length`永远返回的是数组最后一个元素的索引加1。 +* 可通过`arr.length = 0`来清空数组。 +* 可通过`arr.length = len`来设置数组长度。 + +## 2.3 遍历数组 +遍历数组就是以某种方法处理数组的每个元素,简单如下: +* 使用`for`循环: +```js +let arr = ["pingan", "leo", "robin"]; +for (let i = 0; i  [2, 3] +// arr => [1, "hi", "leo", 4] +``` + +## 3.8 sort() +对数组的元素进行排序,**改变原数组**。 +可接受一个回调方法作为比较函数,来决定排序方式。 +比较函数应该具有两个参数 `a` 和 `b`,返回值如下: +若 `a` 小于 `b`,在排序后的数组中 a 应该出现在 b 之前,则返回一个小于 0 的值。 +若 `a` 等于 `b`,则返回 0。 +若 `a` 大于 `b`,则返回一个大于 0 的值。 +```js +let a1 = [1,3,6,9,10]; +a1.sort(); // [1, 10, 3, 6, 9] +a1.sort(function(a,b){ + return a > b ? 1 : a < b ? -1 : 0; +}) // [1, 3, 6, 9, 10] +``` + +## 3.9 indexOf()和lastIndexOf() +两者都是在数组搜索指定元素,只是`indexOf()`返回的是搜索到的**第一个元素**的索引,而`lastIndexOf()`返回的是搜索到的**最后一个元素**的索引。 +语法: +`indexOf(ele[,start])`和`lastIndexOf(ele[,start])`; +参数: +* `ele`: 需要搜索的元素。 +* `start`: 开始搜索的索引。 +```js +let arr = ["hh1", "hh2", "hh2", "hh2", "hh3", "hh4"]; +let a1 = arr.indexOf("hh2"); // 1 +let a2 = arr.lastIndexOf("hh2"); // 3 +let a3 = arr.indexOf("hh2",2); // 2 +``` + +# 4. 数组方法(迭代) + +|方法名称|方法介绍| +|-|-| +|`forEach()`|为数组中的每个元素执行一次回调函数。| +|`every()`|如果数组中的每个元素都满足测试函数,则返回 true,否则返回 false。| +|`some()`|如果数组中至少有一个元素满足测试函数,则返回 true,否则返回 false。| +|`filter()`|将所有在过滤函数中返回 true 的数组元素放进一个新数组中并返回。| +|`map()`|返回一个由回调函数的返回值组成的新数组。| +|`reduce()`|从左到右为每个数组元素执行一次回调函数,并把上次回调函数的返回值放在一个暂存器中传给下次回调函数,并返回最后一次回调函数的返回值。| +|`reduceRight()`|从右到左为每个数组元素执行一次回调函数,并把上次回调函数的返回值放在一个暂存器中传给下次回调函数,并返回最后一次回调函数的返回值。| + +**以下是ES6规范新增的数组方法:** + +|方法名称|方法介绍| +|-|-| +|`keys() `|返回一个数组迭代器对象,该迭代器会包含所有数组元素的键。| +|`values() `|返回一个数组迭代器对象,该迭代器会包含所有数组元素的值。| +|`entries() `|返回一个数组迭代器对象,该迭代器会包含所有数组元素的键值对。| +|`find() `|找到第一个满足测试函数的元素并返回那个元素的值,如果找不到,则返回 undefined。| +|`findIndex() `|找到第一个满足测试函数的元素并返回那个元素的索引,如果找不到,则返回 -1。| + +可参考[MDN Array](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array) 的详细介绍。 + +## 4.1 forEach() +对数组的每个元素执行一次提供的函数。 + +语法: +`arr.forEach(callback)`。 + +参数: +`callback(val, index, arr)` : 需要执行的函数,接收三个参数: +* `val` : 正在处理的当前元素; +* `index` : 可选,正在处理的当前元素的索引; +* `arr` : 可选,正在操作的数组; + +```js +let a = [1,3,5,7]; +a.forEach(function(val, index, arr){ + arr[index] = val * 2 +}) +a ; // [2, 6, 10, 14] +``` + +## 4.2 every() +测试数组的所有元素是否**都通过**了指定函数的测试。 +语法: +`arr.every(callback)`。 + +参数: +`callback(val, index, arr)` : 需要执行的函数,接收三个参数: +* `val` : 正在处理的当前元素; +* `index` : 可选,正在处理的当前元素的索引; +* `arr` : 可选,正在操作的数组; + +返回值: +若都通过返回`true`,否则返回`false`。 + +```js +let a = [1, "", "aa", 13, 6]; +let res = a.every(function(val, index, arr){ + return typeof val == "number"; +}) +res;// false + +let b = [1, 2, 3]; +let r = b.every(function(val, index, arr){ + return typeof val == "number"; +}) +r; // true +``` + +## 4.3 some() +测试数组中的某些元素是否通过由提供的函数实现的测试。 +语法: +`arr.some(callback)`。 + +参数: +`callback(val, index, arr)` : 需要执行的函数,接收三个参数: +* `val` : 正在处理的当前元素; +* `index` : 可选,正在处理的当前元素的索引; +* `arr` : 可选,正在操作的数组; + +返回值: +若有一个通过返回`true`,否则返回`false`。 + +```js +let a = [1, "", "aa", 13, 6]; +let res = a.some(function(val, index, arr){ + return typeof val == "number"; +}) +res;// true + +let b = [1, 2, 3]; +let r = b.some(function(val, index, arr){ + return typeof val == "number"; +}) +r; // true +``` + +## 4.4 filter() +将所有在过滤函数中返回 `true` 的数组元素放进一个新数组中并返回。 + +语法: +`arr.filter(callback)`。 + +参数: +`callback(val, index, arr)` : 需要执行的函数,接收三个参数: +* `val` : 正在处理的当前元素; +* `index` : 可选,正在处理的当前元素的索引; +* `arr` : 可选,正在操作的数组; + +返回值: +一个返回通过测试的元素的数组,若都没有则返回空数组。 + +```js +let a = [1, "", "aa", 13, 6]; +let res = a.filter(function(val, index, arr){ + return typeof val == "number"; +}) +res;//[1, 13, 6] +``` + +## 4.5 map() +传入一个操作函数,对每个元素执行此方法,并返回一个执行后的数组。 + +语法: +`arr.map(callback)`。 + +参数: +`callback(val, index, arr)` : 需要执行的函数,接收三个参数: +* `val` : 正在处理的当前元素; +* `index` : 可选,正在处理的当前元素的索引; +* `arr` : 可选,正在操作的数组; + +返回值: +一个新数组,每个元素都是回调函数的结果。 + +```js +let a = [1, 3, 5]; +let b = a.map(function(val, index, arr){ + return val + 2; +}) +b; //[3, 5, 7] +``` + + +# 5. 数组的拓展(ES6) +## 5.1 拓展运算符 +拓展运算符使用(`...`),类似`rest`参数的逆运算,将数组转为用(`,`)分隔的参数序列。 +```js +console.log(...[1, 2, 3]); // 1 2 3 +console.log(1, ...[2,3], 4); // 1 2 3 4 +``` +拓展运算符主要使用在函数调用。 +```js +function f (a, b){ + console.log(a, b); +} +f(...[1, 2]); // 1 2 + +function g (a, b, c, d, e){ + console.log(a, b, c, d, e); +} +g(0, ...[1, 2], 3, ...[4]); // 0 1 2 3 4 +``` +**若拓展运算符后面是个空数组,则不产生效果**。 +```js +[...[], 1]; // [1] +``` + +**替代apply方法** +```js +// ES6之前 +function f(a, b, c){...}; +var a = [1, 2, 3]; +f.apply(null, a); + +// ES6之后 +function f(a, b, c){...}; +let a = [1, 2, 3]; +f(...a); + +// ES6之前 +Math.max.apply(null, [3,2,6]); + +// ES6之后 +Math.max(...[3,2,6]); +``` + +**拓展运算符的运用** +* **(1)复制数组**: +通常我们直接复制数组时,只是浅拷贝,如果要实现深拷贝,可以使用拓展运算符。 +```js +// 通常情况 浅拷贝 +let a1 = [1, 2]; +let a2 = a1; +a2[0] = 3; +console.log(a1,a2); // [3,2] [3,2] + +// 拓展运算符 深拷贝 +let a1 = [1, 2]; +let a2 = [...a1]; +// let [...a2] = a1; // 作用相同 +a2[0] = 3; +console.log(a1,a2); // [1,2] [3,2] +``` +* **(2)合并数组**: +注意,这里合并数组,只是浅拷贝。 +```js +let a1 = [1,2]; +let a2 = [3]; +let a3 = [4,5]; + +// ES5 +let a4 = a1.concat(a2, a3); + +// ES6 +let a5 = [...a1, ...a2, ...a3]; + +a4[0] === a1[0]; // true +a5[0] === a1[0]; // true +``` +* **(3)与解构赋值结合**: +与解构赋值结合生成数组,但是使用拓展运算符需要放到参数最后一个,否则报错。 +```js +let [a, ...b] = [1, 2, 3, 4]; +// a => 1 b => [2,3,4] + +let [a, ...b] = []; +// a => undefined b => [] + +let [a, ...b] = ["abc"]; +// a => "abc" b => [] +``` + +## 5.2 Array.from() +将 **类数组对象** 和 **可遍历的对象**,转换成真正的数组。 +```js +// 类数组对象 +let a = { + '0':'a', + '1':'b', + length:2 +} +let arr = Array.from(a); + +// 可遍历的对象 +let a = Array.from([1,2,3]); +let b = Array.from({length: 3}); +let c = Array.from([1,2,3]).map(x => x * x); +let d = Array.from([1,2,3].map(x => x * x)); +``` + +## 5.3 Array.of() +将一组数值,转换成**数组**,弥补`Array`方法参数不同导致的差异。 +```js +Array.of(1,2,3); // [1,2,3] +Array.of(1).length; // 1 + +Array(); // [] +Array(2); // [,] 1个参数时,为指定数组长度 +Array(1,2,3); // [1,2,3] 多于2个参数,组成新数组 +``` + +## 5.4 find()和findIndex() +`find()`方法用于找出第一个符合条件的数组成员,参数为一个回调函数,所有成员依次执行该回调函数,返回第一个返回值为`true`的成员,如果没有一个符合则返回`undefined`。 +```js +[1,2,3,4,5].find( a => a < 3 ); // 1 +``` +回调函数接收三个参数,当前值、当前位置和原数组。 +```js +[1,2,3,4,5].find((value, index, arr) => { + // ... +}); +``` +`findIndex()`方法与`find()`类似,返回第一个符合条件的数组成员的**位置**,如果都不符合则返回`-1`。 +```js +[1,2,3,4].findIndex((v,i,a)=>{ + return v>2; +}); // 2 +``` + +## 5.5 fill() +用于用指定值**填充**一个数组,通常用来**初始化空数组**,并抹去数组中已有的元素。 +```js +new Array(3).fill('a'); // ['a','a','a'] +[1,2,3].fill('a'); // ['a','a','a'] +``` +并且`fill()`的第二个和第三个参数指定填充的**起始位置**和**结束位置**。 +```js +[1,2,3].fill('a',1,2);// [1, "a", 3] +``` + +## 5.6 entries(),keys(),values() +主要用于遍历数组,`entries()`对键值对遍历,`keys()`对键名遍历,`values()`对键值遍历。 +```js +for (let i of ['a', 'b'].keys()){ + console.log(i) +} +// 0 +// 1 + +for (let e of ['a', 'b'].values()){ + console.log(e) +} +// 'a' +// 'b' + +for (let e of ['a', 'b'].entries()){ + console.log(e) +} +// 0 'a' +// 1 'b' +``` + +## 5.7 includes() +用于表示数组是否包含给定的值,与字符串的`includes`方法类似。 +```js +[1,2,3].includes(2); // true +[1,2,3].includes(4); // false +[1,2,NaN].includes(NaN); // true +``` +第二个参数为**起始位置**,默认为`0`,如果负数,则表示倒数的位置,如果大于数组长度,则重置为`0`开始。 +```js +[1,2,3].includes(3,3); // false +[1,2,3].includes(3,4); // false +[1,2,3].includes(3,-1); // true +[1,2,3].includes(3,-4); // true +``` + +## 5.8 flat(),flatMap() +`flat()`用于将数组一维化,返回一个新数组,不影响原数组。 +默认一次只一维化一层数组,若需多层,则传入一个整数参数指定层数。 +若要一维化所有层的数组,则传入`Infinity`作为参数。 +```js +[1, 2, [2,3]].flat(); // [1,2,2,3] +[1,2,[3,[4,[5,6]]]].flat(3); // [1,2,3,4,5,6] +[1,2,[3,[4,[5,6]]]].flat('Infinity'); // [1,2,3,4,5,6] +``` +`flatMap()`是将原数组每个对象先执行一个函数,在对返回值组成的数组执行`flat()`方法,返回一个新数组,不改变原数组。 + `flatMap()`只能展开一层。 +```js +[2, 3, 4].flatMap((x) => [x, x * 2]); +// [2, 4, 3, 6, 4, 8] +``` + + +# 6. 数组的拓展(ES7) +## 6.1 Array.prototype.includes()方法 +`includes()`用于查找一个值是否在数组中,如果在返回`true`,否则返回`false`。 +```js +['a', 'b', 'c'].includes('a'); // true +['a', 'b', 'c'].includes('d'); // false +``` +`includes()`方法接收两个参数,**搜索的内容**和**开始搜索的索引**,默认值为**0**,若搜索值在数组中则返回`true`否则返回`false`。 +```js +['a', 'b', 'c', 'd'].includes('b'); // true +['a', 'b', 'c', 'd'].includes('b', 1); // true +['a', 'b', 'c', 'd'].includes('b', 2); // false +``` +与`indexOf`方法对比,下面方法效果相同: +```js +['a', 'b', 'c', 'd'].indexOf('b') > -1; // true +['a', 'b', 'c', 'd'].includes('b'); // true +``` +**includes()与indexOf对比:** +* `includes`相比`indexOf`更具语义化,`includes`返回的是是否存在的具体结果,值为布尔值,而`indexOf`返回的是搜索值的下标。 +* `includes`相比`indexOf`更准确,`includes`认为两个`NaN`相等,而`indexOf`不会。 +```js +let a = [1, NaN, 3]; +a.indexOf(NaN); // -1 +a.includes(NaN); // true +``` +另外在判断`+0`与`-0`时,`includes`和`indexOf`的返回相同。 +```js +[1, +0, 3, 4].includes(-0); // true +[1, +0, 3, 4].indexOf(-0); // 1 +``` + +# 参考资料 +1.[MDN 索引集合类](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Indexed_collections) +2.[MDN 数组对象](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array) +3.[W3school JavaScript Array 对象](http://www.w3school.com.cn/jsref/jsref_obj_array.asp) + +--- +**本部分内容到这结束** + +|Author|王平安| +|---|---| +|E-mail|pingan8787@qq.com| +|博 客|www.pingan8787.com| +|微 信|pingan8787| +|每日文章推荐|https://github.com/pingan8787/Leo_Reading/issues| +|ES小册|js.pingan8787.com| \ No newline at end of file diff --git "a/Cute-JavaScript/Cute-JS/level1/11.Map\345\222\214Set\345\257\271\350\261\241.md" "b/Cute-JavaScript/Cute-JS/level1/11.Map\345\222\214Set\345\257\271\350\261\241.md" new file mode 100644 index 00000000..7389a057 --- /dev/null +++ "b/Cute-JavaScript/Cute-JS/level1/11.Map\345\222\214Set\345\257\271\350\261\241.md" @@ -0,0 +1,294 @@ +本文是 **重温基础** 系列文章的第十一篇。 +今日感受:注意身体,生病花钱又难受。 + +**本章节复习的是JS中的Map和Set对象,是个集合。** + +前置知识: +Map和Set对象是在ES6中被引入的,作为一种由`key`值标记的数据容器。 +Map和Set对象承载的数据元素可以按照插入时的顺序,被迭代遍历。 + +# 1 Set对象 +**介绍**: +`Set`数据结构类似数组,但所有成员的值**唯一**。 +`Set`本身为一个构造函数,用来生成`Set`数据结构,使用`add`方法来添加新成员。 +```js +let a = new Set(); +[1,2,2,1,3,4,5,4,5].forEach(x=>a.add(x)); +for(let k of a){ + console.log(k) +}; +// 1 2 3 4 5 +``` +**基础使用**: +```js +let a = new Set([1,2,3,3,4]); +[...a]; // [1,2,3,4] +a.size; // 4 + +// 数组去重 +[...new Set([1,2,3,4,4,4])];// [1,2,3,4] +``` + +**注意**: +* 向`Set`中添加值的时候,不会类型转换,即`5`和`'5'`是不同的。 +```js +[...new Set([5,'5'])]; // [5, "5"] +``` + +**属性和方法**: +* 属性: + * `Set.prototype.constructor`:构造函数,默认就是`Set`函数。 + * `Set.prototype.size`:返回`Set`实例的成员总数。 + +* 操作方法: + * `add(value)`:添加某个值,返回 Set 结构本身。 + * `delete(value)`:删除某个值,返回一个布尔值,表示删除是否成功。 + * `has(value)`:返回一个布尔值,表示该值是否为Set的成员。 + * `clear()`:清除所有成员,没有返回值。 + +```js +let a = new Set(); +a.add(1).add(2); // a => Set(2) {1, 2} +a.has(2); // true +a.has(3); // false +a.delete(2); // true a => Set(1) {1} +a.clear(); // a => Set(0) {} +``` +**数组去重**: +```js +let a = new Set([1,2,3,3,3,3]); +``` +# 2 Set的应用 +**数组去重**: +```js +// 方法1 +[...new Set([1,2,3,4,4,4])]; // [1,2,3,4] +// 方法2 +Array.from(new Set([1,2,3,4,4,4])); // [1,2,3,4] +``` +**遍历和过滤**: +```js +let a = new Set([1,2,3,4]); + +// map 遍历操作 +let b = new Set([...a].map(x =>x*2));// b => Set(4) {2,4,6,8} + +// filter 过滤操作 +let c = new Set([...a].filter(x =>(x%2) == 0)); // b => Set(2) {2,4} +``` +**获取并集、交集和差集**: +```js +let a = new Set([1,2,3]); +let b = new Set([4,3,2]); + +// 并集 +let c1 = new Set([...a, ...b]); // Set {1,2,3,4} + +// 交集 +let c2 = new Set([...a].filter(x => b.has(x))); // set {2,3} + +// 差集 +let c3 = new Set([...a].filter(x => !b.has(x))); // set {1} +``` + +* 遍历方法: + * `keys()`:返回**键名**的遍历器。 + * `values()`:返回**键值**的遍历器。 + * `entries()`:返回**键值对**的遍历器。 + * `forEach()`:使用回调函数遍历**每个成员**。 + +`Set`遍历顺序是**插入顺序**,当保存多个回调函数,只需按照顺序调用。但由于`Set`结构**没有键名只有键值**,所以`keys()`和`values()`是返回结果相同。 +```js +let a = new Set(['a','b','c']); +for(let i of a.keys()){console.log(i)}; // 'a' 'b' 'c' +for(let i of a.values()){console.log(i)}; // 'a' 'b' 'c' +for(let i of a.entries()){console.log(i)}; +// ['a','a'] ['b','b'] ['c','c'] +``` +并且 还可以使用`for...of`直接遍历`Set`。 +```js +let a = new Set(['a','b','c']); +for(let k of a){console.log(k)}; // 'a' 'b' 'c' +``` +`forEach`与数组相同,对每个成员执行操作,且无返回值。 +```js +let a = new Set(['a','b','c']); +a.forEach((v,k) => console.log(k + ' : ' + v)); +``` + + +# 3 Map对象 +由于传统的`JavaScript`对象只能用字符串当做键,给开发带来很大限制,ES6增加`Map`数据结构,使得**各种类型的值**(包括对象)都可以作为键。 +`Map`结构提供了“**值—值**”的对应,是一种更完善的 Hash 结构实现。 +**基础使用**: +```js +let a = new Map(); +let b = {name: 'leo' }; +a.set(b,'my name'); // 添加值 +a.get(b); // 获取值 +a.size; // 获取总数 +a.has(b); // 查询是否存在 +a.delete(b); // 删除一个值 +a.clear(); // 清空所有成员 无返回 +``` +**注意**: +* 传入数组作为参数,**指定键值对的数组**。 +```js +let a = new Map([ + ['name','leo'], + ['age',18] +]) +``` +* 如果对同一个键**多次赋值**,后面的值将**覆盖前面的值**。 +```js +let a = new Map(); +a.set(1,'aaa').set(1,'bbb'); +a.get(1); // 'bbb' +``` +* 如果读取一个未知的键,则返回`undefined`。 +```js +new Map().get('abcdef'); // undefined +``` +* **同样的值**的两个实例,在 Map 结构中被视为两个键。 +```js +let a = new Map(); +let a1 = ['aaa']; +let a2 = ['aaa']; +a.set(a1,111).set(a2,222); +a.get(a1); // 111 +a.get(a2); // 222 +``` +**遍历方法**: +Map 的遍历顺序就是插入顺序。 +* `keys()`:返回键名的遍历器。 +* `values()`:返回键值的遍历器。 +* `entries()`:返回所有成员的遍历器。 +* `forEach()`:遍历 Map 的所有成员。 +```js +let a = new Map([ + ['name','leo'], + ['age',18] +]) + +for (let i of a.keys()){...}; +for (let i of a.values()){...}; +for (let i of a.entries()){...}; +a.forEach((v,k,m)=>{ + console.log(`key:${k},value:${v},map:${m}`) +}) +``` +**将Map结构转成数组结构**: +```js +let a = new Map([ + ['name','leo'], + ['age',18] +]) + +let a1 = [...a.keys()]; // a1 => ["name", "age"] +let a2 = [...a.values()]; // a2 =>  ["leo", 18] +let a3 = [...a.entries()];// a3 => [['name','leo'], ['age',18]] +``` + +# 4 Map与其他数据结构互相转换 +* Map 转 数组 +```js +let a = new Map().set(true,1).set({f:2},['abc']); +[...a]; // [[true:1], [ {f:2},['abc'] ]] +``` +* 数组 转 Map +```js +let a = [ ['name','leo'], [1, 'hi' ]] +let b = new Map(a); +``` +* Map 转 对象 +如果所有 Map 的键都是字符串,它可以无损地转为对象。 +如果有非字符串的键名,那么这个键名会被转成字符串,再作为对象的键名。 +```js +function fun(s) { + let obj = Object.create(null); + for (let [k,v] of s) { + obj[k] = v; + } + return obj; +} + +const a = new Map().set('yes', true).set('no', false); +fun(a) +// { yes: true, no: false } +``` +* 对象 转 Map +```js +function fun(obj) { + let a = new Map(); + for (let k of Object.keys(obj)) { + a.set(k, obj[k]); + } + return a; +} + +fun({yes: true, no: false}) +// Map {"yes" => true, "no" => false} +``` + +* Map 转 JSON +**(1)Map键名都是字符串,转为对象JSON:** +```js +function fun (s) { + let obj = Object.create(null); + for (let [k,v] of s) { + obj[k] = v; + } + return JSON.stringify(obj) +} +let a = new Map().set('yes', true).set('no', false); +fun(a); +// '{"yes":true,"no":false}' +``` +**(2)Map键名有非字符串,转为数组JSON:** +```js +function fun (map) { + return JSON.stringify([...map]); +} + +let a = new Map().set(true, 7).set({foo: 3}, ['abc']); +fun(a) +// '[[true,7],[{"foo":3},["abc"]]]' +``` +* JSON 转 Map +**(1)所有键名都是字符串:** +```js +function fun (s) { + let strMap = new Map(); + for (let k of Object.keys(s)) { + strMap.set(k, s[k]); + } + return strMap; + return JSON.parse(strMap); +} +fun('{"yes": true, "no": false}') +// Map {'yes' => true, 'no' => false} +``` +**(2)整个 JSON 就是一个数组,且每个数组成员本身,又是一个有两个成员的数组**: +```js +function fun2(s) { + return new Map(JSON.parse(s)); +} +fun2('[[true,7],[{"foo":3},["abc"]]]') +// Map {true => 7, Object {foo: 3} => ['abc']} +``` + + + +# 参考资料 +[1.阮一峰ES6入门](http://es6.ruanyifeng.com/#docs/set-map) + +--- +**本部分内容到这结束** + +|Author|王平安| +|---|---| +|E-mail|pingan8787@qq.com| +|博 客|www.pingan8787.com| +|微 信|pingan8787| +|每日文章推荐|https://github.com/pingan8787/Leo_Reading/issues| +|ES小册|js.pingan8787.com| \ No newline at end of file diff --git "a/Cute-JavaScript/Cute-JS/level1/12.\344\275\277\347\224\250\345\257\271\350\261\241.md" "b/Cute-JavaScript/Cute-JS/level1/12.\344\275\277\347\224\250\345\257\271\350\261\241.md" new file mode 100644 index 00000000..08df6f3d --- /dev/null +++ "b/Cute-JavaScript/Cute-JS/level1/12.\344\275\277\347\224\250\345\257\271\350\261\241.md" @@ -0,0 +1,527 @@ +本文是 **重温基础** 系列文章的第十二篇。 +今日感受:需要总结下2018。 + +这几天,重重的感冒发烧,在家休息好几天,伤···。 + + +**本章节复习的是JS中对象的使用,这是重点。** + +前置知识: +JavaScrip的设计是一个简单的基于对象的范式。 +对象是一系列属性的集合,一个属性包含一个键和一个值,也叫**键值对**。 +若一个属性的值,是一个函数,则称这个属性为方法。 + +一个对象,可以有很多方法,就像一个杯子,可以有颜色,重量,形状等属性。 + +**注意:** +对象的名称,对大小写敏感。 + +# 1.创建对象 +本文主要是复习对象的使用,至于对象的创建,下面这里简单介绍一下常见的创建对象的方法: + +**创建方法1**: +```js +let obj = new Object(); // 声明一个空对象 +``` + +**创建方法2**: +```js +let obj = {}; // 声明一个空对象 +``` +上面的`name`是对象`obj`中的一个属性,对应的值为`"leo"`。 + + +# 2.设置对象属性和访问属性 +设置对象属性,也有两种方法: +**直接设置**: +```js +let obj = {}; +obj.name = "leo"; // 为对象添加属性和值 +``` + +**创建时设置**: +```js +let obj = {name : 'leo'}; +obj.name = "leo"; // 为对象添加属性和值 +``` + +当一个对象定义了一个属性,我们可以用点符号(`.`)来访问它。 +```js +obj.name; // "leo" +``` + +**注意**: +* 属性的另外一种写法: +```js +let obj = {}; +let n = "name"; +obj[n] = "leo"; // 属性名使用变量 +obj["height"] = 188; // 字符串 +obj["age" + "Is"] = 15; // 字符串拼接 +console.log(obj); +/* +obj = { + ageIs: 15 + height: 188 + name: "leo" +} +*/ +``` + +* 属性的值也可以是个方法: +```js +let obj = {}; +obj.getTime = function(){ + return new Date(); +} +obj.getTime(); // 访问属性的方法 +//Wed Jan 02 2019 21:07:59 GMT+0800 (中国标准时间) +``` + +# 3.枚举对象的所有属性 +从 [ECMAScript 5](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_5_support_in_Mozilla) 开始,有三种原生的方法用于列出或枚举对象的属性: +## 3.1 for...in 循环 + +该方法依次访问一个对象及其**原型链**中所有可枚举的属性。 +```js +let obj = {a:1, b:2, c:3}; +for (let i in obj) { + console.log("obj." + i + " = " + obj[i]); +} +/* +"obj.a = 1" +"obj.b = 2" +"obj.c = 3" +*/ +``` + +## 3.2 Object.keys(o) + +该方法返回一个对象 `o` 自身包含(**不包括原型中**)的所有属性的名称的数组。 +```js +let obj = {a:1, b:2, c:3}; +let arr = Object.keys(obj); +console.log(arr); +/* +["a", "b", "c"] +*/ +arr.forEach(function(val,index,array){ + console.log("key:" + val+",val:"+obj[val]) +}) +/* +key:a,val:1 +key:b,val:2 +key:c,val:3 +*/ +``` + + +## 3.3 Object.getOwnPropertyNames(o) + +该方法返回一个数组,它包含了对象 `o` 所有拥有的属性(**无论是否可枚举**)的名称。 + + +```js +let obj = {a:1, b:2, c:3}; +let arr = Object.getOwnPropertyNames(obj); +console.log(arr); +/* +["a", "b", "c"] +*/ +arr.forEach(function(val,index,array){ + console.log("key:" + val+",val:"+obj[val]) +}) +/* +key:a,val:1 +key:b,val:2 +key:c,val:3 +*/ +``` + + +# 4.ES6新增:对象的拓展 +## 4.1 属性的简洁表示 +```js +let a = 'a1'; +let b = { a }; // b => { a : 'a1' } +// 等同于 +let b = { a : a }; + +function f(a, b){ + return {a, b}; +} +// 等同于 +function f (a, b){ + return {a:a ,b:b}; +} + +let a = { + fun () { + return 'leo'; + } +} +// 等同于 +let a = { + fun : function(){ + return 'leo'; + } +} +``` + +## 4.2 属性名表达式 +`JavaScript`提供2种方法**定义对象的属性**。 +```js +// 方法1 标识符作为属性名 +a.f = true; + +// 方法2 字符串作为属性名 +a['f' + 'un'] = true; +``` +延伸出来的还有: +```js +let a = 'hi leo'; +let b = { + [a]: true, + ['a'+'bc']: 123, + ['my' + 'fun'] (){ + return 'hi'; + } +}; +// b.a => undefined ; b.abc => 123 ; b.myfun() => 'hi' +// b[a] => true ; b['abc'] => 123 ; b['myfun'] => ƒ ['my' + 'fun'] (){ return 'hi'; } +``` +**注意**: +属性名表达式不能与简洁表示法同时使用,否则报错。 +```js +// 报错 +let a1 = 'aa'; +let a2 = 'bb'; +let b1 = {[a1]}; + +// 正确 +let a1 = 'aa'; +let b1 = { [a1] : 'bb'}; +``` + +## 4.3 Object.is() +`Object.is()` 用于比较两个值是否严格相等,在ES5时候只要使用**相等运算符**(`==`)和**严格相等运算符**(`===`)就可以做比较,但是它们都有缺点,前者会**自动转换数据类型**,后者的`NaN`不等于自身,以及`+0`等于`-0`。 +```js +Object.is('a','a'); // true +Object.is({}, {}); // false + +// ES5 ++0 === -0 ; // true +NaN === NaN; // false + +// ES6 +Object.is(+0,-0); // false +Object.is(NaN,NaN); // true +``` + +## 4.4 Object.assign() +`Object.assign()`方法用于对象的合并,将原对象的所有可枚举属性复制到目标对象。 +**基础用法**: +第一个参数是**目标对象**,后面参数都是**源对象**。 +```js +let a = {a:1}; +let b = {b:2}; +Object.assign(a,b); // a=> {a:1,b:2} +``` +**注意**: +* 若目标对象与源对象有同名属性,则后面属性会覆盖前面属性。 +```js +let a = {a:1, b:2}; +let b = {b:3, c:4}; +Object.assign(a, b); // a => {a:1, b:3, c:4} +``` +* 若只有**一个**参数,则返回该参数。 +```js +let a = {a:1}; +Object.assign(a) === a; // true +``` +* 若参数**不是对象**,则先转成对象后返回。 +```js +typeof Object.assign(2); // 'object' +``` +* 由于`undefined`或`NaN`无法转成对象,所以做为参数会报错。 +```js +Object.assign(undefined) // 报错 +Object.assign(NaN); // 报错 +``` +* `Object.assign()`实现的是浅拷贝。 + +`Object.assign()`拷贝得到的是这个对象的引用。这个对象的任何变化,都会反映到目标对象上面。 +```js +let a = {a: {b:1}}; +let b = Object.assign({},a); +a.a.b = 2; +console.log(b.a.b); // 2 +``` +* 将数组当做对象处理,键名为数组下标,键值为数组下标对应的值。 +```js +Object.assign([1, 2, 3], [4, 5]); // [4, 5, 3] +``` + +# 5.ES8新增:Object.values(),Object.entries() +ES7中新增加的 `Object.values()`和`Object.entries()`与之前的`Object.keys()`类似,返回数组类型。 +回顾下`Object.keys()`: +```js +var a = { f1: 'hi', f2: 'leo'}; +Object.keys(a); // ['f1', 'f2'] +``` +## 5.1 Object.values() +返回一个数组,成员是参数对象自身的(不含继承的)所有**可遍历属性**的键值。 +```js +let a = { f1: 'hi', f2: 'leo'}; +Object.values(a); // ['hi', 'leo'] +``` +如果参数不是对象,则返回空数组: +```js +Object.values(10); // [] +Object.values(true); // [] +``` + +## 5.2 Object.entries() +返回一个数组,成员是参数对象自身的(不含继承的)所有**可遍历属性**的键值对数组。 +```js +let a = { f1: 'hi', f2: 'leo'}; +Object.entries(a); // [['f1','hi'], ['f2', 'leo']] +``` +* **用途1**: +遍历对象属性。 +```js +let a = { f1: 'hi', f2: 'leo'}; +for (let [k, v] of Object.entries(a)){ + console.log( + `${JSON.stringfy(k)}:${JSON.stringfy(v)}` + ) +} +// 'f1':'hi' +// 'f2':'leo' +``` +* **用途2**: +将对象转为真正的Map结构。 +```js +let a = { f1: 'hi', f2: 'leo'}; +let map = new Map(Object.entries(a)); +``` +手动实现`Object.entries()`方法: +```js +// Generator函数实现: +function* entries(obj){ + for (let k of Object.keys(obj)){ + yield [k ,obj[k]]; + } +} + +// 非Generator函数实现: +function entries (obj){ + let arr = []; + for(let k of Object.keys(obj)){ + arr.push([k, obj[k]]); + } + return arr; +} +``` + +# 6.ES8新增:Object.getOwnPropertyDescriptors() +之前有`Object.getOwnPropertyDescriptor`方法会返回某个对象属性的描述对象,新增的`Object.getOwnPropertyDescriptors()`方法,返回指定对象所有自身属性(非继承属性)的描述对象,所有原对象的属性名都是该对象的属性名,对应的属性值就是该属性的描述对象 +```js +let a = { + a1:1, + get f1(){ return 100} +} +Object.getOwnPropetyDescriptors(a); +/* +{ + a:{ configurable:true, enumerable:true, value:1, writeable:true} + f1:{ configurable:true, enumerable:true, get:f, set:undefined} +} +*/ +``` +实现原理: +```js +function getOwnPropertyDescriptors(obj) { + const result = {}; + for (let key of Reflect.ownKeys(obj)) { + result[key] = Object.getOwnPropertyDescriptor(obj, key); + } + return result; +} +``` +引入这个方法,主要是为了解决`Object.assign()`无法正确拷贝`get`属性和`set`属性的问题。 +```js +let a = { + set f(v){ + console.log(v) + } +} +let b = {}; +Object.assign(b, a); +Object.a(b, 'f'); +/* +f = { + configurable: true, + enumable: true, + value: undefined, + writeable: true +} +*/ +``` +`value`为`undefined`是因为`Object.assign`方法不会拷贝其中的`get`和`set`方法,使用`getOwnPropertyDescriptors`配合`Object.defineProperties`方法来实现正确的拷贝: +```js +let a = { + set f(v){ + console.log(v) + } +} +let b = {}; +Object.defineProperties(b, Object.getOwnPropertyDescriptors(a)); +Object.getOwnPropertyDescriptor(b, 'f') +/* + configurable: true, + enumable: true, + get: undefined, + set: function(){...} +*/ +``` +`Object.getOwnPropertyDescriptors`方法的配合`Object.create`方法,将对象属性克隆到一个新对象,实现浅拷贝。 +```js +const clone = Object.create(Object.getPrototypeOf(obj), + Object.getOwnPropertyDescriptors(obj)); + +// 或者 +const shallowClone = (obj) => Object.create( + Object.getPrototypeOf(obj), + Object.getOwnPropertyDescriptors(obj) +); +``` + +# 7.ES9新增:对象的拓展运算符 +## 7.1 介绍 +对象的拓展运算符,即对象的Rest/Spread属性,可将对象解构赋值用于从一个对象取值,搜键值对分配到指定对象上,与数组的拓展运算符类似: +```js +let {x, y, ...z} = {x:1, y:2, a:3, b:4}; +x; // 1 +y; // 2 +z; // {a:3, b:4} +``` +对象的解构赋值要求等号右边必须是个对象,所以如果等号右边是`undefined`或`null`就会报错无法转成对象。 +```js +let {a, ...b} = null; // 运行时报错 +let {a, ...b} = undefined; // 运行时报错 +``` +解构赋值必须是最后一个参数,否则报错。 +```js +let {...a, b, c} = obj; // 语法错误 +let {a, ...b, c} = obj; // 语法错误 +``` +**注意**: +* 1.解构赋值是浅拷贝。 +```js +let a = {a1: {a2: 'leo'}}; +let {...b} = a; +a.a1.a2 = 'leo'; +b.a1.a2 = 'leo'; +``` +* 2.拓展运算符的解构赋值,不能复制继承自原型对象的属性。 +```js +let o1 = { a: 1 }; +let o2 = { b: 2 }; +o2.__proto__ = o1; +let { ...o3 } = o2; +o3; // { b: 2 } +o3.a; // undefined +``` + +## 7.2 使用场景 +* 1.取出参数对象所有可遍历属性,拷贝到当前对象中。 +```js +let a = { a1:1, a2:2 }; +let b = { ...a }; +b; // { a1:1, a2:2 } + +// 类似Object.assign方法 +``` +* 2.合并两个对象。 +```js +let a = { a1:1, a2:2 }; +let b = { b1:11, b2:22 }; +let ab = { ...a, ...b }; // {a1: 1, a2: 2, b1: 11, b2: 22} +// 等同于 +let ab = Object.assign({}, a, b); +``` +* 3.将自定义属性放在拓展运算符后面,覆盖对象原有的同名属性。 +```js +let a = { a1:1, a2:2, a3:3 }; +let r = { ...a, a3:666 }; +// r {a1: 1, a2: 2, a3: 666} + +// 等同于 +let r = { ...a, ...{ a3:666 }}; +// r {a1: 1, a2: 2, a3: 666} + +// 等同于 +let r = Object.assign({}, a, { a3:666 }); +// r {a1: 1, a2: 2, a3: 666} +``` +* 4.将自定义属性放在拓展运算符前面,就会成为设置新对象的默认值。 +```js +let a = { a1:1, a2:2 }; +let r = { a3:666, ...a }; +// r {a3: 666, a1: 1, a2: 2} + +// 等同于 +let r = Object.assign({}, {a3:666}, a); +// r {a3: 666, a1: 1, a2: 2} + +// 等同于 +let r = Object.assign({a3:666}, a); +// r {a3: 666, a1: 1, a2: 2} +``` +* 5.拓展运算符后面可以使用表达式。 +```js +let a = { + ...(x>1? {a:!:{}), + b:2 +} +``` +* 6.拓展运算符后面如果是个空对象,则没有任何效果。 +```js +{...{}, a:1}; // {a:1} +``` +* 7.若参数是`null`或`undefined`则忽略且不报错。 +```js +let a = { ...null, ...undefined }; // 不报错 +``` +* 8.若有取值函数`get`则会执行。 +```js +// 不会打印 因为f属性只是定义 而不没执行 +let a = { + ...a1, + get f(){console.log(1)} +} + +// 会打印 因为f执行了 +let a = { + ...a1, + ...{ + get f(){console.log(1)} + } +} +``` + +# 参考资料 +1.[MDN 使用对象](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Working_with_Objects) +2.[W3school JavaScript 对象](http://www.w3school.com.cn/js/js_obj_intro.asp) + +--- +**本部分内容到这结束** + +|Author|王平安| +|---|---| +|E-mail|pingan8787@qq.com| +|博 客|www.pingan8787.com| +|微 信|pingan8787| +|每日文章推荐|https://github.com/pingan8787/Leo_Reading/issues| +|ES小册|js.pingan8787.com| \ No newline at end of file diff --git "a/Cute-JavaScript/Cute-JS/level1/13.\350\277\255\344\273\243\345\231\250\345\222\214\347\224\237\346\210\220\345\231\250.md" "b/Cute-JavaScript/Cute-JS/level1/13.\350\277\255\344\273\243\345\231\250\345\222\214\347\224\237\346\210\220\345\231\250.md" new file mode 100644 index 00000000..b4cbc8de --- /dev/null +++ "b/Cute-JavaScript/Cute-JS/level1/13.\350\277\255\344\273\243\345\231\250\345\222\214\347\224\237\346\210\220\345\231\250.md" @@ -0,0 +1,565 @@ +本文是 **重温基础** 系列文章的第十三篇。 +今日感受:每次自我年终总结,都会有各种情绪和收获。 + +**本章节复习的是JS中的迭代器和生成器,常常用来处理集合。** + +前置知识: +JavaScrip已经提供多个迭代集合的方法,从简单的`for`循环到`map()`和`filter()`。 +迭代器和生成器将迭代的概念直接带入核心语言,并提供一种机制来自定义`for...of`循环的行为。 + +**本文会将知识点分为两大部分,简单介绍和详细介绍**: +简单介绍,适合基础入门会使用的目标; +详细介绍,会更加深入的做介绍,适合理解原理; + +# 1. 概述 +当我们使用循环语句迭代数据时,需初始化一个变量来记录每一次迭代在数据集合中的位置: +```js +let a = ["aaa","bbb","ccc"]; +for (let i = 0; i< a.length; i++){ + console.log(a[i]); +} +``` +这边的`i`就是我们用来记录迭代位置的变量,但是在**ES6**开始,JavaScrip引入了迭代器这个特性,并且**新的数组方法**和**新的集合类型**(如`Set集合`与`Map集合`)都依赖迭代器的实现,这个新特性对于**高效的数据处理**而言是不可或缺的,在语言的其他特性中也都有迭代器的身影:新的`for-of循环`、展开运算符(`...`),甚至连**异步编程**都可以使用迭代器。 + +本文主要会介绍ES6中新增的迭代器(Iterator)和生成器(Generator)。 + +# 2. 迭代器(简单介绍) +迭代器是一种特殊对象,它具有一些专门为迭代过程设计的专有接口,所有的迭代器对象都有一个`next()`方法,每次调用都会返回一个结果对象。 +这个结果对象,有两个属性: +* `value`: 表示下一个将要返回的值。 +* `done`: 一个布尔值,若没有更多可返回的数据时,值为`true`,否则`false`。 + +如果最后一个值返回后,再调用`next()`,则返回的对象的`done`值为`true`,而`value`值如果没有值的话,返回的为`undefined`。 + +**ES5**实现一个迭代器: +```js +function myIterator(list){ + var i = 0; + return { + next: function(){ + var done = i >= list.length; + var value = !done ? list[i++] : undefined; + return { + done : done, + value : value + } + } + } +} + +var iterator = myIterator([1,2,3]); +iterator.next(); // "{done: false, value: 1}" +iterator.next(); // "{done: false, value: 2}" +iterator.next(); // "{done: false, value: 3}" +iterator.next(); // "{done: true, value: undefined}" +// 以后的调用都一样 +iterator.next(); // "{done: true, value: undefined}" +``` + +从上面代码可以看出,ES5的实现还是比较麻烦,而ES6新增的生成器,可以使得创建迭代器对象的过程更加简单。 + +# 3. 生成器(简单介绍) +生成器是一种返回迭代器的函数,通过`function`关键字后的星号(`*`)来表示,函数中会用到新的关键字`yield`。星号可以紧挨着`function`关键字,也可以在中间添加一个空格。 + +```js +function *myIterator(){ + yield 1; + yield 2; + yield 3; +} +let iterator = myIterator(); +iterator.next(); // "{done: false, value: 1}" +iterator.next(); // "{done: false, value: 2}" +iterator.next(); // "{done: false, value: 3}" +iterator.next(); // "{done: true, value: undefined}" +// 以后的调用都一样 +iterator.next(); // "{done: true, value: undefined}" +``` + +生成器函数最有趣的部分是,每当执行完一条`yield`语句后函数就会自动停止执行,比如上面代码,当`yield 1;`执行完后,便不会执行任何语句,而是等到再调用迭代器的`next()`方法才会执行下一个语句,即`yield 2;`. +使用`yield`关键字可以返回任何值和表达式,因为可以通过生成器函数批量给迭代器添加元素: +```js +function *myIterator(list){ + for(let i = 0; i< list.length ; i ++){ + yield list[i]; + } +} + +var iterator = myIterator([1,2,3]); +iterator.next(); // "{done: false, value: 1}" +iterator.next(); // "{done: false, value: 2}" +iterator.next(); // "{done: false, value: 3}" +iterator.next(); // "{done: true, value: undefined}" +// 以后的调用都一样 +iterator.next(); // "{done: true, value: undefined}" +``` + +生成器的适用返回很广,可以将它用于所有支持函数使用的地方。 + +# 4. 迭代器(详细介绍) +## 4.1 Iterator迭代器概念 +> **Iterator**是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 **Iterator** 接口,就可以完成迭代操作(即依次处理该数据结构的所有成员)。 + +**Iterator三个作用**: +* 为各种数据结构,提供一个**统一**的、**简便**的访问接口; +* 使得数据结构的成员能够按某种次序排列; +* **Iterator** 接口主要供ES6新增的`for...of`消费; + +## 4.2 Iterator迭代过程 +1. 创建一个指针对象,指向当前数据结构的起始位置。也就是说,迭代器对象本质上,就是一个指针对象。 +2. 第一次调用指针对象的`next`方法,可以将指针指向数据结构的第一个成员。 +3. 第二次调用指针对象的`next`方法,指针就指向数据结构的第二个成员。 +4. 不断调用指针对象的`next`方法,直到它指向数据结构的结束位置。 + +每一次调用`next`方法,都会返回数据结构的当前成员的信息。具体来说,就是返回一个包含`value`和`done`两个属性的对象。 + +* `value`属性是当前成员的值; +* `done`属性是一个布尔值,表示迭代是否结束; + +模拟`next`方法返回值: +```js +let f = function (arr){ + var nextIndex = 0; + return { + next:function(){ + return nextIndex < arr.length ? + {value: arr[nextIndex++], done: false}: + {value: undefined, done: true} + } + } +} + +let a = f(['a', 'b']); +a.next(); // { value: "a", done: false } +a.next(); // { value: "b", done: false } +a.next(); // { value: undefined, done: true } +``` + +## 4.3 默认Iterator接口 +若数据**可迭代**,即一种数据部署了Iterator接口。 +ES6中默认的Iterator接口部署在数据结构的`Symbol.iterator`属性,即如果一个数据结构具有`Symbol.iterator`属性,就可以认为是**可迭代**。 +`Symbol.iterator`属性本身是函数,是当前数据结构默认的迭代器生成函数。执行这个函数,就会返回一个迭代器。至于属性名`Symbol.iterator`,它是一个表达式,返回`Symbol`对象的`iterator`属性,这是一个预定义好的、类型为 Symbol 的特殊值,所以要放在方括号内(参见《Symbol》一章)。 + +**原生具有Iterator接口的数据结构有**: +* Array +* Map +* Set +* String +* TypedArray +* 函数的 arguments 对象 +* NodeList 对象 + +## 4.4 Iterator使用场景 +* **(1)解构赋值** +对数组和 `Set` 结构进行解构赋值时,会默认调用`Symbol.iterator`方法。 +```js +let a = new Set().add('a').add('b').add('c'); +let [x, y] = a; // x = 'a' y = 'b' +let [a1, ...a2] = a; // a1 = 'a' a2 = ['b','c'] +``` + +* **(2)扩展运算符** +扩展运算符(`...`)也会调用默认的 Iterator 接口。 +```js +let a = 'hello'; +[...a]; // ['h','e','l','l','o'] + +let a = ['b', 'c']; +['a', ...a, 'd']; // ['a', 'b', 'c', 'd'] +``` + +* **(2)yield*** +`yield*`后面跟的是一个可迭代的结构,它会调用该结构的迭代器接口。 +```js +let a = function*(){ + yield 1; + yield* [2,3,4]; + yield 5; +} + +let b = a(); +b.next() // { value: 1, done: false } +b.next() // { value: 2, done: false } +b.next() // { value: 3, done: false } +b.next() // { value: 4, done: false } +b.next() // { value: 5, done: false } +b.next() // { value: undefined, done: true } +``` + +* **(4)其他场合** +由于数组的迭代会调用迭代器接口,所以任何接受数组作为参数的场合,其实都调用了迭代器接口。下面是一些例子。 + +* for...of +* Array.from() +* Map(), Set(), WeakMap(), WeakSet()(比如`new Map([['a',1],['b',2]])`) +* Promise.all() +* Promise.race() + +## 4.5 for...of循环 +只要数据结构部署了`Symbol.iterator`属性,即具有 iterator 接口,可以用`for...of`循环迭代它的成员。也就是说,`for...of`循环内部调用的是数据结构的`Symbol.iterato`方法。 +**使用场景**: +`for...of`可以使用在**数组**,**`Set`和`Map`结构**,**类数组对象**,**Genetator对象**和**字符串**。 + +* **数组** +`for...of`循环可以代替数组实例的`forEach`方法。 +```js +let a = ['a', 'b', 'c']; +for (let k of a){console.log(k)}; // a b c + +a.forEach((ele, index)=>{ + console.log(ele); // a b c + console.log(index); // 0 1 2 +}) +``` +与`for...in`对比,`for...in`只能获取对象键名,不能直接获取键值,而`for...of`允许直接获取键值。 +```js +let a = ['a', 'b', 'c']; +for (let k of a){console.log(k)}; // a b c +for (let k in a){console.log(k)}; // 0 1 2 +``` + +* **Set和Map** +可以使用数组作为变量,如`for (let [k,v] of b){...}`。 +```js +let a = new Set(['a', 'b', 'c']); +for (let k of a){console.log(k)}; // a b c + +let b = new Map(); +b.set('name','leo'); +b.set('age', 18); +b.set('aaa','bbb'); +for (let [k,v] of b){console.log(k + ":" + v)}; +// name:leo +// age:18 +// aaa:bbb +``` + +* **类数组对象** +```js +// 字符串 +let a = 'hello'; +for (let k of a ){console.log(k)}; // h e l l o + +// DOM NodeList对象 +let b = document.querySelectorAll('p'); +for (let k of b ){ + k.classList.add('test'); +} + +// arguments对象 +function f(){ + for (let k of arguments){ + console.log(k); + } +} +f('a','b'); // a b +``` + +* **对象** +普通对象不能直接使用`for...of`会报错,要部署Iterator才能使用。 +```js +let a = {a:'aa',b:'bb',c:'cc'}; +for (let k in a){console.log(k)}; // a b c +for (let k of a){console>log(k)}; // TypeError +``` + +## 4.6 跳出for...of +使用`break`来实现。 +```js +for (let k of a){ + if(k>100) + break; + console.log(k); +} +``` + +# 5. 生成器(详细介绍) +## 5.1 基本概念 +`Generator`生成器函数是一种异步编程解决方案。 +**原理**: +执行`Genenrator`函数会返回一个遍历器对象,依次遍历`Generator`函数内部的每一个状态。 +`Generator`函数是一个普通函数,有以下两个特征: +* `function`关键字与函数名之间有个星号; +* 函数体内使用`yield`表达式,定义不同状态; + +通过调用`next`方法,将指针移向下一个状态,直到遇到下一个`yield`表达式(或`return`语句)为止。简单理解,`Generator`函数分段执行,`yield`表达式是暂停执行的标记,而`next`恢复执行。 +```js +function * f (){ + yield 'hi'; + yield 'leo'; + return 'ending'; +} +let a = f(); +a.next(); // {value: 'hi', done : false} +a.next(); // {value: 'leo', done : false} +a.next(); // {value: 'ending', done : true} +a.next(); // {value: undefined, done : false} +``` + +## 5.2 yield表达式 +`yield`表达式是暂停标志,遍历器对象的`next`方法的运行逻辑如下: +1. 遇到`yield`就暂停执行,将这个`yield`后的表达式的值,作为返回对象的`value`属性值。 +2. 下次调用`next`往下执行,直到遇到下一个`yield`。 +3. 直到函数结束或者`return`为止,并返回`return`语句后面表达式的值,作为返回对象的`value`属性值。 +4. 如果该函数没有`return`语句,则返回对象的`value`为`undefined` 。 + +**注意:** +* `yield`只能用在`Generator`函数里使用,其他地方使用会报错。 +```js +// 错误1 +(function(){ + yiled 1; // SyntaxError: Unexpected number +})() + +// 错误2 forEach参数是个普通函数 +let a = [1, [[2, 3], 4], [5, 6]]; +let f = function * (i){ + i.forEach(function(m){ + if(typeof m !== 'number'){ + yield * f (m); + }else{ + yield m; + } + }) +} +for (let k of f(a)){ + console.log(k) +} +``` + +* `yield`表达式如果用于另一个表达式之中,必须放在**圆括号**内。 +```js +function * a (){ + console.log('a' + yield); // SyntaxErro + console.log('a' + yield 123); // SyntaxErro + console.log('a' + (yield)); // ok + console.log('a' + (yield 123)); // ok +} +``` + +* `yield`表达式用做函数参数或放在表达式右边,可以**不加括号**。 +```js +function * a (){ + f(yield 'a', yield 'b'); // ok + lei i = yield; // ok +} +``` + +## 5.3 next方法 +`yield`本身没有返回值,或者是总返回`undefined`,`next`方法可带一个参数,作为上一个`yield`表达式的返回值。 +```js +function * f (){ + for (let k = 0; true; k++){ + let a = yield k; + if(a){k = -1}; + } +} +let g =f(); +g.next(); // {value: 0, done: false} +g.next(); // {value: 1, done: false} +g.next(true); // {value: 0, done: false} +``` +这一特点,可以让`Generator`函数开始执行之后,可以从外部向内部注入不同值,从而调整函数行为。 +```js +function * f(x){ + let y = 2 * (yield (x+1)); + let z = yield (y/3); + return (x + y + z); +} +let a = f(5); +a.next(); // {value : 6 ,done : false} +a.next(); // {value : NaN ,done : false} +a.next(); // {value : NaN ,done : true} +// NaN因为yeild返回的是对象 和数字计算会NaN + +let b = f(5); +b.next(); // {value : 6 ,done : false} +b.next(12); // {value : 8 ,done : false} +b.next(13); // {value : 42 ,done : false} +// x 5 y 24 z 13 +``` + +## 5.4 for...of循环 +`for...of`循环会自动遍历,不用调用`next`方法,需要注意的是,`for...of`遇到`next`返回值的`done`属性为`true`就会终止,`return`返回的不包括在`for...of`循环中。 +```js +function * f(){ + yield 1; + yield 2; + yield 3; + yield 4; + return 5; +} +for (let k of f()){ + console.log(k); +} +// 1 2 3 4 没有 5 +``` + +## 5.5 Generator.prototype.throw() +`throw`方法用来向函数外抛出错误,并且在Generator函数体内捕获。 +```js +let f = function * (){ + try { yield } + catch (e) { console.log('内部捕获', e) } +} + +let a = f(); +a.next(); + +try{ + a.throw('a'); + a.throw('b'); +}catch(e){ + console.log('外部捕获',e); +} +// 内部捕获 a +// 外部捕获 b +``` + +## 5.6 Generator.prototype.return() +`return`方法用来返回给定的值,并结束遍历Generator函数,如果`return`方法没有参数,则返回值的`value`属性为`undefined`。 +```js +function * f(){ + yield 1; + yield 2; + yield 3; +} +let g = f(); +g.next(); // {value : 1, done : false} +g.return('leo'); // {value : 'leo', done " true} +g.next(); // {value : undefined, done : true} +``` + +## 5.7 next()/throw()/return()共同点 +相同点就是都是用来恢复Generator函数的执行,并且使用不同语句替换`yield`表达式。 +* `next()`将`yield`表达式替换成一个值。 +```js +let f = function * (x,y){ + let r = yield x + y; + return r; +} +let g = f(1, 2); +g.next(); // {value : 3, done : false} +g.next(1); // {value : 1, done : true} +// 相当于把 let r = yield x + y; +// 替换成 let r = 1; +``` +* `throw()`将`yield`表达式替换成一个`throw`语句。 +```js +g.throw(new Error('报错')); // Uncaught Error:报错 +// 相当于将 let r = yield x + y +// 替换成 let r = throw(new Error('报错')); +``` +* `next()`将`yield`表达式替换成一个`return`语句。 +```js +g.return(2); // {value: 2, done: true} +// 相当于将 let r = yield x + y +// 替换成 let r = return 2; +``` + +## 5.8 yield* 表达式 +用于在一个Generator中执行另一个Generator函数,如果没有使用`yield*`会没有效果。 +```js +function * a(){ + yield 1; + yield 2; +} +function * b(){ + yield 3; + yield * a(); + yield 4; +} +// 等同于 +function * b(){ + yield 3; + yield 1; + yield 2; + yield 4; +} +for(let k of b()){console.log(k)} +// 3 +// 1 +// 2 +// 4 +``` + +## 5.9 应用场景 +1. **控制流管理** +解决回调地狱: +```js +// 使用前 +f1(function(v1){ + f2(function(v2){ + f3(function(v3){ + // ... more and more + }) + }) +}) + +// 使用Promise +Promise.resolve(f1) + .then(f2) + .then(f3) + .then(function(v4){ + // ... + },function (err){ + // ... + }).done(); + +// 使用Generator +function * f (v1){ + try{ + let v2 = yield f1(v1); + let v3 = yield f1(v2); + let v4 = yield f1(v3); + // ... + }catch(err){ + // console.log(err) + } +} +function g (task){ + let obj = task.next(task.value); + // 如果Generator函数未结束,就继续调用 + if(!obj.done){ + task.value = obj.value; + g(task); + } +} +g( f(initValue) ); +``` + +2. **异步编程的使用** +在真实的异步任务封装的情况: +```js +let fetch = require('node-fetch'); +function * f(){ + let url = 'http://www.baidu.com'; + let res = yield fetch(url); + console.log(res.bio); +} +// 执行该函数 +let g = f(); +let result = g.next(); +// 由于fetch返回的是Promise对象,所以用then +result.value.then(function(data){ + return data.json(); +}).then(function(data){ + g.next(data); +}) +``` + + +# 参考资料 +[1.MDN 迭代器和生成器](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Iterators_and_generators) +[2.ES6中的迭代器(Iterator)和生成器(Generator)](https://www.cnblogs.com/xiaohuochai/p/7253466.html) + +--- +**本部分内容到这结束** + +|Author|王平安| +|---|---| +|E-mail|pingan8787@qq.com| +|博 客|www.pingan8787.com| +|微 信|pingan8787| +|每日文章推荐|https://github.com/pingan8787/Leo_Reading/issues| +|ES小册|js.pingan8787.com| \ No newline at end of file diff --git "a/Cute-JavaScript/Cute-JS/level1/14.\345\205\203\347\274\226\347\250\213.md" "b/Cute-JavaScript/Cute-JS/level1/14.\345\205\203\347\274\226\347\250\213.md" new file mode 100644 index 00000000..87e231d2 --- /dev/null +++ "b/Cute-JavaScript/Cute-JS/level1/14.\345\205\203\347\274\226\347\250\213.md" @@ -0,0 +1,281 @@ +本文是 **重温基础** 系列文章的第十四篇。 +**这是第一个基础系列的最后一篇,后面会开始复习一些中级的知识了,欢迎持续关注呀** +接下来会统一整理到我的[【Cute-JavaScript】](http://js.pingan8787.com/)的**JavaScript基础系列**中。 + +今日感受:独乐乐不如众乐乐。 + +**本章节复习的是JS中的元编程,涉及的更多的是ES6的新特性。** + +# 1. 概述 +元编程,其实我是这么理解的:**让代码自动写代码,可以更改源码底层的功能**。 +元,是指程序本身。 +有理解不到位,还请指点,具体详细的介绍,可以查看[维基百科 元编程](https://zh.wikipedia.org/wiki/%E5%85%83%E7%BC%96%E7%A8%8B) 。 +从ES6开始,JavaScrip添加了对`Proxy`和`Reflect`对象的支持,允许我们连接并定义基本语言操作的自定义行为(如属性查找,赋值,枚举和函数调用等),从而实现JavaScrip的元级别编程。 + +* `Reflect`: 用于替换直接调用`Object`的方法,并不是一个函数对象,也没有`constructor`方法,所以不能用`new`操作符。 +* `Proxy`: 用于自定义对象的行为,如修改`set`和`get`方法,可以说是ES5中`Object.defineProperty()`方法的ES6升级版。 +* 两者联系: API完全一致,但`Reflect`一般在`Proxy`需要处理默认行为的时候使用。 + +**参考资料**: + +|名称|地址| +|---|---| +|`Reflect`|[MDN Reflect](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect)| +|`Proxy`|[MDN Proxy](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy)| +|元编程|[MDN 元编程](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Meta_programming)| + + +**本文主要从Proxy介绍,还会有几个案例,实际看下怎么使用。** + +# 2. Proxy介绍 +`proxy` 用于修改某些操作的**默认行为**,可以理解为一种拦截外界对目标对象访问的一种机制,从而对外界的访问进行过滤和修改,即代理某些操作,也称“**代理器**”。 +## 2.1 基础使用 +基本语法: +```js +let p = new Proxy(target, handler); +``` +`proxy`实例化需要传入两个参数,`target`参数表示所要拦截的目标对象,`handler`参数也是一个对象,用来定制拦截行为。 +```js +let p = new Proxy({}, { + get: function (target, handler){ + return 'leo'; + } +}) +p.name; // leo +p.age; // leo +p.abcd; // leo +``` +上述`a`实例中,在第二个参数中定义了`get`方法,来拦截外界访问,并且`get`方法接收两个参数,分别是**目标对象**和**所要访问的属性**,所以不管外部访问对象中任何属性都会执行`get`方法返回`leo`。 + +**注意**: +* 只能使用`Proxy`实例的对象才能使用这些操作。 +* 如果`handler`没有设置拦截,则直接返回原对象。 +```js +let target = {}; +let handler = {}; +let p = new Proxy(target, handler); +p.a = 'leo'; +target.a; // 'leo' +``` +**同个拦截器函数,设置多个拦截操作**: +```js +let p = new Proxy(function(a, b){ + return a + b; +},{ + get:function(){ + return 'get方法'; + }, + apply:function(){ + return 'apply方法'; + } +}) +``` +这里还有一个简单的案例: +```js +let handler = { + get : function (target, name){ + return name in target ? target[name] : 16; + } +} + +let p = new Proxy ({}, handler); +p.a = 1; +console.log(p.a , p.b); +// 1 16 +``` +这里因为 `p.a = 1` 定义了`p`中的`a`属性,值为`1`,而没有定义`b`属性,所以`p.a`会得到`1`,而`p.b`会得到`undefined`从而使用`name in target ? target[name] : 16;`返回的默认值`16`; + + +**`Proxy`支持的13种拦截操作**: +13种拦截操作的详细介绍:[打开阮一峰老师的链接](http://es6.ruanyifeng.com/#docs/proxy)。 +* `get(target, propKey, receiver)`: +拦截对象属性的读取,比如proxy.foo和proxy['foo']。 + +* `set(target, propKey, value, receiver)`: +拦截对象属性的设置,比如proxy.foo = v或proxy['foo'] = v,返回一个布尔值。 + +* `has(target, propKey)`: +拦截propKey in proxy的操作,返回一个布尔值。 + +* `deleteProperty(target, propKey)`: +拦截delete proxy[propKey]的操作,返回一个布尔值。 + +* `ownKeys(target)`: +拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。 + +* `getOwnPropertyDescriptor(target, propKey)`: +拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。 + +* `defineProperty(target, propKey, propDesc)`: +拦截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。 + +* `preventExtensions(target)`: +拦截Object.preventExtensions(proxy),返回一个布尔值。 + +* `getPrototypeOf(target)`: +拦截Object.getPrototypeOf(proxy),返回一个对象。 + +* `isExtensible(target)`: +拦截Object.isExtensible(proxy),返回一个布尔值。 + +* `setPrototypeOf(target, proto)`: +拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。 + +* `apply(target, object, args)`: +拦截 Proxy 实例作为函数调用的操作,比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。 + +* `construct(target, args)`: +拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(...args)。 + +## 2.2 取消Proxy实例 +使用`Proxy.revocable`方法取消`Proxy`实例。 +```js +let a = {}; +let b = { + get: function(target, name) { + return "[[" + name + "]]"; + } +}; +let revoke = Proxy.revocable(a, b); +let proxy = revoke.proxy; + +proxy.age; // "[[age]]" +revoke.revoke(); +proxy.age; // Uncaught TypeError: Cannot perform 'get' on a proxy that has been revoked + +proxy.age = 10; // Uncaught TypeError: Cannot perform 'set' on a proxy that has been revoked +delete proxy.age; // Uncaught TypeError: Cannot perform 'deleteProperty' on a proxy that has been revoked +typeof proxy; // "object" +``` + +## 2.3 实现 Web服务的客户端 +```js +const service = createWebService('http://le.com/data'); +service.employees().than(json =>{ + const employees = JSON.parse(json); +}) + +function createWebService(url){ + return new Proxy({}, { + get(target, propKey, receiver{ + return () => httpGet(url+'/'+propKey); + }) + }) +} +``` + +# 3. Proxy实践 +## 3.1 数据拦截验证 +通过`Proxy`代理对象的`set`和`get`方法来进行拦截数据,像`Vue`就是用数据拦截来实现数据绑定。 +```js +let handler = { + // 拦截并处理get方法 + // 可以理解为设置get方法返回的默认值 + get : function (target, key){ + return key in target ? target[key] : 30; + }, + + // 拦截并处理set方法 + // 可以理解为设置set方法的默认行为 + set : function (target, key, value){ + if(key === "age"){ + if (!Number.isInteger(value)){ + throw new TypeError("age不是一个整数!"); + } + if (value > 200){ + throw new TypeError("age不能大于200!"); + } + } + // 保存默认行为 + target[key] = value; + } +} + +let p = new Proxy({}, handler); +p.a = 10; // p.a => 10 +p.b = undefined; // p.b => undefined +p.c; // 默认值 30 +p.age = 100; // p.age => 100 +p.age = 300; // Uncaught TypeError: age不能大于200! +p.age = "leo"; // Uncaught TypeError: age不是一个整数! +``` + +## 3.2 函数节流 +通过拦截`handler.apply()`方法的调用,实现函数只能在1秒之后才能再次被调用,经常可以用在防止重复事件的触发。 +```js +let p = (fun, time) => { + // 获取最后点击时间 + let last = Date.now() - time; + return new Proxy (fun, { + apply(target, context, args){ + if(Date.now() - last >= time){ + fun.bind(target)(args); + // 重复设置当前时间 + last = Date.now(); + } + } + }) +} + +let p1 = () => { + console.log("点击触发"); +} +let time = 1000; // 设置时间 +let proxyObj = p(p1, time); +// 监听滚动事件 +document.addEventListener('scroll', proxyObj); +``` + +## 3.3 实现单例模式 +通过拦截`construct`方法,让不同实例指向相同的`constructer`,实现单例模式。 +```js +let p = function(fun){ + let instance; + let handler = { + // 拦截construct方法 + construct: function(targer, args){ + if(!instance){ + instance = new fun(); + } + return instance; + } + } + return new Proxy(fun, handler); +} + +// 创建一个construct案例 +function Cons (){ + this.value = 0; +} + +// 创建实例 +let p1 = new Cons(); +let p2 = new Cons(); + +// 操作 +p1.value = 100; +// p1.value => 100 , p2.value => 0 +// 因为不是相同实例 + +// 通过Proxy实现单例 +let singleton = p(Cons); +let p3 = new singleton(); +let p4 = new singleton(); +p3.value = 130; +// p1.value => 130 , p2.value => 130 +// 现在是相同实例 +``` + + +# 参考资料 +[1.MDN 元编程](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Meta_programming) +[2. ES6中的元编程-Proxy & Reflect](https://www.cnblogs.com/buzhiqianduan/p/9687804.html) +**本部分内容到这结束** + +|Author|王平安| +|---|---| +|E-mail|pingan8787@qq.com| +|博 客|www.pingan8787.com| +|微 信|pingan8787| +|每日文章推荐|https://github.com/pingan8787/Leo_Reading/issues| +|ES小册|js.pingan8787.com| \ No newline at end of file diff --git "a/Cute-JavaScript/Cute-JS/level1/2.\346\265\201\347\250\213\346\216\247\345\210\266\345\222\214\351\224\231\350\257\257\345\244\204\347\220\206.md" "b/Cute-JavaScript/Cute-JS/level1/2.\346\265\201\347\250\213\346\216\247\345\210\266\345\222\214\351\224\231\350\257\257\345\244\204\347\220\206.md" new file mode 100644 index 00000000..295009a1 --- /dev/null +++ "b/Cute-JavaScript/Cute-JS/level1/2.\346\265\201\347\250\213\346\216\247\345\210\266\345\222\214\351\224\231\350\257\257\345\244\204\347\220\206.md" @@ -0,0 +1,129 @@ +本文是 **重温基础** 系列文章的第二篇,需要让自己静下心来,学习,养成好习惯。 + +**本章节复习的是JS中的控制流语句,让我们能实现更多的交互功能。** + +注意一点:在ES6之前,JS是没有**块作用域**的,如果在语句块外部声明的变量,如果在块内部声明一个相同名称的变量,那么程序将取后声明的这个变量的值: +```js +var a = 1; +{ + var a = 2; +} +a; // 2 +``` + +但是ES6开始,用`let`声明的变量是块作用域的: +```js +let a = 1; +{ + let a = 2; +} +a; // 1 +``` + +# 1.条件判断语句 +用于根据指定条件返回结果,常见的是`if...else`和`switch`: + +## if...else语句 +若条件为**真**,则执行`if`后面的语句,若条件为**假**,则执行`else`后面的语句: +```js +if(condition){ + // do something +}else{ + // else 为可选 + // do something +} +``` +**False等效值**: +在JS中下面的值常常被计算为`false` +* false +* undefined +* null +* 0 +* NaN +* 空字符串("") + +**注意**: +不要使用原始布尔值`true`和`false` 与 Boolean对象的真和假混淆: +```js +let a = new Boolean(false); // Boolean {true} +if (a); // 永真 +if (a == true); // 永假 +``` + +# 2.switch语句 +通过匹配表达式的值到每个`case`标签,若匹配成功则执行相关语句: +```js +switch ( 'leo' ){ + case 'pingan': + // do something + break; // 可选 + case 'leo': + // do something + break; + default: // 都不匹配 则执行默认 + // do something + break; +} +``` +`break`为可选,目的用于保证在正确匹配后,能跳出程序的`switch`语句,并继续执行其他代码,若没有`break`则程序会继续执行下一个`case`语句。 + +# 3.异常处理语句 +当`throw`语句抛出的异常,我们可以使用`try...catch`捕获并处理,这里需要先介绍两个概念: +## throw语句: +用于抛出异常,后面可以是任何表达式: +```js +throw "error !"; +throw 404; +throw {msg: 'err'}; +``` +## try...catch语句: +用于捕获异常,`try`后面是程序正常时候执行的程序,`catch`后面是当前面有错误抛出的时候执行,并且捕获错误信息作为参数,并且在`catch`块执行完成,参数不可再用。 +```js +function f(){ + throw 'test error!' +} +try{ + f(); + console.log('success'); +}catch (err){ // err 为前面返回的错误信息 + console.log(err); + console.log('failed'); +} +// test error! +// failed +``` +通常在`try...catch`后还有一个`finally`语句块,用于不论前面是否有报错,都会执行`finally`语句: +```js +try{ + // do something +}catch(err){ + // do something +}finally{ + // do something +} +``` +`try...catch`常常也用在做网络请求的情况下: +```js +function getData (){ + try{ + let a = fetch(url); + }catch(err){ + console.log(err); + } +} +``` + + +# 参考资料 +[1.MDN 流程控制与错误处理](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Control_flow_and_error_handling) + +--- +**本部分内容到这结束** + +|Author|王平安| +|---|---| +|E-mail|pingan8787@qq.com| +|博 客|www.pingan8787.com| +|微 信|pingan8787| +|每日文章推荐|https://github.com/pingan8787/Leo_Reading/issues| +|ES小册|js.pingan8787.com| \ No newline at end of file diff --git "a/Cute-JavaScript/Cute-JS/level1/3.\345\276\252\347\216\257\345\222\214\350\277\255\344\273\243.md" "b/Cute-JavaScript/Cute-JS/level1/3.\345\276\252\347\216\257\345\222\214\350\277\255\344\273\243.md" new file mode 100644 index 00000000..9a239359 --- /dev/null +++ "b/Cute-JavaScript/Cute-JS/level1/3.\345\276\252\347\216\257\345\222\214\350\277\255\344\273\243.md" @@ -0,0 +1,170 @@ +本文是 **重温基础** 系列文章的第三篇,今天想起鬼脚七的一句话:人不一定自由,但思想一定是自由的。思想没有对和错,也没有高和低,只有不同。了解一个人可以去了解他的思想。 +。 + +**本章节复习的是JS中的循环语句,让我们能更快速且简单的完成一些需求。** + +首先我们要知道:循环实际上就是把一个事情重复n次执行,也有可能是0次,JS中有以下几种循环语句类型: +* `for`语句 +* `do...while`语句 +* `while`语句 +* `labeled`语句 +* `break`语句 +* `continue`语句 +* `for...in`语句 +* `for...of`语句 + +# 1.`for`语句 +重复执行`for`的条件语句,直到循环条件为`false`退出循环: +```js +var a = 1; +for ( a < 3){ + a ++; +} +``` +这个语句大概执行了以下操作: +* 1.定义并初始化一个变量`a`的值为`1`; +* 2.执行循环语句,条件为当`a < 3`的时候,`a`每次递增`1`; +* 3.返回第2步继续循环; +* 4.当`a`在等于4的时候,不满足循环条件`a < 3`,然后退出循环; +其他例子: +```js +// 求数组中所有值的和 +var a = [ 1, 3, 4, 6]; +var sum = 0; +for (var i = 0; i < a.length; i++){ + sum += a[i]; +} +sum; // 14 +``` + +# 2.`do...while`语句 +重复执行`do`的条件,直到不符合`while`的条件,退出循环: +```js +do { + a += 1; + console.log(a); +} while (a < 5); +``` + +# 3.`while`语句 +重复执行`while`的条件,直到`while`的条件为`false`,退出循环: +```js +var a = 0; +var b = 0; +while (a < 5){ + a ++; + b += a; +} +// a => 5; b => 15 +``` + +# 4.`labeled`语句 +用来标识一个程序位置的标识符,如标识一个循环,并在`break`或`continue`中指出中国标识符,来停止这个循环。 +```js +var a = [1, 2, 3, 4, 5]; +labelName: +for(var i = 0 ;i< a.length; i++){ + console.log(i); + if(i > 1){ + break labelName; + } +} +// 0 +// 1 +// 2 +``` + +# 5.`break`语句 +用于终止一个循环,还可以在`switch`中终止,通常这么使用: +* 终止一个循环: +```js +for(var i = 0 ;i< a.length; i++){ + if(a[i] == 1){ + break; + } +} +``` +* 终止一个label +```js +leo: +for(var i = 0 ;i< a.length; i++){ + for(var j = 0 ;j< a.length; j++){ + if(a[i] == a[j]){ + break leo; + } + } +} +``` + +# 6.`continue`语句 +用来跳过当前循环,进入下个循环,可以使用在`while`、`do...while`、`for`或者`label`语句: +* 有使用`continue` +```js +var a = 0; +var b = 0; +while (a < 5 ){ + a ++; + if(a == 2){ + continue; + } + b += a; + console.log(b); +} +// 1 4 8 13 +``` +* 没有使用`continue` +```js +var a = 0; +var b = 0; +while (a < 5 ){ + a ++; + if(a == 2){ + // continue; + } + b += a; + console.log(b); +} +// 1,3,6,10,15 +``` + +# 7.`for...in`语句 +通常用于遍历一个对象的所有可枚举的属性,执行指定方法: +```js +var a = [ + {name : 'leo'}, + {name : 'pingan'}, + {name : '平安'}, +] +for(var k in a){ + // a为循环对象 k为当前指针位置 + console.log(a[k]); +} +``` + +# 8.`for...of`语句 +通常用于遍历一个可迭代对象(包括`Array`,`Map`,`Set`和参数对象`arguments`等),执行指定方法: +```js +var a = [1, 2, 5]; +for(var k in a){ + console.log(k); // k 为当前元素的下标 +} +for(var m of a){ + console.log(m); // m 为当前元素的值 +} +``` + + + +# 参考资料 +[1.MDN 循环和迭代](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Loops_and_iteration) + +--- +**本部分内容到这结束** + +|Author|王平安| +|---|---| +|E-mail|pingan8787@qq.com| +|博 客|www.pingan8787.com| +|微 信|pingan8787| +|每日文章推荐|https://github.com/pingan8787/Leo_Reading/issues| +|ES小册|js.pingan8787.com| \ No newline at end of file diff --git "a/Cute-JavaScript/Cute-JS/level1/4.\345\207\275\346\225\260.md" "b/Cute-JavaScript/Cute-JS/level1/4.\345\207\275\346\225\260.md" new file mode 100644 index 00000000..ff2285f3 --- /dev/null +++ "b/Cute-JavaScript/Cute-JS/level1/4.\345\207\275\346\225\260.md" @@ -0,0 +1,273 @@ +本文是 **重温基础** 系列文章的第四篇。 +今日感受:常怀感恩之心,对人对己。 + + +**本章节复习的是JS中的基础组件之一,函数,用来复用特定执行逻辑。** + +# 1.定义函数 +定义函数有两种方法:**函数声明** 和 **函数表达式** : +## 1.1 函数声明 +也成为**函数声明**,通常格式为: +```js +function f (a){ + return a + 1; +} +``` +**解释**:这里声明一个函数 `f` ,并传入一个参数 `a` ,当函数执行以后,通过 `return` 关键字返回了 `a+1`的值。 + +**参数**: +当传入的参数是一个数字/字符串等具体的值的时候,若参数的值被改变,不会影响到全局或调用函数。 +但如果参数是个对象,若函数内改变的这个参数的属性,则函数外部的这个参数原始的值会被修改。 +```js +var leo = { + age:20 +} +function f(obj){ + obj.age = 15; + obj.name = 'leo'; +} +f(leo); +console.log(leo); //{age: 15, name: "leo"} +``` + +## 1.2函数表达式 +通过定义一个匿名的函数,来赋值给一个变量,通过这个变量来调用这个函数。 +```js +var f = function (a){ + return a + 1; +} +``` +但是函数表达式也可以提供函数名,用于函数内部调用,并指代本身,也可以作为调试器堆栈跟踪中识别该函数。 +```js +var f = function g(a){ + return n < 2 ? 1 : a*g(a-1); +} +``` +另外,函数表达式声明可以用来根据不同条件,来定义一个函数: +```js +var f; +if(a == 1){ + f = function (){ + return 'when a == 1'; + } +}else { + f = function (){ + return 'when a != 1'; + } +} +``` + +# 2.函数调用 +函数定义完成后不会自动执行,需要我们通过函数名称来调用,才能真正执行: +```js +var f = function (){ + console.log('ok'); +} +f(); // 'ok' +``` +另外,函数也可以调用自身,这就是递归过程: +```js +function f (n){ + if( n==0 || n==1) { + return 1; + }else { + return n * f(n-1); + } +} +// 三目运算 +function f (n){ + return (n==0 || n==1)?1: n*f(n-1); +} +``` + +# 3.函数作用域 +由于函数只在函数的内部有定义,所以函数内部定义的变量在函数外部不能访问,函数内部就是这个函数的作用域。 +当一个父级函数内,还定义了一个子级函数,则这个子级函数可以访问父级函数定义的变量。 +```js +// 全局作用域 global scope +var a = 1, b = 2; +function f (){ + return a + b; +} +f(); // 3 + +function g(){ + var a1 = 'leo', b1 = 'pingan'; + function hi (){ + return a1 + '和' + b1 + } + return hi(); +} +g(); // 'leo和pingan' +``` +## 3.1 闭包 +闭包是 JavaScript 中最强大的特性之一,并且JS允许函数嵌套。 +在一个函数内部在嵌套一个函数,而嵌套的这个函数对外面的函数是私有的,则形成一个闭包,闭包是一个可以自己拥有独立的环境和变量的表达式,通常是函数。 +理解一下,前面说的内部函数可以调用外部函数的变量和方法,那么可以这么理解:**闭包的函数继承了父级容器函数的参数和变量**,即**内部函数包含外部函数的作用域**。 +总结一下: +* 内部函数只能在外部函数中访问; +* 内部函数形成闭包:可以访问外部函数的参数和变量,但外部函数却不能使用这个内部函数的参数和变量; +```js +function f(a) { + function g(b){ + return a + b; + } + return g; +} +var a1 = f(5); // ƒ g(b){ return a + b; } +var a2 = a1(6); // 11 +var a3 = f(5)(6); // 11 +``` +闭包可以给内部函数的变量提供一定的**安全保障**。 +另外,闭包还有复杂的用法: +```js +var f = function (name){ + var age ; + return { + setName : function (newName){ + name = newName; + }, + + getName : function (){ + return name; + }, + + getAge : function (){ + return age; + }, + setAge : function (newAge){ + age = newAge; + } + } +} + +var leo = f('leo'); +leo.setName('pingan'); +leo.setAge(20); +leo.getName(); // 'pingan' +leo.getAge(); // 20 +``` + +## 3.2命名冲突 +在同一个闭包作用域下若参数或变量名相同,产生冲突,则**优先使用作用域最近**: +```js +function f(){ + var a = 1; + function g(a){ + return a + 1; + } + return g; +} +f()(3); // 4 +``` + +# 4.arguments对象 +函数的实际参数会被保存在一个类数组对象 `arguments` 对象中,通过索引访问具体的参数: +```js +var a = arguments[i] +``` +`arguments`的索引从0开始,也有`arguments.length`属性获取长度。 +当我们不知道参数的数量的时候,可以使用`arguments.length`来获取实际传入参数的数量,再用`arguments`对象来获取每个参数。 +例如: +```js +// 拼接所有参数为一个字符串 +// 参数 s 为分隔符 +function f( s ){ + var text = ''; + for(var i = 0;i<= arguments.length; i++){ + text += arguments[i] + s ; + } + return text; +} + +f('--','leo','pingan','robin'); +// "----leo--pingan--robin--undefined--" +f('**','leo','pingan','robin'); +// "****leo**pingan**robin**undefined**" +``` + +# 5.函数参数 +ES6开始,新增两个类型的参数:**默认参数**和**剩余参数**: +## 5.1默认参数 +若函数没有传入参数,则参数默认值为`undefined`,通常设置参数默认值是这样做的: +```js +// 没有设置默认值 +function f(a, b){ + b = b ? b : 1; + return a * b; +} +f(2,3); // 6 +f(2); // 2 + +// 设置默认值 +function f(a, b = 1){ + return a * b; +} +f(2,3); // 6 +f(2); // 2 +``` + +## 5.2剩余参数 +可以将参数中不确定数量的参数表示成数组,如下: +```js +function f (a, ...b){ + console.log(a, b); +} +f(1,2,3,4); // a => 1 b => [2, 3, 4] +``` + +# 6.箭头函数 +**函数箭头表达式**是ES6新增的函数表达式的语法,也叫**胖箭头函数**,变化:更简洁的函数和`this`。 +* 更简洁的函数 +```js +// 有1个参数 +let f = v => v; +// 等同于 +let f = function (v){return v}; + +// 有多个参数 +let f = (v, i) => {return v + i}; +// 等同于 +let f = function (v, i){return v + i}; + +// 没参数 +let f = () => 1; +// 等同于 +let f = function (){return 1}; + +let arr = [1,2,3,4]; +arr.map(ele => ele + 1); // [2, 3, 4, 5] +``` + +* this +注意这几点: + 1. 箭头函数内的`this`总是指向**定义时所在的对象**,而不是调用时。 + 2. 箭头函数不能当做**构造函数**,即不能用`new`命令,否则报错。 + 3. 箭头函数不存在`arguments`对象,即不能使用,可以使用`rest`参数代替。 + 4. 箭头函数不能使用`yield`命令,即不能用作Generator函数。 + +一个简单的例子: +```js +function Person(){ + this.age = 0; + + setInterval(() => { + this.age++; + }, 1000); +} +var p = new Person(); // 定时器一直在执行 p的值一直变化 +``` + +# 参考资料 +[1.MDN 函数](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Functions) + +--- +**本部分内容到这结束** + +|Author|王平安| +|---|---| +|E-mail|pingan8787@qq.com| +|博 客|www.pingan8787.com| +|微 信|pingan8787| +|每日文章推荐|https://github.com/pingan8787/Leo_Reading/issues| +|ES小册|js.pingan8787.com| \ No newline at end of file diff --git "a/Cute-JavaScript/Cute-JS/level1/5.\350\241\250\350\276\276\345\274\217\345\222\214\350\277\220\347\256\227\347\254\246.md" "b/Cute-JavaScript/Cute-JS/level1/5.\350\241\250\350\276\276\345\274\217\345\222\214\350\277\220\347\256\227\347\254\246.md" new file mode 100644 index 00000000..2ef06d6a --- /dev/null +++ "b/Cute-JavaScript/Cute-JS/level1/5.\350\241\250\350\276\276\345\274\217\345\222\214\350\277\220\347\256\227\347\254\246.md" @@ -0,0 +1,304 @@ +本文是 **重温基础** 系列文章的第五篇。 +今日感受:家的意义。 + + +**本章节复习的是JS中的表达式和运算符,用好这些可以大大提高开发效率。** + +一些基础:JavaScript中运算符有一元、二元和三元(条件)运算符,常见写法: +```js +// 操作数 + 运算符 + 操作数 +1 + 2 ; + +// 运算符 + 操作数 +x ++; + +// 操作数 + 运算符 +++ x; +``` + + +本文将介绍一下几类运算符: +* 赋值运算符(Assignment operators) +* 比较运算符(Comparison operators) +* 算数运算符(Arithmetic operators) +* 位运算符(Bitwise operators) +* 逻辑运算符(Logical operators) +* 字符串运算符(String operators) +* 条件(三元)运算符(Conditional operator) +* 逗号运算符(Comma operator) +* 一元运算符(Unary operators) +* 关系运算符(Relational operator) + +# 1.赋值运算符 +最简单的赋值运算符是 `=` ,它将右边操作数的值赋值给左边的操作数,如 `a = b`。 +另外常见的复合赋值运算符有如下: +|名称|简写的操作符|含义| +|---|---|---| +|赋值| `x = y`| `x = y`| +|加法赋值| `x += y` | `x = x + y`| +|减法赋值| `x -= y` | `x = x - y`| +|乘法赋值| `x *= y` | `x = x * y`| +|除法赋值| `x /= y` | `x = x / y`| +|求余赋值| `x %= y` | `x = x % y`| +|求幂赋值| `x **= y`| `x = x ** y`| +|左移位赋值| `x <<= y`| `x = x << y`| +|右移位赋值| `x >>= y`| `x = x >> y`| +|无符号右移位赋值| `x >>>= y`| `x = x >>> y`| +|按位与赋值| `x &= y`| `x = x & y`| +|按位异或赋值| `x ^= y`| `x = x ^ y`| +|按位或赋值| `x |= y`| `x = x | y`| + +另外在ES6中,新增一类**解构赋值**: +```js +let a = ['aa', 'bb', 'cc']; + +// 不使用解构赋值 +let a1 = a[0]; +let a2 = a[1]; + +// 使用解构赋值 +let [a1, a2] = a; +``` + +# 2.比较运算符 +通过比较两个比较对象来返回一个是否为真的布尔值,当两个比较的对象不是相同类型,JavaScript会尝试将两个比较对象转换成相同类型进行比较: +```js +let a = 10; +let b = '12'; +a > b; // false +``` + +常用的比较运算符有: +|名称|描述|返回true的示例| +|---|---|---| +|等于 `==` | 操作符两边数据相等 | `3 == '3'` | +|不等于 `!==` | 操作符两边数据不相等 | `3 != '4'` | +|全等 `===` | 操作符两边数据相等且类型相同 | `3 === 3` | +|不全等 `!==` | 操作符两边数据不相等或类型不相同 | `3 !== '3'` | +|大于 `>` | 判断操作符左边大于右边 | `3 > 2` | +|大于等于 `>=` | 判断操作符左边大于或等于右边 | `3 >= 2` | +|小于 `<` | 判断操作符左边小于右边 | `3 < 4` | +|小于等于 `<=` | 判断操作符左边小于或等于右边 | `3 <= 4` | + +**注意:** +`=>`不是运算符,而是ES6中新增的**箭头函数**的标记符号。 + +# 3.算数运算符 +除了标准的加减乘除这些基本运算符,JavaScript还提供一些新的算数运算符: +|名称|描述|示例| +|---|---|---| +|求余 `%` | 返回相除之后的余数 | `11 % 5` 返回 1 | +|自增 `++` | `++N`返回加一以后的值,`N++`返回原数值然后加一 | `++3`返回4,`3++`返回3 | +|自减 `--` | `--N`返回减一以后的值,`N--`返回原数值然后减一 | `--3`返回2,`3--`返回3 | +|一元负值符 `-` | 返回操作数的负数,若不是`Number`则试图转换为`Number`再取负值 |`-'-2'` 返回`2`;`-2`返回`2` | +|一元正值符 `+` | 若操作数不是`Number`类型则试图转换为`Number`|`+'-2'` 返回`-2`;`+'2'`返回`2` | +|指数运算符 `**` | 计算底数`a`的指数`n`次方 | `2 ** 3` 返回 8 | + +# 4.位运算符 +位运算符是在数字底层(即表示数字的 32 个数位)进行操作的。 +[复习数字32位数的表示](http://www.w3school.com.cn/js/pro_js_operators_bitwise.asp) +|名称|描述|示例| +|---|---|---| +|按位与 `AND` `&`| 在`a`和`b`的位表示中,每一个对应的位都为1则返回1,否则0 | `a & b`| +|按位或 `OR` `|` | 在`a`和`b`的位表示中,每一个对应的位,只要有一个为1则返回1,否则0 | `a | b`| +|按位异或 `XOR` `^` | 在`a`和`b`的位表示中,每一个对应的位,两个不相同则返回1,否则0 | `a ^ b`| +|按位非 `NOT` `~` | 反转被操作数的位 | `~a`| +|左移 `shift` `<<` | 将`a`的二进制串向左移动`b`位,右边移入0 | `a << b`| +|算术右移 `>>`| 译注:算术右移左边空出的位是根据最高位是0和1来进行填充的 | `a >> b`| +|无符号右移(左边空出位用0填充) `>>>` | 把`a`的二进制表示向右移动`b`位,丢弃被移出的所有位,并把左边空出的位都填充为0 | `a >>> b`| + +示例解释: +1的二进制表示为 `0 0 0 0 0 0 1` +3的二进制表示为 `0 0 0 0 0 1 1` +* 1.按位与 `&` +```js +1 & 3 ; // 1 +1 | 3 ; // 3 +1 ^ 3 ; // 2 +~1 ; // -2 +1>>1 ; // 0 +``` + +## 使用案例 +* 1.16进制颜色值转RGB: +```js +function hexToRGB(hex){ + let h = hex.replace('#','0x'), + r = h >> 16, + g = h >> 8 & 0xff, + b = h & 0xff; + return `rgb(${r},${g},${b})` +} +hexToRGB('#eeddff'); // "rgb(238,221,255)" +``` + +* 2.RGB转16进制: +```js +function RGBToHex(rgb){ + let r = rgb.split(/[^\d]+/), + c = r[1]<<16 | r[2]<<8 | r[3]; + return `#${c.toString(16)}`; +} +RGBToHex('rgb(238,221,255)'); // "#eeddff" +``` + +# 5.逻辑运算符 +常用来处理布尔值,但是当处理非布尔值的时候,往往返回非布尔值: +|运算符|描述|示例| +|---|---|---| +|逻辑与 `&&` |若`a`和`b`都能转为`true`则返回`true`| `1+1==2 && 1-1==0` 返回 `true` | +|逻辑或 `||` |若`a`和`b`其中一个能转为`true`则返回`true`,若都是`false`则返回`false`| `1+1==3 || 1-1==0` 返回 `true` | +|逻辑非 `!` |若`a`能转为`true`则返回`false`| `!1+1==2` 返回 `false` | + +**注意**: 能被转成`false`的值有`null`,`0`,`NaN`,空字符串`""`和`undefined`。 +几个示例: +```js +let a1 = true && true; // true +let a2 = true && false; // false +let a3 = false && true; // false +let a4 = false && false; // false +let a5 = false && "leo"; // false +let a6 = true && "leo"; // "leo" +let a7 = "leo" && "robin";// "robin" + + +let b1 = true || true; // true +let b2 = true || false; // true +let b3 = false || true; // true +let b4 = false || false; // false +let b5 = false || "leo"; // "leo" +let b6 = true || "leo"; // true +let b7 = "leo" || "robin";// "leo" + +let c1 = !true; // false +let c2 = !false; // true +let c3 = !"leo"; // false +``` +常常还使用**短路求值**: +```js +false && anything ; // 被短路求值为false +true || anything ; // 被短路求值为true +``` + +# 6.字符串运算符 +在拼接字符串中,由 `+` 来连接两个字符串: +```js +let a = 'leo ' + 'cute~'; // 'leo cute~' + +let b = 'ha'; +a += b; // "leo cute~ha" +``` + +# 7.条件(三元)运算符 +可以使用三个操作数的运算符,运算结果为根据给定条件在两个值中取一个: +```js +// 当条件为真 则取 值1 ,否则取 值2 +// 条件 ? 值1 : 值2 +let a = 10; +let b = a > 5 ? 'yes' : 'no'; // 'yes' +``` + +# 8.逗号运算符 +对两个操作数求值并且返回最终操作数的值,通常用于`for`循环中,在每次循环时对多个变量进行更新: +```js +let a1 = [1,2,3,9,6,6]; +for(let i = 0,j = 5; i<=j; i++, j--){ + console.log(`i:${i},j:${j},i值:${a1[i]},j值:${a1[j]}`) +} +// i:0,j:5,i值:1,j值:6 +// i:1,j:4,i值:2,j值:6 +// i:2,j:3,i值:3,j值:9 +``` + +# 9.一元运算符 +一元操作符仅对应一个操作数。 +## delete +删除一个对象或一个对象的属性或者一个数组中某一个键值,返回一个布尔值,删除成功返回`true`,否则返回`false`: +```js +let a = {name : 'leo',age : '15'}; +delete a.name; // true +a; // {age: "15"} + +let b = [1,3,5]; +delete b[0]; // true +b; // [empty, 3, 5] +b[0]; // undefined +``` +## typeof +返回一个参数的类型的字符串值,参数可以输字符串,变量,关键词或者对象: +```js +typeof new Function(); // "function" +typeof "leo" ; // "string" +typeof 11 ; // "number" +typeof undefined ; // "undefined" + +typeof true ; // "boolean" +typeof null ; // "object" +``` +参数也可以是表达式,`typeof`会根据其返回结果返回所包含的类型: +```js +typeof (1+1) ; // "number" +typeof (1+1==2 ? 'yes' : 'no') ; // "string" +``` +## void +表示一个运算没有返回值,常常用在创建一个超链接文本,但是点击的时候没有任何效果: +```html +点击 +点击 +``` + +# 10.关系运算符 +比较两个操作数: +## in +判断指定属性是否在指定对象中,若是则返回`true`: +```js +// 对象 +let a = {name:'leo',age:'15'}; +'name' in a; // true + +// 数组 +let b = ['leo', 'pingan', 'robin']; +0 in b; // true +'length' in b;// true +``` + +## instanceof +判断一个对象是否是指定类型,若是则返回`true`: +```js +let d = new Date(); +d instanceof Date; // true +``` + +# 11.运算符优先级 +当我们需要调整表达式计算顺序,就需要用到运算符的优先级,通过括号来实现排序,常见优先级从高到低: +|运算符|描述| +|---|---| +|`. [] ()` |字段访问、数组下标、函数调用以及表达式分组| +|`++ -- - ~ ! delete new typeof void` |一元运算符、返回数据类型、对象创建、未定义值| +|`* / %`|乘法、除法、取模| +|`+ - +`|加法、减法、字符串连接| +|`<< >> >>>`|移位| +|`< <= > >= instanceof`|小于、小于等于、大于、大于等于、instanceof| +|`== != === !==`|等于、不等于、严格相等、非严格相等| +|`&`|按位与| +|`^`|按位异或| +|`|`|按位或| +|`&&`|逻辑与| +|`||`|逻辑或| +|`?:`|条件| +|`= oP=`|赋值、运算赋值| +|`,`|多重求值| + +# 参考资料 +[1.MDN 表达式和运算符](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Expressions_and_Operators) + +--- +**本部分内容到这结束** + +|Author|王平安| +|---|---| +|E-mail|pingan8787@qq.com| +|博 客|www.pingan8787.com| +|微 信|pingan8787| +|每日文章推荐|https://github.com/pingan8787/Leo_Reading/issues| +|ES小册|js.pingan8787.com| \ No newline at end of file diff --git "a/Cute-JavaScript/Cute-JS/level1/6.\346\225\260\345\255\227.md" "b/Cute-JavaScript/Cute-JS/level1/6.\346\225\260\345\255\227.md" new file mode 100644 index 00000000..1675cc03 --- /dev/null +++ "b/Cute-JavaScript/Cute-JS/level1/6.\346\225\260\345\255\227.md" @@ -0,0 +1,248 @@ +本文是 **重温基础** 系列文章的第六篇。 +今日感受:自己需要多总结,会有不同收获(比如今晚我做的转正总结)。 + +**本章节复习的是JS中的数字类型,涉及的API比较多。** + +前置基础: +在JavaScript中,数字为双精度浮点类型(即一个数字范围只能在-(253-1)和(253-1)之间),整数类型也一样。 +另外数字类型也可以是以下三种符号值: +* `+Infinity` : 正无穷; +* `-Infinity` : 负无穷; +* `NaN` : 非数字(not a number); + +# 1.数字对象 +JS中内置了`Number`对象的一些常量属性: + +|属性|描述| +|-|-| +|`Number.MAX_VALUE`|可表示的最大值| +|`Number.MIN_VALUE`|可表示的最小值| +|`Number.NaN`|特指“非数字”| +|`Number.NEGATIVE_INFINITY`|特指“负无穷”;在溢出时返回| +|`Number.POSITIVE_INFINITY`|特指“正无穷”;在溢出时返回| +|`Number.EPSILON`|表示1和比最接近1且大于1的最小Number之间的差别| +|`Number.MIN_SAFE_INTEGER`|JavaScript最小安全整数.| +|`Number.MAX_SAFE_INTEGER`|JavaScript最大安全整数.| + +注意:以上所有属性都是**不可写,不可枚举,也不可配置**。 + +* `Number.MAX_VALUE` + +`Number.MAX_VALUE`是 `Number` 对象的一个**静态属性**,值接近于 `1.79E+308`。大于 `Number.MAX_VALUE` 的值代表 "`Infinity`"。 +```js +let a = 100; +if(a < Number.MAX_VALUE){ + console.log('success'); +} +// success +``` + +* `Number.MIN_VALUE` + +`Number.MIN_VALUE`是 `Number` 对象的一个**静态属性**,值接近于 `5e-324`,是 JavaScript 里最接近 0 的正值,而不是最小的负值。 +```js +let a = 100; +if(a > Number.MIN_VALUE){ + console.log('success'); +} +// success +``` + +* `Number.NaN` + +`Number.NaN` 表示“非数字”,和 `NaN` 一样。 + +* `Number.POSITIVE_INFINITY` + +`Number.POSITIVE_INFINITY` 属性表示正无穷大,值同全局对象 `Infinity` 属性的值相同。 +```js +let a = Number.MAX_VALUE * 2; +if(a == Number.POSITIVE_INFINITY){ + console.log('success'); +} +// success +``` + +* `Number.NEGATIVE_INFINITY` + +`Number.NEGATIVE_INFINITY` 属性表示负无穷大,值和全局对象的 `Infinity` 属性的**负值**相同。 +```js +let a = - Number.MAX_VALUE * 2; +if(a == Number.NEGATIVE_INFINITY){ + console.log('success'); +} +// success +``` + +* `Number.EPSILON` + +`Number.EPSILON`属性表示 1 与Number可表示的大于 1 的最小的浮点数之间的差值,值接近于 2-52 。 +```js +let a = 0.1, b = 0.2, c = 0.3; +let d = (Math.abs(a + b - c) < Number.EPSILON); +d; // true +``` + +* `Number.MIN_SAFE_INTEGER` + +JS中最小的安全的integer型数字 (-(253 - 1))。 + +* `Number.MAX_SAFE_INTEGER` + +JS中最大的安全的integer型数字 (253 - 1)。 + + +# 2.数字方法 +常见的方法有: + +|方法|描述| +|-|-| +|`Number.parseFloat()`|把字符串参数解析成浮点数,和全局方法 `parseFloat()` 作用一致.| +|`Number.parseInt()`|把字符串解析成特定基数对应的整型数字,和全局方法 `parseInt()` 作用一致.| +|`Number.isFinite()`|判断传递的值是否为有限数字。| +|`Number.isInteger()`|判断传递的值是否为整数。| +|`Number.isNaN()`|判断传递的值是否为 `NaN`.| +|`Number.isSafeInteger()`|判断传递的值是否为安全整数。| + +使用方法: +* Number.parseFloat() +```js +let a1 = 3.1415, a2 = '3.1114'; +Number.parseFloat(a1); // 3.1415; +Number.parseFloat(a2); // 3.1111; +parseFloat(a1); // 3.1415; +parseFloat(a2); // 3.1111; +Number.parseFloat == parseFloat;// true +``` +* Number.parseInt() +```js +let a1 = '0110'; +Number.parseInt(a1, 2); // 6 +Number.parseInt(a1, 10); // 110 +Number.parseInt = parseInt; // true +``` +* Number.isFinite() +```js +Number.isFinite(Infinity); // false +Number.isFinite(NaN); // false +Number.isFinite(-Infinity); // false +Number.isFinite(0); // true +Number.isFinite(2e64); // true +Number.isFinite('0'); // false, 全局函数 isFinite('0') 会返回 true +``` +* Number.isInteger() +```js +Number.isInteger(0); // true +Number.isInteger(1); // true +Number.isInteger(-100000); // true +Number.isInteger(0.1); // false +Number.isInteger(Math.PI); // false +Number.isInteger(Infinity); // false +Number.isInteger(-Infinity); // false +Number.isInteger("10"); // false +Number.isInteger(true); // false +Number.isInteger(false); // false +Number.isInteger([1]); // false +``` +* Number.isNaN() +```js +Number.isNaN(NaN); // true +Number.isNaN(Number.NaN); // true +Number.isNaN(0 / 0) // true +// 下面这几个如果使用全局的 isNaN() 时,会返回 true。 +Number.isNaN("NaN"); // false,字符串 "NaN" 不会被隐式转换成数字 NaN。 +Number.isNaN(undefined); // false +Number.isNaN({}); // false +Number.isNaN("blabla"); // false +// 下面的都返回 false +Number.isNaN(true); +Number.isNaN(null); +Number.isNaN(37); +Number.isNaN("37"); +Number.isNaN("37.37"); +Number.isNaN(""); +Number.isNaN(" "); +``` +* Number.isSafeInteger() +```js +Number.isSafeInteger(3); // true +Number.isSafeInteger(Math.pow(2, 53)) // false +Number.isSafeInteger(Math.pow(2, 53) - 1) // true +Number.isSafeInteger(NaN); // false +Number.isSafeInteger(Infinity); // false +Number.isSafeInteger("3"); // false +Number.isSafeInteger(3.1); // false +Number.isSafeInteger(3.0); // true +``` + +数字类型原型上的方法: + +|方法|描述|案例| +|-|-|-| +|`toExponential()`|返回一个数字的指数形式的字符串|1.23e+2| +|`toFixed()`|返回指定小数位数的表示形式|var a=123,b=a.toFixed(2)//b="123.00"| +|`toPrecision()`|返回一个指定精度的数字。|a=123中,3会由于精度限制消失var a=123,b=a.toPrecision(2)//b="1.2e+2"| + +* `toExponential()` + +以**指数表示法**返回该数值**字符串**表示形式,可接收一个参数指定小数点后几位数字。 +```js +let a = 99.6633; +let a1 = '字符串:' + a.toExponential(); // "字符串:9.96633e+1" +let a2 = '字符串:' + a.toExponential(2);// "字符串:9.97e+1" +``` + +* `toFixed()` + +使用定点表示法来格式化一个数,可接收一个参数指定保留小数点后几位,取值为0-20之间。 +注意: 返回的数据类型是字符串类型。 +```js +let a = 1.2345; +a.toFixed(); // "1" +a.toFixed(2); // "1.23" +``` +* `toPrecision()` + +以**指定的精度返**回该数值对象的字符串表示,可接收一个参数,用来指定有效数个数的整数。 +```js +let a = 1.2345; +let a1 = '字符串:' + a.toPrecision(); // "字符串:1.2345" +let a2 = '字符串:' + a.toPrecision(1);// "字符串:1" +let a2 = '字符串:' + a.toPrecision(2);// "字符串:1.2" +``` + +# 3.数学对象 +JS内置的数学对象`Math`,有很多属性和方法,这里需要注意的是`Math`对象中的三角函数参数都是**弧度制**的。 + +|方法|描述| +|-|-| +|`abs()`|绝对值| +|`sin()`, `cos()`, `tan()`|标准三角函数;参数为弧度| +|`asin()`, `acos()`, `atan()`, `atan2()`|反三角函数; 返回值为弧度| +|`sinh()`, `cosh()`, `tanh()`|双曲三角函数; 返回值为弧度.| +|`asinh()`, `acosh()`, `atanh()`|反双曲三角函数;返回值为弧度.| +|`pow()`, `exp()`, `expm1()`, `log10()`, `log1p()`, `log2()`|指数与对数函数| +|`floor()`, `ceil()`|返回最大/最小整数小于/大于或等于参数| +|`min()`,` max()`|返回一个以逗号间隔的数字参数列表中的较小或较大值(分别地)| +|`random()`|返回0和1之间的随机数。| +|`round()`,`fround()`, `trunc()`|四舍五入和截断函数| +|`sqrt()`, `cbrt()`, `hypot()`|平方根,立方根,平方参数的和的平方根| +|`sign()`|数字的符号, 说明数字是否为正、负、零。| +|`clz32()`,`imul()`|在32位2进制表示中,开头的0的数量.返回传入的两个参数相乘结果的类C的32位表现形式| + +完整的描述和使用方法,建议查看 [MDN Math](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Math) + + +# 参考资料 +[1.MDN 数字和日期](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Numbers_and_dates) + +--- +**本部分内容到这结束** + +|Author|王平安| +|---|---| +|E-mail|pingan8787@qq.com| +|博 客|www.pingan8787.com| +|微 信|pingan8787| +|每日文章推荐|https://github.com/pingan8787/Leo_Reading/issues| +|ES小册|js.pingan8787.com| \ No newline at end of file diff --git "a/Cute-JavaScript/Cute-JS/level1/7.\346\227\266\351\227\264\345\257\271\350\261\241.md" "b/Cute-JavaScript/Cute-JS/level1/7.\346\227\266\351\227\264\345\257\271\350\261\241.md" new file mode 100644 index 00000000..4ba86ff5 --- /dev/null +++ "b/Cute-JavaScript/Cute-JS/level1/7.\346\227\266\351\227\264\345\257\271\350\261\241.md" @@ -0,0 +1,268 @@ +本文是 **重温基础** 系列文章的第七篇。 +今日感受:做好自律。 + +**本章节复习的是JS中的时间对象,一些处理的方法。** + +**前置知识**: +JavaScript中的时间是以1970年1月1日00:00:00以来的毫秒数来储存数据类型。 +`Data`对象的范围是相对距离UTC1970年1月1日的前后100,000,000天。 +创建一个时间对象: +```js +let d = new Date([params]); +``` +参数`params`可以是: +* 无参数:默认创建今天的日期和时间。 +* 一个符合以下格式的表示日期的字符串: + +"月 日, 年 时:分:秒."或者"年月日 时分秒" +```js +let d = new Date("2018-12-20"); +``` +如果你省略时、分、秒,那么他们的值将被设置为0。 +* 一个年,月,日的整型值的集合: +```js +let d = new Date(2018, 12, 20); +``` +* 一个年,月,日,时,分,秒的集合: +```js +let d = new Date(2018, 12, 20, 23, 20, 10); +``` + +这里Date对象涉及到的方法特别多,请移步[W3school JavaScript Date 对象](http://www.w3school.com.cn/jsref/jsref_obj_date.asp) + + +# 1.Date对象的方法 +常用处理的方法有以下几类: +* "`set`":用于设置Date对象的日期和时间的值。 +* "`get`":用去获取Date对象的日期和时间的值。 +* "`to`":用于返回Date对象的字符串格式的值。 +* "`parse`和`UTC`":用于解析Date字符串。 + +**需要注意的Date对象的一些数值问题:** +* 秒/分: 0 - 59; +* 时: 0 - 23; +* 星期: 0(周日) - 6(周六) +* 日期: 1 - 31 +* 月份: 0(一月) - 11(十二月) +* 年份: 从1900开始的年数 + +例如: +```js +let d = new Date('2018-12-10'); +let d1 = d.getMonth(); // 11 +let d2 = d.getFullYear(); // 2018 +``` +获取今年剩下的天数: +```js +let d = new Date(); +let e = new Date(2018, 11, 31, 23, 59, 59, 999); // 设置年月日时分秒 +e.setFullYear(d.getFullYear); // 设置为今年 +let m = 24 * 60 * 60 * 1000; // 每日毫秒数 +let result = (e.getTime() - d.getTime()) / m; +result = Math.round(result); // 返回今年剩余天数 +``` + +这里Date对象涉及到的方法特别多,请移步[W3school JavaScript Date 对象](http://www.w3school.com.cn/jsref/jsref_obj_date.asp) + +**注意:** +> 格林尼治标准时间(GMT)英国、爱尔兰、冰岛和葡萄牙属于该时区。这个时区与中国北京时间的时差是8个小时,也就是说比北京时间晚8个小时。 + +# 2.使用Date对象 +## 2.1 **设置日期** +为一个时间对象设置指定日期(2018年12月20日),注意这里:和前面说的一样,12月在JS的Date对象中,是用`11`表示。 +```js +let d = new Date(); +d.setFullYear(2018,11,20); +``` +设置时间对象`10`天以后: +```js +let d = new Date(); +d.setDate(d.getDate() + 10); // 先获取当天的日期,再设置到指定天数以后 +``` + +## 2.2 **比较时间** +通常情况下,像下面这样简单比较: +```js +let d = new Date(); +let e = new Date(); +d.setFullYear(2018,10,10); +let r = d > e ? 'good' : 'nice' ; // nice +``` +还可以比较两个日期相差多少天: +```js +let d1 = new Date('2018-10-10'); +let d2 = new Date('2018-11-11'); +let d3 = (d2 - d1) / (1000 * 60 * 60 * 24); // 32 +``` + +## 2.3 **计算N天后星期几** +```js +function d (num){ + if(typeof Number(num) === 'number'){ + let d1 = new Date(); + let d2 = d1.setDate(d1.getDate() + Number(num)); + let n = new Date(d2).getDay(); + let s = ''; + switch (n){ + case 0 : + s = "星期天"; + break; + case 1 : + s = "星期一"; + break; + case 2 : + s = "星期二"; + break; + case 3 : + s = "星期三"; + break; + case 4 : + s = "星期四"; + break; + case 5 : + s = "星期五"; + break; + case 6 : + s = "星期六"; + break; + } + return s; + }else { + alert('请输入正确数字!'); + } +} +``` + +## 2.4 格式化日期 +常见的日期格式化为字符串的方法有这些: + +* `toDateString()`——以特定于实现的格式显示星期几、月、日和年; + +* `toTimeString()`——以特定于实现的格式显示时、分、秒和时区; + +* `toLocaleDateString()`——以特定与地区的格式显示星期几、月、日和年; + +* `toLocaleTimeString()`——以特定于实现的格式显示时、分、秒; + +* `toUTCString()`——以特定于实现的格式完整的UTC日期。 + +**获取并格式化日期:年-月-日**: + +```js +function d (date){ + return date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate(); +} +d(new Date()); // "2018-12-20" +``` + +**日期字符串转为 年-月-日**: + +```js +function d (str){ + return new Date(Date.parse(str.replace(/-/g, '/'))); + // 或者 + // return new Date(str.replace(/-/g, '/')); +} +``` + +**获取当前星期几**: + +```js +let d = "今天是星期" + "日一二三四五六".charat(new Date().getDay()); +``` + +## 2.5 获取某年某月的天数 +这里有个小技巧,若给`new Date()`传入一个如`aaaa/aa/0`参数时,可以得到`aa`月的**前一个月的最后一天**,如传入`2018/12/0`会得到`2018/11/30`。 + +**值得注意的是:** 在Chrome浏览器上并不支持,会返回`Invalid Date`导致结果为`NaN`,但是我们可以使用`aaaa,aa,0`形式作为参数,下面分别写出这两种: + +```js +// aaaa/aa/0形式 只要传入年和月 +function d (y, m){ + m = parseInt(m, 10) + 1; + let r = new Date(y + '/' + m + '/0'); + return r.getDate(); +} + +// aaaa,aa,0形式 只要传入年和月 +function d (y, m){ + m = parseInt(m, 10) + 1; + let r = new Date(y, m, 0); + return r.getDate(); +} +``` + +## 2.6 获取上个月/下个月日期("yyyy-mm-dd") +传入参数的格式"yyyy-mm-dd",其实也可以是Date()对象,大家可以自行尝试。 +```js +// 上个月 date格式"yyyy-mm-dd" +function my_date (date){ + let arr = date.split('-'); + let y = arr[0] , m = arr[1], d = arr[2]; // 获取当前的年月日 + // ES6语法 let [y,m,d] = arr; + let day = new Date(y,m,0); + day = day.getDate(); // 获取当前月份的天数 + + let y2 = y, m2 = parseInt(m) - 1; + if(m2 == 0){ + y2 = parseInt(y2) -1; + m2 = 12; + } + + let d2 = d, day2 = new Date(y2, m2, 0); + day2 = day2.getDate(); + if(d2 > day2){ + d2 = day2; + } + if(m2 < 10){ + m2 = '0' + m2; + } + + return y2 + '-' + m2 + '-' + d2; +} +my_date('2018-1-20'); //"2017-12-20" +``` +下个月的计算方法也是相似: +```js +// 上个月 date格式"yyyy-mm-dd" +function my_date (date){ + let arr = date.split('-'); + let y = arr[0] , m = arr[1], d = arr[2]; // 获取当前的年月日 + let day = new Date(y,m,0); + day = day.getDate(); // 获取当前月份的天数 + + // 和计算上个月的区别 + let y2 = y, m2 = parseInt(m) + 1; + if(m2 == 13){ + y2 = parseInt(y2) + 1; + m2 = 1; + } + + let d2 = d, day2 = new Date(y2, m2, 0); + day2 = day2.getDate(); + if(d2 > day2){ + d2 = day2; + } + if(m2 < 10){ + m2 = '0' + m2; + } + + return y2 + '-' + m2 + '-' + d2; +} +my_date('2018-12-20'); // "2019-01-20" +``` + +# 参考资料 +[1.MDN 数字和日期](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Numbers_and_dates) +[2. JS日期Date详解与实例扩展](https://www.cnblogs.com/moqiutao/p/4875946.html) + +--- +**本部分内容到这结束** + +|Author|王平安| +|---|---| +|E-mail|pingan8787@qq.com| +|博 客|www.pingan8787.com| +|微 信|pingan8787| +|每日文章推荐|https://github.com/pingan8787/Leo_Reading/issues| +|ES小册|js.pingan8787.com| \ No newline at end of file diff --git "a/Cute-JavaScript/Cute-JS/level1/8.\345\255\227\347\254\246\344\270\262.md" "b/Cute-JavaScript/Cute-JS/level1/8.\345\255\227\347\254\246\344\270\262.md" new file mode 100644 index 00000000..e3e22aa6 --- /dev/null +++ "b/Cute-JavaScript/Cute-JS/level1/8.\345\255\227\347\254\246\344\270\262.md" @@ -0,0 +1,271 @@ +本文是 **重温基础** 系列文章的第八篇。 +今日感受:人在异乡,也不能忘记汤圆。 + +**本章节复习的是JS中的字符串,还有字符串的相关属性和方法。** + +前置知识: +JavaScript中的字符串的每个元素,在字符串中都占据一个位置,第一个元素的索引值为0,往后累加,另外创建字符串有2个方法: +* 1.字面量创建: +```js +let a = 'hello'; // "hello" +typeof a; // "string" +``` +* 2.字符串对象创建: +```js +let a = new String('hello'); //String {"hello"} +typeof a; // "object" +``` +实际开发中,除非必要,建议使用**字面量创建**,因为两种创建方法会有差异: +```js +let a1 = "1+1"; +let a2 = new String("1+1"); +eval(a1); // number 2 +eval(a2); // string "1+1" +``` +**String**有一个`length`属性,表示字符串中字符个数: +```js +let a = "hello"; +a.length; // 5 +``` + +# 1.String对象方法: +String对象的方法非常多,建议大家可以到 [W3school JavaScript String 对象](www.w3school.com.cn/jsref/jsref_obj_string.asp) 学习完整的内容。 + +|方法|描述| +|-|-| +|`charAt`, `charCodeAt`, `codePointAt`|返回字符串指定位置的字符或者字符编码。| +|`indexOf`, `lastIndexOf`|分别返回字符串中指定子串的位置或最后位置。| +|`startsWith`, `endsWith`,` includes`|返回字符串是否以指定字符串开始、结束或包含指定字符串。| +|`concat`|连接两个字符串并返回新的字符串。| +|`fromCharCode`, `fromCodePoint`|从指定的Unicode值序列构造一个字符串。这是一个String类方法,不是实例方法。| +|`split`|通过将字符串分离成一个个子串来把一个String对象分裂到一个字符串数组中。| +|`slice`|从一个字符串提取片段并作为新字符串返回。| +|`substring`, `substr`|分别通过指定起始和结束位置,起始位置和长度来返回字符串的指定子集。| +|`match`, `replace`,` search`|通过正则表达式来工作.| +|`toLowerCase`, `toUpperCase`|分别返回字符串的小写表示和大写表示。| +|`normalize`|按照指定的一种 Unicode 正规形式将当前字符串正规化。| +|`repeat`|将字符串内容重复指定次数后返回。| +|`trim`|去掉字符串开头和结尾的空白字符。| + +## 1.1 charAt +作用:查找字符串中**指定位置**的**内容**。 +`str.charAt(index)` index : 查找的字符的下标(大于等于0,若小于0则返回空字符串),若没传则表示1。 +```js +let a = "hello leo!" +a.charAt(); // "h" +a.charAt(1); // "e" +a.charAt(-1);// "" +``` + +## 1.2.indexOf和lastIndexOf +作用:查找**指定字符串**的**位置**。 +`indexOf`和`lastIndexOf`相同点: + 两者接收的参数一致,没有查到内容,返回`-1`。 +`indexOf`和`lastIndexOf`不同点: + 若查找到内容,则`indexOf`返回**第一次出现的索引**而`lastIndexOf`返回**最后一次出现的索引**。 + +`str.indexOf(value[, fromIndex])`接收2个参数: +* `value` : 需要查找的字符串内容; +* `fromIndex` : 可选,开始查找的位置,默认0; + +```js +let a = 'hello leo'; +let b = a.indexOf('lo'); // 3 +let c = a.indexOf('lo',4);// -1 +let e = a.lastIndexOf('l'); // 6 +``` +**一定要注意:** +1. 当`fromIndex > a.length`,则`fromIndex`被视为`a.length`。 +```js +let a = 'hello leo'; +let b = a.indexOf('lo',99);// -1 +``` +2. 当`fromIndex < 0`,则`fromIndex`被视为`0`。 +```js +let a = 'hello leo'; +let b = a.indexOf('lo',-1);// 3 +``` +3. `indexOf`和`lastIndexOf`区分大小写。 +```js +let a = 'hello leo'; +let b = a.indexOf('Lo'); // -1 +``` +## 1.3 concat +作用:连接字符串。 +`concat()`接收任意个参数作为连接的字符串,返回一个合并后的新字符串。 +```js +let a = 'hello'; +let b = ' leo '; +let c = '!' +a.concat(b,c); // "hello leo !" +``` + +## 1.4 split +作用:把字符串分割为字符串数组,并可以指定分隔符。 +`split(separator[,limit])`可以接收2个参数: +* `separator`:必需,字符串或者正则表达式,作为分割的内容; +* `limit`:可选,作为指定返回的数组的最大长度; + +若`separator`为`""`,则字符串会在每个字符之间分割; +```js +let a = 'How are you doing today?'; +a.split(); +// ["How are you doing today?"] +a.split(""); +// ["H", "o", "w", " ", "a", "r", "e", " ", "y", "o", "u", " ", "d", "o", "i", "n", "g", " ", "t", "o", "d", "a", "y", "?"] +a.split(" "); +// ["How", "are", "you", "doing", "today?"] +a.split("",4); +// ["H", "o", "w", " "] +a.split(" ",4); +// ["How", "are", "you", "doing"] +``` +使用其他分割符号: +```js +let a = "ni,hao,a!"; +a.split(","); // ["ni", "hao", "a!"] +``` + +## 1.5 slice +作用:提取并返回字符串的片断。 +`slice([start,end])` 可以接收2个参数: +* `start`:要提取的片段的起始下标,若小于零,则从字符串尾部开始算起,如-1表示字符串最后一个字符,-2为倒数第二个字符等等。 +* `end`:要提取的片段的结束下标,若没有传入,则表示从start到字符串结尾,若为负数则从字符串尾部开始算起。 +```js +let a = 'How are you doing today?'; +a.slice(); // "How are you doing today?" +a.slice(1); // "ow are you doing today?" +a.slice(-1); // '?' +a.slice(1,5); // "ow a" +a.slice(1,-1); // "ow are you doing today" +a.slice(-2,-1); // "y" +``` + +# 2.字符串拓展(ES6) +## 2.1 includes(),startsWith(),endsWith() +在我们判断字符串是否包含另一个字符串时,ES6之前,我们只有`typeof`方法,ES6之后我们又多了三种方法: +* **includes()**:返回**布尔值**,表示**是否找到参数字符串**。 +* **startsWith()**:返回**布尔值**,表示参数字符串是否在原字符串的**头部**。 +* **endsWith()**:返回**布尔值**,表示参数字符串是否在原字符串的**尾部**。 +```js +let a = 'hello leo'; +a.startsWith('leo'); // false +a.endsWith('o'); // true +a.includes('lo'); // true +``` +并且这三个方法都支持第二个参数,表示起始搜索的位置。 +```js +let a = 'hello leo'; +a.startsWith('leo',1); // false +a.endsWith('o',5); // true +a.includes('lo',6); // false +``` +`endsWith` 是针对前 `n` 个字符,而其他两个是针对从第`n`个位置直到结束。 + +## 2.2 repeat() +`repeat`方法返回一个新字符串,表示将原字符串重复`n`次。 +**基础用法**: +```js +'ab'.repeat(3); // 'ababab' +'ab'.repeat(0); // '' +``` +**特殊用法**: +* 参数为`小数`,则取整 +```js +'ab'.repeat(2.3); // 'abab' +``` +* 参数为`负数`或`Infinity`,则报错 +```js +'ab'.repeat(-1); // RangeError +'ab'.repeat(Infinity); // RangeError +``` +* 参数为`0到-1的小数`或`NaN`,则取0 +```js +'ab'.repeat(-0.5); // '' +'ab'.repeat(NaN); // '' +``` +* 参数为`字符串`,则转成`数字` +```js +'ab'.repeat('ab'); // '' +'ab'.repeat('3'); // 'ababab' +``` + +## 2.3 padStart(),padEnd() +用于将字符串**头部**或**尾部**补全长度,`padStart()`为**头部补全**,`padEnd()`为**尾部补全**。 +这两个方法接收**2个**参数,第一个指定**字符串最小长度**,第二个**用于补全的字符串**。 +**基础用法** : +```js +'x'.padStart(5, 'ab'); // 'ababx' +'x'.padEnd(5, 'ab'); // 'xabab' +``` +**特殊用法**: +* 原字符串长度,大于或等于指定最小长度,则返回原字符串。 +```js +'xyzabc'.padStart(5, 'ab'); // 'xyzabc' +``` +* 用来补全的字符串长度和原字符串长度之和,超过指定最小长度,则截去超出部分的补全字符串。 +```js +'ab'.padStart(5,'012345'); // "012ab" +``` +* 省略第二个参数,则用`空格`补全。 +```js +'x'.padStart(4); // ' x' +'x'.padEnd(4); // 'x ' +``` +## 2.4 模版字符串 +用于拼接字符串,ES6之前: +```js +let a = 'abc' + + 'def' + + 'ghi'; +``` +ES6之后: +```js +let a = ` + abc + def + ghi +` +``` +**拼接变量**: +在**反引号(\`)**中使用`${}`包裹变量或方法。 +```js +// ES6之前 +let a = 'abc' + v1 + 'def'; + +// ES6之后 +let a = `abc${v1}def` +``` + +# 3.字符串拓展(ES7) +用来为字符串填充特定字符串,并且都有两个参数:**字符串目标长度**和**填充字段**,第二个参数可选,默认空格。 +```js +'es8'.padStart(2); // 'es8' +'es8'.padStart(5); // ' es8' +'es8'.padStart(6, 'woof'); // 'wooes8' +'es8'.padStart(14, 'wow'); // 'wowwowwowwoes8' +'es8'.padStart(7, '0'); // '0000es8' + +'es8'.padEnd(2); // 'es8' +'es8'.padEnd(5); // 'es8 ' +'es8'.padEnd(6, 'woof'); // 'es8woo' +'es8'.padEnd(14, 'wow'); // 'es8wowwowwowwo' +'es8'.padEnd(7, '6'); // 'es86666' +``` +从上面结果来看,填充函数只有在字符长度小于目标长度时才有效,若字符长度已经等于或小于目标长度时,填充字符不会起作用,而且目标长度如果小于字符串本身长度时,字符串也不会做截断处理,只会原样输出。 + + +# 参考资料 +1. [MDN Text formatting](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Text_formatting) +2. [W3school JavaScript String 对象](www.w3school.com.cn/jsref/jsref_obj_string.asp) + +--- +**本部分内容到这结束** + +|Author|王平安| +|---|---| +|E-mail|pingan8787@qq.com| +|博 客|www.pingan8787.com| +|微 信|pingan8787| +|每日文章推荐|https://github.com/pingan8787/Leo_Reading/issues| +|ES小册|js.pingan8787.com| \ No newline at end of file diff --git "a/Cute-JavaScript/Cute-JS/level1/9.\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.md" "b/Cute-JavaScript/Cute-JS/level1/9.\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.md" new file mode 100644 index 00000000..dbd2b3f1 --- /dev/null +++ "b/Cute-JavaScript/Cute-JS/level1/9.\346\255\243\345\210\231\350\241\250\350\276\276\345\274\217.md" @@ -0,0 +1,450 @@ +本文是 **重温基础** 系列文章的第九篇。 +今日感受:时间管理-角色管理法。 + +**本章节复习的是JS中的正则表达式,JS中用来匹配字符串的强大工具。** + +前置知识: +JS中的正则表达式是用来匹配字符串中指定字符组合的模式。 +另外需要记住:正则表达式也是对象。 + +# 1.创建正则表达式 +* 使用一个正则表达式字面量: +```js +let reg = /ab+c/; +let reg = /^[a-zA-z]/gi; +``` +* 使用`RegExp`对象: +`new RegExp(str[, attr])`接收2个参数,`str`是一个字符串,指定正则表达式匹配规则,`attr`可选,表示匹配模式,值有`g`(全局匹配),`i`(区分大小写的匹配)和`m`(多行匹配)。 +```js +let reg = new RegExp('ab+c'); +let reg = new RegExp(/^[a-zA-z]/, "gi"); +let reg = new RegExp("^[a-zA-z]", "gi"); +``` + +正则表达式的返回值,是一个新的`RegExp`对象,具有指定的模式和标志。 +**返回信息介绍**: +|对象|属性|描述|案例中对应的值| +|-|-|-|-| +|`reg`|`lastIndex`|下一个匹配的索引(仅在使用`g`参数时可用)|`0`| +|`reg`|`source`|模式文本。在正则表达式创建时更新,不执行。|`"ab+c"`| +|`reg`|`ignoreCase`|是否使用了 "i" 标记使正则匹配忽略大小写。|`true`| +|`reg`|`global`|是否使用了 "g" 标记来进行全局的匹配。|`true`| +|`reg`|`multiline`|是否使用了 "m" 标记使正则工作在多行模式。|`false`| + + + +**关于正则表达式的一些方法属性,文章后面介绍,这里先复习定义和使用**。 + +# 2.使用正则表达式 +JS的正则表达式可以被用于: +* `RegExp`对象的`exec`和`test`方法; +* `String`对象的`match`、`replace`、`search`和`split`方法。 + +## 2.1 RegExp对象方法 +|方法|介绍| +|-|-| +|`exec`|检索字符串中指定的值。返回找到的值,并确定其位置。| +|`test`|检索字符串中指定的值。返回 `true` 或 `false`。| + +### 2.1.1 `exec(str)` +`str`: 需要检索的字符串。 +若检索成功,返回匹配的数组,否则返回null。 +```js +let str = "hello leo!"; +let reg = new RegExp("leo", "g"); +let result = reg.exec(str); +// 也可以写成 +let result = /leo/g.exec("hello leo!"); + +/* +[ + 0: "leo", + groups: undefined, + index: 6, + input: "hello leo!", + length: 1 +] +*/ + +let result2 = /(leo \S)/g.exec("hello leo hi leo!"); +/* + 0: "leo hi" + 1: "leo hi" + 2: "hi" + groups: undefined + index: 6 + input: "hello leo hi leo!" + length: 3 +*/ +``` +**返回信息介绍**: +|对象|属性|描述|案例中对应的值| +|-|-|-|-| +|`result`|`[0]`|匹配到的所有字符串|`"leo"`| +|`result`|`input`|初始字符串。|`"hello leo!"`| +|`result`|`index`|在输入的字符串中匹配到的以0开始的索引值。|`6`| +|`result2`|`[1],...,[n]`|括号中的分组捕获|`[1]=> "leo hi";[2] => "hi"`| + +### 2.1.2 `test(str)` +`str`:需要检索的字符串。 +若匹配成功返回`true`否则`false`。 +等价于 `reg.exec(str) != null`。 +```js +let str = "hello leo!"; +let res = /^leo/.test(str); // fasle +let res1 = /^leo/.test(str); // true +``` +`^str`表示匹配以`str`开头的字符串,这些符号文章后面会介绍。 + +## 2.2 String对象方法 +|方法|介绍| +|-|-| +|`search`|检索与正则表达式相匹配的值。| +|`match`|找到一个或多个正则表达式的匹配。| +|`replace`|替换与正则表达式匹配的子串。| +|`split`|把字符串分割为字符串数组。| + +### 2.2.1 `search` +`str.search(reg)`: +`str`:被检索的源字符串。 +`reg`:可以是需要检索的**字符串**,也可以是需要检索的`RegExp`对象,可以添加标志,如`i`。 + +若检索成功,返回**第一个**与`RegExp`对象匹配的字符串的起始位置,否则返回`-1`。 +```js +let str = "hello leo!"; +let res = str.search(/leo/g); // 6 + +let str1 = "hello leoleoleoleo!"; +let res1 = str.search(/leo/g); // 6 +let res2 = str.search(/pingan/g); // -1 +``` + +### 2.2.2 `match` +`str.match(reg)`: +`str`:被检索的源字符串。 +`reg`:可以是需要检索的**字符串**,也可以是需要检索的`RegExp`对象,可以添加标志,如`i`。 + +若检索成功,返回与`reg`匹配的所有结果的一个**数组**,数组的第一项是进行匹配完整的字符串,之后的项是用圆括号捕获的结果,否则返回`null`。 +```js +let str = 'For more information, see Chapter 3.4.5.1'; +let reg = /see (chapter \d+(\.\d)*)/i; +let result = str.match(reg); +/* +logs [ 'see Chapter 3.4.5.1', + 'Chapter 3.4.5.1', + '.1', + index: 22, + input: 'For more information, see Chapter 3.4.5.1' ] +*/ +``` +`'see Chapter 3.4.5.1'` 是整个匹配。 +`'Chapter 3.4.5.1'` 被`'(chapter \d+(\.\d)*)'`捕获。 +`'.1'` 是被`'(\.\d)'`捕获的最后一个值。 +`'index'` 属性`(22) `是整个匹配从零开始的索引。 +`'input'` 属性是被解析的原始字符串。 + +### 2.2.3 `replace` +将字符串中**指定字符**替换成**其他字符**,或替换成一个与正则表达式匹配的字符串。 +`str.replace(sub/reg,val)`: +* `str`: 源字符串 +* `sub`: 使用字符串来检索被替换的文本 +* `reg`: 使用RegExp对象来检索来检索被替换的文本 +* `val`: 指定替换文本 +返回替换成功之后的字符串,不改变源字符串内容。 +```js +let str = "hello leo!"; +let res = str.replace('leo','pingan');//"hello pingan!" +``` + +**val可以使用特殊变量名**: +|变量名|代表的值| +|-|-| +|`$$`|插入一个 "$"。| +|`$&`|插入匹配的子串。| +|`$`|插入当前匹配的子串左边的内容。| +|`$'`|插入当前匹配的子串右边的内容。| +|`$n`|假如第一个参数是 RegExp对象,并且 n 是个小于100的非负整数,那么插入第 n 个括号匹配的字符串。提示:索引是从1开始| +```js +let str = "hello leo!"; +let res = str.replace(/(\w+)\s* \s*(\w+)/, "$2:$1"); +// "leo:hello!" +``` + +### 2.2.4 `split` +将一个字符串,按照指定符号分割成一个字符串数组。 +`str.split(sub[, maxlength])`: +* `str`: 源字符串 +* `sub`: 指定的分割符号或正则 +* `maxlength`: 源字符串 +```js +let str = "hello leo!"; +let res = str.split(); //["hello leo!"] +let res = str.split(""); //["h", "e", "l", "l", "o", " ", "l", "e", "o", "!"] +let res = str.split(" ");//["hello", "leo!"] +let res = str.split(/\s+/);//["hello", "leo!"] + +let res = str.split("",3);//["h", "e", "l"] +``` + +## 2.3 使用情况 +* 当我们想要查找一个字符串中的一个匹配**是否找到**,可以用`test`或`search`方法。 +* 当我们想要得到匹配的**更多信息**,我们就需要用到`exec`或`match`方法。 + + +# 3.正则表达式符号介绍 +详细的每个符号的用法,可以查阅 [W3school JavaScript RegExp 对象](www.w3school.com.cn/jsref/jsref_obj_regexp.asp) +## 3.1 修饰符 +|修饰符|描述| +|-|-| +|`i`|执行对大小写不敏感的匹配。| +|`g`|执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。| +|`m`|执行多行匹配。| + +```js +let str = "hello leo!" +let res = /Leo/i.test(str); // i 不区分大小写 所以返回true +let res = /Leo/.test(str); // fasle +``` + +## 3.2 方括号 +用于查找指定返回之内的字符: +|表达式|描述| +|-|-| +|`[abc]`|查找方括号之间的任何字符。| +|`[^abc]`|查找任何不在方括号之间的字符。| +|`[0-9]`|查找任何从 0 至 9 的数字。| +|`[a-z]`|查找任何从小写 a 到小写 z 的字符。| +|`[A-Z]`|查找任何从大写 A 到大写 Z 的字符。| +|`[A-z]`|查找任何从大写 A 到小写 z 的字符。| +|`[adgk]`|查找给定集合内的任何字符。| +|`[^adgk]`|查找给定集合外的任何字符。| +|`(red)`|查找任何指定的选项。| + +```js +let str = "hello leo!"; +let res = str.match(/[a-m]/g); +//["h", "e", "l", "l", "l", "e"] +let res = str.match(/[^a-m]/g); +//["o", " ", "o", "!"] +``` + +## 3.3 元字符 +元字符是拥有特殊含义的字符: +|元字符|描述| +|-|-| +|`.`|查找单个字符,除了换行和行结束符。| +|`\w`|查找单词字符。| +|`\W`|查找非单词字符。| +|`\d`|查找数字。| +|`\D`|查找非数字字符。| +|`\s`|查找空白字符。| +|`\S`|查找非空白字符。| +|`\b`|匹配单词边界。| +|`\B`|匹配非单词边界。| +|`\0`|查找 NUL 字符。| +|`\n`|查找换行符。| +|`\f`|查找换页符。| +|`\r`|查找回车符。| +|`\t`|查找制表符。| +|`\v`|查找垂直制表符。| +|`\xxx`|查找以八进制数 xxx 规定的字符。| +|`\xdd`|查找以十六进制数 dd 规定的字符。| +|`\uxxxx`|查找以十六进制数 xxxx 规定的 Unicode 字符。| + +```js +let str = "hello leo hi pingan!"; +let res = str.match(/o\s/g); +//["o ", "o "] +let res = str.match(/\s/g); +//[" ", " ", " "] +``` + +## 3.4 量词 +|量词|描述| +|-|-| +|`n+`|匹配任何包含至少一个 n 的字符串。| +|`n*`|匹配任何包含零个或多个 n 的字符串。| +|`n?`|匹配任何包含零个或一个 n 的字符串。| +|`n{X}`|匹配包含 X 个 n 的序列的字符串。| +|`n{X,Y}`|匹配包含 X 至 Y 个 n 的序列的字符串。| +|`n{X,}`|匹配包含至少 X 个 n 的序列的字符串。| +|`n$`|匹配任何结尾为 n 的字符串。| +|`^n`|匹配任何开头为 n 的字符串。| +|`?=n`|匹配任何其后紧接指定字符串 n 的字符串。| +|`?!n`|匹配任何其后没有紧接指定字符串 n 的字符串。| +```js +let str = "hello leo!"; +let res = str.match(/^hello/g); +// ["hello"] +let res = str.match(/^pingan/g); +//null + +``` + +# 4. 正则表达式拓展(ES6) +## 4.1 介绍 +在ES5中有两种情况。 +* 参数是**字符串**,则第二个参数为正则表达式的修饰符。 +```js +let a = new RegExp('abc', 'i'); +// 等价于 +let a = /abx/i; +``` +* 参数是**正则表达式**,返回一个原表达式的拷贝,且不能有第二个参数,否则报错。 +```js +let a = new RegExp(/abc/i); +//等价于 +let a = /abx/i; + +let a = new RegExp(/abc/, 'i'); +// Uncaught TypeError +``` +ES6中使用: +第一个参数是正则对象,第二个是指定修饰符,如果第一个参数已经有修饰符,则会被第二个参数覆盖。 +```js +new RegExp(/abc/ig, 'i'); +``` + +## 4.2 字符串的正则方法 +常用的四种方法:`match()`、`replace()`、`search()`和`split()`。 + +## 4.3 u修饰符 +添加`u`修饰符,是为了处理大于`uFFFF`的Unicode字符,即正确处理四个字节的UTF-16编码。 +```js +/^\uD83D/u.test('\uD83D\uDC2A'); // false +/^\uD83D/.test('\uD83D\uDC2A'); // true +``` +由于ES5之前不支持四个字节UTF-16编码,会识别为两个字符,导致第二行输出`true`,加入`u`修饰符后ES6就会识别为一个字符,所以输出`false`。 + +**注意:** +加上`u`修饰符后,会改变下面正则表达式的行为: +* (1)点字符 +点字符(`.`)在正则中表示除了**换行符**以外的任意单个字符。对于码点大于`0xFFFF`的Unicode字符,点字符不能识别,必须加上`u`修饰符。 +```js +var a = "𠮷"; +/^.$/.test(a); // false +/^.$/u.test(a); // true +``` +* (2)Unicode字符表示法 +使用ES6新增的大括号表示Unicode字符时,必须在表达式添加`u`修饰符,才能识别大括号。 +```js +/\u{61}/.test('a'); // false +/\u{61}/u.test('a'); // true +/\u{20BB7}/u.test('𠮷'); // true +``` +* (3)量词 +使用`u`修饰符后,所有量词都会正确识别码点大于`0xFFFF`的 Unicode 字符。 +```js +/a{2}/.test('aa'); // true +/a{2}/u.test('aa'); // true +/𠮷{2}/.test('𠮷𠮷'); // false +/𠮷{2}/u.test('𠮷𠮷'); // true +``` +* (4)i修饰符 +不加`u`修饰符,就无法识别非规范的`K`字符。 +```js +/[a-z]/i.test('\u212A') // false +/[a-z]/iu.test('\u212A') // true +``` + +**检查是否设置`u`修饰符:** +使用`unicode`属性。 +```js +const a = /hello/; +const b = /hello/u; + +a.unicode // false +b.unicode // true +``` + +## 4.4 y修饰符 +`y`修饰符与`g`修饰符类似,也是全局匹配,后一次匹配都是从上一次匹配成功的下一个位置开始。区别在于,`g`修饰符**只要**剩余位置中存在匹配即可,而`y`修饰符是必须从**剩余第一个**开始。 +```js +var s = 'aaa_aa_a'; +var r1 = /a+/g; +var r2 = /a+/y; + +r1.exec(s) // ["aaa"] +r2.exec(s) // ["aaa"] + +r1.exec(s) // ["aa"] 剩余 '_aa_a' +r2.exec(s) // null +``` +**`lastIndex`属性**: +指定匹配的开始位置: +```js +const a = /a/y; +a.lastIndex = 2; // 从2号位置开始匹配 +a.exec('wahaha'); // null +a.lastIndex = 3; // 从3号位置开始匹配 +let c = a.exec('wahaha'); +c.index; // 3 +a.lastIndex; // 4 +``` +**返回多个匹配**: +一个`y`修饰符对`match`方法只能返回第一个匹配,与`g`修饰符搭配能返回所有匹配。 +```js +'a1a2a3'.match(/a\d/y); // ["a1"] +'a1a2a3'.match(/a\d/gy); // ["a1", "a2", "a3"] +``` +**检查是否使用`y`修饰符**: +使用`sticky`属性检查。 +```js +const a = /hello\d/y; +a.sticky; // true +``` + +## 4.5 flags属性 +`flags`属性返回所有正则表达式的修饰符。 +```js +/abc/ig.flags; // 'gi' +``` + +# 5. 正则表达式拓展(ES9) +在正则表达式中,点(`.`)可以表示任意单个字符,除了两个:用`u`修饰符解决**四个字节的UTF-16字符**,另一个是行终止符。 +**终止符**即表示一行的结束,如下四个字符属于“行终止符”: +* U+000A 换行符(\n) +* U+000D 回车符(\r) +* U+2028 行分隔符(line separator) +* U+2029 段分隔符(paragraph separator) +```js +/foo.bar/.test('foo\nbar') +// false +``` +上面代码中,因为`.`不匹配`\n`,所以正则表达式返回`false`。 +换个醒,可以匹配任意单个字符: +```js +/foo[^]bar/.test('foo\nbar') +// true +``` +ES9引入`s`修饰符,使得`.`可以匹配任意单个字符: +```js +/foo.bar/s.test('foo\nbar') // true +``` +这被称为`dotAll`模式,即点(`dot`)代表一切字符。所以,正则表达式还引入了一个`dotAll`属性,返回一个布尔值,表示该正则表达式是否处在`dotAll`模式。 +```js +const re = /foo.bar/s; +// 另一种写法 +// const re = new RegExp('foo.bar', 's'); + +re.test('foo\nbar') // true +re.dotAll // true +re.flags // 's' +``` +`/s`修饰符和多行修饰符`/m`不冲突,两者一起使用的情况下,`.`匹配所有字符,而`^`和`$`匹配每一行的行首和行尾。 + + +# 参考资料 +1.[MDN 正则表达式](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions) +2.[W3school JavaScript RegExp 对象](www.w3school.com.cn/jsref/jsref_obj_regexp.asp) + +--- +**本部分内容到这结束** + +|Author|王平安| +|---|---| +|E-mail|pingan8787@qq.com| +|博 客|www.pingan8787.com| +|微 信|pingan8787| +|每日文章推荐|https://github.com/pingan8787/Leo_Reading/issues| +|ES小册|js.pingan8787.com| \ No newline at end of file diff --git "a/Cute-JavaScript/Cute-JS/other/1-JS\344\270\255\347\232\204\351\253\230\351\230\266\345\207\275\346\225\260.md" "b/Cute-JavaScript/Cute-JS/other/1-JS\344\270\255\347\232\204\351\253\230\351\230\266\345\207\275\346\225\260.md" new file mode 100644 index 00000000..3ba6b965 --- /dev/null +++ "b/Cute-JavaScript/Cute-JS/other/1-JS\344\270\255\347\232\204\351\253\230\351\230\266\345\207\275\346\225\260.md" @@ -0,0 +1,206 @@ +Ps. 晚上加班到快十点,回来赶紧整理整理这篇文章,今天老大给我推荐了一篇文章,[我从写技术博客中收获到了什么?- J_Knight_](https://juejin.im/post/5c02b2bce51d4533253f2f43),感受也是很多,自己也需要慢慢养成记录博客的习惯,即使起步艰难,难以坚持,但还是要让自己加油加油。 +前两天把我整理的[【复习资料】ES6/ES7/ES8/ES9资料整理(个人整理)](https://juejin.im/post/5c02b106f265da61764aa0c1)要分享给大家啦。 + +正文内容开始: + +# 1.介绍 +个人简单理解为,一个函数可以接收其他函数作为参数,这种函数便称为**高阶函数**,而主要目的就是为了能接收其他函数作为参数。 +> Q: 为什么可以接收一个函数作为参数? +> A: 因为函数可以接收变量作为参数,而变量可以声明一个方法。 + +**简单实例:** +```js +function a (x){ + return 'hi ' + x; +} +function f (a, b){ + return a(b); +} +f(a, 'leo'); // "hi leo" +``` +**这段代码的意思**:定义方法`f`,接收两个参数,方法`a`和变量`b`,在方法`a`中返回一段字符串,当执行方法`f`并传入参数方法`a`和参数`b`的时候,返回`"hi leo"`。 + +也可以直接调用JS内置方法: +```js +let a = 3, b = -2; +function my_abs (val, fun){ + return fun(val); +} +my_abs(a, Math.abs); // 3 +my_abs(b, Math.abs); // 2 +``` + +# 2.常用高阶函数 + +## 2.1 map() +`map()`方法的作用是:接收一个函数作为参数,对数组中每个元素按顺序调用一次传入的函数并返回结果,**不改变原数组,返回一个新数组**。 +通常使用方式:`arr.map(callback())`,更多详细介绍可以参考 [MDN Array.map()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/map)。 +**参数**: +* `arr` : 需要操作的数组; +* `callback(currentValue, index, array, thisArg)` : 处理的方法,四个参数; + * 1. `currentValue` 当前处理的元素的**值** + * 2. `index` 当前处理的元素的**索引**,可选 + * 3. `array` 调用`map()`方法的**数组**,可选 + * 4. `currentVthisArgalue` 执行 `callback` 函数时使用的 `this` 值,可选 + +**返回值**: +返回一个处理后的新数组。 + +**实例**: +```js +let arr = [1, 3, -5]; +let a1 = arr.map(Math.abs); +// a1 => [1, 3, 5]; + +let a2 = arr.map(String); +// a2 => ["1", "3", "-5"] + +let a3 = arr.map(function (x){ + return x + 1; +}) +// 等价于 a3=arr.map(x => x+1) +// a3 => [2, 4, -4] +``` +对比 `for...in` 循环,`map()`书写起来更加简洁: +```js +let arr = [1, 3, -5]; +let a1 = []; +for (var i=0; i [2, 4, -4] +``` +`map()`作为高阶函数,事实上它把运算规则抽象了。 + +## 2.2 reduce() +`reduce()`方法的作用是:接收一个函数,对数组进行累加操作,把累计结果和下一个值进行操作,最后返回最终的单个结果值。 + +通常使用方式:`arr.reduce(callback(), initValue)`,更多详细介绍可以参考 [MDN Array.reduce()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) + +**参数**: +* `callback(returnValue, currentValue, currentIndex, array)` : 累记器的方法,四个参数: + * 1. `returnValue` 上一次处理的返回值,或者初始值 + * 2. `currentValue` 当前处理的元素的**值**,可选 + * 3. `currentIndex` 当前处理的元素的**索引**,可选 + * 4. `array` 调用`reduce()`方法的**数组**,可选 +* `initValue` 初次调用`callback()`时候`returnValue`参数的初始值,默认数组第一个元素,可选 + +**返回值**: +返回一个最终的累计值。 + +**实例**: +1. 数组求和 +```js +let arr = [1, 3, -5]; +let sum1 = arr.reduce((res, cur) => res + cur); +// sum1 => -1 + +let sum2 = arr.reduce((res, cur) => res + cur , 1); +// sum1 => 0 +``` +2. 二维数组转化为一维 +```js +let arr = [[1, 2], [3, 4], [5, 6]]; +let con = arr.reduce((res, cur) => res.concat(cur)); +// con => [1, 2, 3, 4, 5, 6] +``` + +## 2.3 filter() +`filter()`方法的作用是:接收一个函数,依次作用数组每个元素,并过滤符合函数条件的元素,将剩下的数组作为一个新数组返回。 + +通常使用方式:`arr.filter(callback(), thisArg)`,更多详细介绍可以参考 [MDN Array.filter()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) + +**参数**: +* `callback(ele, index, array)` : 过滤条件的方法,当返回`true`则保存该元素,反之不保留,三个参数: + * 1. `ele` 当前处理的元素 + * 2. `index` 当前处理的元素的**索引**,可选 + * 3. `array` 调用`filter()`方法的**数组**,可选 +* `thisArg` 执行 `callback` 时的用于 `this` 的值,可选 + +**返回值**: +返回一个过滤剩下的元素组成的新数组。 + +**实例**: +1. 过滤奇数值 +```js +let arr = [1, 2, 3, 4, 5, 6]; +let res = arr.filter(x => x % 2 != 0); +// res => [1, 3, 5] +``` +2. 过滤不满足条件的值 +```js +let arr = [1, 2, 3, 4, 5, 6]; +let res = arr.filter(x => x > 3); +// res => [4, 5, 6] +``` +3. 过滤空字符串 +```js +let arr = ['a', '', null, undefined, 'b', '']; +let tri = arr.filter(x => x && x.trim()); +// tri => ["a", "b"] +``` +总结下: `filter()`主要作为**筛选功能**,因此核心就是正确实现一个“筛选”函数。 + +## 2.4 sort() +`sort()`方法的作用是:接收一个函数,对数组的元素进行排序,并返回排序后的新数组。**默认排序顺序是根据字符串Unicode码点**。 + +通常使用方式:`arr.sort(fun())`,更多详细介绍可以参考 [MDN Array.sort()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) +compareFunction 可选 +用来指定按某种顺序进行排列的函数。如果省略,元素按照转换为的字符串的各个字符的Unicode位点进行排序。 +**参数**: +* `fun(a, b)` : 指定按某种顺序进行排列的函数,若省略则按照转换为的字符串的各个字符的Unicode位点进行排序,两个可选参数: +`fun()` 返回 `a`和`b`两个值的大小的比较结果,`sort()`根据返回结果进行排序: +* 若 `fun(a, b)` 小于 0 ,则 `a` 排在 `b` 前面; +* 若 `fun(a, b)` 等于 0 ,则 `a` `b` 位置不变; +* 若 `fun(a, b)` 大于 0 ,则 `a` 排在 `b` 后面; + + +**返回值**: +返回排序后的新数组,并**修改原数组**。 + +**实例**: +1. 升序降序数组 +```js +let arr = [1,5,2,3]; +let sort1 = arr.sort(); +// 等同于 let sort1 = arr.sort((a, b) => a - b); +// sort1 => [1, 2, 3, 5] + +let sort2 = arr.sort((a, b) => b - a); +// sort2 => [5, 3, 2, 1] +``` +2. 字符串排序 +```js +let arr1 = ['AA', 'CC', 'BB']; +let sort1 = arr1.sort(); +// sort1 => ["AA", "BB", "CC"] + +let arr2 = ['AA', 'aa', 'BB']; +let sort2 = arr2.sort(); +// sort2 => ["AA", "BB", "aa"] + +let arr3 = ['AA', 'aa', 'BB']; +let sort3 = arr3.sort((a, b) => a.toLowerCase() > b.toLowerCase()); +// sort3 => ["AA", "aa", "BB"] +// 也可以写成: +let sort3 = arr3.sort((a, b) => { + let s1 = a.toLowerCase(); + let s2 = b.toLowerCase(); + return s1 > s2 ? 1 : s1 < s2 ? -1 : 0; +}) +``` +总结下: `sort()`主要作为**排序功能**,因此核心就是正确实现一个“排序”函数。 + +# 3. 参考文章 +* [阮一峰 JS高阶函数](https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/001434499355829ead974e550644e2ebd9fd8bb1b0dd721000) + +分享的内容比较简单,但是还是希望能帮助到需要的人哈。~~感谢 + + +|Author|王平安| +|---|---| +|E-mail|pingan8787@qq.com| +|博 客|www.pingan8787.com| +|微 信|pingan8787| +|每日文章推荐|https://github.com/pingan8787/Leo_Reading/issues| +|ES小册|js.pingan8787.com| diff --git "a/Cute-JavaScript/Cute-JS/other/2-instanceof\350\277\220\347\256\227\347\254\246.md" "b/Cute-JavaScript/Cute-JS/other/2-instanceof\350\277\220\347\256\227\347\254\246.md" new file mode 100644 index 00000000..fbab5a11 --- /dev/null +++ "b/Cute-JavaScript/Cute-JS/other/2-instanceof\350\277\220\347\256\227\347\254\246.md" @@ -0,0 +1,142 @@ +最近开始在整理`ES6/ES7/ES8/ES9`的知识点(已经上传到 [我的博客](http://js.pingan8787.com) 上),碰到一些知识点是自己已经忘记(用得少的知识点),于是也重新复习了一遍。 +这篇文章要复习的 `instanceof` 是我在整理过程中遇到的,那就整理下来吧,不然容易忘记。 +要是哪里写得不妥,欢迎各位大佬指点。 + + +## 1.定义 +> `instanceof`运算符用于测试构造函数的`prototype`属性是否出现在对象的原型链中的任何位置。 —— MDN + +简单理解为:`instanceof`可以检测一个实例是否属于某种类型。 +比如: +```js +function F (){ + // ... +} +let a = new F (); + +a instanceof F; // true +a instanceof Object; // true 后面介绍原因 +``` +还可以在**继承关系**中用来判断一个实例是否属于它的父类型。 +比如: +```js +function F (){}; +function G (){}; +function Q (){}; +G.prototype = new F(); // 继承 + +let a = new G(); +a instanceof F; // true +a instanceof G; // true +a instanceof Q; // false +``` + +## 2.使用方法 +语法为: `object instanceof constructor`。 +* `object` : 需要测试的函数 +* `constructor` : 构造函数 + +即:用`instanceof`运算符来检测`constructor.prototype` 是否存在参数`object`的原型链。 +```js +function F (){}; +function G (){}; +let a = new F (); + +a instanceof F; // true 因为:Object.getPrototypeOf(a) === F.prototype +a instanceof Q; // false 因为:F.prototype不在a的原型链上 +a instanceof Object; // true 因为:Object.prototype.isPrototypeOf(a)返回true +F.prototype instanceof Object; // true,同上 +``` +**注意**: +1. `a instanceof F` 返回 `true` 以后,不一定永远都都返回为`true`,`F.prototype`属性的值有可能会改变。 +2. 原表达式`a`的值也会改变,比如 `a.__proto__ = {}`之后,`a instanceof F`就会返回`false`了。 + +**检测对象是不是特定构造函数的实例:** +```js +// 正确 +if (!(obj instanceof F)) { + // ... +} + +// 错误 因为 +if (!obj instanceof F); // 永远返回false +// 因为 !obj 在instanceof之前被处理 , 即一直使用一个布尔值检测是否是F的实例 +``` + +## 3.实现instanceof +```js +/** +* 实现instanceof +* @param obj{Object} 需要测试的对象 +* @param fun{Function} 构造函数 +*/ +function _instanceof(obj, fun) { + let f = fun.prototype; // 取B的显示原型 + obj = obj.__proto__; // 取A的隐式原型 + while (true) { + //Object.prototype.__proto__ === null + if (obj === null) + return false; + if (f === obj) // 这里重点:当 f 严格等于 obj 时,返回 true + return true; + obj = obj.__proto__; + } +} +``` + +## 4.instanceof 与 typeof 对比 +**相同**: +`instanceof`和`typeof`都能用来判断一个变量的类型。 + +**区别**: +`instanceof` 只能用来判断对象、函数和数组,不能用来判断字符串和数字等: +```js +let a = {}; +let b = function () {}; +let c = []; +let d = 'hi'; +let e = 123; + +a instanceof Object; // true +b instanceof Object; // true +c instanceof Array; // true +d instanceof String; // false +e instanceof Number; // false +``` + +`typeof` :用于判断一个表达式的原始值,返回一个字符串。 +```js +typeof 42; // "number" +typeof 'blubber'; // "string" +typeof true; // "boolean" +typeof aa; // "undefined" +``` +一般返回结果有: +* number +* boolean +* string +* function(函数) +* object(NULL,数组,对象) +* undefined。 + +**判断变量是否存在**: +不能使用: +```js +if(a){ + //变量存在 +} +// Uncaught ReferenceError: a is not defined +``` +原因是如果变量未定义,就会报**未定义**的错,而应该使用: +```js +if(typeof a != 'undefined'){ + //变量存在 +} +``` + +## 5.参考资料 +1. [MDN instanceof](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/instanceof) + +2. [IBM instanceof](https://www.ibm.com/developerworks/cn/web/1306_jiangjj_jsinstanceof/index.html) + +3. [js中typeof和instanceof用法区别](https://blog.csdn.net/qq_27626333/article/details/76146078) \ No newline at end of file From 3f7c06b9ac4c769c34dd2da9bd97330513de8838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Wed, 9 Jan 2019 21:24:55 +0800 Subject: [PATCH 199/835] 2019.01.09 --- ...\345\271\266\344\270\213\350\275\275.html" | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 "demo\347\211\207\346\256\265/5-js\345\260\206canvas\344\277\235\345\255\230\346\210\220\345\233\276\347\211\207\345\271\266\344\270\213\350\275\275.html" diff --git "a/demo\347\211\207\346\256\265/5-js\345\260\206canvas\344\277\235\345\255\230\346\210\220\345\233\276\347\211\207\345\271\266\344\270\213\350\275\275.html" "b/demo\347\211\207\346\256\265/5-js\345\260\206canvas\344\277\235\345\255\230\346\210\220\345\233\276\347\211\207\345\271\266\344\270\213\350\275\275.html" new file mode 100644 index 00000000..3dddec50 --- /dev/null +++ "b/demo\347\211\207\346\256\265/5-js\345\260\206canvas\344\277\235\345\255\230\346\210\220\345\233\276\347\211\207\345\271\266\344\270\213\350\275\275.html" @@ -0,0 +1,83 @@ + + + + + + + canvas转img并下载 + + + +
    + + +
    + + \ No newline at end of file From b962b1a47635b3363328a2bb05bf6102c482f680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sat, 12 Jan 2019 20:36:47 +0800 Subject: [PATCH 200/835] 2019.01.12 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d23d4cd7..790a6b02 100644 --- a/README.md +++ b/README.md @@ -101,5 +101,6 @@ ### 10、其他 * [2017-全年总结](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/2017-%E5%85%A8%E5%B9%B4%E6%80%BB%E7%BB%93.md) * [2018-全年计划](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/2018-%E5%85%A8%E5%B9%B4%E8%AE%A1%E5%88%92.md) +* [2018-全年总结](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/2018-%E5%85%A8%E5%B9%B4%E6%80%BB%E7%BB%93.md) * [★ 27-Markdowm语法整理](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/27-Markdowm%E8%AF%AD%E6%B3%95%E6%95%B4%E7%90%86.md) * [39-作为前端需要了解的开源协议知识](https://github.com/pingan8787/Leo-JavaScript/blob/master/article/39-%E4%BD%9C%E4%B8%BA%E5%89%8D%E7%AB%AF%E9%9C%80%E8%A6%81%E4%BA%86%E8%A7%A3%E7%9A%84%E5%BC%80%E6%BA%90%E5%8D%8F%E8%AE%AE%E7%9F%A5%E8%AF%86.md) \ No newline at end of file From 85a2c6c704bfffe86bfbedb21d35fd431c1ca5f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sat, 12 Jan 2019 22:36:04 +0800 Subject: [PATCH 201/835] 2019.01.12 --- ...50\345\271\264\346\200\273\347\273\223.md" | 2 +- ...50\345\271\264\350\256\241\345\210\222.md" | 98 +++++++++++++++++++ 2 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 "article/2019-\345\205\250\345\271\264\350\256\241\345\210\222.md" diff --git "a/article/2018-\345\205\250\345\271\264\346\200\273\347\273\223.md" "b/article/2018-\345\205\250\345\271\264\346\200\273\347\273\223.md" index 02dff167..3867c47b 100644 --- "a/article/2018-\345\205\250\345\271\264\346\200\273\347\273\223.md" +++ "b/article/2018-\345\205\250\345\271\264\346\200\273\347\273\223.md" @@ -5,7 +5,7 @@ |博 客|www.pingan8787.com| |微 信|pingan8787| |每日文章推荐|https://github.com/pingan8787/Leo_Reading/issues| -|ES小册|es.pingan8787.com| +|JS小册|js.pingan8787.com| **** 今年一整年,有这么几个感悟: diff --git "a/article/2019-\345\205\250\345\271\264\350\256\241\345\210\222.md" "b/article/2019-\345\205\250\345\271\264\350\256\241\345\210\222.md" new file mode 100644 index 00000000..5a983645 --- /dev/null +++ "b/article/2019-\345\205\250\345\271\264\350\256\241\345\210\222.md" @@ -0,0 +1,98 @@ +**** +|Author|王平安| +|---|---| +|E-mail|pingan8787@qq.com| +|博 客|www.pingan8787.com| +|微 信|pingan8787| +|每日文章推荐|https://github.com/pingan8787/Leo_Reading/issues| +|JS小册|js.pingan8787.com| +**** + +> 我相信每个人都是幸运,而且聪明。 +> 厚积才能薄发,基础牢固才能做好。 +> 做出改变,做好调整,接受挑战,对自己有好处。 +> 自律很重要。 +以上是摘自我的《2018-全年计划》(这里就不放地址了) + +也许还有一句,我比较喜欢的:你在成就公司,公司也在成就你 + +2019年对我来说,应该会变得更加理性,为人处世,日常生活,今年剩下的12个月(到2020年春节前),计划依旧分三方面:`工作`、`学习`和`生活`。 + +# 1、工作 +今年我会坚持在现在公司沉淀自己,完善自己,也多为公司出力。对于现在公司,我挺满意,产品也好,技术氛围也好,学习氛围还有同事间的氛围,我觉得都很符合我的理想工作环境。而且公司给我们提供很多很棒的资源,如**技术分享会**,**书籍借阅**,**设备支持**,**实践机会**等等,所以今年要利用好这些呢。 +今年呢,工作上有这样的安排: +1. 跟着公司项目的脚步,学习和开发,另外在需求提交之前,一定要做好UI稿**核对**,原型逻辑**核对**等,减少BUG。 +2. 与小伙伴们分享自己的**知识总结**和**技术分享**,锻炼自己,思路和思维。 +3. 向公司老大前辈们学习,对于一些**问题的处理方式**,和**管理团队的方式**等。 +4. 努力尝试能为公司写一些工具,**简化工作流程**,或者**提高工作效率**等。 +5. 多**使用公司产品**,**参与产品运营**,发现问题,提出改善意见等。 +6. 研究一套项目基础架构(如公司现在这一套`flutter`的架构)。 + +这一年工作上,会有更多的挑战,已经能感受到了,还是必须要相信自己,踩坑填坑踩坑填坑...,增长经验沉淀技术咯。 + +# 2.学习 +经过这两年的程序员学习和工作生涯,也算是找到一套自己的学习方法,也是挺适合自己,相信今年的学习之路,效率和质量会高一些。 +今年的话,学习的内容会更加集中,而不会想去年那样涉及那么多方面: + +## 2.1学习内容 + +**前端知识(核心)**: +1. 前端基础:基础依然非常重要,今年需要更深入研究`JavaScript原理层面`(如引擎原理,工作原理等),还有CSS的一些不太常用的知识,另外ES规范还需复习,特别是如`Proxy`/`Set`和`Map`这类用的比较少的,但是用起来效率又特别高的这类知识。 +2. 前端框架:`Angular6`(也有可能升级到7)这个必须学会,而且能用在工作中使用,也需要针对一些知识点去研究原理(这方面可以多跟宝哥还有其他人学习),其他框架,就不需要太去研究,现在觉得学好一个框架,研究清楚原理,其他都会是一样的。 +3. 前端趋势:把握和跟进前端的发展趋势,新技术,新工具等,学着了解未来的变化。 + +**后端知识**: +1. 服务端开发:今年需要把`Nodejs`用于工作中了,开发一些工具,提高公司的开发效率,还是使用`Express`和`Koa`,重点朝`Koa`方向。 +2. 数据库开发:搭配服务端开发,使用`Mongodb`和它延伸出来的`Mongoose`进行实际应用。 + +**混合开发**: +1. APP开发:熟练mac环境开发,学习`flutter`,并且开始使用到公司的一些模块上面(看老大安排),毕竟这个技术很棒,今年自己也要自己开发一个App(demo会是现在在开始的TIMI,正式的后面再规划),`RN`和`Weex`今年不会花时间去研究,除非公司业务需要。 + +**博客**: +1. 个人博客:内容改版,新增栏目(待定),“作品”这个栏目内容要充实上去,同步自己在其他平台推送的文章。今年希望将【原创文章】突破到60篇(目前17篇)。 +2. Cute-JavaScrip:需要添加功能,访问量统计(博客也需要,使用百度流量统计),另外【JS基础系列】【面试题系列】必须完成,有空也需要改一改之前的文章。 +3. github:开源新项目,目前暂定2个(Flutter的两个),将学习过程中生产的一些笔记和代码,整理后也放到github上。另外【每日文章】继续维护,坚持第三年。 +4. 掘金/思否/CSDN/简书:各个平台同步自己的原创文章,首发掘金,另外掘金今年加油**粉丝突破5000**,**点赞突破1W**(虽然不太看重这些)。 + +5. 公众号:继续维护,每日一篇,不做宣传,不去吸粉,只想积累,也许某一天,一个幸运的粉丝发现了它,希望能让他有种如获至宝的感觉。截至今天已经发了第106期 + +**机器学习**: +1. 深度学习:`tensorflow.js`有必要尝试下,毕竟对图像识别还是挺有兴趣的呢。 + +**技术书籍**: +1. CSS:《CSS世界》(喜欢)。 +2. JS:《你不知道的JavaScript》上中下,也是加强基础和原理理解。 +3. 算法:《算法图解》和《学习JavaScript数据结构与算法》(这本之前看过,但没看完),主要还是要多刷题,好的算法能提高代码质量和效率。 +书太多,要取舍,研究好几本就好。 +4. 架构:《前端技术架构》这本需要结合自己工作再去看。 + +**非技术书籍**: +1. 《地球上最后的夜晚》和《南方高速》,尝试着去理解作者想表达的思想和道理。 +## 2.2小结 +这学习计划,看上去真的多,但是在我看来,这些都是必须学的。 +所以,这当做是一整年的计划,我还需要拆分到具体的时间上面,做安排。 +坚持! +自律! + +# 3.生活 +生活,我向往简单,人和事。 +新公司加班的现象比较常见,但是也是给我提供很多的学习机会。 +这一年的生活,应该是健康,且有更多幸福感的。 + +**日常生活**: +1. 业余生活:少熬夜(必须少熬夜),多锻炼(早操和睡前锻炼要坚持),坚持能自己做饭尽量自己做饭(早餐不吃外面),学习做饭做菜(找老妈讨教,换宿舍以后),毕竟我有做饭神器——小米电饭煲和小米电磁炉,研究下健康食谱。 +2. 住宿条件:换个宿舍,不用多么高档,安静舒适,适合自己或者和未来女票。 +3. 旅游:出去旅游一次,国内外都行(现在护照港澳通行证都有),需要旅游一次放松也开阔下视野。 + +**家庭生活**: +1. 未来的她:还需要好好加油,一起加油,一起做一件事的感觉会非常好。 +2. 母亲:让母亲分担更多的压力,每个月多汇钱给母亲,帮忙开个店铺给母亲做,照顾好母亲。 +3. 哥哥姐姐:常回家看看,多跟他们交流,今年找个项目再和哥哥一起做,亲兄弟团结。另外哥哥今年结婚,我要给他包个很大的红包。 + +2019全年规划基本如此,不论多与少,需要分配好,偶尔迷茫的时候,会给我带来动力。和去年一样,加油让自己24小时过程26小时。 + +沉淀自己,自律生活,为人和善,为公司,为家庭,也为自己。 + + + +leo 2019.01.12 \ No newline at end of file From 3e955be746eb3260e734ea171704637629954ff4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sat, 12 Jan 2019 22:39:05 +0800 Subject: [PATCH 202/835] 2019.01.12 --- .../2019-\345\205\250\345\271\264\350\256\241\345\210\222.md" | 2 ++ 1 file changed, 2 insertions(+) diff --git "a/article/2019-\345\205\250\345\271\264\350\256\241\345\210\222.md" "b/article/2019-\345\205\250\345\271\264\350\256\241\345\210\222.md" index 5a983645..812b87cb 100644 --- "a/article/2019-\345\205\250\345\271\264\350\256\241\345\210\222.md" +++ "b/article/2019-\345\205\250\345\271\264\350\256\241\345\210\222.md" @@ -12,6 +12,7 @@ > 厚积才能薄发,基础牢固才能做好。 > 做出改变,做好调整,接受挑战,对自己有好处。 > 自律很重要。 + 以上是摘自我的《2018-全年计划》(这里就不放地址了) 也许还有一句,我比较喜欢的:你在成就公司,公司也在成就你 @@ -68,6 +69,7 @@ **非技术书籍**: 1. 《地球上最后的夜晚》和《南方高速》,尝试着去理解作者想表达的思想和道理。 + ## 2.2小结 这学习计划,看上去真的多,但是在我看来,这些都是必须学的。 所以,这当做是一整年的计划,我还需要拆分到具体的时间上面,做安排。 From 653d460651e9be677d7292a46c7aead238f7781f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sat, 12 Jan 2019 23:07:40 +0800 Subject: [PATCH 203/835] 2019.01.12 --- .../2019-\345\205\250\345\271\264\350\256\241\345\210\222.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/article/2019-\345\205\250\345\271\264\350\256\241\345\210\222.md" "b/article/2019-\345\205\250\345\271\264\350\256\241\345\210\222.md" index 812b87cb..e4716209 100644 --- "a/article/2019-\345\205\250\345\271\264\350\256\241\345\210\222.md" +++ "b/article/2019-\345\205\250\345\271\264\350\256\241\345\210\222.md" @@ -88,7 +88,7 @@ **家庭生活**: 1. 未来的她:还需要好好加油,一起加油,一起做一件事的感觉会非常好。 -2. 母亲:让母亲分担更多的压力,每个月多汇钱给母亲,帮忙开个店铺给母亲做,照顾好母亲。 +2. 母亲:为母亲分担更多的压力,每个月多汇钱给母亲,帮忙开个店铺给母亲做,照顾好母亲。 3. 哥哥姐姐:常回家看看,多跟他们交流,今年找个项目再和哥哥一起做,亲兄弟团结。另外哥哥今年结婚,我要给他包个很大的红包。 2019全年规划基本如此,不论多与少,需要分配好,偶尔迷茫的时候,会给我带来动力。和去年一样,加油让自己24小时过程26小时。 From 56193f8a0e8828927e7025f092ccb4f5ebce1838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 14 Jan 2019 20:44:22 +0800 Subject: [PATCH 204/835] 2019.01.14 --- ...71\350\261\241\344\273\213\347\273\215.md" | 5 ++ Cute-JavaScript/README.md | 46 +++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 "Cute-JavaScript/Cute-JS/level2/1.JS\345\257\271\350\261\241\344\273\213\347\273\215.md" create mode 100644 Cute-JavaScript/README.md diff --git "a/Cute-JavaScript/Cute-JS/level2/1.JS\345\257\271\350\261\241\344\273\213\347\273\215.md" "b/Cute-JavaScript/Cute-JS/level2/1.JS\345\257\271\350\261\241\344\273\213\347\273\215.md" new file mode 100644 index 00000000..c67a3aa2 --- /dev/null +++ "b/Cute-JavaScript/Cute-JS/level2/1.JS\345\257\271\350\261\241\344\273\213\347\273\215.md" @@ -0,0 +1,5 @@ +从这篇文章开始,复习 [MDN 中级教程](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Working_with_Objects) 的内容了,在**初级教程**中,我和大家分享了一些比较简单基础的知识点,并放在我的 【[Cute-JavaScript](http://js.pingan8787.com)】系列文章中。 + +**关于【[Cute-JavaScript](http://js.pingan8787.com)】**: +一本可爱的JavaScript小书,内容分成三大部分:**ES规范系列**、**JS基础系列**和**面试题系列**,目前我还在抓紧更新,喜欢的朋友可以 [github](https://github.com/pingan8787/Leo-JavaScript/tree/master/Cute-JavaScript) 上Star一下呀,下面放一张首页图: +![Cute-JavaScript](http://images.pingan8787.com/Cute-JavaScript.png) \ No newline at end of file diff --git a/Cute-JavaScript/README.md b/Cute-JavaScript/README.md new file mode 100644 index 00000000..ebb3f19d --- /dev/null +++ b/Cute-JavaScript/README.md @@ -0,0 +1,46 @@ +最近开始把精力放在重新复习JavaScript的基础知识上面,不再太追求各种花枝招展的前端框架,框架再多,适合实际项目才是最重要。 + + +上星期在掘金发布了几篇文章,其中最大块算是 [【复习资料】ES6/ES7/ES8/ES9资料整理(个人整理)](https://juejin.im/post/5c02b106f265da61764aa0c1),也是让我好好把这些规范复习了一遍,虽然不是完全的原创,而是自己的一些复习笔记,但是还是让我感觉还是挺有用的,在项目开发过程中,有有意识的去使用到这些新的规范。 + + +这次开始复习 [MDN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide) 这个系列的文章,巩固好自己的基础,也让自己养成记录学习的习惯,当然这些文章我也会同步到自己的博客。 + +# 本文目录 +## JavaScript初级 +1. [语法和数据类型](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/1.%E8%AF%AD%E6%B3%95%E5%92%8C%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B.md) +2. [流程控制和错误处理](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/2.%E6%B5%81%E7%A8%8B%E6%8E%A7%E5%88%B6%E5%92%8C%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86.md) +3. [循环和迭代](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/3.%E5%BE%AA%E7%8E%AF%E5%92%8C%E8%BF%AD%E4%BB%A3.md) +4. [函数](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/4.%E5%87%BD%E6%95%B0.md) +5. [表达式和运算符](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/5.%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%92%8C%E8%BF%90%E7%AE%97%E7%AC%A6.md) +6. [数字](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/6.数字.md) +7. [时间对象](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/7.时间对象.md) +8. [字符串](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/8.字符串.md) +9. [正则表达式](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/9.正则表达式.md) +10. [数组](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/10.数组.md) +11. [Map和Set对象](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/11.Map和Set对象.md) +12. [使用对象](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/12.使用对象.md) +13. [迭代器和生成器](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/13.迭代器和生成器.md) +14. [元编程](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/14.元编程.md) + +## JavaScript中级 +待补充 + +## JavaScript高级 +待补充 + +## 其他细节知识 +1. [JS中的高阶函数](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/other/1-JS中的高阶函数.md) +2. [instanceof运算符](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/other/2-instanceof运算符.md) + + +希望自己的文章会对各位有所帮助,也欢迎各位大佬指点。 + + +|Author|王平安| +|---|---| +|E-mail|pingan8787@qq.com| +|博 客|www.pingan8787.com| +|微 信|pingan8787| +|每日文章推荐|https://github.com/pingan8787/Leo_Reading/issues| +|ES小册|js.pingan8787.com| \ No newline at end of file From 42d7c570d642f6eb09e98dbb484fefc361b26f1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 14 Jan 2019 23:00:43 +0800 Subject: [PATCH 205/835] 2019.01.14 --- ...71\350\261\241\344\273\213\347\273\215.md" | 224 +++++++++++++++++- 1 file changed, 223 insertions(+), 1 deletion(-) diff --git "a/Cute-JavaScript/Cute-JS/level2/1.JS\345\257\271\350\261\241\344\273\213\347\273\215.md" "b/Cute-JavaScript/Cute-JS/level2/1.JS\345\257\271\350\261\241\344\273\213\347\273\215.md" index c67a3aa2..806f3e1e 100644 --- "a/Cute-JavaScript/Cute-JS/level2/1.JS\345\257\271\350\261\241\344\273\213\347\273\215.md" +++ "b/Cute-JavaScript/Cute-JS/level2/1.JS\345\257\271\350\261\241\344\273\213\347\273\215.md" @@ -2,4 +2,226 @@ **关于【[Cute-JavaScript](http://js.pingan8787.com)】**: 一本可爱的JavaScript小书,内容分成三大部分:**ES规范系列**、**JS基础系列**和**面试题系列**,目前我还在抓紧更新,喜欢的朋友可以 [github](https://github.com/pingan8787/Leo-JavaScript/tree/master/Cute-JavaScript) 上Star一下呀,下面放一张首页图: -![Cute-JavaScript](http://images.pingan8787.com/Cute-JavaScript.png) \ No newline at end of file +![Cute-JavaScript](http://images.pingan8787.com/Cute-JavaScript.png) + + +--- +正文开始 + +本文是 **重温基础** 系列文章的第十五篇,耐心为人处世。 + +**本章节复习的是JS中的关于对象的一些知识。** + +前置知识: +关于使用对象,可以先阅读一下我的[《12.使用对象》](https://github.com/pingan8787/Leo-JavaScript/blob/master/Cute-JavaScript/Cute-JS/level1/12.%E4%BD%BF%E7%94%A8%E5%AF%B9%E8%B1%A1.md)这篇文章。 + +下面也先重温一点基础。 + +# 1.概念 +对象是一个包含相关数据和方法的集合,由**变量**和**方法**组成,通常称为对象的**属性**和**方法**,比如: +```js +let me = { + name : 'pingan', + eat: function(){ + console.log('eat eat eat!!!'); + } +} +``` +其中,`name`就是`me`这个对象的一个属性,`eat`就是`me`这个对象的一个方法。 +访问对象的属性是这样的: +```js +me.name; // "pingan" +me.eat(); // "eat eat eat!!!" +``` +另外在访问对象属性时,有以下两种方式: +```js +let me = { + name : 'pingan', +} +// 点表示法 +me.name; // me.name => "pingan" + +// 括号表示法 +me["name"];// me.name => "pingan" +``` +括号表示法中,必须是字符串。 + +我们常常这么设置对象的属性: +```js +let me = { + name : 'pingan', +} +// 点表示法 +me.name = "leo"; // me => {name: "leo"} + +// 括号表示法 +me["name"] = "leo";// me => {name: "leo"} +``` + +# 2.简单的面向对象介绍 +这里简单介绍下JavaScrip的面向对象编程OOP。 +> 面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)是一种计算机编程架构。OOP 的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象组合而成。 —— 百度百科 + +![OOP](http://images.pingan8787.com/OOP1.png) + +我们这里定义一个简单的对象模型,比如我,我的身上可能有很多信息(姓名,年龄,身高等等),这时候我们可以将这些信息抽取出来,像这样: +```js +let leo = { + name : 'leo', + age : 26, + height : 180, +} +``` +这样我们就将我的信息抽取成一个JS的对象了,但是这样有个局限性,这样定义的话,一次只能定义一个人,如果这时候,有一百个人,那么我们就需要定义一百个这样的对象,显然这是不可取的。 +所以,这里就引入一个重要的函数——**构造函数**,**将相同的特性封装成通用的对象**,实现定义一次,其他地方都可以使用,这也是OOP的核心思想: +```js +// 传入 name 参数使得可以定义任何人作为对象 +function Person (name){ + let me = {}; + me.name = name; + me.doSomething = function(){ + console.log(me.name); + } + return me; +} +``` +创建一个函数“`Person`”,只要传入不同的`name`即可得到不同的对象: +```js +let leo = Person("leo"); +leo.name; // "leo" + +let pingan = Person("pingan"); +pingan.name; // "pingan" +``` +但是似乎`Person`对象的定义,显得不够精简,因为还要定义一个**空对象**来接收各个属性和方法,幸好JavaScrip在构造函数中提供一个便捷的方法,我们将代码改造下: +```js +function Person (name){ + this.name = name; + this.doSomething = function(){ + console.log(this.name); + } +} +``` +对于`this`关键词,即无论是该对象的哪个实例被构造函数创建,它的`name`属性都是参数`name`的值,`doSomething`方法中使用的也是参数`name`。简单理解就是用`this`指代了`Person`。 + +**构造函数通常首字母大写,用于区分普通函数。** + +接下来,通过`new`关键词,使用前面创建的构造函数(使用构造函数也叫实例化): +```js +let leo = new Person("leo"); +leo.name; // "leo" + +let pingan = new Person("pingan"); +pingan.name; // "pingan" +``` +然后一个简单的构造函数就写好了,通常在开发的时候,可能会有很多的参数: +```js +function Man(name, age, height, weight){ + this.name = name; + this.age = age + '岁'; + this.HeightAndWeight = { + height, + weight + }; + this.doSomething = function (){ + console.log(`${this.name}: height:${this.HeightAndWeight.height}m, weight:${this.HeightAndWeight.weight}Kg!!`); + }; +} + +let leo = new Man("leo",25,1.8,68); +leo.doSomething(); // leo: height:1.8m, weight:68Kg!! +``` + +# 3.JS中的原型 +## 3.1理解原型 +这里需要先了解一下`Object`和`Function`,这两个函数都是JS的自带函数,`Object`继承自己,`Function`继承自己,相互继承对方,即`Object`和`Function`既是函数也是对象。 +```js +console.log(Function instanceof Object); // true +console.log(Object instanceof Function); // true +``` +`Object` 是 `Function`的实例,而`Function`是它自己的实例。 +```js +console.log(Function.prototype); // ƒ () { [native code] } +console.log(Object.prototype); // Object +``` +另外,只有通过`Function`创建的函数都是函数对象,其他都是普通对象(通常由`Object`创建): +```js +function f1(){}; +typeof f1 //"function" + + +var o1 = new f1(); +typeof o1 //"object" + +var o2 = {}; +typeof o2 //"object" +``` + +**理论知识:** + +JavaScript 常被描述为一种基于原型的语言 (prototype-based language)——每个对象拥有一个**原型对象**,对象以其原型为模板、从原型继承方法和属性。 +原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为**原型链** (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。 +准确地说,这些属性和方法定义在Object的构造器函数(constructor functions)之上的`prototype`属性上,而非对象实例本身。 + +**个人理解:** + +* JS中所有的函数对象,都有一个`prototype`属性,对应当前对象的原型,但普通对象没有,而`prototype`属性下还有一个`constructor`,指向这个函数。 +```js +var p = {}; +p.prototype; // undefined +p instanceof Object; // true + +function f (){}; +f.prototype; // object {constructor: ƒ} +f === f.prototype.constructor; // true +Object === Object.prototype.constructor; // true +``` +* JS中所有的对象,都有一个`_proto_`属性,指向**实例对象的构造函数原型**(由于`_proto_`是个非标准属性,因此只有**ff**和**chrome**两个浏览器支持,标准方法是`Object.getPrototypeOf()`)。 +```js +var p = new Person(); +p._proto === Person.prototype; //true +``` + +**修改原型:** +经常我们也需要对原型进行修改: +```js +function Person (name){ + this.name = name; +} +// 添加一个getName方法 +Person.prototype.getName = function(){ + return "名字:" + this.name; +} +var p = new Person("leo"); +p.getName(); // "名字:leo" +``` + +这里也说明了原型进行继承,`p`继承`Person`原型中新增的函数属性`getName`。 + +## 3.2原型链 +**概念:** +javascript中,每个对象都会在内部生成一个 `proto` 属性,当我们访问一个对象属性时,如果这个对象不存在就回去 `proto` 指向的对象里面找,一层一层找下去,,知道找到为止,如果到了原型链顶端,还没找到,则返回`undefined`,这就是javascript原型链的概念。 + +![原型链:](http://images.pingan8787.com/1.png) + +**总结:** +* 除了`Object`的`prototype`的原型是`null`,所有对象和原型都有自己的原型,对象的原型指向原型对象。 +* JS中所有的东西都是对象,所有的东西都由`Object`衍生而来, 即所有东西原型链的终点指向null。 + +**更加详细的介绍,可以查看下面参考文章。** + +--- +# 参考文章: +[1.MDN JavaScript 对象入门](https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Objects) + +[2.基于js中的原型](https://www.jb51.net/article/123976.htm) + +**本部分内容到这结束** + +|Author|王平安| +|---|---| +|E-mail|pingan8787@qq.com| +|博 客|www.pingan8787.com| +|微 信|pingan8787| +|每日文章推荐|https://github.com/pingan8787/Leo_Reading/issues| +|ES小册|js.pingan8787.com| \ No newline at end of file From bc4c14216064740079fb16c145209d85a60f1f03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 14 Jan 2019 23:03:47 +0800 Subject: [PATCH 206/835] 2019.01.14 --- Cute-JavaScript/Cute-JS/README.md | 4 +++- .../1.JS\345\257\271\350\261\241\344\273\213\347\273\215.md" | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Cute-JavaScript/Cute-JS/README.md b/Cute-JavaScript/Cute-JS/README.md index ebb3f19d..4d85c4aa 100644 --- a/Cute-JavaScript/Cute-JS/README.md +++ b/Cute-JavaScript/Cute-JS/README.md @@ -24,7 +24,9 @@ 14. [元编程](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/14.元编程.md) ## JavaScript中级 -待补充 +15. [JS对象介绍](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level2/15.JS对象介绍.md) + +更新中 ## JavaScript高级 待补充 diff --git "a/Cute-JavaScript/Cute-JS/level2/1.JS\345\257\271\350\261\241\344\273\213\347\273\215.md" "b/Cute-JavaScript/Cute-JS/level2/1.JS\345\257\271\350\261\241\344\273\213\347\273\215.md" index 806f3e1e..a1442c27 100644 --- "a/Cute-JavaScript/Cute-JS/level2/1.JS\345\257\271\350\261\241\344\273\213\347\273\215.md" +++ "b/Cute-JavaScript/Cute-JS/level2/1.JS\345\257\271\350\261\241\344\273\213\347\273\215.md" @@ -124,7 +124,10 @@ function Man(name, age, height, weight){ weight }; this.doSomething = function (){ - console.log(`${this.name}: height:${this.HeightAndWeight.height}m, weight:${this.HeightAndWeight.weight}Kg!!`); + console.log(` + ${this.name}: height:${this.HeightAndWeight.height}m, + weight:${this.HeightAndWeight.weight}Kg!!` + ); }; } From 7bdad479cb78f4f81ad3d45ba392323ebab450c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 14 Jan 2019 23:08:52 +0800 Subject: [PATCH 207/835] 2019.01.14 --- ...S\345\257\271\350\261\241\344\273\213\347\273\215.md" | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git "a/Cute-JavaScript/Cute-JS/level2/1.JS\345\257\271\350\261\241\344\273\213\347\273\215.md" "b/Cute-JavaScript/Cute-JS/level2/1.JS\345\257\271\350\261\241\344\273\213\347\273\215.md" index a1442c27..877395bd 100644 --- "a/Cute-JavaScript/Cute-JS/level2/1.JS\345\257\271\350\261\241\344\273\213\347\273\215.md" +++ "b/Cute-JavaScript/Cute-JS/level2/1.JS\345\257\271\350\261\241\344\273\213\347\273\215.md" @@ -8,11 +8,12 @@ --- 正文开始 -本文是 **重温基础** 系列文章的第十五篇,耐心为人处世。 +本文是 **重温基础** 系列文章的第十五篇。 +今日感受:耐心为人处世。 -**本章节复习的是JS中的关于对象的一些知识。** +**本章节复习的是JS中的关于对象还有原型等相关知识。** -前置知识: +**前置知识**: 关于使用对象,可以先阅读一下我的[《12.使用对象》](https://github.com/pingan8787/Leo-JavaScript/blob/master/Cute-JavaScript/Cute-JS/level1/12.%E4%BD%BF%E7%94%A8%E5%AF%B9%E8%B1%A1.md)这篇文章。 下面也先重温一点基础。 @@ -205,7 +206,7 @@ p.getName(); // "名字:leo" **概念:** javascript中,每个对象都会在内部生成一个 `proto` 属性,当我们访问一个对象属性时,如果这个对象不存在就回去 `proto` 指向的对象里面找,一层一层找下去,,知道找到为止,如果到了原型链顶端,还没找到,则返回`undefined`,这就是javascript原型链的概念。 -![原型链:](http://images.pingan8787.com/1.png) +![原型链:](http://images.pingan8787.com/%E5%8E%9F%E5%9E%8B%E9%93%BE.jpg) **总结:** * 除了`Object`的`prototype`的原型是`null`,所有对象和原型都有自己的原型,对象的原型指向原型对象。 From 985f6e0dfe79d5bfa0439b1fd5bf2bbcfc1803d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Mon, 14 Jan 2019 23:22:01 +0800 Subject: [PATCH 208/835] 2019.01.14 --- .../1.JS\345\257\271\350\261\241\344\273\213\347\273\215.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/Cute-JavaScript/Cute-JS/level2/1.JS\345\257\271\350\261\241\344\273\213\347\273\215.md" "b/Cute-JavaScript/Cute-JS/level2/1.JS\345\257\271\350\261\241\344\273\213\347\273\215.md" index 877395bd..b1a3c09f 100644 --- "a/Cute-JavaScript/Cute-JS/level2/1.JS\345\257\271\350\261\241\344\273\213\347\273\215.md" +++ "b/Cute-JavaScript/Cute-JS/level2/1.JS\345\257\271\350\261\241\344\273\213\347\273\215.md" @@ -228,4 +228,4 @@ javascript中,每个对象都会在内部生成一个 `proto` 属性,当我 |博 客|www.pingan8787.com| |微 信|pingan8787| |每日文章推荐|https://github.com/pingan8787/Leo_Reading/issues| -|ES小册|js.pingan8787.com| \ No newline at end of file +|JS小册|js.pingan8787.com| \ No newline at end of file From d611b954b7bea05cac37eb984a2f79321cfb97b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Thu, 17 Jan 2019 23:40:57 +0800 Subject: [PATCH 209/835] 2019.01.17 --- ...71\350\261\241\344\273\213\347\273\215.md" | 235 ++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 "Cute-JavaScript/Cute-JS/level2/2.JSON\345\257\271\350\261\241\344\273\213\347\273\215.md" diff --git "a/Cute-JavaScript/Cute-JS/level2/2.JSON\345\257\271\350\261\241\344\273\213\347\273\215.md" "b/Cute-JavaScript/Cute-JS/level2/2.JSON\345\257\271\350\261\241\344\273\213\347\273\215.md" new file mode 100644 index 00000000..2fd956fc --- /dev/null +++ "b/Cute-JavaScript/Cute-JS/level2/2.JSON\345\257\271\350\261\241\344\273\213\347\273\215.md" @@ -0,0 +1,235 @@ +本文是 **重温基础** 系列文章的第十六篇。 +今日感受:静。 + +**本章节复习的是JS中的关于JSON对象相关知识。** + +**前置知识**: +`JSON`是一种按照`JavaScript`对象语法的数据格式。 + +# 1.概念 +概念有三点: +> `JSON`全称`JavaScript` 对象表示法(JavaScript Object Notation)。 +> `JSON` 是**存储**和**交换文本信息**的语法。类似 `XML`。 +> `JSON` 比 `XML` 更小、更快,更易解析。 +> ———— 摘自 [W3school JSON教程](http://www.w3school.com.cn/json/index.asp) + +`JSON` 使用 `JavaScript` 语法来描述数据对象,但是 `JSON` 仍然独立于语言和平台。`JSON` 解析器和 `JSON` 库支持许多不同的编程语言。 + +# 2.语法 +`JSON`在使用过程中可作为一个**对象**或者**字符串**存在,当作为**对象**时,用于获取`JSON`中的数据,而作为**字符串**时常用于网络数据传输。 + +`JSON`语法规则: +1. 数据在名称/值对中 +2. 数据由逗号分隔 +3. 花括号保存对象 +4. 方括号保存数组 + +通常,`JSON`数据书写格式是`名称/键值`: +```js +"name" : "pingan" +``` + +而`JSON`的值可以是 : +1. 数字(整数或浮点数) +2. 字符串(在双引号中) +3. 逻辑值(`true` 或 `false`) +4. 数组(在方括号中) +5. 对象(在花括号中) +6. `null` + +**JSON常常有三种类型:** +三种类型:简单之,对象和数组。 +必须注意:JSON字符串必须是**双引号**,单引号会语法错误。 + +## 2.1 简单值: +简单值可以是字符串: +```js +"hello leo!" +``` +也可以是数字,逻辑值: +```js +1 +``` + +## 2.2 对象类型: +内容放在`花括号`内,是多个键值对。 +JSON对象 与 js 对象的三个区别: +1. JSON对象 必须加双引号,而 js 对象属性名可以不加双引号。 +2. JSON对象 没有变量声明,而 js 对象有。 +2. JSON对象 没有分号,而 js 对象有。 +```js +// js 对象 +var obj = { + name : "pingan", + age : "25", +}; +// json 对象 +{ + "name" : "pingan", + "age" : "25", + "box" : [ + "a","b","c" + ] +} +``` + +## 2.3 数组类型: +内容放在`方括号`内。 +JSON数组也没有分号和变量,常常可以把JSON数组和对象结合使用,构成更复杂的数据集合。 +```js +[ + { + "name" : "leo", + "age" : 25, + "box" : ["a","b","c"] + }, + { + "name" : "pingan", + "age" : 25, + "box" : ["a","b","c"] + } +] +``` + +# 3. 使用 +JSON最常见的用法就是,从服务端获取JSON数据,再将JSON数据转成JavaScrip对象使用。 +JSON对象有两个方法: +* `JSON.stringify()`: 序列化操作,将`JavaScript对象`转换成`JSON字符串`。 +* `JSON.prase()`:反序列化操作,将`JSON字符串`解析成`JavaScript值`。 + +## 3.1 序列化操作 +序列化操作常常使用`JSON.stringify()`。 +简单例子: +```js +let leo = { + name : "leo", + age : 25, + box : ["a","b","c"] +} +let pingan = JSON.stringify(leo); +console.log(pingan); // "{"name":"leo","age":25,"box":["a","b","c"]}" +``` + +**注意**: +1. 默认情况下,`JSON.stringify()`输出的JSON字符串不包含任何空格字符或缩进,因此结果就像上面那样。 +2. 序列化`JavaScript对象`时,所有函数及原型成员都会被忽略,不体现在结果上。 +3. 值为`undefined`的任何属性都会被跳过。 + +因此,最终的值都是有效的JSON数据类型的实例属性。 + +## 3.2 反序列化操作 +序列化操作常常使用`JSON.parse()`。 +简单例子: +```js +let copyPingan = JSON.parse(pingan); +copyPingan; // {name: "leo", age: 25, box: Array(3)} +``` +如果传入`JSON.parse()`的字符串不是有效的JSON,则会抛出错误。 +**注意**: +虽然`pingan`和`copyPingan`属性相同,但两者独立,没有任何关系。 + +# 4.序列化选项 +`JSON.stringify()`除了要传入序列化对象作为参数,还可以接收其他两个参数,用来指定序列化JavaScript对象的方式: +1. 过滤器:可以是个**数组**,也可以是个**函数**。 +2. 选项:表示是否在`JSON字符串`中**保留缩进**。 + +单独或组合使用两者,可以更加全面深入的控制JSON的序列化。 + +## 4.1 过滤器 +若过滤器的参数是**数组**,则`JSON.stringify()`返回的结果将只包含数组中的属性: +```js +var leo = { + name : "leo", + age : 25, + box : ["a","b","c"] +} +var pingan = JSON.stringify(leo,["name","age"]); +console.log(pingan); // "{"name":"leo","age":25}" +``` + +若过滤器的参数是**函数**,则情况就不一样了,传入的函数需有两个参数(属性名和属性值): +```js +var leo = { + "name" : "leo", + "age" : 25, + "box" : ["a","b","c"] +} +var pingan = JSON.stringify(leo,function(key, value){ + switch(key){ + case "name": + return "我叫" + value + case "age": + return value + "岁" + default: + return value + } +}); +console.log(pingan); // "{"name":"我叫leo","age":"25岁","box":["a","b","c"]}" +``` +**注意**:使用`switch`的时候,必须指定`default`否则会返回`undefined`。 + +## 4.2 选项 +`JSON.stringify()`第三个参数是个选项,控制结果中的缩进和空白符。 +1. 若选项只有一个值,则表示**每个级别缩进的空格数**,最大值为`10`,超过`10`则只会是`10`。 +```js +var leo = { + "name" : "leo", + "age" : 25, + "box" : ["a","b","c"] +} +var pingan = JSON.stringify(leo, null, 4); +console.log(pingan); +/* +"{ + "name": "leo", + "age": 25, + "box": [ + "a", + "b", + "c" + ] +}" +*/ +``` + +# 5.解析选项 +`JSON.parse()`可以接收一个函数作为参数,对每个键值对调用,为了跟`JSON.stringify()`的`过滤函数`区别,这个函数成为`还原函数`。 +* 若还原函数返回`undefined`,则表示要从结果中删除对应的键。 +* 若还原函数返回其他值,则将该值插入结果中。 + +还原函数接收两个参数:属性名和属性值。 + +举例,在日期字符串转换为Date对象中,经常要用到还原函数: +```js +var leo = { + "name" : "leo", + "age" : 25, + "date" : new Date(1993, 9, 9) +} +var pingan = JSON.stringify(leo); +var copy = JSON.parse(pingan,function (key, value){ + // return key == "date" ? new Date(value) : value; + if(key == "date"){ + return new Date(value); + }else{ + return value; + } +}) +console.log(copy); +// "{"name":"leo","age":25,"date":"1993-10-08T16:00:00.000Z"}" +``` + + +# 参考文章: +1. [W3school JSON教程](http://www.w3school.com.cn/json/index.asp) +2. 《JavaScrip高级程序设计》 + +**本部分内容到这结束** + +|Author|王平安| +|---|---| +|E-mail|pingan8787@qq.com| +|博 客|www.pingan8787.com| +|微 信|pingan8787| +|每日文章推荐|https://github.com/pingan8787/Leo_Reading/issues| +|JS小册|js.pingan8787.com| \ No newline at end of file From 9fb1080cfe2d1397138538263c9316743375d0a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Thu, 17 Jan 2019 23:48:29 +0800 Subject: [PATCH 210/835] 2019.01.17 --- Cute-JavaScript/Cute-JS/README.md | 1 + ...JSON\345\257\271\350\261\241\344\273\213\347\273\215.md" | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Cute-JavaScript/Cute-JS/README.md b/Cute-JavaScript/Cute-JS/README.md index 4d85c4aa..eee7a0ec 100644 --- a/Cute-JavaScript/Cute-JS/README.md +++ b/Cute-JavaScript/Cute-JS/README.md @@ -25,6 +25,7 @@ ## JavaScript中级 15. [JS对象介绍](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level2/15.JS对象介绍.md) +16. [JSON对象介绍](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level2/16.JSON对象介绍.md) 更新中 diff --git "a/Cute-JavaScript/Cute-JS/level2/2.JSON\345\257\271\350\261\241\344\273\213\347\273\215.md" "b/Cute-JavaScript/Cute-JS/level2/2.JSON\345\257\271\350\261\241\344\273\213\347\273\215.md" index 2fd956fc..55259542 100644 --- "a/Cute-JavaScript/Cute-JS/level2/2.JSON\345\257\271\350\261\241\344\273\213\347\273\215.md" +++ "b/Cute-JavaScript/Cute-JS/level2/2.JSON\345\257\271\350\261\241\344\273\213\347\273\215.md" @@ -41,7 +41,7 @@ 三种类型:简单之,对象和数组。 必须注意:JSON字符串必须是**双引号**,单引号会语法错误。 -## 2.1 简单值: +## 2.1 简单值 简单值可以是字符串: ```js "hello leo!" @@ -51,7 +51,7 @@ 1 ``` -## 2.2 对象类型: +## 2.2 对象类型 内容放在`花括号`内,是多个键值对。 JSON对象 与 js 对象的三个区别: 1. JSON对象 必须加双引号,而 js 对象属性名可以不加双引号。 @@ -73,7 +73,7 @@ var obj = { } ``` -## 2.3 数组类型: +## 2.3 数组类型 内容放在`方括号`内。 JSON数组也没有分号和变量,常常可以把JSON数组和对象结合使用,构成更复杂的数据集合。 ```js From 538ebbc2cb6b3fe3ead98973aa3b315b4b2eb86a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B9=B3=E5=AE=89?= Date: Sun, 20 Jan 2019 15:08:18 +0800 Subject: [PATCH 211/835] 2019.01.20 --- Cute-JavaScript/Cute-JS/README.md | 5 +- .../3.WebAPI\344\273\213\347\273\215.md" | 633 ++++++++++++++++++ 2 files changed, 636 insertions(+), 2 deletions(-) create mode 100644 "Cute-JavaScript/Cute-JS/level2/3.WebAPI\344\273\213\347\273\215.md" diff --git a/Cute-JavaScript/Cute-JS/README.md b/Cute-JavaScript/Cute-JS/README.md index eee7a0ec..c90416d2 100644 --- a/Cute-JavaScript/Cute-JS/README.md +++ b/Cute-JavaScript/Cute-JS/README.md @@ -24,8 +24,9 @@ 14. [元编程](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level1/14.元编程.md) ## JavaScript中级 -15. [JS对象介绍](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level2/15.JS对象介绍.md) -16. [JSON对象介绍](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level2/16.JSON对象介绍.md) +15. [JS对象介绍](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level2/1.JS对象介绍.md) +16. [JSON对象介绍](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level2/2.JSON对象介绍.md) +17. [JSON对象介绍](https://github.com/pingan8787/Leo-JavaScript/blob/master/base-javascript/level2/3.WebAPI介绍.md) 更新中 diff --git "a/Cute-JavaScript/Cute-JS/level2/3.WebAPI\344\273\213\347\273\215.md" "b/Cute-JavaScript/Cute-JS/level2/3.WebAPI\344\273\213\347\273\215.md" new file mode 100644 index 00000000..9de86b75 --- /dev/null +++ "b/Cute-JavaScript/Cute-JS/level2/3.WebAPI\344\273\213\347\273\215.md" @@ -0,0 +1,633 @@ +本文是 **重温基础** 系列文章的第十七篇。 +今日感受:挑战。 + +**本章节复习的是JS中的关于WebAPI相关知识,介绍的API比较多。** + +**前置知识:** +需要了解 [JS 对象](http://pingan8787.com/2019/01/14/131-%E3%80%90JavaScript%E3%80%91%E3%80%90%E9%87%8D%E6%B8%A9%E5%9F%BA%E7%A1%80%E3%80%9115-JS%E5%AF%B9%E8%B1%A1%E4%BB%8B%E7%BB%8D/) 的相关知识。 + + +# 1.WebAPI介绍 +> API:应用程序接口,是基于编程语言构建的结构,使开发人员更容易地创建复杂的功能。它们抽象了复杂的代码,并提供一些简单的接口规则直接使用。 + +客户端JavaScript提供很多可用的API,他们本身不是JavaScript语言的一部分,却建立在JavaScript语言核心的顶部,为使用JavaScript代码提供额外的超强能力。他们通常分为两类: +* **浏览器API**: +内置于Web浏览器,可以从浏览器和电脑周围环境获取数据,并用于复杂的操作。例如`Geolocation API`提供了一些简单的JavaScript结构来获取位置数据,这种API通常抽象很多复杂逻辑,我们只要调用API即可。 + +* **第三方API**: +缺省情况下不会内置于浏览器,而必须在Wen中某个地方获取代码和信息,例如`Twitter API`可以推送最新推文给我们,它提供一系列第三方API让我们获取Twitter的服务和信息。 + +## 1.1 API如何工作 +**那么,这些API是如何工作的?** +不同的JavaScript的API工作内容不同,但具有以下几个相同点: +1. **都是基于对象** +API通过使用一个或多个JavaScript对象与我们的代码交互,这些对象作为API使用的数据(包含在对象属性中)的容器,和API提供的功能(包含在对象的方法中)。 +如`Geolocation API`则是由以下几个对象组成: +* `Geolocation`, 包含三种控制地理数据检索的方法。 +* `Position`, 表示在给定的时间的相关设备的位置。它包含一个当前位置的`Coordinates` 对象。还包含了一个时间戳,这个时间戳表示获取到位置的时间。 +* `Coordinates`,包含有关设备位置的大量有用数据,包括经纬度,高度,运动速度和运动方向等。 + +通常这么使用: +```js +navigator.geolocation.getCurrentPosition(function(options){ + // ... do something +}); +``` + +2. **都有可识别的入口点** +即API的入口位置,如`Geolocation API`的入口在`Navigator.geolocation` 属性, 它返回浏览器的 `Geolocation` 对象,所有有用的地理定位方法都可用。 +在**文档对象模型(DOM)**的API入口位置更简单,常常都挂载在`Document`对象上,或者`HTML`元素上: +```js +let a = document.createElement('div');// 创建一个新的div元素 +let b = document.querySelector('div');// 获取一个已经存在的div元素 +a.textContent = "hi leo!"; // 给a元素设置文本 +b.appendChild(a); // 将a元素添加到b元素下 +//
    hi leo!
    +``` +详细的后面介绍。 + +3. **都使用事件来处理状态的变化** +有些特定的API会包含一些事件,当事件触发,我们便可以运行函数的处理属性,做一些不同的操作。例如`XMLHttpRequest`对象的实例,有很多的事件可以调用。 +```js +// 简单写 +const url = "https://www.baidu.com"; +const req = new XMLHttpRequest(); +req.open('GET', url); +req.responseType = "json"; +req.send(); +req.onload = function(){ + // ... do something +} +``` + +4. **都会在适当位置提供额外的安全机制** +主要还是处于安全考虑,提供额外的安全机制,比如常见同源策略,一些特定页面只能在https协议的网页工作等。 + +接下来看看这些API都能实现什么作用。 + +# 2.文档API +我们在开发web页面和应用时,就会经常操作页面文档的结构,这里就会大量用到`document`对象,控制HTML和样式信息的**文档对象模型(DOM)**。 +下面贴一张web页面视图中的浏览器的主要部分(来源MDN): +![浏览器](https://mdn.mozillademos.org/files/14557/document-window-navigator.png) + +**介绍**: +* `window`:是载入浏览器的标签,JavaScript中用`Window`对象表示,可以实现很多操作:获取窗口大小,操作载入窗口的文档,存储文档数据等。 +* `navigator`:浏览器存在web上的状态和表示(即用户代理),JavaScript中用`Navigator`对象表示,用于获取对象的一些信息,如:摄像头的地理信息,用户偏爱的语言等。 +* `document`:是实际载入窗口的页面,JavaScript中用`Document`对象表示,可以实现很多文档操作:获取DOM元素,修改文本内容,设置新样式等。 + +## 2.1 文档对象模型(DOM) +在浏览器标签中当前载入的文档用文档对象模型(Document Object Model,简称DOM)表示。 +这是一个由浏览器生成的“树结构”,使得编程语言可以很容易访问HTML结构,操作等。 + +下面是基本的DOM操作: +```js +let a = document.createElement('a');// 1. 创建一个新的a元素 +let b = document.querySelector('a');// 2. 获取一个已经存在的a元素 +a.textContent = "进入pingan8787博客"; // 3. 给a元素设置文本 +a.href = "http://www.pingan8787.com"; // 4. 给a元素添加跳转地址 +a.style.color = "red"; // 5. 给a元素添加样式 +a.style.backgroundColor = "black"; +a.setAttribute("my_class"); // 6. 给a元素添加class类名 +b.appendChild(a); // 7. 将a元素添加到b元素下 +``` + +这么一个简单的例子,实际可以看出DOM提供的方法很多,下面分类介绍下这些方法: +1. **DOM HTML操作** +* **改变HTML输出流**: +通过`document.write()`直接修改HTML输出流写内容。 +```js +document.write("hello leo"); +``` +**注意:**千万不要在文档加载之后使用,否则覆盖文档。 + +* **改变HTML内容**: +通过`innerHTML`属性来改变HTML元素的内容: +```js +document.getElementById(id).innerHTML = new HTML; +// 通过ID获取 (getElementById) +// 通过name属性(getElementsByName) +// 通过标签名 (getElementsByTagName) +// 通过类名 (getElementsByClassName) +// 获取html的方法 (document.documentElement) +// 获取body的方法 (document.body) +// 通过选择器获取一个元素(querySelector) +// 通过选择器获取一组元素(querySelectorAll) +``` +例子: +```js +document.getElementById("id1").innerHTML = "hello leo!" +``` + +* **改变HTML属性**: +通过`attribute`属性来改变元素的属性: +```js +document.getElementById(id).attribute = new value +``` +例子: +```html + +``` +```js +document.getElementById("id1").src = "leo.png"; +``` +详细的文档可以查看[HTML DOM Document 对象](http://www.w3school.com.cn/jsref/dom_obj_document.asp) + +2. **DOM CSS操作** +* **改变HTML样式** +通过`style.styleName`属性修改元素的样式: +```js +document.getElementById(id).style.property = new style; +``` +例子: +```js +document.getElementById("id1").style.color = "red"; +document.getElementById("id1").style.backgroundColor = "green"; +``` +注意:`style`后面的样式的属性名只能使用**命名小驼峰**。 + +3. **DOM 事件操作** +如要对元素做点击事件的绑定,可以在HTML的`onclick`事件属性上绑定方法: +```html +
    +
    +``` +另外可以绑定的事件类型还有很多: +```js +
    +
    +
    +
    +``` +详细的文档可以查看[HTML DOM Event 对象](http://www.w3school.com.cn/jsref/dom_obj_event.asp) + +4. **DOM 节点操作** +* **创建新的HTML元素** +需要先创建一个新元素节点,然后在使用`appendChild`方法,向一个已存在的元素上追加这个新元素: +```html +
    +``` +```js +// 创建新元素节点 +let a = document.createElement('p'); +let b = document.createTextNode('新的文本'); +a.appendChild(b); + +// 获取已存在元素 +let div = document.getElementById('id1'); + +// 追加新元素 +div.appendChild(a); +``` + +* **删除已有的HTML元素** +如果需要删除HTML元素,就必须先获得该元素的父元素,再使用`removeChild`方法删除: +```html +
    +

    hello leo

    +
    +``` +```js +let a = document.getElementById("id1"); +let b = document.getElementById("id2"); +a.removeChild(b); +``` + +## 2.2 Window对象 +Window 对象表示浏览器中打开的窗口。 +Window 对象涉及到的属性和方法非常多,具体可以查看 [Window 对象](http://www.w3school.com.cn/jsref/dom_obj_window.asp) 比较详细。 +这里一个简单的例子,实现获取视窗(显示文档的内部窗口)的宽高,并设置给指定的Div元素,并且当我们调整窗口时候,也会及时改变Div的宽高。 +```js +let div = document.querySelector('div'); +// 获取宽高 +let w = window.innerWidth; +let h = window.innerHeight; +// 设置宽高 +div.style.width = w + 'px'; +div.style.heitgh = h + 'px'; +// 设置及时调整div宽高 +window.onresize = function(){ + w = window.innerWidth; + h = window.innerHeight; + div.style.width = w + 'px'; + div.style.heitgh = h + 'px'; +} +``` + +# 3.获取服务器数据API +这一部分主要复习`Ajax`(全称:Asynchronous JavaScript and XML)。 +`Ajax`主要要解决的问题是:避免重复加载刷新整个页面,因为有时候我们只是小部分数据更新,这时候我们这要刷新这部分的数据,而不是整个页面。 +`Ajax`不是新的编程语言,而是一种使用现有标准的新方法。 + +下面看一下**Ajax**模型图: +![Ajax模型](https://mdn.mozillademos.org/files/6477/moderne-web-site-architechture@2x.png) + +Ajax模型包括使用Web API作为代理来更智能地请求数据,而不仅仅是让浏览器重新加载整个页面。让我们来思考这个意义: +比如:我们逛淘宝,搜索或打开商品页面时,顶部导航来和页眉页脚等,都保持不变。 +这样做的好处: +* 页面更新更快,减少等待刷新,体验更好,响应更快。 +* 下载的数据更少,减少带宽的浪费。 + +另外为了提高加载速度,网站有时候也会将首次请求和数据存储在用户计算机中,下次再请求就直接先使用本地版本,如果内容有更新才会去服务器获取新数据,原理图: +![存储和获取新数据](https://mdn.mozillademos.org/files/6479/web-app-architecture@2x.png) + + +## 3.1 Ajax基础使用 +`XMLHttpRequest` 是 `AJAX` 的基础。 +所有现代浏览器均支持 `XMLHttpRequest` 对象(IE5 和 IE6 使用 `ActiveXObject`)。 + +创建 `XMLHttpRequest` 对象的语法: +```js +variable=new XMLHttpRequest(); +// IE5 和 IE使用 ActiveX 对象: +variable=new ActiveXObject("Microsoft.XMLHTTP"); +``` +为了兼容所有浏览器(包括IE5 IE6),我们就必须检查浏览器是否支持`XMLHttpRequest`对象,若支持则创建`XMLHttpRequest`对象,否则创建`ActiveXObject`对象。 + +```js +let my_http; +if (window.XMLHttpRequest){ + // 非 ES5 ES6 + my_http=new XMLHttpRequest(); + if (xmlhttp.readyState==4 && xmlhttp.status==200){ + // 网络请求成功后,执行的操作 + } + } +}else{ + // ES5 ES6 + my_http=new ActiveXObject("Microsoft.XMLHTTP"); +} +``` + +## 3.2 Ajax发送请求 +向服务器发送请求时,我们可以使用 `XMLHttpRequest` 对象的 `open()` 和 `send()` 方法: +```js +my_http.open(method,url,async); +my_http.send(string); +``` +参数解释: +`open(method,url,async)`方法接收三个参数: +* `method`:请求的类型;`GET` 或 `POST`。 +* `url`:文件在服务器上的位置。 +* `async`:`true`(异步)或 `false`(同步)。 + +`send(string)`方法接收一个参数: +* `string`:仅用于 `POST` 请求。 + +例子: +```js +// GET +my_http.open("GET","http://www.baidu.com",true); +my_http.send(); + +// POST +my_http.open("POST","http://www.baidu.com",true); +my_http.setRequestHeader( + "Content-type", + "application/x-www-form-urlencoded" +); // 添加 HTTP 头 +my_http.send("name=leo"); +``` +如果POST请求的话需要设置HTTP头: +```js +setRequestHeader(header,value) +``` +参数解释: +`setRequestHeader(header,value)`方法接收两个参数: +* `header`: 规定头的名称。 +* `value`: 规定头的值。 + +## 3.3 Ajax服务器响应 +接收服务器响应,我们可以使用 `XMLHttpRequest` 对象的 `responseText` 或 `responseXML` 属性。 +* `responseText`:获得`字符串形式`的响应数据。 +* `responseXML`:获得 `XML` 形式的响应数据。 + +* **responseText属性** +当服务端的响应不是XML,使用`responseText`属性。 +若是字符串的响应就可以直接使用。 +```js +document.getElementById("id1").inndeHTML = my_http.responseText; +``` + +## 3.4 Ajax readyState +`readyState`保存着`XMLHttpRequest`对象的状态。 +我们发送Ajax请求的整个过程中,`XMLHttpRequest`对象的`readyState`会改变,当`readyState`改变的时候会触发`onreadystatechange`事件。 + +`XMLHttpRequest`对象的三个重要属性: +|属性|描述| +|---|---| +|onreadystatechange|存储函数(或函数名),每当 `readyState` 属性改变时,就会调用该函数。| +|readyState|存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。0(请求未初始化),1(服务器连接已建立),2(请求已接收),3(请求处理中),4(请求已完成,且响应已就绪)| +|status|200("OK"),404(未找到页面)| + +通常我们会在`readyState`等于4且`status`等于200时候表示响应已就绪,可以执行业务操作: +```js +if (xmlhttp.readyState==4 && xmlhttp.status==200){ + // 网络请求成功后,执行的操作 +} +``` + +# 4.图形绘制API +这里主要介绍的是HTML5新增的`canvas`元素,JavaScript为`canvas`添加了很多API,进一步增强`canvas`。 +`canvas` 元素可以通过JavaScript脚本,在网页上绘制图形。 +比如,它可以被用来绘制图形,制作图片集合,甚至用来实现动画效果。你可以(也应该)在元素标签内写入可提供替代的的代码内容,这些内容将会在在旧的、不支持`canvas`元素的浏览器或是禁用了JavaScript的浏览器内渲染并展现。 + +详细完整的课程推荐: +1. [MDN Canvas教程](https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial) +2. [W3C HTML5 Canvas](http://www.w3school.com.cn/html5/html_5_canvas.asp) + +下面复习一下`canvas`的一个使用流程: + +## 4.1 简单绘制 + +1. **创建画布,规定元素id、宽度和高度** + +要在网页中创建 2D 或者 3D 场景,必须在 HTML 文件中插入一个`canvas`元素,以界定网页中的绘图区域。 +```html + + 卧槽你的浏览器竟然不支持 canvas! + +``` +在`canvas`标签内,写一些浏览器不支持画布功能时候的提示内容。 +画布默认尺寸为 300 × 150 像素。 + + +2. **获取画布上下文,并完成设置** + +我们需要获得一个对绘画区域的特殊的引用(称为“**上下文**”)用来在画布上绘图。可通过 `HTMLCanvasElement.getContext()` 方法获得基础的绘画功能,需要提供一个字符串参数来表示所需上下文的类型。 +下面创建一个2d画布: +```js +let ctx = canvas.getContext("2d"); +``` +`ctx` 变量包含一个 `CanvasRenderingContext2D 对象`,画布上所有绘画操作都会涉及到这个对象。 +下面将画布背景涂黑: +```js +ctx.fillStyle = 'rgb(0, 0, 0)'; +ctx.fillRect(0, 0, 200, 100); +``` + +## 4.2 绘制基础 +首先需要知道一些2D画布的知识,画布左上角的坐标是(0, 0),横坐标(x)轴向右延伸,纵坐标(y)轴向下延伸。 +![2D画布](https://mdn.mozillademos.org/files/224/Canvas_default_grid.png) + +1. 绘制实线 +```js +ctx.lineTo(100,50); // 绘制目标坐标 +ctx.lineWidth = 5; // 线条宽度 +ctx.stroke(); // 绘制实线 +``` + +2. 绘制矩形 +`fillRect(x, y, width, height)` 绘制一个填充的矩形 +`strokeRect(x, y, width, height)` 绘制一个矩形的边框 +`clearRect(x, y, width, height)` 清除指定矩形区域,让清除部分完全透明。 +x与y指定了在canvas画布上所绘制的矩形的左上角(相对于原点)的坐标。 +width和height设置矩形的尺寸。 +```js +// 实心矩形 +ctx.fillStyle = 'rgb(255, 0, 0)'; // 矩形颜色 +ctx.fillRect(50, 50, 100, 150); // 矩形起止坐标 + +// 空心矩形 +ctx.strokeStyle = 'rgb(255, 255, 255)';// 矩形边框颜色 +ctx.strokeRect(25, 25, 175, 200);// 矩形起止坐标 +``` + +3. 绘制路径 +可以通过路径来实现复杂的图形,下面整理了一些常用到的方法: +* `beginPath()`:在画笔当前所在位置开始绘制一条路径。在新的画布中,画笔起始位置为 (0, 0)。 +* `moveTo()`:将画笔移动至另一个坐标点,不记录、不留痕迹,只将画笔“跳”至新位置。 +* `fill()`:通过为当前所绘制路径的区域填充颜色来绘制一个新的填充形状。 +* `stroke()`:通过为当前绘制路径的区域描边,来绘制一个只有边框的形状。 +* 路径也可和矩形一样使用 `lineWidth` 和 `fillStyle` / `strokeStyle` 等功能。 + +```js +ctx.fillStyle = 'rgb(255, 0, 0)'; // 设置填充颜色 +ctx.beginPath(); // 开始 +ctx.moveTo(50, 50); // 移动到结束点的坐标 +// .. 可以在到处移动 +ctx.fill(); // 绘制 +``` + +4. 绘制圆形 +`arc(x, y, radius, startAngle, endAngle, anticlockwise)` +画一个以(x,y)为圆心的以radius为半径的圆弧(圆),从startAngle开始到endAngle结束,按照anticlockwise给定的方向(默认为顺时针)来生成。 +`arcTo(x1, y1, x2, y2, radius)` +根据给定的控制点和半径画一段圆弧,再以直线连接两个控制点。 + +`arc`方法,该方法有六个参数: +* `x,y`为绘制圆弧所在圆上的圆心坐标。 +* `radius`为半径。 +* `startAngle`以及`endAngle`参数用弧度定义了开始以及结束的弧度。 +* `anticlockwise`是布尔值,为true时,是逆时针方向,否则顺时针方向。 +这些都是以x轴为基准。 + +**注意**:arc()函数中表示角的单位是弧度,不是角度。角度与弧度的js表达式: +弧度=(Math.PI/180)*角度。 +```js +cxt.fillStyle="#FF0000"; +cxt.beginPath(); +cxt.arc(70,18,15,0,Math.PI*2,true); +cxt.closePath(); +cxt.fill(); +``` + +5. 绘制文本 +`fillText(text, x, y [, maxWidth])` +在指定的(x,y)位置填充指定的文本,绘制的最大宽度是可选的. +`strokeText(text, x, y [, maxWidth])` +在指定的(x,y)位置绘制文本边框,绘制的最大宽度是可选的. + +```js +ctx.strokeStyle = 'white'; +ctx.lineWidth = 1; +ctx.font = '36px arial'; +ctx.strokeText('hello leo !', 50, 50); + +ctx.fillStyle = 'red'; +ctx.font = '48px georgia'; +ctx.fillText('hello leo !', 50, 150); +``` +另外还有一些有样式的文本,可以使用这些属性: +* `font = value` +当前绘制的文本字体.默认是 10px sans-serif。 +* `textAlign = value` +文本对齐选项. 可选的值包括:`start`, `end`, `left`, `right` or `center`. 默认值是 start。 +* `textBaseline = value` +基线对齐选项. 可选的值包括:`top`, `hanging`, `middle`, `alphabetic`, `ideographic`, `bottom`。默认值是 `alphabetic`。 +* `direction = value` +文本方向。可能的值包括:`ltr`, `rtl`, `inherit`。默认值是 `inherit`。 +```js +ctx.font = "48px serif"; +ctx.textBaseline = "hanging"; +ctx.strokeText("Hello leo ", 0, 100); +``` + +6. 绘制图片 +* `drawImage(image, x, y)` +其中 `image` 是 `image` 或者 `canvas` 对象,`x` 和 `y` 是其在目标 `canvas` 里的起始坐标。 +```js +let img = new Image(); +img.src = "leo.png"; +img.onload = function(){ + ctx.drawImage(img, 50, 50); +}; +``` +`drawImage`方法还有更多参数: +```js +ctx.drawImage(image, 20, 20, 185, 175, 50, 50, 185, 175); +``` +* 第一个参数不变,为图片引用。 +* 参数 2、3 表示裁切部分左上顶点的坐标,参考原点为原图片本身左上角的坐标。原图片在该坐标左、上的部分均不会绘制出来。 +* 参数 4、5 表示裁切部分的长、宽。 +* 参数 6、7 表示裁切部分左上顶点在画布中的位置坐标,参考原点为画布左上顶点。 +* 参数 8、9 表示裁切部分在画布中绘制的长、宽。本例中绘制时与裁切时面积相同,你也可以定制绘制的尺寸。 + + +详细完整的课程推荐: +1. [MDN Canvas教程](https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial) +2. [W3C HTML5 Canvas](http://www.w3school.com.cn/html5/html_5_canvas.asp) + + +# 5.视频音频API +HTML5提供了用于文档中嵌入富媒体的元素`