Skip to content

人类第一张在外星球的照片

这张照片原图是我从 NASA 官网找的。

因为据说用的是蔡司镜头,所以去NASA检索了半天,这是一组图片中的一张,并不一定是第一张。

NASA 原图大小,未压缩,右键保存,手机长按。

百度重回百度:陆奇出走 智能驾驶业务或被分拆

来源:腾讯《潜往》
作者:韩依民

种种细节表明,百度公司最重要的业务之一智能驾驶正在发生变化。

2017年3月,在百度整合自动驾驶事业部(L4)、智能汽车事业部(L3)、车联网业务(Car Life etc.)成立智能驾驶事业群组(IDG),且高级副总裁王劲不再担任L4总经理职务的敏感时刻,百度CEO李彦宏在接受彭博社采访时表示:当百度无人驾驶汽车业务走向成熟,且需要更多资金和合作伙伴时,可能考虑分拆该项业务。

李彦宏的该番表态为彼时百度无人车分拆的喧嚷传闻划下了句点,现在,这个时机似乎又已经到来。

据腾讯《潜望》了解,作为陆奇就职百度期间最为看重的两大人工智能业务之一,百度智能驾驶业务被重新列入分拆计划。

不仅仅是计划拆分智能驾驶业务,半年以来百度对于“主航道”的瘦身和重磅押注信息流都表明百度对陆奇路线的修正仍在继续。而取代这一路线的,是以李彦宏、马东敏夫妇为中心的公司整体对百度传统核心业务的亲近。

image

换句话说,百度在渐渐“回归”,曾面对的风险,也可能再次浮现。

QI的出走 QI的问题

在百度,为了表示亲切,员工一般不呼高管的职位,取而代之是他们的简称,比如李彦宏被称为Robin,王劲被称为劲,陆奇则是QI。

离开百度后,QI很快确定了自己的下一站。

8月15日,全球知名的创业加速器Y Combinator宣布正式进入中国,陆奇担任YC中国创始人及CEO,并任YC全球研究院院长。

公布新去向后,陆奇表示:考虑完全部因素,YC 是我唯一剩下的选择。

事实上,摆在陆奇面前的选择并不少。腾讯《潜望》获悉,在百度发出陆奇将离任集团总裁及COO职位的消息后,便有多家知名企业及投资基金萌生邀其加盟的想法,有百度高管对腾讯《潜望》透露,包括他在内的多位百度高管都接到了猎头对于陆奇的背景调查。而据腾讯《潜望》了解,陆奇与百度的竞业协议只到今年年底,明年初陆奇便可自由择业。

该位百度高管表示,“陆奇如果下一站还是去一家互联网公司,尤其是中国的互联网公司,那百度会被打脸的一塌糊涂,去一个投资公司还好说。”

与李彦宏的私人情谊曾是陆奇加入百度的重要原因,在陆奇加入百度第二天举行的媒体沟通会上,李彦宏如此解释为何能顺利邀得陆奇加入:“我们将近20年的交往,相互之间的信任还是起了非常大的作用。”

这份私人情谊最终让陆奇没有做出加入企业的决定,也让陆奇从百度的去职得以保持表面的和平。

在百度的对外公告中,陆奇离任是由于其“个人和家庭原因”,随后有报道称,陆奇家人的变故是促使陆奇转变生活重心的导火索,但据腾讯《潜望》了解,陆奇家人的变故发生在今年4月,而陆奇最早于今年2月份便向李彦宏提出离职,离职过程由其夫人专程回国操作,谈判进行了三个多月,直至5月18日当天,百度的最高管理层——Estaff成员才被告知相关信息,提前一晚获知此变动的百度高管唯有向海龙。

一位接近李彦宏的百度高层人士对腾讯《潜望》表示,陆奇的去职,本质上是因为其与李彦宏的核心价值观不一样,而对于百度商业化“度”的把控,是二者分歧的矛盾集中点。

就职百度期间,陆奇的工作狂风格曾获得李彦宏“工作极其玩命、上下有口皆碑”的评价,尽管是被邀请加入的职业经理人,但在一位百度高管的感受中,陆奇更加看重长远利益。曾与陆奇共事过的一位百度前员工如此记录:他很在意对与错,对的事情,再难也要去做;错的事情,诱惑再大也不能做。

而在该位百度高管的感受中,相较而言,李彦宏与陆奇有着完全不同的风格,李非常关注华尔街,经常表达“我们是一家上市公司,我们要维护我们投资人的利益,所以我们不能做这些事情。”

尽管在陆奇入职之初,李彦宏曾给予其“一人之下,万人之上”的权力,但一旦事涉具体营收,陆奇便会遭遇重重掣肘。据接近陆奇的人士透露,陆奇任内手机百度APP曾有一个很大的商业推广,需要一个很大的弹窗,对此陆奇觉得并不合适,而李彦宏绕过陆奇,直接与向海龙商议,并上线了该弹窗。

加入百度后,陆奇积极与华尔街对话,阐述百度在人工智能上投入的决心和可能获得的巨大回报前景,但随着去年9月中旬原新浪微博CFO余正钧加盟百度出任集团CFO后,陆奇与投资人沟通的职能便被逐渐代替。

上述百度高管向腾讯《潜望》表示,“新CFO过来,任务很明显:砍成本、涨股价,以前陆奇会很积极的去跟投资人聊,Herman(余正钧)来了之后这部分职能就被替代了,Herman聊的话题和陆奇聊的非常不一致。”

今年一月份,李彦宏在参加活动时公开表达从未说过“All in AI”,价值观上的分歧最终导致陆奇与李彦宏分道扬镳。

在很多百度员工眼中,陆奇代表着一种希望,但并非所有人都持有相同看法。据接近百度高层的人士向腾讯《潜望》透露,2017年初回归百度的李彦宏夫人马东敏便对陆奇的管理方式存在异议。

异议主要围绕陆奇的西方式管理文化,入职百度后,陆奇对具体业务负责人进行充分授权,但在复杂的中国市场环境下,一些决策如高价采买内容等,只能放在公司层面推动才可行。

同时,在人才储备方面,在陆奇所熟悉的美国公司治理结构中,集团层面与业务层面有比较明确的分工,但在中国的互联网公司治理结构下,公司决策大多仍集中于核心管理层,其他人主要做执行,人才储备上不够完整,因此陆奇原先的管理方法便可能遭遇水土不服。

去年2月,在宣布全资收购渡鸦科技的同时,百度内部通告将度秘团队升级为度秘事业部,景鲲任事业部总经理。这被认为是陆奇上任后的第一个大动作。在去年举行的首届百度AI开发者大会上,景鲲作为DuerOS的代言人于主论坛环节登场演讲,负责全面介绍DuerOS的开放路线。能够看出,在陆奇的排兵布阵中,具体业务负责人被赋予了更高的地位。

采取如此做法的出发点不难理解:离业务最近的人,做决定平均而言比离业务远的人要好。但上述人士表示,“景鲲当然是一位非常优秀的产品经理,但他从来没有运作过商业,突然间把他放在全局观的业务上,这是需要实践和经验的。”

正因如此,相对陆奇大刀阔斧的明面动作,置身幕后的马东敏也在调动资源进行布局。

过去一年多,马东敏通过其统领的百度战略投资从集团层面在内容与渠道两大端围绕DuerOS做了资源投入:增持了百度视频、纵横文学;战略投资了蜻蜓 FM、梨视频、人人视频等一系列内容产业公司;10月12日,百度还宣布战略领投网易云音乐新一轮融资,根据百度方面提供的信息,双方战略合作首先在智能硬件领域落地,网易云音乐将接入 DuerOS 平台。

除了内容产业外,在终端侧,百度先后投资了极米科技和小鱼在家等终端厂商,马东敏还亲自出面洽谈与华为等手机大厂的合作。在内容产业上的布局以及对终端厂商的投资,均意在为DuerOS铺设更好的发展环境。

百度在集团层面为DuerOS倾斜了大量资源,获得资源倾斜并非没有代价。

在接近百度高层的人士看来,以李彦宏重视华尔街、短期回报的风格来看,景鲲的压力会很大,“接下来会问他要两个:要不给用户数据,增长很快、活跃度很高;要不就给我挣钱。”

事实上,在10月31日举行的百度2018年第三季度财报电话会议上,李彦宏便在回答分析师提问时明确了DuerOS的商业化时间点:DuerOS的增长十分迅猛,预计这种高速增长要一直持续到2019年,商业化将在2020年开始。

显然,作为百度AI战略两大重要业务板块之一,DuerOS已经有了明确的商业化时间表,对于DuerOS团队而言,这意味着更高的增长期许以及随之而来更大的压力。

最近一年,百度投入了大量资源为DuerOS铺量。今年以来,百度推出了多款智能硬件新品:上半年陆续发布了带屏智能音箱小度在家(上市价599元)、自研智能音箱小度音箱(促销价89元);在11月1日举行的2018百度世界大会上,景鲲再次发布了新的智能音箱产品小度智能音箱Pro,以及自研的小度语音车载支架。

