深入理解 JavaScript中的变量、值、函数传参

1. demo 如果你对下面的代码没有任何疑问就能自信的回答出输出的内容,那么本篇文章就不值得你浪费时间了。 var var1 = 1 var var2 = true var var3 = [1,2,3] var var4 = var3 function test (var1, var3) { var1 = 'changed' var3[0] = 'changed' var3 = 'changed' } test(var1, var3) console.log(var1, var2, var3, var4) 2. 深入理解原始类型 原始类型有5个 Undefinded, Null, Boolean, Number, String 2.1. 原始类型变量没有属性和方法 // 抬杠, 下面的length属性,toString方法怎么有属性和方法呢? var a = 'oooo' a.length a.toString 原始类型中,有三个特殊的引用类型Boolean, Number, String,在操作原始类型时,原始类型变量会转换成对应的基本包装类型变量去操作。参考JavaScript高级程序设计 5.6 基本包装类型。 2.2. 原始类型值不可变 原始类型的变量的值是不可变的,只能给变量赋予新的值。 下面给出例子 // str1 开始的值是aaa var str1 = 'aaa' // 首先创建一个能容纳6个字符串的新字符串 // 然后再这个字符串中填充 aaa和bbb // 最后销毁字符串 aaa和bbb // 而不能理解成在str1的值aaa后追加bbb str1 = str1 + 'bbb' 其他原始类型的值也是不可变的, 例如数值类型的。...

2018-12-17 15:24:15 · 2 min · Eddie Wang

WTF!! Vue数组splice方法无法正常工作

当函数执行到this.agents.splice()时,我设置了断点。发现传参index是0,但是页面上的列表项对应的第一行数据没有被删除, WTF!!! 这是什么鬼!然后我打开Vue Devtools, 然后刷新了一下,发现那个数组的第一项还是存在的。什么鬼?? removeOneAgentByIndex: function (index) { this.agents.splice(index, 1) } 然后我就谷歌了一下,发现这个splice not working properly my object list VueJs, 大概意思是v-for的时候最好给列表项绑定:key=。然后我是试了这个方法,发现没啥作用。 最终我决定,单步调试,如果我发现该问题出在Vue自身,那我就该抛弃Vue, 学习React了 单步调试中出现一个异常的情况,removeOneAgentByIndex是被A函数调用的,A函数由websocket事件驱动。正常情况下应该触发一次的事件,服务端却发送了两次到客户端。由于事件重复,第一次执行A删除时,实际上removeOneAgentByIndex是执行成功了,但是重复的第二个事件到来时,A函数又往agents数组中添加了一项。导致看起来,removeOneAgentByIndex函数执行起来似乎没有设么作用。而且这两个重复的事件是在几乎是在同一时间发送到客户端,所以我几乎花了将近一个小时去解决这个bug。引起这个bug的原因是事件重复,所以我在前端代码中加入事件去重功能,最终解决这个问题。 我记得之前看过一篇文章,一个开发者调通过回调函数计费,回调函数是由事件触发,但是没想到有时候事件会重发,导致重复计费。后来这名开发者在自己的代码中加入事件去重的功能,最终解决了这个问题。 事后总结:我觉得我不该怀疑Vue这种库出现了问题,但是我又不禁去怀疑。 通过这个bug, 我也学到了第二方法,可以删除Vue数组中的某一项,参考下面代码。 // Only in 2.2.0+: Also works with Array + index. removeOneAgentByIndex: function (index) { this.$delete(this.agents, index) } 另外Vue devtools有时候并不会实时的观测到组件属性的变化,即使点了Refresh按钮。如果点了Refresh按钮还不行,那建议你重新打开谷歌浏览器的devtools面板。

2018-12-12 20:29:16 · 1 min · Eddie Wang

Node.js 如何找出循环依赖的文件?如何解决循环依赖问题?

本文重点是讲解如何解决循环依赖这个问题。关心这个问题是如何产生的,可以自行谷歌。 如何重现这个问题 // a.js const {sayB} = require('./b.js') sayB() function sayA () { console.log('say A') } module.exports = { sayA } // b.js const {sayA} = require('./a.js') sayA() function sayB () { console.log('say B') } module.exports = { sayB } 执行下面的代码 ➜ test git:(master) ✗ node a.js /Users/dd/wj-gitlab/tools/test/b.js:3 sayA() ^ TypeError: sayA is not a function at Object.<anonymous> (/Users/dd/wj-gitlab/tools/test/b.js:3:1) at Module._compile (module.js:635:30) at Object.Module._extensions..js (module.js:646:10) at Module.load (module.js:554:32) at tryModuleLoad (module....

