时间花在哪里,你就会成为什么样的人

2008-2018 十年,往事如昨 2018年已经是昨天,今天是2019的第一天。 2008年已经是10年前,10年前的傍晚,我走在南京仙林的一个大街上,提着一瓶矿泉水,擦着额头的汗水,仰头看着大屏幕上播放着北京奥运会的开幕式。 10年前的夏天,我带着一步诺基亚手机功能机,独自一人去了南京。 坐过绣球公园的石凳,穿过天妃宫的回廊,吹过阅江楼的凉爽的江风,踏着古老斑驳的城墙,在林荫小路的长椅上,我想着10年后我会在哪里?做着什么事情? 往事如昨,而今将近而立,但是依然觉得自己还是10年的那个独自出去玩的小男孩。 2018 读了10年都没有读完的书,五味杂陈 2018年,在我做手术前,我觉得自己出了工作的时间外,大多数时间都在看书。2018年这一年看的书,要比2008到2018年这十年间的看的书都要多。这都归功于我对每天的看书都有定量的计划,一旦按照这个计划实行几个月,积累的效果还是非常明显的。 2018年,手机几乎成为人的四肢之外的第五肢。对大多人来说,上厕所可以不带纸,但是不能不带手机。 各种APP, 都在极力的吸引用户多花点时间在自己身上 信息流充斥着各种毫无营养,专门吸人眼球的垃圾新闻,但是这种新闻的阅读量还是蛮大的 各种借钱,信用卡,花呗等都像青楼的小姐,妩媚的笑容,说道:官人,进来做一做 共享单车,在今年退潮之后,才发现自己都在裸泳 比特币,挖矿机。不知道谁割了谁的韭菜,总希望有下一个傻子来接盘,最后发现自己可能就是最后一个傻子 AI,人工智能很火,放佛就快要进入终结者那样的世界 锤子垮了,曾经吹过的牛逼,曾经理想主义终于脱去那又黑又亮的面具 图灵测试(The Turing test)由艾伦·麦席森·图灵发明,指测试者与被测试者(一个人和一台机器)隔开的情况下,通过一些装置(如键盘)向被测试者随意提问。 进行多次测试后,如果有超过30%的测试者不能确定出被测试者是人还是机器,那么这台机器就通过了测试,并被认为具有人类智能。图灵测试一词来源于计算机科学和密码学的先驱阿兰·麦席森·图灵写于1950年的一篇论文《计算机器与智能》,其中30%是图灵对2000年时的机器思考能力的一个预测,目前我们已远远落后于这个预测。 最后说一下图灵测试,在AI方面,这个测试无人不知。一个机器如果通过了图灵测试,则说明该机器具有了只能。但是三体的作者大刘曾经说过一句话,给我一种醍醐灌顶的感觉,假如一个机器人有能力通过图灵测试,却假装无法通过,你说这个机器是否具有人工智能。所以大刘的这种说法才更加让人恐惧。机器人能通过图灵测试,只说明这个机器人具有了智能。但是现阶段的智能只不过是条件反射,或者是基于概率计算的结果。后者这种能通话测试,却假装无法通过的智能。这不仅仅是智能,而是机器的城府。 有智能的机器并不可怕,有城府的机器人才是真正的可怕。 如果梦中更加幸福快乐,为什么要回到现实 火影的最后,大筒木辉夜使用无限月读将世界上的所有人都带入梦境,每个人的查克拉都被吸取,并作为神树的养料。 如果真的存在大筒木这样的上帝,那么时间就是查克拉。人类唯一真正拥有过的东西,时间,将作为神树的养料,从每个人身上提取。 各种具有吸引力的术,其实可以理解为无限月读,让人沉醉于梦幻中。 如果梦中更加幸福快乐,为什么要回到现实中承受压力与悲哀呢? 目前我无法回复自己的这个问题,期待2019年我可以得到这个答案。 工作方面 2019年,我会在做一些后端方面的工作,努力加油吧。

2019-01-01 21:02:08 · 1 min · Eddie Wang

深入理解 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' 其他原始类型的值也是不可变的, 例如数值类型的。 2.3. 原始类型值是字面量 3. 变量和值有什么区别? 不是每一个值都有地址,但每一个变量有。《Go程序设计语言》 变量没有类型,值有。变量可以用来保存任何类型的值。《You-Dont-Know-JS》 变量都是有内存地址的,变量有用来保存各种类型的值;不同类型的值,占用的空间不同。 var a = 1 typeof a // 检测的不是变量a的类型,而是a的值1的类型 4. 变量访问有哪些方式? 变量访问的方式有两种: ...

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.js:497:12) at Function.Module._load (module.js:489:3) at Module.require (module.js:579:17) at require (internal/module.js:11:18) at Object.<anonymous> (/Users/dd/wj-gitlab/tools/test/a.js:1:78) at Module._compile (module.js:635:30) sayA is not a function那么sayA是个什么呢,实际上它是 undefined ...

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.js.org/shields-less/example/ ...

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号线 莲花地铁站 转公交拍的】 【每天早上起的很早,能够看到军训的学生在操场上奔跑】 【在古玩店一般都要拍到很晚,因为是按张数算拍照工资,拍的越多,工资越高。还好晚上回公司 打车费用是可以报销的】 ...

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.log(a, b, this, this === myEmitter) }) myEmitter.emit('event', 'a', {name:'wdd'}) 输出: ...

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