延续了上半年推出低价产品的策略,新推出的小度智能音箱Pro定价399元,而尝鲜价只需169元;小度语音车载支架售价99元,即日起将半价优惠49元开始公测。

如此激进的价格策略是为快速获取用户,做大规模,而根本目的则是为商业化做好准备。受促销及渠道成本增加的影响,百度二季度销售成本、综合开销及行政管理费用同比增长了54%;第三季度同比增长51%。

尽管目前DuerOS距离人工智能时代的安卓系统仍有很长的路要走,但在今年7月举行的第二届百度AI开发者大会上,百度发布了DuerOS 3.0版本,根据介绍,3.0版本的最大亮是开始尝试商业模式闭环,将逐渐向用户提供付费应用,在前六个月所有商业收益归开发者所有期限过后,平台将与开发者按比例分成。

一切已在加速。

主航道瘦身

陆奇任内,其曾为百度制定主航道与护城河的大战略。具体来讲,主航道指Feed流和人工智能两大业务,代表百度的未来;护城河是指能够让主航道业务航行更稳健的业务,起到护卫舰队的作用,是百度的现在。

而随着陆奇去职,百度的投入重心明显发生偏移——曾被列入主航道的智能驾驶业务今年的重心已经向实用转化调整。

智能驾驶之于百度意义复杂。

2017年3月1日,百度成立智能驾驶事业群组(IDG),由时任百度集团总裁和首席运营官陆奇兼任总经理。同年4月19日,百度发布Apollo自动驾驶开放平台。

陆奇任内,百度Apollo计划是其公开站台最多的百度业务。在2017年7月举行的第一届百度AI开发者大会上,Apollo与DuerOS被陆奇共同列为百度人工智能战略的两大端,是百度未来从人工智能战略中获取实际回报的重要抓手。在今年四月底陆奇离职传闻愈演愈烈之时,其还出现在北京车展现场与比亚迪董事长王传福会面,成为百度公关对外说明陆奇无职位变动的力证。

更早之前,王劲调动能力范围内重要资源押注百度无人车并推动业务分拆时,这一业务曾被寄予“再造一个百度”的希望。

然而,几经波折后,百度智能驾驶业务虽终被提上分拆日程,但其在内部的地位已经颇为微妙。

与两年前相比,自动驾驶已不再是大公司的保留地,如今,国内外均已出现自动驾驶领域的独角兽,这意味着优秀技术人才的选择面非常广泛,加之陆奇离任,百度吸引优质人才投身智能驾驶业务的难度相较早期大大提升。今年5月18日,百度宣布陆奇卸任集团总裁及COO职位,百度IDG也进行了同步调整:总经理李震宇转向张亚勤汇报。

根据百度Apollo官网上陈列的开放路线图,Apollo今年的目标是量产园区自动驾驶、明年的目标是量产限定区域城市自动驾驶、2020年的目标是量产简单城市道路自动驾驶、2021年的目标是高速和城市道路全网自动驾驶。

image

这与此前陆奇定下来的开放路线图存在差别,首先在时间上,如今的开放路线图时间整体延后了一年;另外,其关键词已由开放技术代码向量产转变。

image

在原有设想中,Apollo最终期待打造的是自动驾驶领域的安卓系统,实现上述目标必须攻克一系列技术难题。而目前,行业在L4的方向上暂时没有取得重大突破,百度同样没有找到特别好的解决方案。

同时,要实现预想中的安卓路径,需要搭建一个完美的生态,然而今年年初,负责百度与车企合作的百度副总裁邬学斌离职,但扩大朋友圈的需求仍驱使着Apollo商务团队每月必须完成一定的合作伙伴数量,在类似KPI的驱使下,部分Apollo的对外合作开始流于表面。据腾讯《潜望》了解,有公司在答应与Apollo合作后,除了Logo被列入展示外,双方无其他实质性接触。

压力当前,Apollo急于展示自己的实用可能,封闭园区成为主要落地场景,如重庆两江新区互联网产业园“百度-盼达自动驾驶示范园区”、湖南湘江新区智能系统测试区、百度与海淀公园合作打造的AI公园等。

更值得关注的变数则是可能进行的分拆。据了解,百度已在与外部潜在投资方进行接触,部分百度智能驾驶团队成员则不再被授予百度公司股票,而是相关业务期权。由于智能驾驶中美两地团队在股票转期权方面暂未达成一致,目前拆分计划尚未进入实质阶段。

随着拆分IDG的设想被重新提上议程,百度对智能驾驶业务的定位和投入已经有了更大不确定性。

转变并非毫无征兆。

今年5月21日,陆奇最后一次参加了百度内部的沟通会,一同参加了沟通会的李彦宏针对现场员工关于“决胜AI时代”战略如何进一步落地的提问时给出的答案是会推出一款名为“简单搜索”的App,让用户能够通过语音、图像等各种各样的输入方式表达需求,而在这背后,则是要做到对用户更加的理解与了解。“这样的创新我认为未来会不断地有,我们会一点一点的把它推向市场”。

同时,李彦宏还向百度员工分享了一个工作细节:“过去这半年的时间不少同学知道,我在亲自带信息流这个团队。每天早上八点半跟核心团队开会,每天都是如此。”

随后在百度2018年二季度财报电话会议上,余正钧向分析师们明确了百度的新策略:“将利润做到最大化而不是利润率最大化是一个更好的策略,我们自今年年初以来开始推行这种策略,只要我们认为还有更多的利润可以获取,我们就会增加流量获取的支出。”

根据百度2018年二、三季度财报披露的信息,百度在内容成本以及销售、总务和行政支出上同比均有大幅增长。

余正钧同时说明了接下来百度预算的两个主要支出方向:在流量获取方面的投入,以及在内容获取方面的投入。这些投入可能会增加百度在市场营销和内容成本上的支出。

相关财务策略已经在被执行。不久前,百度宣布杨紫成为百度APP代言人,借助明星的影响力扩大知名度及市场规模是常见做法,而成为百度APP新代言人的杨紫也非常敬业的在发布会现场演示如何通过百度APP智能小程序获得红包。

据介绍,“对所有新来的百度App用户,红包最少是8.88块,多的可以到880元。”

向用户发红包,这已经是互联网世界里并不新鲜的做法,在前几年的春节空包大战中,互联网巨头们通过向用户发放真金白银的红包,推动了支付等相关业务的快速增长,现在,百度希望复制同行们已被验证过的成功经验。对急于做大信息流业务的百度而言,如此直接的用户补贴手法虽然并不新鲜,但仍然值得一试。

可以看出,相比需要更长远投入的人工智能业务,无论是高层的关注点还是预算支出的方向,百度都在向能看到投入产出的信息流倾斜。

而在百度的最新路线下,来自搜索公司的力量依然被紧紧依赖。

回归搜索核心

被李彦宏寄予厚望的信息流业务始于2016年。

百度信息流业务由用户产品和商业变现两大部分构成,该年9月28日,百度信息流业务用户产品端的重要板块百家号正式上线,11月23日,时任百度副总裁陆复斌宣布,2017年百度将累计向内容生产者分成100亿,所有个人和机构内容生产者都可以入驻百家号,参与百亿分润。百度至此加入内容扶持大战。

2017年5月,入职百度五年的沈抖被晋升为百度公司副总裁,负责手百和Feed事业部,全面统领包括手机百度以及百度Feed流、百家号、好看视频、百度新闻、手机浏览器、Hao123等产品,成为百度信息流用户产品侧的掌门人。

对用户侧产品流量的商业变现由百度高级副总裁、搜索公司总裁向海龙领导的凤巢团队负责。

受2016年年初血友病吧被卖事件负面影响,出于规范管理公司TO B业务的考量,百度于该年上半年将公司旗下原不属于凤巢体系的贴吧、地图等TO B商业变现团队全部合并至凤巢,这支因突发事件而被动调整的团队成为了百度信息流商业变现端的最初执行团队。

与百家号上线初期的大规模推广相比,变现侧的启动显得低调许多。2016年年中,百度搜索公司CTO郑子斌与刚被合并至凤巢的2B端商业变现团队开会,同步了将要做信息流商业化的消息,围绕这项全新的业务,第一次会议重点讨论了接下来的策略,未设定具体KPI。

知情人士对腾讯《潜望》透露,从结果来看,信息流业务第一年的营收事实上很少。为了打开局面,在业务启动初期,百度从公司层面引导广告主投放凤巢推广的时候,搭配投放信息流产品,整合投放在初期占了信息流约50%收入。

2017年初开始,信息流设立单独产品线,广告主可以独立分配预算,与搜索推广完全是并列关系,目前,整合投放的收入对信息流业务而言已经微乎其微。