2018-10-29 09:21:03 · 2 min · Eddie Wang

shields小徽章是如何生成的?以及搭建自己的shield服务器

shields小徽章介绍 一般开源项目都会有一些小徽章来标识项目的状态信息,并且这些信息是会自动更新的。在shields的官网https://shields.io/#/, 上面有各种各样的小图标,并且有很多自定义的方案。 起因:如何给私有部署的jenkins制作shields服务? 私有部署的jenkins是用来打包docker镜像的,而我想获取最新的项目打包的jenkins镜像信息。但是私有的jenkins项目信息,公网的shields服务是无法获取其信息的。那么如果搭建一个私有的shields服务呢? 第一步:如何根据一些信息,制作svg图标 查看shields图标的源码,可以看到这些图标都是svg格式的图标。然后的思路就是,将文字信息转成svg图标。最后我发现这个思路是个死胡同, 有个npm包叫做,text-to-svg, 似乎可以将文本转成svg, 但是看了文本转svg的效果,果断就放弃了。 最后回到起点,看了shields官方仓库,发现一个templates目录,豁然开朗。原来svg图标是由svg的模板生成的,每次生成图标只需要将信息添加到模板中,然后就可以渲染出svg字符串了。 顺着这个思路,发现一个包shields-lightweight var shields = require('shields-lightweight'); var svgBadge = shields.svg('subject', 'status', 'red', 'flat'); 这个包的确可以生成和shields一样的小徽章,但是如果徽章中有中文,那么中文就会溢出。因为一个中文字符的宽度要比一个英文字符宽很多。 所以我就fork了这个项目,重写了图标宽度计算的方式。shields-less npm install shields-less var shieldsLess = require('shields-less') var svgBadge = shieldsLess.svg({ leftText: 'npm 黄河远上白云间', rightText: 'hello 世界' }) var svgBadge2 = shieldsLess.svg({ leftText: 'npm 黄河远上白云间', rightText: 'hello 世界', style: 'square' }) var svgBadge2 = shieldsLess.svg({ leftText: 'npm 黄河远上白云间', rightText: 'hello 世界', leftColor: '#e64a19', rightColor: '#448aff', style: 'square' // just two style: square and plat(default) }) 渲染后的效果,查看在线demo: https://wdd....

2018-10-29 09:14:43 · 1 min · Eddie Wang

Express代理中间件问题与解决方案

前后端分离应用的架构 在前后端分离架构中,为了避免跨域以及暴露内部服务地址。一般来说,我会在Express这层中加入一个反向代理。 所有向后端服务访问的请求,都通过代理转发到内部的各个服务。 这个反向代理服务器,做起来很简单。用http-proxy-middleware这个模块,几行代码就可以搞定。 // app.js Object.keys(proxyTable).forEach(function (context) { app.use(proxyMiddleware(context, proxyTable[context])) }) http-proxy-middleware实际上是对于node-http-proxy的更加简便的封装。node-http-proxy是http-proxy-middleware的底层包,如果node-http-proxy有问题,那么这个问题就会影响到http-proxy-middleware这个包。 最近的bug http-proxy-middleware最近有个问题,请求体在被代理转发前,如果请求体被解析了。那么后端服务将会收不到请求结束的消息,从浏览器的网络面板可以看出,一个请求一直在pending状态。 Cannot proxy after parsing body #299, 实际上这个问题在node-http-proxy也被提出过,而且处于open状态。POST fails/hangs examples to restream also not working #1279 目前这个bug还是处于open状态,但是还是有解决方案的。就是将请求体解析的中间件挂载在代理之后。 下面的代码,express.json()会对json格式的请求体进行解析。方案1在代理前就进行body解析,所有格式是json的请求体都会被解析。 但是有些走代理的请求,如果我们并不关心请求体的内容是什么,实际上我们可以不解析那些走代理的请求。所以,可以先挂载代理中间件,然后挂载请求体解析中间件,最后挂载内部的一些接口服务。 // 方案1 bad app.use(express.json()) Object.keys(proxyTable).forEach(function (context) { app.use(proxyMiddleware(context, proxyTable[context])) }) app.use('/api', (req, res, next)=> { }) // 方案2 good Object.keys(proxyTable).forEach(function (context) { app.use(proxyMiddleware(context, proxyTable[context])) }) app.use(express.json()) app.use('/api', (req, res, next)=> { }) 总结 经过这个问题,我对Express中间件的挂载顺序有了更加深刻的认识。 同时,在使用第三方包的过程中,如果该包bug,那么也需要自行找出合适的解决方案。而这个能力,往往就是高手与新手的区别。

