极光之净产品的生产地北极光在哪里可以看到?

日极光之旅(Tromso地区详细攻略)
日极光之旅(Tromso地区详细攻略)
&&&&&虽然对极光一直心怀向往,但是还从来没想过会在留英期间前往。这次行程主要起源于小狐狸一句今年是太阳黑子活动极大年的话,然后到旅游官网去看说了今年的极光会是50年来最盛大的,加之又查到极光的最佳观测时间是2-3月,就屁颠屁颠去搜攻略申请签证去了。日,在本世纪第二二的日子,两个很二的人,就踏上了追寻极光的旅程。&这次去7天,两个人平均每人花费730GBP(其实本来是400GBP的,但是有一次没有赶上飞机所以临时买了张机票花了200多镑)。初次去没有经验,事后发现很多地方都可以省钱。也算是花钱长教训,这次都列出来,希望能帮助点还要去同学。因为南部攻略已经很多,这次直说北部Tromso这个城市的。
一、前往方式
(1)火车:因为国境是一条狭长的线,从Oslo到Tromso有1643公里,相当于到的距离。铁路最北只延伸到Narvik,Narvik每天有三班公交去Tromso,公交票价450NOK,而且没有学生票,所以坐火车是很费钱的。只建议从入境的同学采用火车的方式进入,因为国铁(SJ,英文版官网https://www.sj.se/start/startpage/index.form?l=sv&&)去Narvik经常有特价票,有些时候提前买从Stockholm到Tromso只要37美元,但是必须提前两个月左右,提前两周以内买是几乎不可能有下950SEK的车票了。如果是要一起玩或者深度游的孩纸,可以考虑游完峡湾之后坐火车去Narvik,国铁(NSB,订票官网http://www.nsb.no/&&),但是其实提早订学生票最便宜也不过299NOK,加上Narvik去Tromso的公交,也不会很便宜,不适宜抱着“省钱为上:宗旨的孩纸们。而且中北部的工业城市很多,拿Bodo举例,主要出口铁矿,城市还是50年代重建的,没什么观赏价值,所以游完峡湾从南至北的路程其实是很无趣的。我建议坐灰机过去。
(2)灰机:国航(Norwegian,订票官网/&&)提前两个月定,甚至有从Oslo到Tromso35GBP的价格!直到提前一周以内,都可能有79GBP的特价票。提前两三天几乎都是94GBP,从中部Bodo飞过去往往是60GBP,综合下来一般都比火车票便宜。机票还有一个建议是乘坐斯堪的纳维亚航空(官网/en/?vst=true&&)这个平时的价格不如国航实惠,但是临时票比国航便宜很多,因为青年票(under25&discount)往往半价,我们从Tromso回Oslo就是前一天下午两点临时买的,那时候票价是1500NOK多,我们买下来直接790NOK,但是搜的时候一定要去到主页选择youth&discount,在别的廉行或者有链接SAS的网站都搜不到这个折扣,这个还是我们住的青旅的前台帅GG提醒我们的。
(3)游轮:最大的游轮公司是海达路(订票官网/&&),这个游轮的线路可以算是最详细的了。北至大陆最北端的,南至最南部的,甚至(这条路貌似不是这个公司开辟的,但是确实有)。很多两天的航线在学生证打完折以后只要360NOK。而且是豪华游轮。行程不满一天的可以买甲板票,就是上面的白菜价,但是可以睡船舱里面的沙发或者自备睡袋。也可以选择船舱,一般两人仓的学生票不是半价,但是相对于配套服务来说,性价比还是蛮高的。下面几张是朋友拍摄的船内设施图,住宿部分是海达路官网盗来的所以比较小。
二、到达之后的流程
(1)去市区:Tromso虽说是北部第一市,但是真正面积其实很小,景点一天都可以走完。Tromso形状像一个脚掌,全市只有一个机场,离市中心5km,坐Airport&Bus去市中心要68NOK,40或42路去只要28NOK.Tromso的公交票是两小时内有效,所以如果要出去玩,可以好好利用一下这点。打的去市中心要450NOK。但40和42路车相较Airport&Bus的车站来说有点小距离,出机场记得找地勤问路。值得一提的是Tromso的公交有时候很不靠谱,去机场的公交一般20分钟一般,但是我和朋友回去的时候居然一小时才来一趟,差点再次误了飞机。之前从住的酒店去跟极光团也因为类似的原因差点没赶上。但是我们下飞机的时候赶公交还是挺准时的。
(2)找住宿:&Tromso住宿非常贵,一般主流网站能搜到的最便宜的是Sydspissen&Hotel,Sydspissen在语里意思是最南端,在的位置也是Tromso的最南端,离市中心10几分钟的公交。最便宜的多人间床位平均一天也要37GBP,而且每天去往景点或者跟团看极光还要坐公交,很不方便,个人不建议住,但是那边的住宿条件算是到以后住过的最好的了。Tromso主要的酒店都集中在市中心游客中心附近,也是主要游轮在Tromso的停靠点。但是多是些四星酒店,住宿一般都要1000NOK以上。这里推荐一个性价比特别高的,在游客中心坐20或者24路公交,过桥以后第一站下车,沿着左边第一个入口往里走大概10分钟。这里的Camping都是些小木屋,适合多人出行还有游的旅客,我们碰到的驴友一行6个人住一间,里面有厨房有客厅有卧室,每个人住三天花费是440多。官网我一下忘了,这是他们的fbook主页/#!/tromsocamping&&下图是他们房间的内部设施
(六人间的客厅)
(六人间的书房)
(六人间的厨房)
相比之下,我和朋友住的四人间惨淡好多…小木屋必须一间一间住,所以我们两个人付了四个人的住宿费,一天一人320NOK
这个是给游的乘客准备的mobile&house,外观很像大巴,很有爱,有驴友自带滑雪设备
这个是Camping的公共餐厅
三、极光之旅
(1)报团:非游的游客报团是必须的,Tromso很多极光团,根据提供服务的不同价格也不同,有狗拉雪橇看极光,豪华游轮看极光,不一而足。大部分价格在1500NOK以上,有些提供学生票。相关信息可以参考这个网站http://www.fjordtravel.no/program_arctic.html&&个人推荐Rica&Hotel每天发出的极光团,大多数极光团需要提前预定,票价高,豪华游轮相对来说便宜(学生半价)但是持续时间短(大概就两个小时)而且出发早,需要极好的人品才能看到满意的极光。Rica&Hotel的在价格上是最便宜的,学生价700NOK,6点发团到凌晨1点。会提供食物和饮料(其实就是一块饼干和一杯热巧)。根据当天报名人数派车,所以一般及时去了都能报到,不用担心预约不到满员的情况。
(2)跟团:这一段是我和朋友跟团经历的总结。
发团后大巴会一路往北开,到远离城市光源的郊外。每趟车配有一名司机两名导游,中途会停靠几个极光观测点,根据当时的极光出现强度和游客要求决定停靠时间。一名导游负责介绍概况,Tromso历史,极光基本知识。另一名导游是摄影向导,专门教授带单反的游客如何把相机调到最适宜拍极光的模式。当天给我们带团的导游一个是人一个是人,说英语都有很浓重的口音,听懂的没几句=&=导游的介绍很抒情,说到极光的时候居然像吟诗似的:请诸君试想一条广阔的河流,从天际一直垂至下游,上游的某个醉汉,打破了绿色的墨水瓶,混合着大自然的油彩,绘出了最美的画卷。更像一条五彩的丝带,缠绕着游人,不舍离去。司机也很热情的说,Tromso是大自然赋予的最富饶的净土,大家都移民到来吧。前排的老夫妇马上接话说,太贵了…司机就很自豪地说,可是我们觉得一点都不贵呀。好像每当提到的生活水平的时候,人就很自豪。之前遇到的一个小正太在提到的时候就很爱说,我们可是世界上最富的国家了~
大巴开了一个半小时到了一个海边,导游千叮咛万嘱咐说一定要踩着他的脚印走,某些积雪太厚,下面又是尖锐的石头,踩下去很有可能腿就拐了,或者摔下去,在这一点城市光源都没有的地方,找到都要费点时间,别说就医了…结果我们等了一个小时,极光都很细微,只有微弱的几条光束,导游说那是“baby&light&”。于是大巴有转战别的地区,大概开了一个小时到了一座山上。临近午夜的时候,终于看到了level5的中等强度的极光。
这是领队去给大家拿热巧叫我看着相机的时候我偷拍的
同行的队友拍摄的
更多的在我的相册,有兴趣的可以移步至/photo//album-&&写在后面:其实我们2月22日肉眼看到的极光没有什么壮观可言,就是一团有别于夜空颜色的光束,手机、卡片都照不出效果,但是用单反拍出来就格外漂亮,让我一度以为极光都是摄影师们弄来骗人的。一边觉得不甘心一边又期望只是自己没遇到level高的,所以23号在Tromso的最后一天一直在想会不会随意一抬头就看到了。然后23号一整天我几乎都在魂不守时地看天,结果居然真的被我撞见了。先是天边一小片绿色的云团,接着阵势越来越大,到目之所及的天空被深蓝色的极光围了个大圈。肉眼看到的比昨天单反效果拍出来的还要好,手机都能拍出明显的效果,这还是在没什么路灯的时候拍的
看到的时候真有种人生圆满了的感觉。但是因为当时在赶路朋友也没有用她的单反照下来,心想这么盛大的极光肯定很多游客会照,结果这成了最大的遗憾。我们在camping安顿好的时候出来拍,极光已经散的差不多了,之后一直到午夜都没有什么太大范围的出现,camping本身已经够远离城市光源的了,到晚上门口各种单反脚架就架了起来,结果一问没一个注意到傍晚的时候出现的极光的。一来觉得那时候出现的几率小没打算去看,二来要去报团到远郊去看没打算在市区看。事后证明我们当天看到的是从那以后最绚烂的一次,可惜那些千里迢迢去的,找最佳观测点带最好的拍摄利器去的游客,反而没几个看到的。多讽刺。我突然想到了电影《蝴蝶》,那一老一少翻山越岭去找Isabella,结果Isabella一直在老头的家里躺着。很多时候我们跑老远去追寻一样东西,它就在我们身边的时候却浑然不知。也许对于他们,那种追寻的过程也是最开心的。我很庆幸我能在太阳黑子活动极大年,最近50年极光最盛大的时期,在极光最佳观测月份,和最佳观测时段(新月),在大陆的最北端,见证了今年2月至今最美的极光。最后,希望这篇不伦不类的攻略能多少帮助下即将要去追寻极光的同道中人
本篇游记共含4115个文字,16张图片。帮助了名游客。
特别的爱给特别的你~
京公网安备号
新出网证(京)字242号 全国统一客服电话:极光环保科技有限公司
五年专注室内空气治理--除甲醛服务公司金华 义乌 东阳 永康专业除甲醛医疗级服务公司
布艺窗帘类、墙纸类材料一般污染释放有15天至1年基本可以弱化到较低的浓度标准,但是板材中的游离态甲醛挥发需要3年甚至15年。0.06㎎/m?的甲醛浓度(低于强制性标准25%依然可引发儿童哮喘),被装修污染问题导致就医人群每年超过700万。
---专注室内除甲醛的服务商 哪怕一个再小的单子都按最正规对待---
总结出行之有效的除甲醛技术,无效退款。誓以实实在在的效果消除业主对除甲醛行业的误解,为除甲醛行业正名以尽微薄之力!
极光环保除甲醛PK传统除甲醛机构
--如何识破那些伪善的面具--_____________________________________________________________________________________________________________________________________________________________________________________________极光环保科技有限公司集科研、开发、生产、销售、服务于一体的高科技除甲醛公司,专注室内空气污染治理、甲醛检测、甲醛治理、新房除甲醛、新车保洁除异味、除甲醛、家庭饮用水净化等装修污染治理服务。公司自成立以来,以一流的品质、规范的服务得到消费者的广泛认可。
1、公司经多年实践与探索总结出行之有效的除甲醛技术,无效退款。与国内知名高校产学研技术研发团队合作,产品 生产治理技术已经处领先水平。2、食品安全级,无二次污染。3、产品经国家质量监督中心检测,权威放心。
1、由国家行业认证专业施工人员进行施工,确保全方位无死角治理到位。2、施工设备采用德国进口SATA喷枪,超静音无油空气压缩机,雾化更细,喷涂更均匀。3、如确认工程质量未达到要求,重新施工,直至达标。
1、施工后该产品强效清除新车内引起的甲醛、苯、TVOC等有机物对车内空气的污染,长效抗菌防霉。2、依据国家标准GB ,施工完毕,室内质保五年。3、依据国家标准GB/T ,施工完毕后,车内质保两年。
1、质保期内每年一次免费空气质量检测,长期跟踪空气质量,提供终身服务。2、老客户再次装修或增添新家具,将优先安排治理并享优惠价。
汽车治理案例
金华幼儿园案例
中联财产保险治理案例
海朵幼儿园治理案例
金华第五幼儿园治理案例
汽车治理案例
壶山幼儿园治理案例
汽车治理案例
金华幼儿园治理案例
子牛茶道治理案例
汽车治理案例
金华建设银行治理案例极光日报极光日报每天为 Makers 导读三篇优质英文文章关注专栏更多最新文章{&debug&:false,&apiRoot&:&&,&paySDK&:&https:\u002F\\u002Fapi\u002Fjs&,&wechatConfigAPI&:&\u002Fapi\u002Fwechat\u002Fjssdkconfig&,&name&:&production&,&instance&:&column&,&tokens&:{&X-XSRF-TOKEN&:null,&X-UDID&:null,&Authorization&:&oauth c3cef7c66aa9e6a1e3160e20&}}{&database&:{&Post&:{&&:{&title&:&REPO 风格之争:MONO VS MULTI&,&author&:&hev1n&,&content&:&\u003Cblockquote\u003E简评:两种管理代码库的方式甚至是两种哲学的碰撞。\u003C\u002Fblockquote\u003E\u003Cp\u003E首先,我们解释一下什么是 monorepo 和 multirepo。这两者都是管理组织代码的方式,顾名思义 monorepo 就是把所有的相关项目都放在一个仓库中(比如 React, Angular, Babel, Google...),multirepo 则是按模块分为多个仓库。\u003C\u002Fp\u003E\u003Cp\u003E这两者的核心区别可以归结为你相信怎样的哲学能让团队在一起工作的效率最高(多元化 vs 集中管理)。\u003C\u002Fp\u003E\u003Cp\u003E从 \u003Cb\u003Emultirepo\u003C\u002Fb\u003E 的角度来看,这样让每个子团队拥有自己的 repo,可以用他们自己擅长的工具、workflow 等等。多元化能促使各个团队尽可能的提升自己的效率。\u003C\u002Fp\u003E\u003Cp\u003E但代价也在于会增加很多沟通成本,如果你在你们项目用到的库中发现了一个 bug,就必须到目标库里修复它、打包、发版本,然后再回到你的库继续工作。在不同的仓库间,你不仅需要处理不同的代码、工具,甚至是不同的工作流程。甚至你只能去问维护这个仓库的人,能不能为你做出改变,然后等着他们去解决。\u003C\u002Fp\u003E\u003Cp\u003E而从 \u003Cb\u003Emonorepo\u003C\u002Fb\u003E 来看,让不同的团队走自己的路,并不见得能提高生产力。虽然有些团队可能会找到自己最佳的工作方式,但他们的收益也会被其他团队不那么好的工作方式所抵消。相反,严格统一的管理更能提升效率,团队中的任何人都可以(并且应该也被鼓励)修改任何东西(因为修改造成的结果马上就能展现出来,)。虽然把所有的鸡蛋都放进了一个篮子里,但我们也可以更小心的照顾这个篮子。\u003C\u002Fp\u003E\u003Cp\u003E如果你们团队选择 monorepo,那主要的挑战自然是随着项目的发展,其会变得非常庞大(因为没有根据模块或功能拆分成不同 repo)。因此会需要很多的工具来应对这样的挑战。\u003C\u002Fp\u003E\u003Cul\u003E\u003Cli\u003E你会需要强大的构建工具,比如 Google 的 \u003Ca href=\&https:\u002F\u002Fbazel.build\u002F\&\u003EBazel\u003C\u002Fa\u003E, Facebook 的 \u003Ca href=\&https:\\u002F\&\u003EBuck\u003C\u002Fa\u003E 和 Twitter 的 \u003Ca href=\&http:\u002F\u002Fwww.pantsbuild.org\u002F\&\u003EPants\u003C\u002Fa\u003E。\u003C\u002Fli\u003E\u003Cli\u003E仓库变得太大,对你们的版本控制技术会有很大的挑战。因为 Git 社区建议的是使用更多更小的代码库,Git 本身并不适合单个巨大的代码库。\u003C\u002Fli\u003E\u003Cli\u003E因为所有的代码都放在一起,你需要时刻保持警惕,以保持良好的项目结构和提交测试。\u003C\u002Fli\u003E\u003Cli\u003E在这么大的 workspace 中工作或使用了非标准化的构建工具,你常用的 IDE 可能会遇到麻烦。Facebook 就选择了构建自己的 IDE。\u003C\u002Fli\u003E\u003C\u002Ful\u003E\u003Cp\u003E那有没有什么两全其美的办法呢?可能并没有。你可以像 Android 使用 \u003Ca href=\&https:\u002F\\u002Fp\u002Fgit-repo\u002F\&\u003Erepo\u003C\u002Fa\u003E 一样,在多个仓库间进行工作,但整体的行为看起来却像是 monorepo。但这样又不清楚你到底想从 multirepo 中获得什么好处?\u003C\u002Fp\u003E\u003Cp\u003E或者在 monorepo 中用分支来管理其中的不同项目,每个项目都存在于一个单独的长期分支中,只在需要时才合并来自其他项目的修改。但这样你就又没办法完全避免菱形依赖等问题。\u003C\u002Fp\u003E\u003Cp\u003E因此建议还是根据团队的情况选定一种方式,然后尽可能的扬长避短。\u003C\u002Fp\u003E\u003Cblockquote\u003E原文:\u003Ca href=\&http:\u002F\\u002Fmono-vs-multi\u002F\&\u003EREPO STYLE WARS: MONO VS MULTI\u003C\u002Fa\u003E\u003C\u002Fblockquote\u003E\u003Cp\u003E扩展阅读:\u003C\u002Fp\u003E\u003Cul\u003E\u003Cli\u003EDan Luu \u003Ca href=\&https:\\u002Fmonorepo\u002F\&\u003Eexplains\u003C\u002Fa\u003E what’s up with monorepos.\u003C\u002Fli\u003E\u003Cli\u003EThe relation between \u003Ca href=\&https:\\u002Fmonorepos\u002F\&\u003Etrunk based developement\u003C\u002Fa\u003E and monorepos.\u003C\u002Fli\u003E\u003Cli\u003E\u003Ca href=\&https:\\u002Fmonorepos\u002F\&\u003EExpanding and contracting\u003C\u002Fa\u003E monorepos.\u003C\u002Fli\u003E\u003Cli\u003E\u003Ca href=\&https:\u002F\\u002Fposts\u002F400\u002Fscaling-mercurial-at-facebook\u002F\&\u003EScaling Mercurial\u003C\u002Fa\u003E at Facebook.\u003C\u002Fli\u003E\u003C\u002Ful\u003E&,&updated&:new Date(&T03:15:40.000Z&),&canComment&:false,&commentPermission&:&anyone&,&commentCount&:0,&likeCount&:6,&state&:&published&,&isLiked&:false,&slug&:&&,&isTitleImageFullScreen&:false,&rating&:&none&,&sourceUrl&:&&,&publishedTime&:&T11:15:40+08:00&,&links&:{&comments&:&\u002Fapi\u002Fposts\u002F2Fcomments&},&url&:&\u002Fp\u002F&,&titleImage&:&https:\u002F\\u002Fv2-f48f36ed6d0b079c8c9ba3e3171004bb_r.png&,&summary&:&&,&href&:&\u002Fapi\u002Fposts\u002F&,&meta&:{&previous&:null,&next&:null},&snapshotUrl&:&&,&commentsCount&:0,&likesCount&:6},&&:{&title&:&如何可视化「排序算法」&,&author&:&Aceyclee&,&content&:&\u003Cblockquote\u003E\u003Cb\u003E简评:\u003C\u002Fb\u003E国外有个开发者洗澡时总会产生一些奇奇妙妙的想法,比如他将排序算法进行可视化,并用声音来辅助体现 ~\u003C\u002Fblockquote\u003E\u003Cp\u003E这是排序算法可视化后录制的视频,确实听起来很整齐!\u003C\u002Fp\u003E\u003Cp\u003E【\u003Ca href=\&https:\u002F\u002Fcaspervonb.github.io\u002Ftoneofsorting\u002F\&\u003ETone of Sorting \u003C\u002Fa\u003E— Quick Sort with 100 Elements】\u003C\u002Fp\u003E\u003Cvideo id=\&None\& data-swfurl=\&\& poster=\&https:\u002F\\u002F80\u002Fv2-d1c58440eefa3ac66e3c105f7e9777c4_b.jpg\& data-sourceurl=\&https:\u002F\\u002Fvideo\u002F913728\& data-name=\&\& data-video-id=\&\& data-video-playable=\&true\& data-lens-id=\&913728\&\u003E\u003C\u002Fvideo\u003E\u003Cp\u003E我们不能把排序算法写成同步代码,浏览器容易杀死这个进程。\u003C\u002Fp\u003E\u003Ch2\u003E\u003Cb\u003E异步算法\u003C\u002Fb\u003E\u003C\u002Fh2\u003E\u003Cp\u003E所以想到的解决方案是让它们异步。例如,冒泡排序可以像下面的代码片段那样实现:\u003C\u002Fp\u003E\u003Ccode lang=\&js\&\u003Efunction test(array, i, j) {\n
return array[i] - array[j];\n}\nfunction swap(array, i, j) {\n
var a = array[i];\n
var b = array[j];\narray[i] =\n
array[j] =\n}\nfunction bubbleSort(callback, array) {\n
setTimeout(function step(i, j, length) {\n
if (test(array, j, j + 1) & 0) {\n
swap(array, j, j + 1);\n
}\nif (j & length) {\n
window.setTimeout(step, 0, ++i, 0, n);\n
} else if (i & length) {\n
window.setTimeout(step, 0, i, ++j, n);
} else {\n
callback(array);\n
}, 0, 0, 0, array.length);\n}\u003C\u002Fcode\u003E\u003Cp\u003E这个方法有一个问题,它直接将迭代与主循环联系起来,因此每个区间执行多个步骤会变得更加繁琐。\u003C\u002Fp\u003E\u003Ch2\u003E\u003Cb\u003E同步算法\u003C\u002Fb\u003E\u003C\u002Fh2\u003E\u003Cp\u003E比较好的解决方案是使算法同步。但由于主线程不能被杀死,我们可以通过将排序算法移动到工作线程并将消息发送回主线程来解决此问题。\u003C\u002Fp\u003E\u003Ccode lang=\&js\&\u003Efunction test(array, i, j) {\n
self.postMessage(['test', i, j]);\nreturn array[i] - array[j];\n}\nfunction swap(array, i, j) {\n
self.postMessage(['swap', i, j]);\nvar temp = array[i];\n
array[i] = array[j];\n
array[j] =\n}\nfunction bubbleSort(array) {\n
var length = array.\n
for (var i = 0; i & i++) {\n
var sorted =\n
for (var j = 0; j & (length - i) - 1; j++) {\n
if (test(a, j + 1, j) & 0) {\n
sorted =\n
swap(a, j, j + 1);\n
}\nif (sorted) {\\n
}\n}\nself.onmessage = function(event) {\n
var fn = eval(event.data[0]);\n
fn(event.data[1], event.data[2]);\n};\u003C\u002Fcode\u003E\u003Cp\u003E然后通过使主线程将消息排队,可以以任何顺序或速率轻松地读取它们。在请求动画帧回调中播放音调,动画文档变得直截了当。\u003C\u002Fp\u003E\u003Ccode lang=\&js\&\u003Evar queue = [];\nvar worker = new Worker('quicksort.js');\nworker.postMessage(['quickSort', \u002F* ... *\u002F]);\nworker.onmessage = function(event) {\n
queue.push(event.data);\n};\nvar then =\nrequestAnimationFrame(function tick(now) {\n
var delta = now -\n
if (delta & 1000) {\n
return window.requestAnimationFrame(tick, now);\n
\u002F\u002F ...\n
requestAnimationFrame(tick, now);\n}, window);\u003C\u002Fcode\u003E\u003Cp\u003E这是\u003Ca href=\&https:\u002F\u002Fcaspervonb.github.io\u002Ftoneofsorting\u002F\&\u003E排序的\u003C\u002Fa\u003E目前的计算方式,但仍然有问题,会冻结选项卡。\u003C\u002Fp\u003E\u003Cp\u003E此外,还有一种叫做「Bogo Sort」的有点特别的算法,也叫做 Stupid Sort 或者 Monkey Sort,可以试试。\u003C\u002Fp\u003E\u003Ch2\u003E\u003Cb\u003E协同算法\u003C\u002Fb\u003E\u003C\u002Fh2\u003E\u003Cp\u003E算法可以根据需要进行部分评估。JavaScript 支持生成器的协同。\u003C\u002Fp\u003E\u003Cp\u003E例如,冒泡排序变成了一个如下所示的生成器:\u003C\u002Fp\u003E\u003Ccode lang=\&js\&\u003Efunction test(array, i, j) {\n
return array[i] - array[j];\n}\nfunction swap(array, i, j) {\n
var temp = array[i];\n
array[i] = array[j];\n
array[j] =\n}\nfunction* bubbleSort(array) {\n
var length = array.\n
for (var i = 0; i & i++) {\n
var sorted =\n
for (var j = 0; j & (length - i) - 1; j++) {\n
yield ['test', j + 1, j];\nif (test(a, j + 1, j) & 0) {\n
sorted =\n
swap(a, j, j + 1);\nyield ['swap', j, j + 1];\n
}\nif (sorted) {\\n
}\n}\u003C\u002Fcode\u003E\u003Cp\u003E从异步回调(如 requestAnimationFrame)中一次只调用几个步骤意味着它是异步的,因为它是按需生成的,所以像「Bogo Sort」这样的算法将起作用。\u003C\u002Fp\u003E\u003Ccode lang=\&js\&\u003Evar array = new Array(100);\nvar algorithm = bubbleSort(array);\nrequestAnimationFrame(function tick(now) {\n
\u002F\u002F ...\n
var step = algorithm.next();\n
\u002F\u002F ...\n}, window);\u003C\u002Fcode\u003E\u003Ch2\u003E\u003Cb\u003E试试看\u003C\u002Fb\u003E\u003C\u002Fh2\u003E\u003Cp\u003E你可以尝试\u003Ca href=\&https:\u002F\u002Fcaspervonb.github.io\u002Ftoneofsorting\u002F\&\u003E在这里排序音调\u003C\u002Fa\u003E,还有一个 \u003Ca href=\&https:\\u002Fcaspervonb\u002Ftoneofsorting\u002F\&\u003EGitHub Repository\u003C\u002Fa\u003E。如果你正在寻找关于该主题的书籍,可以查阅\u003Ca href=\&http:\u002F\u002Famzn.to\u002F2il5Njw\&\u003E「算法简介」\u003C\u002Fa\u003E。\u003C\u002Fp\u003E\u003Chr\u003E\u003Cblockquote\u003E\u003Cb\u003E原文链接:\u003C\u002Fb\u003E\u003Ca href=\&https:\u002F\u002Fmedium.freecodecamp.org\u002Fhow-i-visualized-the-sorting-algorithms-and-brought-them-to-life-with-sound-ce7c5c6cb6ef\&\u003EHow I Visualized Sorting Algorithms and Brought Them to Life with Sound\u003C\u002Fa\u003E\u003Cbr\u003E\u003Cb\u003E推荐阅读:\u003C\u002Fb\u003E\u003Ca href=\&https:\u002F\\u002Fp\u002F\&\u003EPython 的数学仙境之旅\u003C\u002Fa\u003E\u003C\u002Fblockquote\u003E\u003Cp\u003E极光日报,\u003Ca href=\&http:\u002F\\u002F?target=https%3A\u002F\\u002F%3Fsrc%3Djiguangdaily%26hmsr%3D%25E6%259E%%E6%%25E6%258A%25A5%26hmpl%3D%26hmcu%3D%26hmkw%3D%26hmci%3D\&\u003E极光开发者\u003C\u002Fa\u003E 的 Side Project,欢迎关注。\u003C\u002Fp\u003E&,&updated&:new Date(&T02:22:21.000Z&),&canComment&:false,&commentPermission&:&anyone&,&commentCount&:15,&likeCount&:121,&state&:&published&,&isLiked&:false,&slug&:&&,&isTitleImageFullScreen&:false,&rating&:&none&,&sourceUrl&:&&,&publishedTime&:&T10:22:21+08:00&,&links&:{&comments&:&\u002Fapi\u002Fposts\u002F2Fcomments&},&url&:&\u002Fp\u002F&,&titleImage&:&https:\u002F\\u002Fv2-8ba5d7ec1525_r.jpg&,&summary&:&&,&href&:&\u002Fapi\u002Fposts\u002F&,&meta&:{&previous&:null,&next&:null},&snapshotUrl&:&&,&commentsCount&:15,&likesCount&:121},&&:{&title&:&时代周刊评选出的 2017 十大游戏&,&author&:&McDoge&,&content&:&\u003Cblockquote\u003E简评:不知算不算客观中立,但第一名绝对是实至名归。\u003C\u002Fblockquote\u003E\u003Cp\u003E对 Video(之前手残写成了veadio) Game 来说,这是糟糕的一年。\u003C\u002Fp\u003E\u003Cp\u003E不过随着新的游戏机任天堂 Switch 和 Xbox One X 的到来,也迎来了一系列的新游戏,有我们期待已久的续作也有令人震惊的开放世界全新大冒险。\u003C\u002Fp\u003E\u003Cp\u003E以下是 TIME's 评选出的本年 TOP 10 游戏。\u003C\u002Fp\u003E\u003Chr\u003E\u003Ch2\u003E10.Destiny 2 命运 2(Xbox One、PS4、PC)\u003C\u002Fh2\u003E\u003Cimg data-rawheight=\&560\& src=\&v2-a4cd0ef0eea98a047fec6a.jpg\& data-size=\&normal\& data-rawwidth=\&996\&\u003E\u003Cp\u003E《命运 2》引发了一个小狂潮,不论是游戏论坛还是播客,更不用说 Reddit 上面的各种相关主题了。简而言之,开发商 Bungie 成功完成了 Destiny 2 中大部分构想。本作对于 PVP 也更加完善,展示了大型多人在线射击游戏的新概念。游戏要呈现的东西很多,比如各种游戏材料收集和各种高难挑战。\u003C\u002Fp\u003E\u003Cp\u003E但是,并不是所有人都能心平气和地接受 MMORPG 与 FPS 混搭所产生的奇妙化学反应。请想象这么一个场景:你和朋友拿着同一型号的枪走上战场,他能够游刃有余地大杀四方,你则需要对着敌人脑袋射完一整匣子弹才能勉强取得一次击杀。\u003Cb\u003E而造成这种现状的原因,竟然是朋友玩的时间比你久、等级比你高、装备数值比你好\u003C\u002Fb\u003E。不过《命运 2》努力把自己定义为「值得再次回归的游戏」,因为明年还有好多更新和 DLC 需要玩家来买单。\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cvideo id=\&None\& data-swfurl=\&\& poster=\&https:\u002F\\u002F80\u002Fv2-eee032d2aed0d1133dbc_b.jpg\& data-sourceurl=\&https:\u002F\\u002Fvideo\u002F684096\& data-name=\&\& data-video-id=\&\& data-video-playable=\&true\& data-lens-id=\&684096\&\u003E\u003C\u002Fvideo\u003E\u003Cbr\u003E\u003Cbr\u003E\u003Chr\u003E\u003Ch2\u003E9.Horizon Zero Dawn 地平线 零之曙光 (PS 4)\u003C\u002Fh2\u003E\u003Cimg data-rawheight=\&560\& src=\&v2-3d3ae7cbba11a019f84e34f.jpg\& data-size=\&normal\& data-rawwidth=\&996\&\u003E\u003Cp\u003E《地平线:黎明时分》是一款关于机械恐龙、原始人和末日启事的第三人称动作游戏,游戏的背景设置在遥远的未来,在那里人类文明已经结束,被损毁的星球正在重建,人类并不是最优种群,高度发达的智能机械兽稳坐食物链的顶端。玩家在游戏中扮演一个被部落抛弃的年轻人 Aloy,为了解开围绕她身边的一些神秘事件,踏上了冒险征程。\u003C\u002Fp\u003E\u003Cp\u003E别的暂且不论,有一件事情,Guerrilla 在《地平线:黎明时分》中怎么都算是做到了满分,即游戏的\u003Cb\u003E画面\u003C\u002Fb\u003E。他们确实很有可能给我们带来的是本世代主机上最美丽的开放世界,这是一种无处不在的精致感,从一片草叶到一缕飞花,几乎每张随手截来的图都经得住玩家的仔细观察。而这都是在本世代硬件的基本环境下实现的,本质上这依然是对有限硬件资源的拆东墙补西墙,可就是这个拆补的手艺,别家恐怕还真就比不上。\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cvideo id=\&None\& data-swfurl=\&\& poster=\&https:\u002F\\u002F80\u002Fv2-c56ead26de8bdd_b.jpg\& data-sourceurl=\&https:\u002F\\u002Fvideo\u002F228288\& data-name=\&\& data-video-id=\&\& data-video-playable=\&true\& data-lens-id=\&228288\&\u003E\u003C\u002Fvideo\u003E\u003Cbr\u003E\u003Cbr\u003E\u003Chr\u003E\u003Ch2\u003E8.Mario + Rabbids:Kingdom Battle 马里奥疯兔:王国之战(任天堂 Switch)\u003C\u002Fh2\u003E\u003Cimg data-rawheight=\&750\& src=\&v2-4dd919e21dd16e0ba562ea17d3b93eae.jpg\& data-size=\&normal\& data-rawwidth=\&1200\&\u003E\u003Cp\u003E在过去的 30 多年里,马里奥做过水管工、驯兽师、医生、赛车手、建筑师、篮球手等几十职业,可谓救得了公主、搞得了事业,还拿得了冠军,是游戏圈最为全能的一哥,且无一例外,马里奥的每一次登场也都会为该类型作品带来一些革命性的创新,为游戏界树立一个新的标杆,鉴于马里奥的履历太丰富,我都不敢确定这就是他的第一款 SLG(战棋)作品,但同育碧官方逗比疯兔的这次合作,确实又成功催生了一款新的经典《马里奥疯狂兔子:王国之战》。\u003C\u002Fp\u003E\u003Cp\u003E尽管《马兔》主要由育碧研发,但玩家惊讶的发现,游戏的灵魂实际上属于任天堂,大胆的创新,精巧的设计,哪怕在极为成熟的玩法机制上,也总能创造出意想不到的惊喜,这可能要得益于育碧那位看到宫本茂就已经泪流满面的制作人吧。总体游戏素质很高,\u003Cb\u003E休闲轻松\u003C\u002Fb\u003E,值得一试。\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cvideo id=\&None\& data-swfurl=\&\& poster=\&https:\u002F\\u002F80\u002Fv2-ccdfb395b74e604e8c5d38a_b.jpg\& data-sourceurl=\&https:\u002F\\u002Fvideo\u002F100672\& data-name=\&\& data-video-id=\&\& data-video-playable=\&true\& data-lens-id=\&100672\&\u003E\u003C\u002Fvideo\u003E\u003Cbr\u003E\u003Cbr\u003E\u003Chr\u003E\u003Ch2\u003E7.PlayerUnknown Battlegrounds 绝地求生:大逃杀(PC、Xbox One)\u003C\u002Fh2\u003E\u003Cimg data-rawheight=\&560\& src=\&v2-ecb1bb179d03d3f745c4.jpg\& data-size=\&normal\& data-rawwidth=\&996\&\u003E\u003Cp\u003E不要把这款游戏当做一个纯射击类游戏。虽然这款游戏还是个未完成品,但\u003Cb\u003E核心玩法\u003C\u002Fb\u003E非常有趣。通常每局 30 分钟左右,很容易入手。100 名玩家跳伞到荒岛上,捡装备拼杀,地图的活动范围随着时间缩减,最终面对面火拼。这款游戏有着很多意外性,很难,但是很有趣。\u003C\u002Fp\u003E\u003Cp\u003E游戏直播也是这款游戏大火的原因,很有娱乐看点。\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cvideo id=\&None\& data-swfurl=\&\& poster=\&https:\u002F\\u002F80\u002Fv2-fac57f24a006b098b711710_b.jpg\& data-sourceurl=\&https:\u002F\\u002Fvideo\u002F887104\& data-name=\&\& data-video-id=\&\& data-video-playable=\&true\& data-lens-id=\&887104\&\u003E\u003C\u002Fvideo\u003E\u003Cbr\u003E\u003Cbr\u003E\u003Chr\u003E\u003Ch2\u003E6.Cuphead 茶杯头(PC、Xbox One)\u003C\u002Fh2\u003E\u003Cimg data-rawheight=\&560\& src=\&v2-c7d02c71f1bf1dbd32b25.jpg\& data-size=\&normal\& data-rawwidth=\&996\&\u003E\u003Cp\u003E《茶杯头》以优秀的\u003Cb\u003E素质\u003C\u002Fb\u003E完美地诠释了「游戏为什么能被称之为第九艺术」这一命题。虽然业内关于重现上世纪经典的旅程一直都没有过停歇,但是却从没有一部作品,无论在动画、音乐还是其他地方,在复古方面做到《茶杯头》这般极致,就连迪士尼自己曾做过的《汽船威利》游戏也难望其项背。\u003C\u002Fp\u003E\u003Cp\u003E另外,制作游戏所耗费的人力和物力都是个巨大的数字,制作者兄弟俩为了游戏能够完成,甚至在资金匮乏的时候将自己家的房子卖了继续游戏的开发,倘若不是真心热爱自己的游戏,很少有人能够做到这份坚持。\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cvideo id=\&None\& data-swfurl=\&\& poster=\&https:\u002F\\u002F80\u002Fv2-e922d163dd7b5e9f17ad_b.jpg\& data-sourceurl=\&https:\u002F\\u002Fvideo\u002F035648\& data-name=\&\& data-video-id=\&\& data-video-playable=\&true\& data-lens-id=\&035648\&\u003E\u003C\u002Fvideo\u003E\u003Cbr\u003E\u003Cbr\u003E\u003Chr\u003E\u003Ch2\u003E5.Persona 5 女神异闻录 5(PS4)\u003C\u002Fh2\u003E\u003Cimg data-rawheight=\&560\& src=\&v2-3bbae5d5cc90e37c624c6ab12a99daa5.jpg\& data-size=\&normal\& data-rawwidth=\&996\&\u003E\u003Cp\u003E如果我年少时,白天上学,晚上与恶势力战斗,并且身处时尚浪潮之巅的东京,我可能永远都不想长大。这是《女神异闻录 5》的大背景。\u003C\u002Fp\u003E\u003Cp\u003E日式 RPG 在一些人眼里是带有原罪的,比如万年不变的回合制,比如长达上百小时才能通关的游戏时间,比如大量的日常对话和不那么写实与精良的画面等等。你可以因为这些「特点」而不去喜欢《P5》,但真的不能把它们强行算作缺陷。在 JRPG 领域来说,《P5》可能是近年来综合素质最让人满意的一部作品,无论是剧情还是系统都能做到\u003Cb\u003E令人痴迷\u003C\u002Fb\u003E的程度。\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cvideo id=\&None\& data-swfurl=\&\& poster=\&https:\u002F\\u002F80\u002Fv2-e97bd053c5dfb95_b.jpg\& data-sourceurl=\&https:\u002F\\u002Fvideo\u002F629120\& data-name=\&\& data-video-id=\&\& data-video-playable=\&true\& data-lens-id=\&629120\&\u003E\u003C\u002Fvideo\u003E\u003Cbr\u003E\u003Cbr\u003E\u003Chr\u003E\u003Ch2\u003E4.Wolffenstein II:The New Colossus 重返德军总部2:新巨像(PS4、Xbox One、PC、Switch)\u003C\u002Fh2\u003E\u003Cimg data-rawheight=\&560\& src=\&v2-527c17f0ec6e55ffdf980efd55ca249c.jpg\& data-size=\&normal\& data-rawwidth=\&996\&\u003E\u003Cp\u003E这是 2017 最具\u003Cb\u003E故事性,冲击力和挑衅性\u003C\u002Fb\u003E的游戏之一。一如既往的是一部充满文化细节、性、暴力、血腥、科幻元素的硬汉 FPS 游戏。射击手感非常不错,枪枪到肉的感觉和即时喷溅的血浆都非常的爽快,很难相信编剧的脑洞,游戏中期剧情开始紧张刺激起来,一波接一波的惊喜。\u003C\u002Fp\u003E\u003Cp\u003E杀戮并不是《德军总部2》的全部,本作在人性的痛苦和兴奋之间找到了平衡,在一个荒诞的世界中演绎了我们内心最黑暗的冲动与光明。游戏中的许多时刻都令人血脉扩张。\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cvideo id=\&None\& data-swfurl=\&\& poster=\&https:\u002F\\u002F80\u002Fv2-1a35ffd07d0a_b.jpg\& data-sourceurl=\&https:\u002F\\u002Fvideo\u002F621504\& data-name=\&\& data-video-id=\&\& data-video-playable=\&true\& data-lens-id=\&621504\&\u003E\u003C\u002Fvideo\u003E\u003Cbr\u003E\u003Cbr\u003E\u003Chr\u003E\u003Ch2\u003E3.What Remains of Edith Finch 艾迪芬奇的记忆(PS4、Xbox One、PC)\u003C\u002Fh2\u003E\u003Cimg data-rawheight=\&521\& src=\&v2-98ce180b6a3eb6823eef425df527c547.jpg\& data-size=\&normal\& data-rawwidth=\&835\&\u003E\u003Cp\u003E大麻雀团队 5 年的努力,为我们呈现了一个非常精彩,发人反思的魔幻现实主义游戏。本作中以奇异的房屋开始展开,主人公在搜寻的经历中讲述了这个家族的发展史,每一个家族成员都有自己独自的领地,相互分离却彼关联。游戏的故事性看似暗藏玄机,但其实一切都是围绕一个点展开的。就是一开始就提到的诅咒。而通过死亡,我们又能够看到\u003Cb\u003E爱\u003C\u002Fb\u003E在其中的重量。\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cvideo id=\&None\& data-swfurl=\&\& poster=\&https:\u002F\\u002F80\u002Fv2-baf62a59db522b600b5dc_b.jpg\& data-sourceurl=\&https:\u002F\\u002Fvideo\u002F313984\& data-name=\&\& data-video-id=\&\& data-video-playable=\&true\& data-lens-id=\&313984\&\u003E\u003C\u002Fvideo\u003E\u003Cbr\u003E\u003Cbr\u003E\u003Chr\u003E\u003Ch2\u003E2. Super Mario Odyssey 超级马里奥 奥德赛(任天堂 Switch)\u003C\u002Fh2\u003E\u003Cimg data-rawheight=\&560\& src=\&v2-dcd90eedc75e7c.jpg\& data-size=\&normal\& data-rawwidth=\&996\&\u003E\u003Cp\u003E《超级马里奥:奥德赛》是一款由任天堂开发的角色扮演游戏,本作为 NGC 《阳光马里奥》的续作,沙盒玩法,游戏会有很多现实世界中的场景。本作依旧是要解救被库巴抢走碧琪公主的故事,而且这回库巴还要和碧琪公主结婚。\u003C\u002Fp\u003E\u003Cp\u003E用有趣的关卡去奖励玩家的\u003Cb\u003E探索\u003C\u002Fb\u003E,这是非常有吸引力也非常困难的,而这却正是任天堂的强项,在较低的技术指标下,《奥德赛》实现了优秀的\u003Cb\u003E画面表现,\u003C\u002Fb\u003E是那种虽然看着不高科技,但感觉很高级、很舒服的画面,配上本作海量的 BGM,许多曲子还分为普通版和 8Bit 版,会根据游戏情况适时的响起,很好的烘托了游戏的气氛。\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cvideo id=\&None\& data-swfurl=\&\& poster=\&https:\u002F\\u002F80\u002Fv2-6c0dba020efba48ede56a4e_b.jpg\& data-sourceurl=\&https:\u002F\\u002Fvideo\u002F101184\& data-name=\&\& data-video-id=\&\& data-video-playable=\&true\& data-lens-id=\&101184\&\u003E\u003C\u002Fvideo\u003E\u003Cbr\u003E\u003Cbr\u003E\u003Chr\u003E\u003Ch2\u003E1. The Legend of Zelda: Breath of the Wild 塞尔达传说荒野之息(任天堂 Switch)\u003C\u002Fh2\u003E\u003Cimg data-rawheight=\&560\& src=\&v2-9d855ed8c61edd02ab697e13.jpg\& data-size=\&normal\& data-rawwidth=\&996\&\u003E\u003Cp\u003ESwitch 的首发护航之作,内容十分丰富,可以按个人选择\u003Cb\u003E自由\u003C\u002Fb\u003E探索整个世界,火焰系统,攀爬系统,烹饪系统等等可以说是非常严谨了。火焰系统十分贴近现实物理效果,可以烤肉,用树枝、木制品传递火源,着火的草地产生气流,箭传过火焰会变成火箭矢,去到火山身上的木制品会烧坏等等。会冷的打颤,会热的头晕等等温度系统。大大小小的神殿也充分利用了各种能力来解密。\u003Cb\u003E内容算是非常丰富\u003C\u002Fb\u003E。玩着玩着也会发现很多有趣的\u003Cb\u003E细节\u003C\u002Fb\u003E。画质比不上其他平台的3A 大作,但是 1080P 也足够清晰,\u003Cb\u003E画风清新自然\u003C\u002Fb\u003E。\u003Cb\u003E游戏性\u003C\u002Fb\u003E极强,很容易\u003Cb\u003E沉浸\u003C\u002Fb\u003E在荒野之中。\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cvideo id=\&None\& data-swfurl=\&\& poster=\&https:\u002F\\u002F80\u002Fv2-0a95b8e1f8f00da8fc16b9_b.jpg\& data-sourceurl=\&https:\u002F\\u002Fvideo\u002F004992\& data-name=\&\& data-video-id=\&\& data-video-playable=\&true\& data-lens-id=\&004992\&\u003E\u003C\u002Fvideo\u003E\u003Cbr\u003E\u003Cbr\u003E\u003Chr\u003E\u003Cp\u003E以上就是时代周刊评选出的 2017 十大游戏。\u003C\u002Fp\u003E\u003Cblockquote\u003E原文:\u003Ca href=\&http:\\u002F2Ftop-10-video-games-F\&\u003EThe Top 10 Video Games of C\u002Fa\u003E\u003C\u002Fblockquote\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cp\u003E问题来了,这上面游戏你玩过几个?\u003C\u002Fp\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E极光日报,\u003Ca href=\&http:\u002F\\u002F?target=http%3A\\u002F6AAFc\&\u003E极光开发者\u003C\u002Fa\u003E旗下媒体。\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E每天导读三篇英文技术文章。\u003C\u002Fb\u003E\u003C\u002Fp\u003E&,&updated&:new Date(&T09:12:51.000Z&),&canComment&:false,&commentPermission&:&anyone&,&commentCount&:433,&likeCount&:1798,&state&:&published&,&isLiked&:false,&slug&:&&,&isTitleImageFullScreen&:true,&rating&:&none&,&sourceUrl&:&&,&publishedTime&:&T17:12:51+08:00&,&links&:{&comments&:&\u002Fapi\u002Fposts\u002F2Fcomments&},&url&:&\u002Fp\u002F&,&titleImage&:&https:\u002F\\u002Fv2-18b4c41ccad_r.jpg&,&summary&:&&,&href&:&\u002Fapi\u002Fposts\u002F&,&meta&:{&previous&:null,&next&:null},&snapshotUrl&:&&,&commentsCount&:433,&likesCount&:1798},&&:{&title&:&现代编程语言中的十大有趣功能&,&author&:&Aceyclee&,&content&:&\u003Cblockquote\u003E\u003Cb\u003E简评:\u003C\u002Fb\u003E喜欢研究编程语言的人,推荐看看 Kasper Peulen 的这篇文章。他利用几种新语言,例如 \u003Cu\u003E\u003Ca href=\&http:\u002F\\u002FGNHfXdJ?m=web\&\u003EReason\u003C\u002Fa\u003E\u003C\u002Fu\u003E、\u003Cu\u003E\u003Ca href=\&http:\u002F\\u002FmTvjRiQ?m=web\&\u003EKotlin\u003C\u002Fa\u003E\u003C\u002Fu\u003E、\u003Cu\u003E\u003Ca href=\&http:\u002F\\u002FEkJuUEq?m=web\&\u003EDart\u003C\u002Fa\u003E\u003C\u002Fu\u003E、以及 Apple 的 \u003Cu\u003E\u003Ca href=\&http:\u002F\\u002FtEI0CpE?m=web\&\u003ESwift\u003C\u002Fa\u003E\u003C\u002Fu\u003E,来介绍几种有趣的程序写法,例如 pipeline、cascade、以及 currying 等。\u003C\u002Fblockquote\u003E\u003Cp\u003E虽然这些语言相对来讲比较新,但这些写法可能早在 Lisp (1958),Smalltalk (1972),Objective-C (1984),Haskell (1990) 或 OCaml (1996) 的语言里就有了。\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E#1 管道操作(Pipeline operator)\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&js\&\u003Elet result = \&hello\&\n
|& doubleSay\n
|& capitalize\n
|&\n\n\u002F* same as `let result = exclaim(capitalize(doubleSay(\&hello\&)));` *\u002F\n\u002F* result is \&Hello, hello!\& *\u002F\u003C\u002Fcode\u003E\u003Cp\u003E没有找到来自 Reason 的官方文档,不过它似乎与 \u003Ca href=\&https:\\u002Ftc39\u002Fproposal-pipeline-operator\&\u003EECMAScript\u003C\u002Fa\u003E 有点相似 ~\u003C\u002Fp\u003E\u003Ccode lang=\&js\&\u003Etype person = { score: int };\nlet me = { score: 25 };\nlet double = (x) =& x +\nlet add = (x, y) =& x +\nlet boundScore = (lower, upper, score) =& max(lower, min(upper, score));\n\nlet newScore = me.score\n
|& double\n
|& (it) =& add(7, it)\n
|& (it) =& boundScore(0, 100, it);\n\u002F* same as boundScore(0, 100, add(7, double(me.score))); *\u002F\u003C\u002Fcode\u003E\u003Cp\u003E\u003Cb\u003E#2 模式匹配(Pattern matching)\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&js\&\u003Elet reply =\n
switch message {\n
| \&Reason's pretty cool\& =& \&Yep\&\n
| \&good night\& =& \&See ya!\&\n
| \&hello\& | \&hi\& | \&heya\& | \&hey\& =& \&hello to you too!\&\n
| _ =& \&Nice to meet you!\&\n
};\u003C\u002Fcode\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&js\&\u003Ewhen (obj) {\n
-& \&One\&\n
-& \&Greeting\&\n
-& \&Long\&\n
!is String -& \&Not a string\&\n
-& \&Unknown\&\n}\n\nwhen (x) {\n
in 1..10 -& print(\&x is in the range\&)\n
in validNumbers -& print(\&x is valid\&)\n
!in 10..20 -& print(\&x is outside the range\&)\n
else -& print(\&none of the above\&)\n}\u003C\u002Fcode\u003E\u003Cp\u003E\u003Cb\u003E#3 Reactive (Rx) programming build in the language\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&js\&\u003Einput.onKeyDown
.where((e) =& e.ctrlKey && e.code == 'Enter')
.forEach((e) =& dispatch(addTodoAction(e.target.value)));\n\n\u002F\u002F First gets a Async Iterable of Keyboard Events from the input element\n\u002F\u002F Then filters on Keyboard Events that are Ctrl+Enter\n\u002F\u002F Dispatches an action for each of those filtered events\u003C\u002Fcode\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&js\&\u003Evar wachterStream = new Wachter('src\u002Flibrary').\nawait for (var event in wachterStream) {\n
print('The following path has changed ${event.path}');\n}\n\n\u002F\u002F The watcherStream is an \&Async Iterable\& (`Stream` type in Dart)\n\u002F\u002F It can be iterated in a for loop similarly as normal Iterables\u003C\u002Fcode\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&js\&\u003E\u002F\u002F Async Generator, generates all natural numbers asynchronous\nStream&int& naturals() async* {\n
int k = 1; while (true) { yield k++; }\n}\n\n\u002F\u002F maps the Stream (Async Iterable) so that every iterations takes a second\nvar delayedNaturals = naturals()\n
.asyncMap((e) =& new Future.delayed(new Duration(seconds: 1), () =& e));\n\n\u002F\u002F Prints every second the next natural number (up to infinity)\ndelayedNaturals.forEach(print);\u003C\u002Fcode\u003E\u003Cp\u003E\u003Cb\u003E#4 在 lambda 函数里使用 it 作为单一参数\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003EImplicit name (using “it”) of a single parameter in a lambda function\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&js\&\u003Estrings.filter{ it.length == 5 }.map{ it.toUpperCase() }\n\n\u002F\u002F same as strings.filter{ it -& it.length == 5 }.map{ it -& it.toUpperCase() }\u003C\u002Fcode\u003E\u003Cp\u003E\u003Cb\u003E#5 解构(Destructuring)\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&js\&\u003Elet someInts = (10, 20);\nlet (ten, twenty) = someI\n\ntype person = {name: string, age: int};\nlet somePerson = {name: \&Guy\&, age: 30};\nlet {name, age} = someP\u003C\u002Fcode\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&text\&\u003Edata class Person(val name: String, val age: Int)\nval(name, age) = Person(\&Guy\&, 20)\u003C\u002Fcode\u003E\u003Cp\u003E\u003Cb\u003E#6 级联操作(Cascade operator)\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&js\&\u003EquerySelector('#button') \u002F\u002F Get an object.\n
..text = 'Confirm' \u002F\u002F Use its members.\n
..classes.add('important')\n
..onClick.listen((e) =& dispatch(confirmedAction()));\n\n\u002F\u002F same as \n\u002F\u002F var button = querySelector('#button');\n\u002F\u002F button.text = 'Confirm';\n\u002F\u002F button.classed.add('important');\n\u002F\u002F button.onClick.listen((e) =& dispatch(confirmedAction()));\u003C\u002Fcode\u003E\u003Cp\u003E\u003Cb\u003E#7 If 表达式\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&js\&\u003Eval result = if (param == 1) {\n
\&one\&\n} else if (param == 2) {\n
\&two\&\n} else {\n
\&three\&\n}\n\u002F\u002F same as val result = param == 1 ? \&one\& : param == 2 ? \&two\& : \&three\&; \u003C\u002Fcode\u003E\u003Cp\u003E\u003Cb\u003E#8 Try 表达式\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&js\&\u003Eval result = try {\n
count()\n} catch (e: ArithmeticException) {\n
throw IllegalStateException(e)\n}\u003C\u002Fcode\u003E\u003Cp\u003E\u003Cb\u003E#9 Automatic currying\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&js\&\u003Elet add = (x, y) =& x +
\u002F* same as (x) =& (y) =& x + *\u002F\nlet five = add(2,3);
\u002F* 5 *\u002F\nlet alsoFive = add(2)(3);
\u002F* 5 *\u002F\nlet addFive = add(5);
\u002F* y =& 5 + *\u002F\nlet eleven = addFive(6);
\u002F* 11 *\u002F\nlet twelve = addFive(7);
\u002F* 12 *\u002F\u003C\u002Fcode\u003E\u003Cp\u003E\u003Cb\u003E#10 方法拓展(Method extensions)\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&js\&\u003Epublic extension Int {\n
func clamp (_ min: Int, _ max: Int) -& Int {\n
return Swift.max(min, Swift.min(max, self))\n
func abs () -& Int {\n
return Swift.abs(self)\n
}\n}\n\n1.clamp(0, 10); \u002F\u002F 1\n20.clamp(0, 10); \u002F\u002F 10\n-3.abs(); \u002F\u002F 3\u003C\u002Fcode\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&js\&\u003Efun Int.clamp(min:Int, max:Int) = Math.min( Math.max(this, min), max);\n\n\u002F\u002F 12.clamp(0,10) gives 10\u003C\u002Fcode\u003E\u003Cp\u003EHappy coding :)\u003C\u002Fp\u003E\u003Cblockquote\u003E说实话我没看太懂,但大家都说有趣,下边有原链,看懂了的可以跟我港一港 ~\u003C\u002Fblockquote\u003E\u003Chr\u003E\u003Cblockquote\u003E\u003Cb\u003E原文链接:\u003C\u002Fb\u003E\u003Ca href=\&https:\\u002F@kasperpeulen\u002F10-features-from-various-modern-languages-that-i-would-like-to-see-in-any-programming-language-f2a4a8ee6727\&\u003ETen interesting features from various modern languages\u003C\u002Fa\u003E \u003Cbr\u003E\u003Cbr\u003E\u003Cb\u003E推荐阅读:\u003C\u002Fb\u003E\u003Ca href=\&https:\u002F\\u002Fp\u002F\&\u003E如何可视化「排序算法」\u003C\u002Fa\u003E\u003C\u002Fblockquote\u003E\u003Cp\u003E极光日报,\u003Ca href=\&http:\u002F\\u002F?target=https%3A\u002F\\u002F%3Fsrc%3Djiguangdaily%26hmsr%3D%25E6%259E%%E6%%25E6%258A%25A5%26hmpl%3D%26hmcu%3D%26hmkw%3D%26hmci%3D\&\u003E极光开发者\u003C\u002Fa\u003E 的 Side Project,欢迎关注。\u003C\u002Fp\u003E&,&updated&:new Date(&T02:51:33.000Z&),&canComment&:false,&commentPermission&:&anyone&,&commentCount&:27,&likeCount&:76,&state&:&published&,&isLiked&:false,&slug&:&&,&isTitleImageFullScreen&:false,&rating&:&none&,&sourceUrl&:&&,&publishedTime&:&T10:51:33+08:00&,&links&:{&comments&:&\u002Fapi\u002Fposts\u002F2Fcomments&},&url&:&\u002Fp\u002F&,&titleImage&:&https:\u002F\\u002Fv2-92a4f91b755c604f2f09a1c3898bce15_r.png&,&summary&:&&,&href&:&\u002Fapi\u002Fposts\u002F&,&meta&:{&previous&:null,&next&:null},&snapshotUrl&:&&,&commentsCount&:27,&likesCount&:76},&&:{&title&:&如何避免写出烂代码&,&author&:&helperhaps&,&content&:&\u003Cblockquote\u003E简评:本文是关于 JavaScript 编程中的一些实践,即:linting,测试,CI 和类型检查。当然,这些实践建议同样也适用于非 Javascript 编程的情况。\u003C\u002Fblockquote\u003E\u003Ch2\u003E\u003Cb\u003ELinting\u003C\u002Fb\u003E\u003C\u002Fh2\u003E\u003Cp\u003E当你在电脑上写东西(英文)而不确定拼写是否正确时,你会做怎么办? 答案可能不是字典,甚至不是百度一下 —— 只要写下来,看看拼写检查器(spellchecker)是否有提示。代码linting 的工作流程相似。\u003C\u002Fp\u003E\u003Cimg src=\&v2-b5ba091c2ac8d8f96659a2.jpg\& data-caption=\&有趣的是 「linting」 这个单词本身 无法通过拼写检查\& data-size=\&normal\& data-rawwidth=\&393\& data-rawheight=\&64\&\u003E\u003Ch2\u003E\u003Cb\u003E测试\u003C\u002Fb\u003E\u003C\u002Fh2\u003E\u003Cp\u003E对于任何有经验的程序员来说,这是非常明显的,但是我却花了很长时间才真正意识到编写测试的重要性。这里的问题是复杂性 —— 在编程时,某些代码看起来很明显会简单地工作,你实际上有点为它的简洁而自豪,它是如何做一项工作,并做得很好。但是可能会有这样一个边缘情况与另一个边缘情况相结合,然后还有其他的东西弥补了停止显示的错误。\u003C\u002Fp\u003E\u003Cimg src=\&v2-9cacdf1d7d8dd59a59e726.jpg\& data-caption=\&\& data-size=\&normal\& data-rawwidth=\&658\& data-rawheight=\&268\&\u003E\u003Cp\u003E另一个写测试的理由是,当需要重构的时候,一个可靠的测试套件将使程序员专注于代码,而不用担心程序是否因为不明显的变化而中断。最后,测试覆盖报告就像代码上的质量标志,这是一些表示做了一些工作的信号。\u003C\u002Fp\u003E\u003Ch2\u003E\u003Cb\u003E持续集成(CI)\u003C\u002Fb\u003E\u003C\u002Fh2\u003E\u003Cp\u003E但是,如果在代码部署之前 linter 和测试没有强制执行并运行的话,那又能带来什么好处呢? 这就是持续集成派上用场的地方。CI 基本上是自动执行一系列任务(首先是运行测试),确保代码稳定并准备部署到生产环境。\u003C\u002Fp\u003E\u003Cp\u003E这么说来,CI 是执行上述实践的好方法,并确保所有必要的检查都已经完成。为 GitHub 仓库配置 TravisCI 是简单并且免费的 —— 只需在代码仓库的根目录添加一个 .travis.yml 文件,在travis-ci.org 上建立一个账户,在那里配置 CI,那闪亮的「build: passing」徽章就在等待着。\u003C\u002Fp\u003E\u003Ch2\u003E\u003Cb\u003E类型检查\u003C\u002Fb\u003E\u003C\u002Fh2\u003E\u003Cp\u003E在编程中,类型只是特定函数处理的数据类型。它们可以是字符串、布尔值、数字等,也可以是基本类型的自定义结构,就像这个:\u003C\u002Fp\u003E\u003Ccode lang=\&js\&\u003Etype Person = {\n
name: string,\n
age: number\n};\u003C\u002Fcode\u003E\u003Cp\u003E静态类型检查器读取类型注释,并检查对特定函数的所有调用是否遵守此 「contract(合同)」:\u003C\u002Fp\u003E\u003Ccode lang=\&js\&\u003E\u002F\u002F add takes `num`, which must be a number, and returns a string\nconst isItTheAnswer = (num: number): string =& {\n
if (num === 42) {\n
return `${num} is a the answer to life, the universe and everything!`\n
} else {\n
return `${num} is not a the answer, try harder.`\n
}\n}\n\nisItTheAnswer(42) \u002F\u002F =& ? compiles\nisItTheAnswer('eating cat food') \u002F\u002F =& ? flow error - incompatible types\u003C\u002Fcode\u003E\u003Cp\u003E在 JavaScript 中,类型检查的两个主要选择是 TypeScript 和 Flow。上面的例子是使用 Flow,这是一个由 Facebook 开发的类型注释系统,可以很轻松地引入到一个项目中。\u003C\u002Fp\u003E\u003Ch2\u003E\u003Cb\u003E结论\u003C\u002Fb\u003E\u003C\u002Fh2\u003E\u003Cp\u003E如果你没有使用 linting、测试或者使用类型检查器,我希望能够说服你做一切。所有这些工具和实践不仅可以帮助编写更好的代码,还可以教你一些关于编程的知识。\u003C\u002Fp\u003E\u003Cblockquote\u003E原文:\u003Ca href=\&https:\u002F\u002Fjavascript.\u002Fblog\u002FBecome-a-Better-Programmer-by-Making-It-Hard-to-Write-Bad-Code\&\u003EJavaScript Works - Become a Better Programmer by Making It Hard to Write Bad Code\u003C\u002Fa\u003E\u003C\u002Fblockquote\u003E\u003Cp\u003E扩展阅读:\u003C\u002Fp\u003E\u003Cul\u003E\u003Cli\u003E\u003Ca href=\&https:\u002F\\u002Fp\u002F\&\u003EGithub 欢迎所有的持续集成工具\u003C\u002Fa\u003E\u003C\u002Fli\u003E\u003Cli\u003E\u003Ca href=\&https:\u002F\\u002Fp\u002F\&\u003E一些非常有用的 VSCode 扩展\u003C\u002Fa\u003E\u003C\u002Fli\u003E\u003C\u002Ful\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cblockquote\u003E极光日报,\u003Ca href=\&http:\u002F\\u002F?target=http%3A\\u002F6AAFc\&\u003E极光开发者\u003C\u002Fa\u003E旗下媒体。\u003Cbr\u003E每天导读三篇英文技术文章。\u003C\u002Fblockquote\u003E&,&updated&:new Date(&T02:47:10.000Z&),&canComment&:false,&commentPermission&:&anyone&,&commentCount&:0,&likeCount&:2,&state&:&published&,&isLiked&:false,&slug&:&&,&isTitleImageFullScreen&:false,&rating&:&none&,&sourceUrl&:&&,&publishedTime&:&T10:47:10+08:00&,&links&:{&comments&:&\u002Fapi\u002Fposts\u002F2Fcomments&},&url&:&\u002Fp\u002F&,&titleImage&:&https:\u002F\\u002Fv2-7b93ca5b895ed1432a63bb_r.jpg&,&summary&:&&,&href&:&\u002Fapi\u002Fposts\u002F&,&meta&:{&previous&:null,&next&:null},&snapshotUrl&:&&,&commentsCount&:0,&likesCount&:2},&&:{&title&:&Android 国际货币格式化的一个小知识点&,&author&:&hev1n&,&content&:&\u003Cblockquote\u003E简评:今天介绍下 Android 中国际货币格式化的一个小小知识点。\u003C\u002Fblockquote\u003E\u003Cp\u003E目前为止,货币格式化最简单的方式是调用 \u003Ci\u003ENumberFormat.getCurrencyInstance()\u003C\u002Fi\u003E 获得 NumberFormat 实例来把数字格式化为货币格式的字符串(当然也可以把字符串转换成数字)。可以根据当前设备的位置来获取 \u003Ci\u003Ejava.util.Currency\u003C\u002Fi\u003E 实例再以此进行货币的格式化。\u003C\u002Fp\u003E\u003Cp\u003E但如果我们的应用只接受特定的几种货币,那这种随着用户设备位置而修改货币格式就不是一个好的做法。\u003C\u002Fp\u003E\u003Cp\u003E你可能会说「这简单啊,那就在国内默认显示人民币,其他国家就显示美元嘛」。\u003C\u002Fp\u003E\u003Cp\u003E嗯,你很有想法。。。\u003C\u002Fp\u003E\u003Cp\u003E这里就要讲到这篇文章的重点了。\u003C\u002Fp\u003E\u003Cp\u003E假设你给美国地区展示的是 $1,那他们会默认这是 1 美元,这没问题。\u003C\u002Fp\u003E\u003Cp\u003E但世界上还有超过二十个国家和地区的本地货币也叫 dollar ($),比如加拿大、澳大利亚和新西兰。这时候如果你还是展示 $1,那这些国家的用户就会默认这是指他们的货币,这就会造成误解,让用户觉得你们的收费不对。\u003C\u002Fp\u003E\u003Cp\u003E因此,如果当前用户是在加拿大的,而商品价格需要为美元,那么在进行格式化时还需要明确符号,以表明显示的是美元而不是加元。\u003C\u002Fp\u003E\u003Cp\u003E下面是 Kotlin 代码的一个例子:\u003C\u002Fp\u003E\u003Ccode lang=\&kotlin\&\u003Eclass MainActivity : AppCompatActivity() {\n \n
override fun onCreate(savedInstanceState: Bundle?) {\n
super.onCreate(savedInstanceState)\n
setContentView(R.layout.activity_main)\n \n
textView1.text = formatCurrency(1f, CURRENCY_US_DOLLARS, LANGUAGE_ENGLISH, COUNTRY_US)\n
textView2.text = formatCurrency(1f, CURRENCY_US_DOLLARS, LANGUAGE_ENGLISH, COUNTRY_CANADA)\n
textView3.text = formatCurrency(1f, CURRENCY_US_DOLLARS, LANGUAGE_ENGLISH, COUNTRY_AUSTRALIA)\n
private fun formatCurrency(amount: Float, currency: String, language: String, country: String) =\n
currencyInLocale(currency, language, country).format(amount)\n \n
private fun currencyInLocale(\n
currencyCode: String,\n
language: String,\n
country: String = \&\&,\n
variant: String = \&\&): NumberFormat =\n
Locale(language, country, variant).let {\n
NumberFormat.getCurrencyInstance(it).apply {\n
currency = Currency.getInstance(currencyCode)\n
companion object {\n
private const val CURRENCY_US_DOLLARS: String = \&USD\&\n
private const val LANGUAGE_ENGLISH: String = \&EN\&\n
private const val COUNTRY_US: String = \&US\&\n
private const val COUNTRY_CANADA: String = \&CA\&\n
private const val COUNTRY_AUSTRALIA: String = \&AU\&\n
}\n}\u003C\u002Fcode\u003E\u003Cp\u003E展示效果,从上到下分别是美国、加拿大和澳大利亚:\u003C\u002Fp\u003E\u003Cimg src=\&v2-0df3a8fb120e194baa9d5a.jpg\& data-caption=\&\& data-size=\&normal\& data-rawwidth=\&1440\& data-rawheight=\&1080\&\u003E\u003Cp\u003E这里对于加拿大显示 US$,而澳大利亚显示 USD。虽然两者都能理解,但能符合各语言环境的具体情况当然还是更好的。\u003C\u002Fp\u003E\u003Cp\u003E虽然这可能只是一个小知识点,但我个人觉得知道了还是蛮有用的。\u003C\u002Fp\u003E\u003Cblockquote\u003E原文:\u003Ca href=\&https:\u002F\\u002Fcurrency-curiosities\u002F\&\u003ECurrency Curiosities\u003C\u002Fa\u003E\u003C\u002Fblockquote\u003E\u003Cp\u003E日报扩展阅读:\u003C\u002Fp\u003E\u003Cul\u003E\u003Cli\u003E\u003Ca href=\&https:\u002F\\u002Fp\u002F\&\u003EAndroid 实现颜色渐变的一个小 tip\u003C\u002Fa\u003E\u003C\u002Fli\u003E\u003C\u002Ful\u003E&,&updated&:new Date(&T10:00:57.000Z&),&canComment&:false,&commentPermission&:&anyone&,&commentCount&:1,&likeCount&:14,&state&:&published&,&isLiked&:false,&slug&:&&,&isTitleImageFullScreen&:false,&rating&:&none&,&sourceUrl&:&&,&publishedTime&:&T18:00:57+08:00&,&links&:{&comments&:&\u002Fapi\u002Fposts\u002F2Fcomments&},&url&:&\u002Fp\u002F&,&titleImage&:&https:\u002F\\u002Fv2-2d48add7f2c09591ac80_r.png&,&summary&:&&,&href&:&\u002Fapi\u002Fposts\u002F&,&meta&:{&previous&:null,&next&:null},&snapshotUrl&:&&,&commentsCount&:1,&likesCount&:14},&&:{&title&:&作为设计师的我做了个小 APP,并且有稳定的被动收入&,&author&:&McDoge&,&content&:&\u003Cblockquote\u003E\u003Cb\u003E简评\u003C\u002Fb\u003E:原作者没有什么改变世界的想法,就是在现有解决方案上再改进优化一点点,被动收入 10 万人民币,有一定的借鉴作用。他有句话说的很好,很多人都是瞎比比,连试都没试过就带节奏。\u003C\u002Fblockquote\u003E\u003Cp\u003E(本文翻译,我代表原作者 \u003Ca href=\&https:\u002F\\u002Fprofile\u002FAndrew-Ou-2\&\u003EAndrew Ou\u003C\u002Fa\u003E)\u003C\u002Fp\u003E\u003Chr\u003E\u003Cimg src=\&v2-c5e9bf3f3f806c.jpg\& data-caption=\&\& data-size=\&normal\& data-rawwidth=\&1247\& data-rawheight=\&900\&\u003E\u003Cp\u003E我是个设计师,我做了个简单的天气壁纸 App,这个小项目每个月为我带来了 300 美元的被动收入。\u003C\u002Fp\u003E\u003Cp\u003E几年前,我有一个想法,并且付出了实践,就做了一个天气壁纸的应用程序,这是现在市面上最好的天气壁纸之一。市面上已经有了数百款壁纸 App 和 天气 App,那我能做些什么不一样的呢?我意识到,我见到的壁纸和天气是分离的,我想是不是可以让壁纸和天气融合在一起,这是我这个项目的关键点。\u003C\u002Fp\u003E\u003Cimg src=\&v2-c981e6ccbeafcaf03bc5557.jpg\& data-caption=\&\& data-size=\&normal\& data-rawwidth=\&867\& data-rawheight=\&900\&\u003E\u003Cp\u003E可能这就是个小 idea,不一定能赚什么钱,但总归是个好的开始。我问了身边的一些朋友他们的想法,有些人觉得很酷,但是绝大多数都不认为我能从中赚钱,他们甚至怀疑我仅仅是说说而已,压根做不出来产品。\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E很多人告诉你「需要解决一个痛点」,但这并不是绝对的。\u003C\u002Fb\u003E他们只是在重复他们所知道的教条主义,看到的一些文章观点,自己却没有任何实践。这一点你需要牢记于心。\u003C\u002Fp\u003E\u003Cp\u003E在 Google Play Store 上面,有很多非常简单的壁纸 App,售价 0.99 美元,但是已经卖出了数百万份,你可以自己在商城里查一下,这说明,这是一个既有的市场,是可以做的。\u003C\u002Fp\u003E\u003Cp\u003E总之,这个想法在我脑海生根发芽。我是一名设计师,我可以很好地执行设计的部分,但是我不会编程,我就找\u003Cb\u003E外包\u003C\u002Fb\u003E根据我的要求完成了产品。我的应用程序是免费的,并提供基本的天气效果,但是想要全面的效果,用户需要花费 2.49 美元解锁。这是一个很关键的地方,为用户提供一些免费版本非常重要,如果他们喜欢,可以为他们提供更高级的付费版本。\u003C\u002Fp\u003E\u003Cp\u003E我首先发布了应用程序的测试版,这时候人们就已经付费购买高级功能了。这真的令我很兴奋。我从中学到了很多东西,并且继续努力,完善 App。\u003C\u002Fp\u003E\u003Cp\u003E我在论坛,比如 Redit 推广我的 App。有时候一些博客会推荐一下我的 App,我会因此获得巨大的下载量,记得有次被博客推荐了,那周我就赚了 1000 美元,但是这种高峰不会持续太久。\u003C\u002Fp\u003E\u003Cp\u003E现在我的应用程序每个月可以获得 300 美元的稳定收入,我的 App 已经发布了 4 年,\u003Cb\u003E总共为我赚取了 15000 美元\u003C\u002Fb\u003E。想一下,一个简单的天气壁纸 App 就能做到如此。\u003C\u002Fp\u003E\u003Cp\u003E在这个项目我学到了:\u003C\u002Fp\u003E\u003Cul\u003E\u003Cli\u003E你的应用需要做一些有用的事情。它不一定需要多大,励志要做下个 Facebook 或者 Google,它只需要比现有的解决方案更方便,更人性化,这样想会有很多点子涌现。虽然它可能不是一个价值百万美元的想法,但可能是一个价值 5 万美元的想法,被动的赚 5 万美元,也挺不错的。\u003C\u002Fli\u003E\u003Cli\u003E你需要精心的设计和良好的执行。美丽的 UX 和扎实的产品。\u003C\u002Fli\u003E\u003Cli\u003E\u003Cb\u003E你需要尝试失败\u003C\u002Fb\u003E。有些人总是说这个行不通,那个做不了,或者产品以前都出现过了。这些人甚至都没有自己做过任何事情就瞎bb。你需要尝试一下,如果失败了,你也能学到很多的经验和教训,如果你不试试,任何事情都无法完成。\u003C\u002Fli\u003E\u003C\u002Ful\u003E\u003Cp\u003E\u003Cu\u003E最后安利一下我的 App:\u003Ca href=\&https:\u002F\\u002Fstore\u002Fapps\u002Fdetails?id=com.andrewou.weatherback\&\u003EWeather - Weatherback and lock screen - Android Apps on Google Play\u003C\u002Fa\u003E\u003C\u002Fu\u003E\u003C\u002Fp\u003E\u003Cimg src=\&v2-6de5d7ebc64.jpg\& data-caption=\&\& data-size=\&normal\& data-rawwidth=\&569\& data-rawheight=\&473\&\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cblockquote\u003E原文:\u003Ca href=\&https:\u002F\\u002FHow-do-I-get-rich-by-creating-an-Android-app\u002Fanswer\u002FAndrew-Ou-2?srid=us7Pv\&\u003EHow do I get rich by creating an Android app?\u003C\u002Fa\u003E\u003C\u002Fblockquote\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E极光日报,\u003Ca href=\&http:\u002F\\u002F?target=http%3A\\u002F6AAFc\&\u003E极光开发者\u003C\u002Fa\u003E旗下媒体。\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E每天导读三篇英文技术文章。\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003C\u002Fp\u003E&,&updated&:new Date(&T09:54:48.000Z&),&canComment&:false,&commentPermission&:&anyone&,&commentCount&:11,&likeCount&:85,&state&:&published&,&isLiked&:false,&slug&:&&,&isTitleImageFullScreen&:false,&rating&:&none&,&sourceUrl&:&&,&publishedTime&:&T17:54:48+08:00&,&links&:{&comments&:&\u002Fapi\u002Fposts\u002F2Fcomments&},&url&:&\u002Fp\u002F&,&titleImage&:&https:\u002F\\u002Fv2-0bb135bc79bf_r.png&,&summary&:&&,&href&:&\u002Fapi\u002Fposts\u002F&,&meta&:{&previous&:null,&next&:null},&snapshotUrl&:&&,&commentsCount&:11,&likesCount&:85},&&:{&title&:&JavaScript 成本分析&,&author&:&huminios&,&content&:&\u003Cblockquote\u003E简评:本文从不同角度分析 JavaScript 的成本。\u003C\u002Fblockquote\u003E\u003Ch2\u003E网络\u003C\u002Fh2\u003E\u003Cp\u003E大多数开发者考虑 JavaScript 成本的时候,都会考虑到下载和执行成本。\u003C\u002Fp\u003E\u003Cp\u003EJavaScript 代码量越大请求时间会越长,从而导致网页响应时间(从用户请求到用户可交互的时长)变长。\u003C\u002Fp\u003E\u003Cimg src=\&v2-37fbabd40.jpg\& data-caption=\&\& data-size=\&normal\& data-rawwidth=\&1600\& data-rawheight=\&986\&\u003E\u003Cp\u003E我们可以通过以下方式降低 JavaScript 的网络传输成本:\u003C\u002Fp\u003E\u003Cul\u003E\u003Cli\u003E\u003Cb\u003E只传输用户需要的代码\u003C\u002Fb\u003E,可以使用 Code splitting 来拆分我们的代码。\u003C\u002Fli\u003E\u003Cli\u003E\u003Cb\u003E缩小代码\u003C\u002Fb\u003E(可以使用 Uglify、\u003Ca href=\&https:\\u002Fbabel\u002Fminify\&\u003Ebabel-minify\u003C\u002Fa\u003E 或者 \u003Ca href=\&https:\u002F\\u002Fpackage\u002Fuglify-es\&\u003Euglify-es\u003C\u002Fa\u003E)\u003C\u002Fli\u003E\u003Cli\u003E\u003Cb\u003E压缩代码\u003C\u002Fb\u003E(可以使用
\u003Ca href=\&https:\u002F\\u002F\u002Fnext-generation-server-compression-with-brotli\u002F\&\u003EBrotli\u003C\u002Fa\u003E ~\u003Ca href=\&https:\\u002Fpaulcalvano\u002Fstatus\u002F208514\&\u003Eq11\u003C\u002Fa\u003E, Zopfli 或者 gzip)\u003C\u002Fli\u003E\u003Cli\u003E\u003Cb\u003E删除一些无用的代码\u003C\u002Fb\u003E(可以使用 DevTools 的 \u003Ca href=\&https:\u002F\\u002Fweb\u002Fupdates\u002F\u002Fdevtools-release-notes\&\u003Ecoverage\u003C\u002Fa\u003E 来检测没有用到的 CSS 和 JS 代码,使用 \u003Ca href=\&https:\u002F\u002Fwebpack.js.org\u002Fguides\u002Ftree-shaking\u002F\&\u003Etree-shaking\u003C\u002Fa\u003E 或 \u003Ca href=\&https:\u002F\\u002Fclosure\u002Fcompiler\u002F\&\u003EClosure Compiler\u003C\u002Fa\u003E 来剥离这些没有用的代码)\u003C\u002Fli\u003E\u003Cli\u003E\u003Cb\u003E缓存减少网络传输\u003C\u002Fb\u003E,比如设置 max-age 和 ETag 来避免重复传输没有改动的数据。\u003C\u002Fli\u003E\u003C\u002Ful\u003E\u003Cimg src=\&v2-fabcaf4d74beced626f4.jpg\& data-caption=\&\& data-size=\&normal\& data-rawwidth=\&1920\& data-rawheight=\&1080\&\u003E\u003Ch2\u003E解析 \u002F 编译(Parse \u002F Compile)\u003C\u002Fh2\u003E\u003Cp\u003E代码下载完成后, JavaScript 一个重要的成本就是 JS 引擎 Parse\u002FCompile 这段代码。在 Chrome DevTools 中 Performence 板块中黄色部分就是解析和编译花费的时间。\u003C\u002Fp\u003E\u003Cimg src=\&v2-ff880d0edbe2a6b0eaca93.jpg\& data-caption=\&\& data-size=\&normal\& data-rawwidth=\&1194\& data-rawheight=\&246\&\u003E\u003Cp\u003E在 Performent -& Bottom-Up\u002FCall Tree 可以查看解析\u002F编译花费的详细时间。\u003C\u002Fp\u003E\u003Cimg src=\&v2-19dad5b7f88a.jpg\& data-caption=\&\& data-size=\&normal\& data-rawwidth=\&1206\& data-rawheight=\&344\&\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cimg src=\&v2-5ff91bcd921fdcb9b56a2aa6.jpg\& data-caption=\&\& data-size=\&normal\& data-rawwidth=\&1600\& data-rawheight=\&442\&\u003E\u003Cp\u003E如果解析\u002F编译时间长的话会延长用户等待的时间,影响用户体验。 Javascript 代码越多解析\u002F编译时间就越长。\u003C\u002Fp\u003E\u003Cimg src=\&v2-fac.jpg\& data-caption=\&\& data-size=\&normal\& data-rawwidth=\&1600\& data-rawheight=\&900\&\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cp\u003E浏览器在处理相同大小的 JavaScript 代码、图片或字体时,JavaScript 会花费更长的时间。\u003C\u002Fp\u003E\u003Cimg src=\&v2-006febe3c158ddeb6d05e6b.jpg\& data-caption=\&\& data-size=\&normal\& data-rawwidth=\&2000\& data-rawheight=\&1293\&\u003E\u003Ch2\u003E解析 JavaScript 代码时间在不同性能手机有很大差距\u003C\u002Fh2\u003E\u003Cp\u003E下图为 2017 年不同手机解析 1MB 的 JavaScript(没有进过压缩),所花费的时间。\u003C\u002Fp\u003E\u003Cimg src=\&v2-fedd71f188a.jpg\& data-caption=\&\& data-size=\&normal\& data-rawwidth=\&1920\& data-rawheight=\&1080\&\u003E\u003Cp\u003E可以看到最快的手机 iPhone8 速度比 Moto G4 快 3 倍。\u003C\u002Fp\u003E\u003Cimg src=\&v2-ef2b00ad72789cdd2b7f4a.jpg\& data-caption=\&\& data-size=\&normal\& data-rawwidth=\&1920\& data-rawheight=\&1080\&\u003E\u003Cp\u003E我们测试得时候不应该只使用我们自己的手机来测试性能,更应该使用平均硬件(如 Moto G4)来进行测试。\u003C\u002Fp\u003E\u003Cimg src=\&v2-71f287db5c4efd62a7aad4efc26695a7.jpg\& data-caption=\&\& data-size=\&normal\& data-rawwidth=\&1600\& data-rawheight=\&900\&\u003E\u003Cp\u003E可以使用 \u003Ca href=\&https:\u002F\\u002Fanalytics\u002F\&\u003EAnalytics\u003C\u002Fa\u003E 来了解访问网站的用户的具体使用情况。\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E网站访问速度慢是因为 JavaScript 代码太大了吗? 可能吧\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003E使用 HTTP Archive (前 500K 的网站)来分析移动设备上 JavaScript 的状态,我们可以看到 50% 的网站用户花费 14 秒就得到响应,它们最多花费 4 秒来解析\u002F编译 JavaScript 代码。\u003C\u002Fp\u003E\u003Cimg src=\&v2-31b5e7f5bb.jpg\& data-caption=\&\& data-size=\&normal\& data-rawwidth=\&1600\& data-rawheight=\&889\&\u003E\u003Cp\u003E在获取和处理 JavaScript 和其他资源所花费的时间中,因为感觉网页已经可以使用,所以用户可以等待一段时间也许并不奇怪。我们一定可以在这里做得更好。\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E从网页中删除不重要的JavaScript可以减少传输时间,减小 CPU Parse\u002Fcompiling 以及内存开销。这也有助于让您的网页更快地交互。\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Ch2\u003E执行时间\u003C\u002Fh2\u003E\u003Cp\u003E不仅 Parse\u002FCompile 会花费时间,执行 JavaScript 代码的时候也会,如果 JavaScript 执行时间过长,也会影响网页的响应时间。\u003C\u002Fp\u003E\u003Cimg src=\&v2-c269e4a32b70a48a5da5f94.jpg\& data-caption=\&\& data-size=\&normal\& data-rawwidth=\&1600\& data-rawheight=\&900\&\u003E\u003Cp\u003E为了解决这个问题,我们应该尽量使用小块的代码来避免阻塞主线程。\u003C\u002Fp\u003E\u003Ch2\u003E减少 JavaScript 交互花费的模式\u003C\u002Fh2\u003E\u003Cp\u003E可以使用 \u003Ca href=\&https:\u002F\\u002Fweb\u002Ffundamentals\u002Fperformance\u002Fprpl-pattern\u002F\&\u003EPRPL(通过代码分割和缓存来优化交互性能的模式)\u003C\u002Fa\u003E来减少页面响应时间。\u003C\u002Fp\u003E\u003Cimg src=\&v2-59cd72dfad73f.jpg\& data-caption=\&\& data-size=\&normal\& data-rawwidth=\&2000\& data-rawheight=\&1089\&\u003E\u003Cp\u003E我们来看看它的作用:\u003C\u002Fp\u003E\u003Cp\u003E我们使用 V8’s Runtime Call Stats 分析流行的移动网站和 Progressive Web Apps 的加载时间,如下图:\u003C\u002Fp\u003E\u003Cimg src=\&v2-fbf6d2e01cbff0.jpg\& data-caption=\&\& data-size=\&normal\& data-rawwidth=\&1920\& data-rawheight=\&1080\&\u003E\u003Cp\u003E可以看到许多站点的橙色部分(解析\u002F编译时间)占了很大的比重。\u003C\u002Fp\u003E\u003Cp\u003E\u003Ca href=\&https:\\u002F\&\u003EWego\u003C\u002Fa\u003E 是一个使用 PRPL 的网站,明显可以看出解析所占的比重小了很多。\u003C\u002Fp\u003E\u003Ch2\u003E其他花费\u003C\u002Fh2\u003E\u003Cp\u003E其他的方式影响页面性能:\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E内存:\u003C\u002Fb\u003E在进行garbage collection (浏览器回收内存)的时候页面可能会出现暂停情况(JS 执行也会暂停)。应该尽量避免内存泄露和频繁的 GC 中断,来保持页面的流畅。\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E运行时长:\u003C\u002Fb\u003E运行JavaScript 代码时间过长会阻塞主线程,将代码分成很小。\u003C\u002Fp\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cblockquote\u003E原文: \u003Ca href=\&https:\\u002Fdev-channel\u002Fthe-cost-of-javascript-e\&\u003EThe Cost Of JavaScript\u003C\u002Fa\u003E\u003Cbr\u003E\u003Cbr\u003E推荐阅读:\u003Ca href=\&https:\u002F\\u002Fp\u002F\&\u003E图片加载时使用 SVG 作为图片 placehold\u003C\u002Fa\u003E\u003C\u002Fblockquote\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E极光日报,\u003Ca href=\&http:\u002F\\u002F?target=http%3A\\u002F6AAFc\&\u003E极光开发者\u003C\u002Fa\u003E旗下媒体。\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E每天导读三篇英文技术文章。\u003C\u002Fb\u003E\u003C\u002Fp\u003E&,&updated&:new Date(&T05:12:14.000Z&),&canComment&:false,&commentPermission&:&anyone&,&commentCount&:4,&likeCount&:32,&state&:&published&,&isLiked&:false,&slug&:&&,&isTitleImageFullScreen&:true,&rating&:&none&,&sourceUrl&:&&,&publishedTime&:&T13:12:14+08:00&,&links&:{&comments&:&\u002Fapi\u002Fposts\u002F2Fcomments&},&url&:&\u002Fp\u002F&,&titleImage&:&https:\u002F\\u002Fv2-bdefbdcde14_r.png&,&summary&:&&,&href&:&\u002Fapi\u002Fposts\u002F&,&meta&:{&previous&:null,&next&:null},&snapshotUrl&:&&,&commentsCount&:4,&likesCount&:32},&&:{&title&:&源于十九世纪的硅谷科技创业文化&,&author&:&Aceyclee&,&content&:&\u003Cblockquote\u003E\u003Cb\u003E简评:\u003C\u002Fb\u003E硅谷色彩斑斓、轻松惬意的办公环境成

我要回帖

更多关于 极光在哪里看 的文章

 

随机推荐