得益于2016年制定的策略,百度信息流业务在2017年取得了将近100亿的营收,尽管100亿的营收规模在百度2017年全年848亿的营收中占比有限,但对于一项刚刚完成从0到1的业务而言,这一成绩足以让百度高层看到重振的希望。

在可观的变现前景驱动下,凤巢系统的产品和研发被大量抽调,信息流商业变现团队规模从2017年年初开始迅速扩张,目前团队规模已经达到最初规模的20倍,超过200人。

知情人士告诉腾讯《潜望》,在2017年,能感觉到团队每个人都在“ALL in 原生”,负责信息流商业变现的员工经常能接到来自郑子斌或者向海龙下派的紧急项目——在一个月内上线一个新功能,这些新功能将影响到所有投放信息流的广告主。信息流业务加速推进的同时,陆奇也正在百度大施拳脚,然而在相关团队成员的回忆中,他们却几乎很难感受到来自陆奇的影响。

伴随信息流业务初具规模,百度凤巢体系随之拓展,初始只为提升百度搜索推广变现效率的凤巢,现已囊括包括搜索、信息流、网盟在内的百度主要变现方式,成为相当于阿里妈妈之于阿里这样的数字营销大中台,这一关乎百度钱袋子的中枢由向海龙牢牢把控。

一年多前,意图推动百度革新的陆奇曾在一次高管会议上对百度贴吧做出了“关、停、并、转”的建议——为了调配百度内部资源,陆奇触碰到了百度早期赖以成长的根基上。但如今,随着陆奇战略被修正,百度重点押注信息流,以向海龙为代表的百度传统核心势力搜索公司的地位愈加重要。

重入流量赌局

就职百度的一年零六个月内,陆奇为百度做出的最大贡献,一是对百度战略进行了全面梳理,二是通过新风会等方式重塑了百度内部的文化及沟通氛围。不过随着陆奇去职,其留下的痕迹正在被逐渐抹去。

根据多位百度员工提供的信息,在陆奇职位调整消息公布后的一两个月里,百度内部能够明显感觉到一股“去陆奇化”趋势:“陆奇来了有个新风会,现在就说全员沟通我们以前就有了;自动驾驶我们多少年前就开始做了;DuerOS也一样。但其实以前的全员沟通都是假的,陆奇来了才是真的;以前百度的人工智能战略不清晰,现在很清晰。”

陆奇曾向资本市场讲出了百度摆脱对搜索流量单一依赖的另一种可行路径,即ALL in AI,资本市场也曾以助推百度市值接近千亿美元回应了期待。

但随着百度抛弃陆奇路线回归传统,AI故事带来的资本溢价已经蒸发,这意味着怎样获得更大流量、使流量价值最大化再次成为百度的核心,其中暗藏的风险在于,一旦流量的增长未达预期,为了取得足够好看的商业成绩,对现有流量价值的过分榨取可能复现,类似做法曾在两三年前为百度带来了巨大的道德危机。

这是一场赌博,而百度显然已决心重回牌桌。

在百度修正陆奇路线的大背景下,信息流已成百度可供资本市场咀嚼的最重要商业故事。

据腾讯《潜望》了解,百度今年对信息流的营收目标已调高至300亿左右。上述知情人士对《潜望》表示,今年完成200亿左右的营收应该没什么问题,问题是如此巨大的增长规模在明年以及之后能否持续。

在该成员看来,2017年信息流业务业绩好,一方面是因为流量够,另外一方面是因为2016年年底的时候基本定了接下来的策略,2017年照章执行即可。“广告这个业务能预估到有多少流量过来,经过一些数据推导可以算能挤出多少水,我们就一直在朝那个方向努力。”

信息流业务得以持续高速增长的前提是流量也能够同步高速增长,沈抖负责的信息流用户产品承担着吸引更多流量的重责,正因如此,李彦宏从去年下半年开始为之投入大量精力。但是,互联网整体的流量红利已经消退,流量获取的难度和成本均已提升,从目前来看,百度信息流赖以依托的仍旧以百度APP为主,好看视频、百度新闻等应用与同类产品相比尚未显示出明显竞争优势。

为了最大程度转化流量价值,百度在今年推出了智能小程序,目前,最新版的百度APP已经上线了下拉进入小程序的入口。

事实上,类似的做法百度在几年前便有尝试,但此前直达号、轻应用等产品均未能取得理想效果。对此,沈抖的解释是,彼时很多开发者还没有意识到获客成本会这么高,因此时机不对,同时,当时的体验也没有做到现在这么好。

根据百度方面的介绍,百度的智能小程序最大特点是开放,代码开源,让所有合作伙伴可以在他们的自有APP上运行百度的小程序。

百度希望在用户使用百度想完成一个服务时,能够非常自然的进入到小程序中。然而一个依然回避不了的问题是:要让用户体验到百度智能小程序,大前提仍是提升用户使用百度APP的频率,而在移动应用已经如此丰富和发达的现在,百度APP是否还有成为超级入口的机会,充满疑问和挑战。

身肩重任的沈抖正试图为外界建立对百度APP的信心,在最近的一次采访中,他表示“巨型APP的出现在这个时代是成立的,尤其是小程序战略的顺序推进,使得我描述的愿景和目标更容易实现,将来大家可以真的生活在百度APP里面。”

入口问题对于百度并不是一个新问题,而百度在回归百度后,它似乎又一次站在了曾经的起跑线前。

冷知识阶段汇总(第1期)

生活

身份证前2位是省份,3到6位是区县(区县可能会有变更,所以你和你爸妈可能不一样),7-14位是出生年月日,15-16是发证派出所代号(你和你附近的人都是一样的),17是性别(奇男偶女),最后一位是用公式根据前17位计算的,计算结果是0-10,如果是10,就用x表示。

高铁没有E座,(按照国际通用排座方法)A和F是靠窗,C和D是过道,如果AC之间有座就是B,如果DF之间有座就是E。一排四座会没有B和E。

上行电梯扶手比电梯快,为了拉着你前倾,防止后仰摔倒。

(上条:国标要求扶手速度是电梯速度的100%~102%)

马路不是马走的路,因为全称是马卡丹路。

中国第一条马路在上海。

澳洲啤酒瓶是可以拧开的。

啤酒瓶盖有21个褶。

(根据实验)啤酒瓶盖最合理的是24个,能够有效密封并容易开启,但是他们发现24个褶容易卡住他们的机器,就改成了21个。

(上条:为什么不改进机器?)

mp3全称是 Moving Picture Experts Group Audio Layer 3,起初是一种文件格式的协议,并不是播放器。

美国整个20世纪消耗了44亿吨水泥,中国2011-2013三年消耗了66亿吨。

宫保鸡丁和宫爆鸡丁是两道不同的菜,宫保是人名。

蒙娜丽莎画像时24岁。

(根据联合国教科文组织的定义)一本现代意义上的图书最少要包含49页,不含封面封底。

玛丽莲梦露有11个脚趾。

Google 的意思是 googol,10的100次方。

央视天气预报背景音乐《渔舟唱晚》,从1984年开始使用。

北大校徽是鲁迅设计的,鲁迅还设计过国徽,印在某一版中华民国的大洋上。

鲁迅后期的月收入差不多要赶上蒋介石的工资了。

鹤顶红就是含有杂质呈红色的砒霜。

微信添加好友数量的上限是多少?不是5000个,而是一个特殊数字5040。这个数字有说法称是源自古希腊哲学家柏拉图的《理想国》,书中完美城邦人数正是5040人。

自然

玉米横截面的颗粒数是双数。

打喷嚏一定会闭上眼睛。

上海海拔最高的非人工地点只有100米。

(来自《梦溪笔谈》)鲤鱼有36片鳞,每片鳞边上都组成一个“十”字,36乘以10是360,古代360步为1里,所以这个鱼叫鲤鱼。

香芋和芋头没有关系。

青笋和芦笋没有关系,青笋就是莴苣,可以生吃。

日本豆腐是鸡蛋做的,和豆腐没关系。

人物

前总理李鹏女儿叫李小琳,前主席李先念女儿叫李小林,前作协主席巴金女儿叫李小林。

毛泽东的英文老师章含之,养父是民国教育部长章士钊,章士钊做过农大校长,章含之生父是皖军总司令陈调元的儿子,她是爸爸和交际花婚外孕生下的,章含之的丈夫是外交部长乔冠华,因支持四人帮文革后隔离审查,被习大大他爹习仲勋特赦。章含之和前夫有个女儿,女儿的其中一个前夫是陈凯歌。

陈凯歌曾是倪萍前男友,倪萍的初恋是郭达。

王刚(铁三角和珅)的前妻成方圆的妈妈徐琳琳初中最好的伙伴许燕吉的爸爸是《落花生》的作者许地山。

熊希龄(民国第一任总理,双清别墅以前的主人)的四弟的老婆的哥哥的女婿是沈从文。