2018-09-30 09:41:44 · 1 min · Eddie Wang

IE11跨域检查跨域设置

IE11有安全设置中有两个选项, 跨域浏览窗口和框架 通过域访问数据源 如果上面两个选项被禁用,那么IE11会拒绝跨域请求。如果想要跨域成功,必须将上面两个选项设置为启用。 第一步 打开IE11 点击浏览器右上角的齿轮图标 点击弹框上的 Internet选项 第二步 点击安全 点击Internet 点击自定义级别 第三步 找到跨域浏览窗口和框架 如果这项是禁用的,那么要勾选启用。 找到通过域访问数据源 如果这项是禁用的,那么要勾选启用。 最后在点击确定。 最后,如果跨域浏览窗口和框架,通过域访问数据源都启用了,还是无法跨域。那么最好重启一下电脑。有些设置可能在重启后才会生效。

2018-08-23 10:20:10 · 1 min · Eddie Wang

毕业后,青春像一艘船,沉入海底

大三那年的暑假 大三那年暑假,很多同学都回去了,寝室大楼空空如也。 留在上海的同学都在各自找着兼职的工作,为了不显得无聊,我也在网上随便发了一些简历,试试看运气。 写简历最难写的部分就是写你自己的长处是什么?搜索枯肠,觉得自己似乎也没什特长。感觉大学三年学到一些东西,又感觉什么都没学到。 如果没有特长,总该也有点理想吧,比如想干点什么? 似乎我也没什么想做的事情。 小时候我们都有理想,慢慢长大后,理想越来越模糊,变得越来越迷茫。 大学里,大部分的人都是在打游戏。我也曾迷恋过打游戏,但是因为自己比较菜,总是被虐,所以放弃了。 但是我也不是那种天天对着笔记本看电视剧的人。 回忆初三那年的暑假 记得,初三的暑假,我参加了一个学校看展的一个免费的计算机培训班。因为培训的老师说,培训结束前会有一个测试,成绩最好的会有几百块的奖励。 为了几百块的奖励,我第一个背诵完五笔拆字法。随后老师教了我们PS, 就是photoshop。当时我的理解就是,ps可以做出很多搞笑的图片。 为了成为一个有能力做出搞笑图片的人。我在高中和大学期间,断断续续的系统的自学了PS。 下面给展示几张我的PS照片 【毕业照】 【帮别人做的艺术照】 【刺客信条 换脸 我自己】 【旅游照 换脸 我自己】 【宿舍楼 上面ps了一条狼】 古玩艺术电商中的店小二 基本上,我的PS技术还是能够找点兼职做的。没过多久,我收到了面试邀请,面试的公司位于一个古玩收藏品市场中。 当然我面试成功了,开出的日薪也是非常诱人,每天35元。 在上海,35元一天的工资,除去来回上下班做地铁和公交,还有中午饭的费用外,基本上不会剩下什么,有时候稍微午饭丰盛点,自己就要倒贴。但是这也是一次不错的尝试,至少有史以来,除去父母以外,我用能力问别人要钱了。 35元的日薪持续很短一段时间,然后我就涨薪了,到达每天100元。在这个做兼职的地方,我最高拿到的日薪是200元。 兼职期间我做了各式各样的工作: 古玩艺术品摄影 海报制作 拍卖图册制作 linux运维 APP UI 设计 网页设计 python爬虫 兼职的日志过得很苦,单是还算充实。虽然工资不高,但是因为还没毕业,也没有奢望过高的工资。 【上图 我在一个古玩店的拍摄玉器的时候,有个小女孩过来找我玩,我随手拍的】 【上图 是在1号线 莲花路地铁站 因为错过了地铁拍的】 【上图 是从1号线 莲花地铁站 转公交拍的】 【每天早上起的很早,能够看到军训的学生在操场上奔跑】 【在古玩店一般都要拍到很晚,因为是按张数算拍照工资,拍的越多,工资越高。还好晚上回公司 打车费用是可以报销的】 【晚上还要回到学校,一般到学校就快晚上10点左右了】 【毕业了,新校区依然很漂亮】 【毕业了,老校区下了一场雨】 【毕业了,青春像一艘船,沉入海底】 【毕业了,我等的人,你在哪里?】