熊希龄的七弟的老婆的姐姐的儿子是沈从文。

熊希龄的外甥的老婆的弟弟是沈从文。

熊希龄续弦朱氏的侄女朱濂嫁给了一个姓周的做妾,姓周的和原配有一个女儿,生了一个儿子易中天。

迪奥创始人迪奥是男同性恋,圣罗兰创始人伊夫圣罗兰曾是迪奥员工,也是男同性恋。

陈佩斯之所以叫佩斯,是因为他哥哥出生的时候他爸爸在布达佩斯演出,起名陈布达,他出生的时候就补上叫佩斯。

公元989年,范仲淹出生在河北正定一个叫做高平村的小村子里,950年后,这里发生了地道战。

东汉曹腾,家道中落,从小就被送到宫中做太监,陪皇太子读书。曹腾在宫中三十多年,侍四代天子,被升为正一品官。曹腾入宫后与一女吴氏结为“对食”夫妻,收养一子取名曹嵩。曹嵩155年7月18日生下长子曹操。

影视

《武林外传》当中,小郭服装最多,有18套。

历史

1865年,李鸿章在上海创办了江南制造局,诺基亚也诞生在这一年。

叶公好龙发生在河南叶县,属于春秋时期的楚国,主人公沈诸梁,姓芈,沈尹氏,被当今部分叶姓追为始祖。叶作为地名和姓氏在以前读 shè。

叶公好龙首次出现在刘向所著《新序》,刘向是刘邦亲弟弟的孙子的孙子。

每年六月初,各大网站和app可能无法更换头像,以及一些图片评论。

1966年提出废除高考的人是中信董事长,当时是北京四中学生,他的弟弟是中国航空总经理,他爸爸是海关总署署长,他爸和邓小平同一天结婚。

唐代以前的皇帝一般叫什么帝,比如汉武帝、魏孝文帝、隋炀帝。唐朝开始一般叫什么祖什么宗,比如宋徽宗、明成祖。什么帝是谥号,什么宗什么祖是庙号,唐以后之所以不叫谥号,是因为皇帝死后后人给他拍得马屁太多谥号太长了,不好记。比如明太祖朱元璋谥号是钦明启运峻德成功统天大孝高皇帝。

地理

景德镇名字来源于年号,景德元年这里出的瓷器被宋真宗赏识。

美国的名字America来自于意大利商人Amerigo,哥伦布发现新大陆以为是亚洲,Amerigo命名了新大陆。

法国国旗的图案是红、白、蓝三色条纹,最初设计时,国旗上的三条色带宽度完全相等,但是,当制成的国旗升到空中后,人们总觉得这三种颜色在国旗上所占的分量不相等,似乎白色的面积最大,蓝色的最小。为此,设计者们专门招集色彩专家进行分析,才发现这与色彩的膨胀感和收缩感有关。当把这三色的真实面积比例调整为蓝:白:红=30:33:37时,看上去反而相等了。

朝鲜和挪威之间只隔了一个国家俄罗斯。

语言

寿司是音译,刺身是训读汉字。

以前人吃生鱼片,因为去了皮就不认识是什么鱼了,所以用竹签带一块鱼皮在身上。

宋体字诞生在明朝,据说因为常常翻刻宋本得名。并在明朝传入日本,所以在日本称为明体。

牛轧糖,音译自 Nougat。

荷兰豆在中国叫“荷兰豆”,在荷兰叫“中国豆”,原因大概是在荷兰控制海上霸权的时代,荷兰人从东南亚带到了中国,后来中国大量种植并改进影响到了西方的叫法。

北京方言“嗝儿屁”意思是说一个人死了,是德语舶来词,原词krepieren。

蛤蜊,在山东和东北读作“gá la”是因为日殖时期的日语カラ(ke la)残留,而日语读音是来源于英文clam。

文化

为什么唐僧的白龙马是一匹白马?白马在佛教里面是重要的符号,传说东汉时期就是白马把佛经和佛像驼入洛阳建了白马寺,成为佛教进入中国的标志。另外据说佛祖释迦牟尼的坐骑也是一匹白马。更重要的是,以上都不重要,唐僧原型玄奘取经时骑的就是白马,作者沿用事实而已。

寡人,即为寡德之人,意为“在道德方面做得不足的人”。是古代君主、诸侯王对自己的谦称。中国古代讲究“以德治国”,“以德配天”,就是说君主、诸侯王的权位是上天赋予的,但上天只会把天下给有德的人,君主、诸侯王如果失德就会失去尊贵的权位,所以君主、诸侯王就谦称自己是“寡人”。

1997年修订的刑法将「流氓罪」删除了;最后一名流氓罪罪犯将于2020年重获自由。

多米诺骨牌是由意大利传教士多米诺把中国牌九带回去之后发展来的

其他

人在沟通的时候最关注的是面部表情,因为大家希望对方通过面部表情将内心情绪表达出来以便于理解。在东方传统审美当中,会觉得脸大的形象更易于亲近。所以葫芦娃脑袋很大,蛇精就是小脸。年画里的财神观音娃娃,都是肥头大耳的。

便利店711的英文是SEVEn-ELEVEn,并非全部大写。
image

欢迎关注

image

JavaSript模块规范:AMD规范与CMD规范介绍

JavaSript模块化

在了解AMD,CMD规范前,还是需要先来简单地了解下什么是模块化,模块化开发?

模块化是指在解决某一个复杂问题或者一系列的杂糅问题时,依照一种分类的思维把问题进行系统性的分解以之处理。模块化是一种处理复杂系统分解为代码结构更合理,可维护性更高的可管理的模块的方式。可以想象一个巨大的系统代码,被整合优化分割成逻辑性很强的模块时,对于软件是一种何等意义的存在。对于软件行业来说:解耦软件系统的复杂性,使得不管多么大的系统,也可以将管理,开发,维护变得“有理可循”。

还有一些对于模块化一些专业的定义为:模块化是软件系统的属性,这个系统被分解为一组高内聚,低耦合的模块。那么在理想状态下我们只需要完成自己部分的核心业务逻辑代码,其他方面的依赖可以通过直接加载被人已经写好模块进行使用即可。

首先,既然是模块化设计,那么作为一个模块化系统所必须的能力:

  1. 定义封装的模块。
  2. 定义新模块对其他模块的依赖。
  3. 可对其他模块的引入支持。

好了,思想有了,那么总要有点什么来建立一个模块化的规范制度吧,不然各式各样的模块加载方式只会将局搅得更为混乱。那么在JavaScript中出现了一些非传统模块开发方式的规范 CommonJS的模块规范,AMD(Asynchronous Module Definition),CMD(Common Module Definition)等。

AMD 与 RequireJS

AMD

Asynchronous Module Definition,用白话文讲就是异步模块定义,对于 JSer 来说,异步是再也熟悉不过的词了,所有的模块将被异步加载,模块加载不影响后面语句运行。所有依赖某些模块的语句均放置在回调函数中。

AMD规范定义了一个自由变量或者说是全局变量 define 的函数。

define( id?, dependencies?, factory );

第一个参数 id 为字符串类型,表示了模块标识,为可选参数。若不存在则模块标识应该默认定义为在加载器中被请求脚本的标识。如果存在,那么模块标识必须为顶层的或者一个绝对的标识。

第二个参数,dependencies ,是一个当前模块依赖的,已被模块定义的模块标识的数组字面量。

第三个参数,factory,是一个需要进行实例化的函数或者一个对象。

创建模块标识为 alpha 的模块,依赖于 require, export,和标识为 beta 的模块

define("alpha", [ "require", "exports", "beta" ], function( require, exports, beta ){
    export.verb = function(){
        return beta.verb();
        // or:
        return require("beta").verb();
    }
});

一个返回对象字面量的异步模块

define(["alpha"], function( alpha ){
    return {
        verb : function(){
            return alpha.verb() + 1 ;
        }
    }
});

无依赖模块可以直接使用对象字面量来定义

define( {
    add : function( x, y ){
        return x + y ;
    }
});

类似与 CommonJS 方式定义

define( function( require, exports, module){
    var a = require('a'),
          b = require('b');

    exports.action = function(){};
});

require();

在 AMD 规范中的 require 函数与一般的 CommonJS中的 require 不同。由于动态检测依赖关系使加载异步,对于基于回调的 require 需求强烈。

局部 与 全局 的require

局部的 require 需要在AMD模式中的 define 工厂函数中传入 require。

define( ['require'], function( require ){
  // ...
});

or:

define( function( require, exports, module ){
  // ...
});

局部的 require 需要其他特定的 API 来实现。

全局的 require 函数是唯一全局作用域下的变量,像 define一样。全局的 require 并不是规范要求的,但是如果实现全局的 require函数,那么其需要具有与局部 require 函数 一样的以下的限定:

  1. 模块标识视为绝对的,而不是相对的对应另一个模块标识。
  2. 只有在异步情况下,require的回调方式才被用来作为交互操作使用。因为他不可能在同步的情况下通过 require(String) 从顶层加载模块。

依赖相关的API会开始模块加载。如果需要有互操作的多个加载器,那么全局的 reqiure 应该被加载顶层模块来代替。

require(String)
define( function( require ){
    var a = require('a'); // 加载模块a
});

require(Array, Function)
define( function( require ){
    require( ['a', 'b'], function( a,b ){ // 加载模块a b 使用
        // 依赖 a b 模块的运行代码
    }); 
});

require.toUrl( Url )
define( function( require ){
    var temp = require.toUrl('./temp/a.html'); // 加载页面
});

RequireJS

RequireJS 是一个前端的模块化管理的工具库,遵循AMD规范,它的作者就是AMD规范的创始人 James Burke。所以说RequireJS是对AMD规范的阐述一点也不为过。

RequireJS 的基本思想为:通过一个函数来将所有所需要的或者说所依赖的模块实现装载进来,然后返回一个新的函数(模块),我们所有的关于新模块的业务代码都在这个函数内部操作,其内部也可无限制的使用已经加载进来的以来的模块。

<script data-main='scripts/main' src='scripts/require.js'></script>

那么scripts下的main.js则是指定的主代码脚本文件,所有的依赖模块代码文件都将从该文件开始异步加载进入执行。

defined用于定义模块,RequireJS要求每个模块均放在独立的文件之中。按照是否有依赖其他模块的情况分为独立模块和非独立模块。

  1. 独立模块,不依赖其他模块。直接定义:
define({
    method1: function(){},
    method2: function(){}
});

也等价于

define(function(){
    return{
        method1: function(){},
        method2: function(){}
    }
});
  1. 非独立模块,对其他模块有依赖。
define([ 'module1', 'module2' ], function(m1, m2){
    ...
});

或者:

define( function( require ){
    var m1 = require( 'module1' ),
          m2 = require( 'module2' );
    ...
});

简单看了一下RequireJS的实现方式,其 require 实现只不过是将 function 字符串然后提取 require 之后的模块名,将其放入依赖关系之中。

require 方法调用模块

在require进行调用模块时,其参数与define类似。

require( ['foo', 'bar'], function( foo, bar ){
    foo.func();
    bar.func();
});

在加载 foo 与 bar 两个模块之后执行回调函数实现具体过程。

当然还可以如之前的例子中的,在define定义模块内部进行require调用模块

define( function( require ){
    var m1 = require( 'module1' ),
          m2 = require( 'module2' );
    ...
});

define 和 require 这两个定义模块,调用模块的方法合称为AMD模式,定义模块清晰,不会污染全局变量,清楚的显示依赖关系。AMD模式可以用于浏览器环境并且允许非同步加载模块,也可以按需动态加载模块。

CMD 与 seaJS

CMD

在CMD中,一个模块就是一个文件,格式为:

define( factory );

全局函数define,用来定义模块。

参数 factory 可以是一个函数,也可以为对象或者字符串。

当 factory 为对象、字符串时,表示模块的接口就是该对象、字符串。

定义JSON数据模块:

define({ "foo": "bar" });

通过字符串定义模板模块:

define('this is {{data}}.');

factory 为函数的时候,表示模块的构造方法,执行构造方法便可以得到模块向外提供的接口。

define( function(require, exports, module) { 
    // 模块代码
});

define( id?, deps?, factory );

define也可以接受两个以上的参数,字符串id为模块标识,数组deps为模块依赖:

define( 'module', ['module1', 'module2'], function( require, exports, module ){
    // 模块代码
});

其与 AMD 规范用法不同。

require 是 factory 的第一个参数。

require( id );

接受模块标识作为唯一的参数,用来获取其他模块提供的接口:

define(function( require, exports ){
    var a = require('./a');
    a.doSomething();
});

require.async( id, callback? );

require是同步往下执行的,需要的异步加载模块可以使用 require.async 来进行加载:

define( function(require, exports, module) { 
    require.async('.a', function(a){
        a.doSomething();
    });
});

require.resolve( id )

可以使用模块内部的路径机制来返回模块路径,不会加载模块。

exports 是 factory 的第二个参数,用来向外提供模块接口。

define(function( require, exports ){
    exports.foo = 'bar'; // 向外提供的属性
    exports.do = function(){}; // 向外提供的方法
});

当然也可以使用 return 直接向外提供接口。

define(function( require, exports ){
    return{
        foo : 'bar', // 向外提供的属性
        do : function(){} // 向外提供的方法
    }
});

也可以简化为直接对象字面量的形式:

define({
    foo : 'bar', // 向外提供的属性
    do : function(){} // 向外提供的方法
});
```js

与nodeJS中一样需要注意的是,一下方式是错误的:

```js
define(function( require, exports ){
    exports = {
        foo : 'bar', // 向外提供的属性
        do : function(){} // 向外提供的方法
    }
});

需要这么做

define(function( require, exports, module ){
    module.exports = {
        foo : 'bar', // 向外提供的属性
        do : function(){} // 向外提供的方法
    }
});

传入的对象引用可以添加属性,一旦赋值一个新的对象,那么值钱传递进来的对象引用就会失效了。开始之初,exports 是作为 module.exports 的一个引用存在,一切行为只有在这个引用上 factory 才得以正常运行,赋值新的对象后就会断开引用,exports就只是一个新的对象引用,对于factory来说毫无意义,就会出错。

module 是factory的第三个参数,为一个对象,上面存储了一些与当前模块相关联的属性与方法。
– module.id 为模块的唯一标识。
– module.uri 根据模块系统的路径解析规则得到模块的绝对路径。
– module.dependencies 表示模块的依赖。
– module.exports 当前模块对外提供的接口。

seaJS

sea.js 核心特征:

  1. 遵循CMD规范,与NodeJS般的书写模块代码。
  2. 依赖自动加载,配置清晰简洁。

兼容 Chrome 3+,Firefox 2+,Safari 3.2+,Opera 10+,IE 5.5+。

seajs.use

用来在页面中加载一个或者多个模块

// 加载一个模块 
seajs.use('./a');
// 加载模块,加载完成时执行回调
seajs.use('./a',function(a){
    a.doSomething();
});
// 加载多个模块执行回调
seajs.use(['./a','./b'],function(a , b){
    a.doSomething();
    b.doSomething();
});

其define 与 require 使用方式基本就是CMD规范中的示例。

AMD 与 CMD 区别到底在哪里?

看了以上 AMD,requireJS 与 CMD, seaJS的简单介绍会有点感觉模糊,总感觉较为相似。因为像 requireJS 其并不是只是纯粹的AMD固有思想,其也是有CMD规范的思想,只不过是推荐 AMD规范方式而已, seaJS也是一样。

下面是玉伯对于 AMD 与 CMD 区别的解释:

AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。

CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。

类似的还有 CommonJS Modules/2.0 规范,是 BravoJS 在推广过程中对模块定义的规范化产出还有不少??

这些规范的目的都是为了 JavaScript 的模块化开发,特别是在浏览器端的。

目前这些规范的实现都能达成浏览器端模块化开发的目的。

区别:

  1. 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。CMD 推崇 as lazy as possible.
  2. CMD 推崇依赖就近,AMD 推崇依赖前置。看代码:
// CMD
define(function(require, exports, module) {
    var a = require('./a')
    a.doSomething()
    // 此处略去 100 行
    var b = require('./b') // 依赖可以就近书写
    b.doSomething()
    // ...
})

// AMD 默认推荐的是
define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好
    a.doSomething()
    // 此处略去 100 行
    b.doSomething()
    // ...
})

虽然 AMD 也支持 CMD 的写法,同时还支持将 require 作为依赖项传递,但 RequireJS 的作者默认是最喜欢上面的写法,也是官方文档里默认的模块定义写法。

  1. AMD 的 API 默认是一个当多个用,CMD 的 API 严格区分,推崇职责单一。比如 AMD 里,require 分全局 require 和局部 require,都叫 require。CMD 里,没有全局 require,而是根据模块系统的完备性,提供 seajs.use 来实现模块系统的加载启动。CMD 里,每个 API 都简单纯粹。

  2. 还有一些细节差异,具体看这个规范的定义就好,就不多说了。
    另外,SeaJS 和 RequireJS 的差异,可以参考:https://github.com/seajs/seajs/issues/277

总结

本文主要是介绍了一下 AMD CMD的规范,顺便简单的讲述了一下 requireJS 与 seaJS。讲的较为笼统,下面的扩展阅读可以更好的帮助你理解模块化以及各个规范。

扩展阅读

原文链接:JavaSript模块规范 – AMD规范与CMD规范介绍

JavaScript的api设计原则

前言