2018-08-14 18:36:40 · 1 min · Eddie Wang

NodeJS Events 模块笔记

1. 环境 node 8.11.3 2. 基本使用 // 01.js const EventEmitter = require('events'); class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter(); myEmitter.on('event', () => { console.log('an event occurred!'); }); myEmitter.emit('event'); 输出: an event occurred! 3. 传参与this指向 emit()方法可以传不限制数量的参数。 除了箭头函数外,在回调函数内部,this会被绑定到EventEmitter类的实例上 // 02.js const EventEmitter = require('events') class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter() myEmitter.on('event', function (a, b){ console.log(a, b, this, this === myEmitter) }) myEmitter.on('event', (a, b) => { console....

2018-08-10 10:18:57 · 2 min · Eddie Wang

JavaScript动态下载文件

需求描述 可以把字符串下载成txt文件 可以把对象序列化后下载json文件 下载由ajax请求返回的Excel, Word, pdf 等等其他文件 基本思想 downloadJsonIVR () { var data = {name: 'age'} data = JSON.stringify(data) data = new Blob([data]) var a = document.createElement('a') var url = window.URL.createObjectURL(data) a.href = url a.download = 'what-you-want.json' a.click() }, 从字符串下载文件 从ajax请求中下载文件

2018-06-27 09:09:01 · 1 min · Eddie Wang

Restful API 架构思考

1. 什么是REST? 2. REST API最为重要的约束 3. REST API HTTP方法 与 CURD 4. 状态码 5. RESTful架构设计 6. 文档 7. 版本 8. 深入理解状态与无状态 9. 参考 1. 什么是REST? 表现层状态转换(REST,英文:Representational State Transfer)是Roy Thomas Fielding博士于2000年在他的博士论文[1] 中提出来的一种万维网软件架构风格,目的是便于不同软件/程序在网络(例如互联网)中互相传递信息。表现层状态转换(REST,英文:Representational State Transfer)是根基于超文本传输协议(HTTP)之上而确定的一组约束和属性,是一种设计提供万维网络服务的软件构建风格。匹配或兼容于这种架构风格(简称为 REST 或 RESTful)的网络服务,允许客户端发出以统一资源标识符访问和操作网络资源的请求,而与预先定义好的无状态操作集一致化。wikipdeia REST API 不是一个标准或者一个是协议,仅仅是一种风格,一种style。 RESTful API的简单定义可以轻松解释这个概念。 REST是一种架构风格,RESTful是它的解释。也就是说,如果您的后端服务器具有REST API,并且您(从网站/应用程序)向客户端请求此API,则您的客户端为RESTful。 2. REST API最为重要的约束 Client-Server 通信只能由客户端单方面发起,表现为请求-响应的形式 Stateless 通信的会话状态(Session State)应该全部由客户端负责维护 Cache 响应内容可以在通信链的某处被缓存,以改善网络效率 Uniform Interface 通信链的组件之间通过统一的接口相互通信,以提高交互的可见性 Layered System 通过限制组件的行为(即每个组件只能“看到”与其交互的紧邻层),将架构分解为若干等级的层。 Code-On-Demand 支持通过下载并执行一些代码(例如Java Applet、Flash或JavaScript),对客户端的功能进行扩展。 3. REST API HTTP方法 与 CURD REST API 使用POST,GET, PUT, DELETE的HTTP方法来描述对资源的增、查、改、删。 这四个HTTP方法在数据层对应着SQL的插入、查询、更新、删除操作。...

2018-06-07 22:35:08 · 1 min · Eddie Wang