本篇博文来自一次公司内部的前端分享,从多个方面讨论了在设计接口时遵循的原则,总共包含了七个大块。系卤煮自己总结的一些经验和教训。本篇博文同时也参考了其他一些文章,相关地址会在后面贴出来。很难做到详尽充实,如果有好的建议或者不对的地方,还望不吝赐教斧正。

一 接口的流畅性

好的接口是流畅易懂的,他主要体现如下几个方面:

1 简单

操作某个元素的css属性,下面是原生的方法:

document.querySelector('#id').style.color = 'red';

封装之后

function a(selector, color) {
  document.querySelector(selector).style.color = color
}
a('#a', 'red');

从几十个字母长长的一行到简简单单的一个函数调用,体现了api设计原则之一:简单易用。

2 可阅读性

a(‘#a’, ‘red’)是个好函数,帮助我们简单实用地改变某个元素,但问题来了,如果第一次使用该函数的人来说会比较困惑,a函数是啥函数,没有人告诉他。开发接口有必要知道一点,大多数人都是懒惰的(包括卤煮自己),从颜色赋值这个函数来说,虽然少写了代码,但是增加了单词字母的个数,使得它不再好记。每次做这件事情的时候都需要有映射关系: a—->color. 如果是简单的几个api倒是无所谓,但是通常一套框架都有几十甚至上百的api,映射成本增加会使得程序员哥哥崩溃。 我们需要的就是使得接口名称有意义,下面我们改写一下a函数:

function letSomeElementChangeColor(selector, color) {
  document.querySelectorAll(selector, color).style.color = color; }

letSomeElementChangeColor相对于a来说被赋予了现实语言上的意义,任何人都不需要看说明也能知道它的功能。

3 减少记忆成本

我们刚刚的函数太长了,letSomeElementChangeColor虽然减少了映射成本,有了语言上的意义,但是毫无疑问增加了记忆成本。要知道,包括学霸在内,任何人都不喜欢背单词。不仅仅在此处,原生获取dom的api也同样有这个问题: document.getElementsByClassName; document.getElementsByName; document.querySelectorAll;这些api给人的感觉就是单词太长了,虽然他给出的意义是很清晰,然而这种做法是建立在牺牲简易性和简忆性的基础上进行的。于是我们又再次改写这个之前函数

function setColor(selector, color) {
 xxxxxxxxxxxx
}

在语言意义不做大的变化前提下,缩减函数名称。使得它易读易记易用。

4 可延伸

所谓延伸就是指函数的使用像流水一样按照书写的顺序执行形成执行链条:

document.getElementById('id').style.color = 'red';
document.getElementById('id').style.fontSize = '12px';
document.getElementById('id').style.backgourdColor = 'pink';

如果我们需要实现像以上有强关联性的业务时,用我们之前的之前的方法是再次封装两个函数 setFontSize, setbackgroundColor; 然后执行它们 setColor(‘id’, ‘red’);setFontSiez(‘id’, ’12px’); setbackgroundColor(‘id’, ‘pink’); 显然,这样的做法没有懒出境界来;id元素每次都需要重新获取,影响性能,失败;每次都需要添加新的方法,失败; 每次还要调用这些方法,还是失败。下面我们将其改写为可以延伸的函数 首先将获取id方法封装成对象,然后再对象的每个方法中返回这个对象:

function getElement(selector) {
  this.style = document.querySelecotrAll(selector).style;
}

getElement.prototype.color = function(color) {
  this.style.color = color;
  return this;
}
getElement.prototype.background = function(bg) {
  this.style.backgroundColor = bg;
  return this;
}
getElement.prototype.fontSize = function(size) {
  this.style.fontSize = size;
  return this;
}
//调用
var el = new getElement('#id')
el.color('red').background('pink').fontSize('12px');

简单、流畅、易读,它们看起来就像行云流水一样,即在代码性能上得到了提升优化,又在视觉上悦目。后面我们会在参数里面讲到如何继续优化。

所以,大家都比较喜欢用jquery的api,虽然一个$符号并不代表任何现实意义,但简单的符号有利于我们的使用。它体现了以上的多种原则,简单,易读,易记,链式写法,多参处理。

nightmare:

document.getElementById('id').style.color = 'red';
document.getElementById('id').style.fontSize = '12px';
document.getElementById('id').style.backgourdColor = 'pink';

dream:

$('id').css({color:'red', fontSize:'12px', backgroundColor:'pink'})

二 一致性

1 接口的一致性

相关的接口保持一致的风格,一整套 API 如果传递一种熟悉和舒适的感觉,会大大减轻开发者对新工具的适应性。 命名这点事:既要短,又要自描述,最重要的是保持一致性 “在计算机科学界只有两件头疼的事:缓存失效和命名问题” — Phil Karlton 选择一个你喜欢的措辞,然后持续使用。选择一种风格,然后保持这种风格。

Nightmare:

setColor,
letBackGround
changefontSize
makedisplay

dream:

setColor;
setBackground;
setFontSize
set.........

尽量地保持代码风格和命名风格,使别人读你的代码像是阅读同一个人写的文章一样。

三 参数的处理

1 参数的类型

判断参数的类型为你的程序提供稳定的保障

//我们规定,color接受字符串类型
function setColor(color) {
  if(typeof color !== 'string') return;
dosomething
}

2 使用json方式传参

使用json的方式传值很多好处,它可以给参数命名,可以忽略参数的具体位置,可以给参数默认值等等 比如下面这种糟糕的情况:

function fn(param1, param2...............paramN)

你必须对应地把每一个参数按照顺序传入,否则你的方法就会偏离你预期去执行,正确的方法是下面的做法。

function fn(json) {
//为必须的参数设置默认值
   var default = extend({
    param: 'default',
    param1: 'default'
    ......
   },json)
}

这段函数代码,即便你不传任何参数进来,他也会预期运行。因为在声明的时候,你会根据具体的业务预先决定参数的缺省值。

四 可扩展性

软件设计最重要的原则之一:永远不修改接口,而是去扩展它!可扩展性同时会要求接口的职责单一,多职责的接口很难扩展。 举个栗子:

//需要同时改变某个元素的字体和背景
// Nightmare:
function set(selector, color) {
  document.querySelectroAll(selector).style.color = color;
  document.querySelectroAll(selector).style.backgroundColor = color;
}

//无法扩展改函数,如果需要再次改变字体的大小的话,只能修改此函数,在函数后面填加改变字体大小的代码

//Dream
function set(selector, color) {
  var el = document.querySelectroAll(selector);
  el.style.color = color;
  el.style.backgroundColor = color;
  return el;
}

//需要设置字体、背景颜色和大小
function setAgain (selector, color, px) {
  var el = set(selector, color)
  el.style.fontSize = px;
  return el;
}

以上只是简单的添加颜色,业务复杂而代码又不是你写的时候,你就必须去阅读之前的代码再修改它,显然是不符合开放-封闭原则的。修改后的function是返回了元素对象,使得下次需要改变时再次得到返回值做处理。

2 this的运用

可扩展性还包括对this的以及call和apply方法的灵活运用:

function sayBonjour() {
  alert(this.a)
}

obj.a = 1;
obj.say = sayBonjour;
obj.say();//1
//or
sayBonjour.call||apply(obj);//1

五 对错误的处理

1 预见错误

可以用 类型检测 typeof 或者try…catch。 typeof 会强制检测对象不抛出错误,对于未定义的变量尤其有用。

2 抛出错误

大多数开发者不希望出错了还需要自己去找带对应得代码,最好方式是直接在console中输出,告诉用户发生了什么事情。我们可以用到浏览器为我们提供的api输出这些信息:console.log/warn/error。你还可以为自己的程序留些后路: try…catch。

function error (a) {
  if(typeof a !== 'string') {
    console.error('param a must be type of string')
  }
}

function error() {
  try {
    // some code excucete here maybe throw wrong
  }catch(ex) {
    console.wran(ex);
  }
}

六 可预见性

可预见性味程序接口提供健壮性,为保证你的代码顺利执行,必须为它考虑到非正常预期的情况。我们看下不可以预见的代码和可预见的代码的区别用之前的setColor

//nighware
function set(selector, color) {
  document.getElementById(selector).style.color = color;
}

//dream
zepto.init = function(selector, context) {
  var dom
  // If nothing given, return an empty Zepto collection
  if (!selector) return zepto.Z()
  // Optimize for string selectors
  else if (typeof selector == 'string') {
    selector = selector.trim()
    // If it's a html fragment, create nodes from it
    // Note: In both Chrome 21 and Firefox 15, DOM error 12
    // is thrown if the fragment doesn't begin with <
    if (selector[0] == '<' && fragmentRE.test(selector))
      dom = zepto.fragment(selector, RegExp.$1, context), selector = null
    // If there's a context, create a collection on that context first, and select
    // nodes from there
    else if (context !== undefined) return $(context).find(selector)
    // If it's a CSS selector, use it to select nodes.
    else dom = zepto.qsa(document, selector)
  }
  // If a function is given, call it when the DOM is ready
  else if (isFunction(selector)) return $(document).ready(selector)
  // If a Zepto collection is given, just return it
  else if (zepto.isZ(selector)) return selector
  else {
    // normalize array if an array of nodes is given
    if (isArray(selector)) dom = compact(selector)
    // Wrap DOM nodes.
    else if (isObject(selector))
      dom = [selector], selector = null
    // If it's a html fragment, create nodes from it
    else if (fragmentRE.test(selector))
      dom = zepto.fragment(selector.trim(), RegExp.$1, context), selector = null
    // If there's a context, create a collection on that context first, and select
    // nodes from there
    else if (context !== undefined) return $(context).find(selector)
    // And last but no least, if it's a CSS selector, use it to select nodes.
    else dom = zepto.qsa(document, selector)
  }
  // create a new Zepto collection from the nodes found
  return zepto.Z(dom, selector)
}

以上是zepto的源码,可以看见,作者在预见传入的参数时做了很多的处理。其实可预见性是为程序提供了若干的入口,无非是一些逻辑判断而已。zepto在这里使用了很多的是非判断,这样做的好处当然是代码比之前更健壮,但同时导致了代码的冗长,不适合阅读。总之,可预见性真正需要你做的事多写一些对位置实物的参数。把外部的检测改为内部检测。是的使用的人用起来舒心放心开心。呐!做人嘛最重要的就是海森啦。

七 注释和文档的可读性

一个最好的接口是不需要文档我们也会使用它,但是往往接口量一多和业务增加,接口使用起来也会有些费劲。所以接口文档和注释是需要认真书写的。注释遵循简单扼要地原则,给多年后的自己也给后来者看:

//注释接口,为了演示PPT用
function commentary() {
  //如果你定义一个没有字面意义的变量时,最好为它写上注释:a:没用的变量,可以删除
  var a;

  //在关键和有歧义的地方写上注释,犹如画龙点睛:路由到hash界面后将所有的数据清空结束函数
  return go.Navigate('hash', function(){
    data.clear();
  });
}

最后

推荐markdown语法书写API文档,github御用文档编写语法。简单、快速,代码高亮、话不多说上图

卤煮在此也推荐几个在线编辑的网站。诸君可自行前往练习使用。

https://www.zybuluo.com/mdeditor

http://mahua.jser.me/

参考博文:JavaScript API 设计原则

原文链接:javascript的api设计原则

VSCODE插件推荐

本文从一款前端开发编辑器的基本需求出发,推荐在VSCODE使用过程中让人愉悦的一些插件。

本文目录


  • 代码补全
  • 运行调试
  • 代码同步
  • 生产化
  • 效率
  • 编辑器主题

前言

如何在VSCODE中安装插件
  1. Ctrl + Shift + P 或者点击左侧快捷图标打开扩展(Extentions)。
  2. 选择 “Extensions: Install Extensions”。
  3. 在左侧搜索需要的插件安装即可。
多设备

你需要用 Settings Sync 这个插件在不同的设备同步你的
VSCODE 设置和插件。

1 代码补全

HTML Boilerplate

通过使用 HTML 模版插件,你就摆脱了为 HTML 新文件重新编写头部和正文标签的苦恼。你只需在空文件中输入 html,并按 Tab 键,即可生成干净的文档结构。
image

HTML Snippets

超级实用且初级的 H5代码片段以及提示
image

HTML CSS Support

让 html 标签上写class 智能提示当前项目所支持的样式
新版已经支持scss文件检索
image

Path Intellisense

自动路劲补全,默认不带这个功能的,赶紧装
image

2 运行调试

Open In Browser

由于 VSCode 没有提供直接在浏览器中打开文件的内置界面,所以此插件在快捷菜单中添加了在默认浏览器查看文件选项,以及在客户端(Firefox,Chrome,IE)中打开命令面板选项。
image

Quokka.js

Quokka 是一个调试工具插件,能够根据你正在编写的代码提供实时反馈。它易于配置,并能够预览变量的函数和计算值结果。另外,在使用 JSX 或 TypeScript 项目中,它能够开箱即用。
image

Regex Previewer

实时测试正则表达式。
image

Debugger for Chrome

让 vscode 映射 chrome 的 debug功能,静态页面都可以用 vscode 来打断点调试。

jQuery Code Snippets

jquery 重度患者必须品,废话不多说,上图
image

3 代码同步

Git

VSCODE 自带了git功能,非常方便。

FTP

4 生产化

Prettier – Code formatter

Prettier 是目前 Web 开发中最受欢迎的代码格式化程序。安装了这个插件,它就能够自动应用 Prettier,并将整个 JS 和 CSS 文档快速格式化为统一的代码样式。如果你还想使用 ESLint,那么还有个 Prettier – Eslint 插件,你可不要错过咯!
image

minify

压缩合并 JavaScript 和 CSS 文件。
image

5 效率

vscode-faker

Faker 是一个流行的 JavaScript 库,能够帮你快速的插入用例数据。Faker 可以随机生成姓名、地址、图像、电话号码,或者经典的乱数假文段落,并且每个类别还包含了各种子类别,你可以根据自身的需求来使用这些数据。
image

CSS Peek

使用此插件,你可以追踪至样式表中 CSS 类和 ids 定义的地方。当你在 HTML 文件中右键单击选择器时,选择“ Go to Definition 和 Peek definition ”选项,它便会给你发送样式设置的 CSS 代码。
image

Color Info

鼠标悬停在 CSS 的颜色值上,就可以预览颜色以及 HEX、RGB、HSL、CMYK等信息。
image

SVG Viewer

支持在编辑器直接打开 SVG 文件。
image

TODO Highlight

在注释里面写关键字,就能够更方便的查看注释,还可以自定义样式。
image

change-case

快速按照一定规则修改文本。
image

Beautify

格式化代码的工具

6 编辑器主题(Themes)

vscode-icons

让 vscode 资源树目录加上图标,必备良品!
image

Icon Fonts

这是一个能够在项目中添加图标字体的插件。该插件支持超过 20 个热门的图标集,包括了 Font Awesome、Ionicons、Glyphicons 和 Material Design Icons。
image

Material Icon Theme
Monokai++

用 Sublime Text 的时候就习惯了这个主题

Material

冷门、好看、实用。此主题已停更许久
image

Dracula

目前我觉得是vscode上最漂亮的主题,vscode 1.11+允许自定义statusBar等全局ui后,该主题也跟进改了很多小细节,良心!~
image

One Dark Pro

源于Atom,老版本的Atom One Dark主题可以扔了.
image

Bimbo

image

7 其他

npm

运行npm命令

Npm Intellisense

require 时的包提示(最新版的vscode已经集成此功能)
image

Document this

js 的注释模板 (注意:新版的vscode已经原生支持,在function上输入/** tab)
image

ESlint

ESlint 接管原生 js 提示,可以自定制提示规则。这个比较高玩,不会的就算了,
详情配置

HTMLHint

html代码检测
image

Project Manager

在多个项目之前快速切换的工具

Bootstrap 3 Sinnpet

常用 bootstrap 的可以下

Atuo Rename Tag

修改 html 标签,自动帮你完成尾部闭合标签的同步修改,不过有些bug。
image

GitLens

丰富的git日志插件
image

fileheader

顶部注释模板,可定义作者、时间等信息,并会自动更新最后修改时间
image

filesize

在底部状态栏显示当前文件大小,点击后还可以看到详细创建、修改时间
image

Bracket Pair Colorizer

让括号拥有独立的颜色,易于区分。可以配合任意主题使用。
image

vetur

语法高亮、智能感知、Emmet等
image

VueHelper

vue代码提示插件,包括了vue2所有api,vue-router2和vuex2的代码提示

// 首选项-设置-用户设置配置: 
// 小程序语法高亮: 
"files.associations": { 
"*.vue": "vue", 
"*.wpy": "vue", 
"*.wxml": "html", 
"*.wxss": "css" 
}

// 个人习惯配置: 
"editor.lineHeight": 26, // 行高 
"editor.fontSize": 16, // 字体 
"editor.wordWrap": "on" // 自动换行 
"editor.formatOnSave": true // 保存自动格式化代码

image

Import Cost

引入包大小计算,对于项目打包后体积掌握很有帮助
image

Auto Close Tag — 自动闭合HTML标签

Auto Rename Tag

修改HTML标签时,自动修改匹配的标签

background

背景

Beautify css/sass/scss/less

代码高亮

Easy Sass

scss/sass文件保存可自动生成并同步编译成同名css文件

Easy WXLESS

微信小程序WXSS文件专用,保存可自动生成并同步编译成同名css文件

File Peek

鼠标移到路径名按住ctrl可打开文件

Git History

git log

GitLens

显示文件最近的commit和作者,显示当前行commit信息

HTML Class Suggestions

类名命名提示

Indenticator

缩进高亮

IntelliSense for CSS class names

CSS类名智能命名提示

JavaScript (ES6) code snippets

JS语法提示

JavaScript Snippet Pack — 代码片段(Tab或者Enter补全),Console命令,DOM

文档对象模型,Loop,Function,Timer,NodeJS,BDD,Misc

Live Server

http服务器(相当于使用nodejs的http-server,首选项-设置-用户设置可配置更改端口:”liveServer.settings.port”: 8999)

Output Colorizer

彩色输出信息

px2rem

px值转rem

stylelint

CSS/SCSS/LESS检查工具

// 首选项-设置-用户设置配置: 
"stylelint.enable": true, 
"css.validate": false, 
"scss.validate": false 
Vetur

Vue语法高亮

VSCode Great Icons

文件图标(首选项-文件图标主题修改)

VSCode-Element-Helper

elementUI语法提示高亮

vue

Vue语法高亮(

// 首选项-设置-用户设置配置: 
"emmet.syntaxProfiles": { 
  "vue-html": "html", 
  "vue": "html" 
}
Vue 2 Snippets

基于最新的 Vue 官方语法高亮文件添加了语法高亮,并且依据 Vue 2 的 API 添加了代码补全

Vue Peek

查找vue组件文件

下载和安装WebP格式转换工具

本系列文章由 Mukti 翻译自 Google WebP 官方网站
原文链接:https://developers.google.com/speed/webp/download
中文链接:https://feizhaojun.com/?p=1945

所有版本的下载包可以在谷歌的下载仓库中找到,其中包括:

已编译的WebP工具和库(适用于Linux、Windows 和 Mac OS X),包括

  • libwebp 库,可以用于在你的程序中添加WebP编码和解码。

  • cwebp — WebP 编码工具

  • dwebp — WebP 解码工具

  • vwebp — WebP 文件查看器

  • webpmux — WebP 复合工具

  • gif2webp — 将 GIF 图像转换为 WebP 的工具

安装说明 | Windows 下载 | Linux 下载 | Mac OS X 下载

已编译 WebP 框架(适用于 iOS)。构建细节请见 README。

下载

WebP 库和工具的源码。如果已编译的文件不符合你的需求,你可以使用源码自己编译。

安装说明 | 下载 | 最新版源码

除非有特殊说明, 本页内容遵从 CC BY 3.0 许可,代码示例遵从 Apache 2.0 许可,更多细节请查看 Google 网站政策
Google 官方原文更新日期:2016-04-26

webp:一种新的网络图片格式

本系列文章由 Mukti 翻译自 Google WebP 官方网站
原文链接:https://developers.google.com/speed/webp/
中文链接:https://feizhaojun.com/?p=1924

本文目录



WebP是一种现代 图像格式,可以为网络上的图像提供高品质的 无损和有损 压缩。网站管理员和开发人员可以使用WebP创建更小、更丰富的图片来提高网站的速度。

与PNG格式的图片相比,WebP格式的无损图像在体积上缩小了26%。在同样的SSIM图像质量指标下,WebP格式的有损图像比JPEG图像小了25-34%

无损的WebP支持透明度(也叫alpha通道),只需要额外22%的字节。如果能接受有损RGB压缩,有损的WebP也支持透明度,文件大小通常比PNG小3倍。

提供给网站管理员的更多信息

WebP的工作原理

有损WebP压缩使用预测编码对图像进行编码,与VP8视频编解码器用于压缩视频中的关键帧的方法相同。预测编码使用相邻像素块中的值来预测块中的值,然后仅对差异进行编码。

无损WebP压缩使用图片的已知部分来精确地重建新像素。如果没有找到目标匹配,它也可以使用本地调色板。

WebP 压缩技术详解

WebP文件由 VP8VP8L 图像数据和基于RIFF 的容器组成。独立的libwebp库提供了一个 WebP 的参考实例,可以到 git 仓库tarball 获取。

WebP支持

Chrome 和 Opera 以及许多其他的工具和软件库对 WebP 提供了原生支持。WebP 开发人员还增加了对各种图像编辑工具的支持。

WebP包括轻量级编码和解码库libwebp 以及命令行工具cwebp,dwebp用于将图像转换为WebP格式以及从WebP格式转换图像,以及用于查看,复用和动画WebP图像的工具。完整的源代码可在 下载页面上找到。

WebP 包括轻量级编码和解码库libwebp和命令行工具cwebpdwebp,用来将图片转成 WebP 格式以及从 WebP格式转成普通图片,同样也有查看、合成 WebP 图片以及创建 WebP 动画的工具。完整的源码可以在下载页找到。

WebP转换工具下载

下载 Linux, Windows or Mac OS X 系统下已编译的cwebp转换工具,将你喜欢的图片从 JPEG 和 PNG 转成 WebP。

Google 的 WebP 项目提供了一个讨论区,你可以去发表意见。

除非有特殊说明, 本页内容遵从 CC BY 3.0 许可,代码示例遵从 Apache 2.0 许可,更多细节请查看 Google 网站政策

Google 官方原文更新日期:2016-03-04

突破百度网盘下载限制

百度网盘下载速度被限制,最高都不到200KB/s,如果你想下载的快一点,就要开通超级会员(30元/月,不差钱点这里去开通)。

其实我们可以借助第三方工具来突破下载速度限制。

本方法需要在电脑上操作,手机无法进行

我是用的工具是 proxyee-down,这个软件不需要安装,下载解压就可以用。官方提供了百度云下载(https://pan.baidu.com/s/1fgBnWJ0gl6ZkneGkVDIEfQ 提取码:d92x),Window 和 Mac 版本都有。下载解压之后直接运行 proxyee-down.exe 就可以了。如果你需要这个软件详细的说明,点这里

proxyee-down 其实只是一个下载工具,只支持 http 链接,但是百度网盘里面文件的下载链接怎么取得呢?

这里使用一个 Chrome 插件 baidudl (在 Chrome Web Store 打开),前提是你是用 Chrome 浏览器,然后打开 https://chrome.google.com/webstore/detail/baidudl/lflnkcmjnhfedgibjackiibmcdnnoadb 安装。

安装以后在你的 Chrome 浏览器插件栏会出现一个图标,打开你的百度网盘,需要下载的文件所在的页面,然后点击这个图标,在展开的页面点击 Generate 就可以取得下载链接了。

然后复制链接到 proxyee-down 里面下载就可以了。

XD60客制化键盘DIY教程

据说每个男人心里都有一个机械键盘的梦想。

其实我是不太在意机械键盘的(可能我是个比较穷的程序员),但是我喜欢鼓捣好看的小玩意儿,你要说 ikbc Poker 这种键盘好用吗?我觉得没有数字键和方向键其实很不方便,但是确实很漂亮,颜值就足够吸引我了。

然后在搜索便携的机械键盘的时候我发现了 GH60 这种神奇的东西,正好看到一个改良版的 XD60 支持方向键和删除键,我的好奇心驱使我要搞一搞,但是自己DIY键盘要求动手能力,目前的教程又过于零散,于是我就整理了这篇文章。

背景知识

什么是 GH60 和 XD60?

大家知道标准的键盘上大概有104个键,包括了主要的字符键盘,以及最上面一排F键,右侧功能键、方向键,还有最右侧的数字小键盘。还有的键盘可能不是标准的104个,会加几个功能键(声音、电源等等)。

我们通常把这种标准键盘称为 100% 键盘。那什么是不标准的呢?有的键盘省略了右侧的数字键盘,但是保留了方向键,键位大概有80多个,那这种就叫做 80% 键盘。同样,如果把F键、右侧功能键(Insert、Home、PageUp等)、方向键也省掉,只剩下60多个键,就是 60% 键盘。

GH60 就是一种 60% 键盘,最早是2012年在 geekhack 论坛上,由一帮键盘爱好者开发的,键位在 60 个左右,也不是确定只有 60 个。

XD60 是一位叫 xiudi 的工程师根据 GH60 的改良版本。

步骤概要

  1. 购买零件。
  2. 组装。
  3. 刷固件。

所需零件及工具

零件

  1. 一个pcb板,电路板,如果是 xd60 只能选择这家:https://item.taobao.com/item.htm?spm=a1z09.2.0.0.62502e8dG4sn2L&id=537485105086&_u=k42u11ed19a
  2. XD60 或 GH60 适用的键盘外壳(底座)。
  3. 键盘轴体,樱桃的是最好的,为了便宜,我选择了佳达隆 Gateron,也就是平常说的 G轴,使用五脚轴,更稳固。
  4. 键帽。
  5. 卫星轴5个,1个长的(6.25X)用于空格键,4个小的(2X)用于Shift、Enter等。

工具

  1. 电络铁1把。
  2. 焊锡丝若干。

参考资料:

https://tieba.baidu.com/p/4978712249?red_tag=2221842070


TOP