受余果的文章:达人访谈启发,写一篇面向团队新人的访谈,希望能有所帮助。
我是 2018 年本科毕业校招进入的百度,准确的说是通过 2018 年春招进来的。在此之前我的工作经历是一张白纸。
出于对正式工作的兴奋和好奇,我在 18 年 4 月中下旬拿到 offer 后,稍作调整 5 月初就来北京开启了约一个月的实习。之后就是 6 月底的正式入职 - 直到现在,司龄两年。
而我在百度的工作经历可以划分为四个时期:
如你一样,刚入职的我对工作中的一切都充满了新鲜感和兴奋感,以及一些期待。其中有些期待是我在面试时种下的种子(见关于公司 95 后的调查问题),另有一些是来自圈内人士的经验分享(@宇寰 @毫升 @余果)。
然后发现真实情况和预期值有一些出入(一方面也是鹅厂的员工关怀方面做的确实不错,让我提高了期待值)。例如面试官、导师的陆续离职,团队、manager 的频繁更换,业务的游离等。当然,具体细节也就不表了。
做的事情现在看不成体系,可以统称为打杂类工作。
在这一期间,我作为一个新鲜人,在动荡中摸索前行。(感谢好友 @宇寰 在此期间的大力帮助)
一方面在经历多次变动后从中吸取了经验,另一方面得益于主动探索问题背后的答案(参与线下培训课程,向许多老百度、高工、业内 OG 提问等),我“渐渐修炼了一项将一弯金钩看成一轮玉盘的本领”。
恰逢此时团队也趋于稳定,更得益余技术栈的统一化推广,自己有了比较稳定的工作产出、学习成长。工作内容主要是百度 App webpages 的开发,使用 San 生态。
这段时期的我更多的是执虚如盈的思路,在大方向稳住局势,并伴随着低调的成长。
如果说有些成长不是一点一滴,而是一块一块顿悟的话,在这个时期我完成了一大块的消化:重新焕发了 willingness。
Ownership 应该都听过,但我更喜欢 willingness 这个词 -> 意愿。
我是强自我驱动的类型,而 willingness 像是自己的燃料。在经历新鲜动荡期的冷水后,虽然也成功过度到了执虚如盈阶段,但是总感觉少了些什么。
在这一时期随着 willingness 的焕发,无论是工作本身,抑或是更细节的业务需求、技术项目、沟通类工作、产品观、个人业余时间的成长,都有了不错的进益。
而这期间我会在日常工作的求精上参与一些团队内的技术项目(chrome extension,C 端组件库等),收获较大。
给这一阶段做个小结:千金难买 willingness,成长中的收获令人欣喜。
然而好景不长,我也不例外的被一场突如其来的疫情打乱了节奏。迫于 COVID-19 带来的全方位影响,我不得不开始重新审视自己的职业规划路线(比如说湾区在当下甚至不远的未来,已经不合适作为一个选项),并调整自己在”疫情时代”下的策略。
除了工作上的经验提升和更重视效能外,一个显著的改变是加大对自己的投资。在对公司发的电脑性能失望一百次后,我组建了梦寐以求的工作台,并租了个两倍于原来次卧面积的主卧(可以轻松放得下大桌子),搭建 “Project RayJune Studio”,作为业余时间修行的 “妙木山”。
以及购置更清晰的显示器和升降桌和在公司使用,一方面提升工作体验,另一方面减缓久坐的隐患。
辅以日常规律性的运动和采风,我在编程和生活、工作与成长中形成了新的动态平衡。
因为在初期拥抱了许多变化,加上导师很早就离职,我经历了很长时间的自由放养期。而放养期带来的负面效应之一,就是 “不上路”。
这件事情发生在接手一个运营活动时,一切环节对我来说都是未知。而项目排期是倒排的,可以想象当事人的窘态。
苦思冥想了一天,工位附近的 help-guy(这里使用代号)友好的询问需不需要什么帮助。在一整套操作下来后,不夸张的说,我的整个世界都被点亮了。
技术上踏实可靠,态度上温润如玉,and always ready to help~!凭一己之力将我拉出深渊。
事后我逐渐意识到,help-guy 像是团队内业务和技术支撑点的存在,有什么难题,大家找 help-guy 就对了。
我会永远感激职业生涯中带自己上路的人,不单是因为这个帮助行为本身,更是塑造了我对这份工作本身的认识,以及树立一个优秀的榜样。
刚刚的工作经历介绍中详细的描述了我的心态变化,可以看出内心戏挺足的。
以上面罗列的四个时期来谈:
至于工作中有心态经历起伏是很正常的,因为所有过程本就是茫茫的曲线和弯路。
我的话会在低潮时回忆电影 Warrior 中的台词:Why are we here, RayJune?。
然后沉着地走自己的路。
所有重要而值得做的事情,都是需要耐心和坚持的。小到一个需求,中到一个判断,大到一段成长。
如果需要租房的话,建议租的离公司近一些(大约 2 km 以内)。如百度科技园附近的春夏秋冬园,西北旺地铁站附近的小区,马连洼地铁站附近的小区等。
比起租在回龙观之类偏远点的地方,会多出来一些租金,但相比较省下来的时间和精力,简直划算极了。
一个朋友在他29岁生日的时候,给过他年轻的朋友们一句话:「Gaudeāmus igitur, iuvenēs dum sumus(拉丁文)」,翻译是「在我们还年轻的时候,让我们快乐吧。」,换成一首诗就是「花开堪折直须折,莫待无花空折枝。」想想看,我们正当人生中最美好的岁月,为什么不去做自己喜欢的事情呢?不要被所谓的现实羁绊,试想人在年轻的时候如果还有如此多的「不能」,那么将来的「不能」祗会更多。所以,大胆去做吧,无需后悔。
希望你可以勇敢做你最想做的事情,在正好的年纪。
]]>“The function Array.fill is using the same object for all the indexes.”
问题来源于 Matrix Spiral 这个经典的 leetcode medium 算法题。题目描述就不在这里粘贴了,可以 check https://leetcode.com/problems/spiral-matrix/ 。
首先来写一个 JS 的解,我用的是这个思路 Create a NxN Matrix Spiral with JavaScript,其中加上了自己的一些个性化处理:
1 | /** |
其中和原版最大的不同是,我没有使用常规的 for
循环创建 result 数组的方法,而是使用了看起来更加简洁的 array.fill
方法:
1 | // 常规 for 循环创建 |
但是运行发现出问题了:
1 | matrix(3); |
将创建 result 数组的方式用 for
循环方式替换掉后,运行恢复正常。可以把原因锁定在 Array(n).fill([])
这个处理上了。
那么是为什么呢?
发现 MDN 上关于 Array.prototype.fill() 的文档没有这方面特例的说明。
在查遍 stackoverflow 后找到了原因:”The function Array.fill is using the same object for all the indexes.”
带着这个解释我们来还原一下 Array(n).fill([])
内部处理的过程:
1 | const result = Array(n).fill([]); |
既然不能使用 Array(n).fill([])
,有没有其他比 for
循环更加简洁的处理呢?
容易想到可以使用 array.map()
这个方法:
1 | const result = Array(n).map(() => []); |
但是这样就踏入下一个陷阱了,因为 Array(n)
生成的数组不能直接使用 map
方法:
“
map
only operates on defined integer properties of an array.Array(n)
does not set integer properties, whileArray(n).fill()
does. There’s a difference between a property that doesn’t exist and an extant property whose value is undefined.”Array(n) sets the length property of the array, but it does not set any properties. The array object does not have any integer properties.
.fill sets all of the integer properties for an array from zero up to one less than length.
1 | // 可以用 Object.keys() 来测试一下二者的不同 |
所以应该在 map
前加一个 .fill()
方法,使之拥有 defined integer properties,进而才能使用它:
1 | const result = Array(n).fill().map(() => []); |
Array.from()
同样是个合适的替代方案: The Array.from() method creates a new, shallow-copied Array instance from an array-like or iterable object.
shallow-copied 说明了它在我们这种情况下的可用性:
1 | // perfect! |
话说回来,有没有什么 array.fill
大放异彩的使用场景呢?
是时候搬出另一道 leetcode medium 算法题 Pyramid Transition Matrix 了,题目介绍在 https://leetcode.com/problems/pyramid-transition-matrix/ 。
有了 array.fill
,这道题从未如此简单:
1 | /** |
stackoverflow: Whats the difference between Array.fill and a for loop to create Array
stackoverflow: differrent-interaction-of-array-constructor-and-using-array-literal
Create a NxN Matrix Spiral with JavaScript
]]>简单的问题和回答。
Yep
选择互联网行业的原因很简单:Web 真切了改变了我的人生轨迹。
聊一聊后者:
简单的说:和面试官气味相投,极佳的面试体验。
具体的说:
面试官温文尔雅,循循善诱;不会居高临下,语气奇怪;或者语速很快、压力很大、咄咄逼人、很赶时间,抑或性格不是欣赏的性格,不能够“气味相投”)。
面试官是什么样子一定程度反应了以后共事的同事是什么样子。
面试有难度,且有一定的 弹性/拓展性(“有机”);
面试的问题、难度水平能一定程度看出这个团队对哪些技术的重视,进而判断是否是自己内心想做的工作侧重点。
简单的关系,工程师文化。
得不到好的成长机会,即“温水煮青蛙”。
一向不关注”网络传言”。
positive
比如一个高 T 的英文名叫 Tom,我就叫他 Tom(而不是 Tom 哥,Tom 神)。一般根据别人喜好,判断 他/她 喜欢被别人叫什么。
认真记录下批评的内容,回去反思整理总结,避免下次。
最喜欢的地方:文化夜谈会,和高工无压力畅聊(职位很高的架构师)。
最开心的地方:写出令自己满意的代码,这会让人开心很久。
偶尔到过西二旗的大厦(因为办公地点在科技园),感觉大厦之外的地路上空气较“紧张”,行人神色匆匆。
每周一部电影;整理个人博客;周末最少来公司半天,安静的样子很像图书馆。
一向不关注”网络传言”。
在科技园工作,mobike。
早起早睡是习惯。
不贪心就足够,life & love。
一片冰心在玉壶。
奇怪的风俗。
今天我感到非常烦闷,我想念你。
]]>Snapshots, Not Differences.
https://git-scm.com/book/en/v2/Getting-Started-Git-Basics#_snapshots_not_differences
Todo: Explaining some background on version control tools.
Target: Should understand why Git is around, why you should use it.
What is “version control”? (aka Version Control System, VCS)
Version control is a system that records changes to a file or set of files over time so that you can recall specific versions later. (And compare changes over time, see who last modified something that might be causing a problem, who introduced an issue and when.)
So using a VCS also generally means that if you screw things up or lose files, you can easily recover.
Local VCSs is which had a simple database that kept all the changes to files under revision control.
Such as RCS, it works by keeping patch sets (that is, the differences between files) in a special format on disk; it can then re-create what any file looked like at any point in time by adding up all the patches.
Centralized VCS (such as CVS, Subversion) have a single server that contains all the versioned files, and a number of clients that check out files from that central place.
The most obvious downside is the single point of failure: whenever you have the entire history of the project in a single place, you risk losing everything.
In a DVCS (such as Git), clients don’t just check out the latest snapshot of the files; rather, they fully mirror the repository, including its full history.
Thus, if any server dies, any of the client repositories can be copied back up to the server to restore it. Every clone is really a full backup of all the data.
Some of the goals of Git were as follows:
Result:
Git stores and thinks about information in a very different way (compared to other VCS), and understanding these differences will help you avoid becoming confused while using it.
Conceptually, most other systems store information as a list of file-based changes.(this is commonly described as delta-based version control).
Instead, Git thinks of its data more like a series of snapshots of a miniature filesystem.
With Git, every time you commit, Git basically takes a picture of what all your files look like at that moment and stores a reference to that snapshot.
To be efficient, if files have not changed, Git doesn’t store the file again, just a link to the previous identical file it has already stored.
Git thinks about its data more like a stream of snapshots.
We’ll explore some of the benefits you gain by thinking of your data this way when we cover Git branching in Git Branching.
This may not seem like a huge deal, but you may be surprised what a big difference it can make.
Everything in Git is check-summed before it is stored and is then referred to by that checksum.(The mechanism that Git uses for this checksumming is called a SHA-1 hash, a 40-character string composed of hexadecimal characters (0–9 and a–f))
When you do actions in Git, nearly all of them only add data to the Git database.
This makes using Git a joy because we know we can experiment without the danger of severely screwing things up.
Git has three main states that your files can reside in: modified, staged and committed:
The working tree is a single checkout of one version of the project. These files are pulled out of the compressed database in the Git directory and placed on disk for you to use or modify.
The staging area is a file, generally contained in your Git directory, that stores information about what will go into your next commit. Its technical name in Git parlance is the “index”, but the phrase “staging area” works just as well.
The Git directory(.git) is where Git stores the metadata and object database for your project. This is the most important part of Git, and it is what is copied when you clone a repository from another computer.
The basic Git workflow goes something like this:
While your choice of graphical client is a matter of personal taste, all users will have the command-line tools installed and available.
1 | git config --global user.name "RayJune" |
There are two equivalent ways to get the comprehensive manual page (manpage) help for any of the Git commands:
1 | git help <verb> |
In addition, if you don’t need the full-blown manpage help, but just need a quick refresher on the available options for a Git command, you can ask for the more concise “help” output with the -h or –help options.
1 | git add -h |
If you can read only one chapter to get going with Git, this is it.
Remember that each file in your working directory can be in one of two states: tracked or untracked.
认真编写的题目能测出代码水平,而有趣的题目则能激发人的“代码欲望”。
前后参加过网易、美团、头条、滴滴等公司的在线编程题。简单的认为题目大体有以下三种类型:
笔试题在很多时候确实是个“坑”,能避开就避开,因为毕竟像状况 2 的是少数。但优质的题目确实是一个很好的编程能力检验,遇到了就不要错过。
2018 年春招的携程前端笔试题是一个不错的例子,下面对其中的编程题做一番分析。
P.S. 原文显示效果更好喔:) check:https://www.rayjune.me/2018/03/31/interesting-programming-problems-ctrip-2018-spring-recruit/
作者:RayJune(转载请署名,请尊重博主含辛茹苦、遍查资料、一行一行含泪码出来的成果)
简单列举一下可能被问到的问题:
非常确定 100% AC。同时这意味着细节复杂度上的处理到位。(实际前端开发中要处理大量细节复杂度的东西,这同样很有意思)
避免有些笔试平台不支持 ES6 的状况,你懂的
new Set()
来去重呢?同上,另外顺便回顾一下数组去重。在面试的时候写 new Set
来数组去重会被 diss 的,别问我为什么知道 :>
一种编程品味。
简单陈述一下文中代码使用的编程风格:
ES5
,以避免有些在线编程平台不支持 ES6
的状况(所以在这里没有用 new Set()
)var
模式var
),函数体(body
),return
值三者用空行隔开,逻辑鲜明另外还有 根据不同场合使用合适的类型判断方式:
Array.isArray
判断数组,Object.prototype.toString.call
来判断纯对象typeof
判断基本类型和 function
instanceof
来判断自定义的对象给定一个长度小于 50 且包含字母和数字的任意字符串,要求按顺序取出当中的数字和英文字母,数字需要去重,重新排列后的字符串数字在前,字母在后。
需要截取的字符串(包含数字和字母)
按照要求重新排列的字符串
1 | '携程C2t0r1i8p2020校招' |
1 | '2018Ctrip' |
肯定有同学表示第一题不值得分析。但我还是想抛砖引玉一下,思路如下:
str.split('')
(进而使用数组的各种操作方法,如 arr.forEach
)/\d/.test(element)
或者 Number.isNaN(Number(element)
/[a-zA-Z]/.test(element)
由此有了这一版代码:
1 | function handleStr(str) { |
作为前端开发超高频面试题,相信大家早已对数组去重熟捻于心:
基本类型去重:
1 | function unique(arr) { |
基本+复杂类型去重:
1 | function unique(arr) { |
由于数字去重(str
,基本类型)基于数组去重,我们要对原来的数组去重做一点修改:
1 | function uniqueStr(str) { |
string.split()
和 array.join()
帮助我们自由的游走在字符串和数组间。
1 | function handleStr(str) { |
非常感谢评论区 @while大水逼 大神的宝贵建议,博主笔试的时候没想到 str.match(regex)
的方法。实现更简洁、逻辑的展示更好,在此补上:
1 | function handleStr(str) { |
对一维数组,根据 type
类型分组成二维数组
[]
,空对象 null
,undefined
,数字,字符串等异常值;[{ type, content}]
的有效值;[null, null, (type, content)]
等有效和非法值混合的数据。[]
type
值的元素合并,形成新元素 {"type": "A", "contents": [content1, content2]}
,其中,contents
为一个数组,元素为所有 type 值相同的 content
值。JSON
格式1 | var input = [null, 2, "test", undefined, { |
1 | [{"type":"product","contents":["product1","product2","product3"]},{"type":"tag","contents":["tag1","tag2"]}] |
乍一看要求颇多,我们一点点来拆解:
当输入数据不合法时,输出空数组
[]
什么数据不合法?输入值不为 JSON
格式(即 array
类型);
还有呢?输入值为 JSON
格式(即 array
类型),但长度为 0
;
由此写下第一句:
1 | function groupList(list) { |
当输入数据有效时(请先过滤数组里的异常元素)
过滤掉[]
,空对象 null
,undefined
,数字,字符串等异常元素:
1 | function groupList(list) { |
且慢,结构不为 { "type": "xx", "content": "yy" }
的值,是不是也为异常元素呢?为此在 getValidItems
里加上一句:
1 | function getValidItems(json) { |
可能有同学会问,这里为什么不用 typeof
判断 object
,而是那么麻烦撸了一个 isPureObject
呢?
首先明确 typeof
用来判断基本类型和 function
(check: 根据不同场合使用合适的类型判断方式),举个例子:
1 | var demo = [1, 2]; |
如果是
1 | function getValidItems(json) { |
显然无法过滤 demo
这种情况了,更何况还可以是 regex 等各种非 function
的对象。
所以在线编程题请慎重考虑边缘情况。
过滤完成后,将相同
type
值的元素合并,形成新元素
1 | function groupList(list) { |
貌似我们已经完成了将相同 type
值合并这一步骤,但是:
当前的结构是 {type1: contentsArr1, type2: contentsArr2}
的结构,与题目要求的:[{type1: contentsArr1}, {type1: contentsArr2}]
不相同。
不难,再加一步便是:
1 | function adjustFormat(obj) { |
且慢,根据一个数组产生一个新的数组,用 array.map
是不是更物尽其用呢?(再次感谢评论区 @while大水逼 提出的方案)
更纯粹的函数式编程,更直观的逻辑展示:
1 | function adjustFormat(obj) { |
完整的代码:
1 | function groupList(list) { |
回到文章题目本身上来,什么算是有趣的前端笔试题?
如果是现场面试手写编程题,我觉得应该再加上一条:
如果哪家公司有这样的编程题,请把我一波流内推带走 :)
号外:博主为 18 届应届生,目前状态是前端开发补招进行时。如有内推机会,欢迎一波带走 :》
欢迎 check 简历:resume.pdf
有同学问为神马没有第三题的题解,因为自己在第二题的细节复杂度中消耗了大量时间(盯了一二十分钟才发现需要进行 Array.isArray(input)
的判断) - =(相信有不少同学也是这样),没有时间把第三题撸出来了。。。
面试官:小伙子排序算法了解吗?
回答:我能写出来四种冒泡排序,两种选择排序,两种插入排序,两种哈希排序,两种归并排序,两种堆排序,四种快速排序。
用我自己的方式。
文中所有代码位于位于 https://github.com/RayJune/Elegant-JavaScript-Sorting-Algorithms 仓库中,推荐下载代码进行练习、推敲。
号外:博主为 18 届应届生,目前状态是前端开发补招进行时。如有内推机会,欢迎一波带走 :》
欢迎 check 简历:resume.pdf
另,如果觉得这些用心敲出的代码对你有帮助的话,欢迎 star 一下代码仓库,众筹博主找到一份体面的工作,在这里给大家递茶了:)
P.S. 原文显示效果更好喔:) check:https://www.rayjune.me/2018/03/22/elegant-javascript-sorting-algorithm-es6/
作者:RayJune(转载请署名,请尊重博主含辛茹苦、遍查资料、一行一行含泪码出来的成果。参考&感谢 部分里代码参考地址都已列出)
另,本文中常使用 swap
函数,在这里提前列出来,以下就省略了。
1 | function swap(arr, indexA, indexB) { |
通过依次比较、交换相邻的元素大小(按照由小到大的顺序,如果符合这个顺序就不用交换)。
1 次这样的循环可以得到一个最大值,n - 1
次这样的循环可以排序完毕。
O(n²)
O(n²)
O(n)
(但是这种情况下不如插入排序块,请继续看下文)postion
来优化1 | function bubbleSort(arr) { |
设置一标志性变量 pos
,用于记录每趟排序中最后一次进行交换的位置。
由于 pos
位置之后的记录均已交换到位,故在进行下一趟排序时只要扫描到 pos
位置即可。
1 | function bubbleSort2(arr) { |
传统冒泡排序中每一趟排序操作只能找到一个最大值或最小值,
我们可以 在每趟排序中进行正向和反向两遍冒泡 ,
一次可以得到两个最终值(最大和最小) , 从而使外排序趟数几乎减少了一半。
1 | function bubbleSort3(arr) { |
前两种优化方式(缓存 pos
、双向遍历)的结合:
1 | function bubbleSort4(arr) { |
来自于蚂蚁金服的一道面试题:
对于冒泡排序来说,能不能传入第二个参数(参数为函数),来控制升序和降序?(联想一下
array.sort()
)
1 | function bubbleSort(arr, compareFunc) { |
每一次内循环遍历寻找最小的数,记录下 minIndex
,并在这次内循环结束后交换 minIndex
和 i
的位置。
重复这样的循环 n - 1
次即得到结果。
Θ(n²)
无论什么输入,均为 Θ(n²)
Θ(n) 交换
: 注意,这里只有 n
次的交换,选择排序的唯一优点*关于 Θ(n) swaps:
Selection sort has the property of minimizing the number of swaps. In applications where the cost of swapping items is high, selection sort very well may be the algorithm of choice.
可见即使是我们觉得最慢的选择排序,也有它的用武之地。
O(n²)
,但不稳定,唯一的优点是减少了 swap
次数。1 | function selectionSort(arr) { |
如果你想在每次内循环中找到最大值并把其交换到数组的末尾(相比较 minIndex
有点麻烦),以下是实现的代码:
1 | function selectionSort2(arr) { |
默认 a[0]
为已排序数组中的元素,从 arr[1]
开始逐渐往已排序数组中插入元素,从后往前一个个比较,如果待插入元素小于已排序元素,则已排序元素往后移动一位,直到待插入元素找到合适的位置并插入已排序数组。
经过 n - 1
次这样的循环插入后排序完毕。
O(n)
O(n²)
由于它的优点(自适应,低开销,稳定,几乎排序时的
O(n)
时间),插入排序通常用作递归基本情况(当问题规模较小时)针对较高开销分而治之排序算法, 如希尔排序或快速排序。
1 | function insertionSort(arr) { |
因为对于插入排序的优化方法是二分查找优化,这里补充一下二分查找的算法的实现。
核心概念是:折半。
1 | function binarySearch(arr, value) { |
首先把二分查找算法做一点小修改,以适应我们的插入排序:
1 | function binarySearch(arr, maxIndex, value) { |
然后在查找插入位置时使用二分查找的方式来优化性能:
1 | function insertionSort2(arr) { |
希尔排序是插入排序的改进版,它克服了插入排序只能移动一个相邻位置的缺陷(希尔排序可以一次移动 gap
个距离),利用了插入排序在排序几乎已经排序好的数组的非常快的优点。
使用可以动态定义的 gap
来渐进式排序,先排序距离较远的元素,再逐渐递进,而实际上排序中元素最终位置距离初始位置远的概率是很大的,所以希尔排序大大提升了性能(尤其是 reverse 的时候非常快,想象一下这时候冒泡排序和插入排序的速度)。
而且希尔排序不仅效率较高(比冒泡和插入高),它的代码相对要简短,低开销(继承插入排序的优点),追求这些特点(效率要求过得去就好,代码简短,开销低,且数据量较小)的时候希尔排序是好的 O(n·log(n))
算法的替代品。
总而言之:希尔排序的性能优化来自增量队列的输入和 gap
的设定。
O(n·log(n))
的时间复杂度(并且它对于反转数组的速度非常快)O(n^3/2)
time as shown (想要了解更多细节,请查阅 wikipedia Shellsort)关于不稳定:
我们知道, 单次直接插入排序是稳定的,它不会改变相同元素之间的相对顺序,但在多次不同的插入排序过程中, 相同的元素可能在各自的插入排序中移动,可能导致相同元素相对顺序发生变化。因此, 希尔排序并不稳定。
关于 worse-case time 有一点复杂:
The worse-case time complexity of shell sort depends on the increment sequence. For the increments 1 4 13 40 121…, which is what is used here, the time complexity is O(n3/2). For other increments, time complexity is known to be O(n4/3) and even O(n·log2(n)).
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
O(n)
的效率;其中 gap
(增量)的选择是希尔排序的重要部分。只要最终 gap
为 1 任何 gap
序列都可以工作。算法最开始以一定的 gap
进行排序。然后会继续以一定 gap
进行排序,直到 gap = 1
时,算法变为插入排序。
Donald Shell 最初建议 gap
选择为 n / 2
并且对 gap
取半直到 gap
达到 1 。虽然这样取可以比 O(n²) 类的算法(插入排序、冒泡排序)更好,但这样仍然有减少平均时间和最差时间的余地。
(关于优化 gap
的细节涉及到复杂的数学知识,我们这里不做深究,详细可以参考 wikipedia 上的页面)
Donald Shell 的最初建议(gap = n / 2
)版代码(方便理解):
1 | function shellSort(arr) { |
常见的、易生成的、优化 gap
的序列方法(来自 Algorithms (4th Edition) ,有些更快的方法但序列不容易生成,因为用到了比较深奥的数学公式):
1 | function shellSort(arr) { |
归并排序使用分而治之的思想,以折半的方式来递归/迭代排序元素,利用空间来换时间,做到了时间复杂度 O(n·log(n))
的同时保持了稳定。
这让它在一些更考虑排序效率和稳定性,次考虑存储空间的场合非常适用(如数据库内排序,和堆排序相比,归并排序的稳定是优点)。并且归并排序非常适合于链表排序。
O(n·log(n))
时间复杂度的排序算法中,归并排序是唯一稳定的)O(n·log(n))
以迭代的方式来实现(但要注意防止函数调用过深导致 JavaScript 的运行栈溢出):
1 | function mergeSort(arr) { |
用 array.splice
取代 array.slice
,减少一半的空间消耗。
1 | function mergeSort2(arr) { |
堆排序可以认为是选择排序的改进版,像选择排序一样将输入划分为已排序和待排序。
不一样的是堆排序利用堆这种近似完全二叉树的良好的数据结构来实现排序,本质上使用了二分的思想。
arr[0]
到数组末尾(已排序区域)利用堆这种良好的数据结构,它在拥有良好的可预测性的同时(不管输入什么都是 O(n·log(n))
时间复杂度),但它的缺点也有:即不稳定,而且 O(n·log(n))
的平均效率决定了它的效率不如快速排序。适用于数据库内引擎排序(需要这样的可预测性性能)。
O(n·log(n)
time)1 | function heapSort(arr) { |
wikipedia 上给出的方法于第一版的区别在于维护堆性质时采用的方式不同,本质是一样的:
1 | function heapSort(arr) { |
When implemented well, it can be about two or three times faster than its main competitors, merge sort and heap sort
1 | function quickSort(arr) { |
函数式编程:结构清晰,一目了然。
1 | function quickSort2(arr) { |
等等,有没有觉得第一版中的代码虽然看起来简洁,但是却对空间消耗很大呢?
由此有了 in-place 版本:
1 | function quickSort3(arr, left = 0, right = arr.length - 1) { |
这一版的亮点是 pivot 的选取,不再是简单的取 arr[0]
,而是:
1 | const pivot = left + Math.ceil((right - left) * 0.5) |
感谢评论区的大神@Chris_dong 的解释:
const pivot = left + Math.ceil((right - left) * 0.5)
=> (去掉MAth.ceil是不是很好理解)left + (right - left) * 0.5
=>(right + left) * 0.5
。
看到真相的我眼泪掉下来,原来是取中间值。。。
由此有了以下版本:
1 | function quickSort4(arr, left = 0, right = arr.length - 1) { |
提出几个问题,可以当做自我检测:
插入排序不解释
性能大小:希尔排序 > 插入排序 > 冒泡排序 > 选择排序
O(n²)
的情况)(如数据库中)?堆排序
归并排序
性能大小:快速排序 > 堆排序 > 归并排序
因为虽然堆排序做到了 O(n·log(n)
,而快速排序的最差情况是 O(n²)
,但是快速排序的绝大部分时间的效率比 O(n·log(n)
还要快,所以快速排序真的无愧于它的名字。(十分快速)
选择排序只需要 O(n)
次交换,这一点它完爆冒泡排序。
答疑:
都是博主含辛茹苦、遍查资料、一行一行含泪认真码出来的。参考&感谢 部分里列出了所有来源地址:)
实际上这篇文章继承于优雅的 JavaScript 排序算法 。这一版是上一般的姐妹版(解释精简,使用 ES6 使代码更精简),若想参考英文引用、ES5 代码、过程详细解释可以参考第一版。
用 ES6
是为了更强大的表现力,从而让我们更加关注于算法的内在,不被一些边边角角所束缚。
博主一向认为是有【代码品味】这种东西存在的,可以从之前的这篇文章从 shuffle 看代码品味一窥端倪。
再次表达一下自己的观点:
但是追求的最终目的是一致的:好读又简洁,稳定易维护。
为了这个目标我做了这些努力:
preIndex
, temp
, size
;len / 2
的取整时为了可读性选择了 Math.floor(len / 2)
,没有选择 len >> 1
和 parseInt(len / 2, 10)
;for
和 while
的使用场景,具体可以看这个问题的答案:Array.isArray()
,Object.prototype.toString.call()
,typeOf
, instanceOf
来检查 arr
是不是数组类型,默认 arr
就是数组类型;( ? : )
来减少 if
的嵌套,提高代码可读性;++
)和自减(--
)运算符使用 +=
和 -=
代替 (for
中的最后一个条件除外);ES6
中的默认参数方式(快速排序中)简化代码,将关键逻辑突出;Eslint
+ Airbnb 全局控制代码风格;function
声明函数,具体原因见:从 shuffle 看代码品味。这是我的品味,你的呢:)
号外:博主为 18 届应届生,目前状态是前端开发补招进行时。如有内推机会,欢迎一波带走 :)
Asynchronous JavaScript And XML.
Summarized from MDN
AJAX stands for Asynchronous JavaScript And XML. In a nutshell, it is the use of the XMLHttpRequest object to communicate with servers.
AJAX’s most appealing characteristic is its “asynchronous” nature, which means it can communicate with the server, exchange data, and update the page without having to refresh the page.
The two major features of AJAX allow you to do the following:
1 | var request = new XMLHttpRequest(); |
After making a request, you will receive a response back.
By setting the onreadystatechange
property of the object, like this:
1 | request.onreadystatechange = () => { doSomething }; |
Next, you need to actually make the request, by calling the open()
and send()
methods of the HTTP request object, like this:
1 | request.open('GET', 'http://www.rayjune.me/resume.pdf', true); |
parameter:
The parameter to the send()
method can be any data you want to send to the server if POST-ing the request.
Form data should be sent in a format that the server can parse, like a query string:
1 | "name=value&anothername="+encodeURIComponent(myVar)+"&so=on" |
or other formats, like multipart/form-data, JSON, XML, and so on.
Note that if you want to POST data, you may have to set the MIME type of the request.
For example, use the following before calling send()
for form data sent as a query string:
1 | request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); |
When you sent the request, you provided the name of a JavaScript function to handle the response:
1 | request.onreadystatechange = nameOfTheFunction; |
First, the function needs to check the request’s state.
If the state has the value of XMLHttpRequest.DONE
(corresponding to 4), that means that the full server response was received and it’s OK for you to continue processing it.
1 | if (request.readyState === XMLHttpRequest.DONE) { |
The full list of the readyState
values is as follows:
Next, check the response code of the HTTP response. In the following example, we differentiate between a successful and unsuccessful AJAX call by checking for a 200 OK response code.
1 | if (request.status === 200) { |
Next, we can do whatever we want with the data the server sent. We have two options to access that data:
httpRequest.responseText
: returns the server response as a string of texthttpRequest.responseXML
: returns the server response as an XMLDocument object you can traverse with JavaScript DOM functionsNote that the steps above are valid only if you used an asynchronous request (the third parameter of open() was unspecified or set to true). If you used a synchronous request you don’t need to specify a function, but this is highly discouraged as it makes for an awful user experience.
Let’s put it all together with a simple HTTP request. Our JavaScript will request an HTML document, test.html, which contains the text “I’m a test.” Then we’ll alert()
the contents of the response.
1 | <button id="AJAXButton" type="button">Make a request</button> |
In the event of a communication error (such as the server going down), an exception will be thrown in the onreadystatechange
method when accessing the response status. To mitigate this problem, you could wrap your if...then
statement in a try...catch
:
1 | function alertContents() { |
1 | <label>Your name: |
the server’s response would look like this:
1 | {"userData":"Jane","computedString":"Hi, Jane!"} |
To use this data within alertContents()
, we need to parse it and alert computedString, the property we want:
1 | function alertContents() { |
面试官:小伙子写一个 shuffle?(JavaScript)
shuffle:顾名思义,将数组随机排序,常在开发中用作实现随机功能,又称洗牌算法。
我们来看看一个 shuffle 可以体现出什么代码品味。
1 | function shuffle(arr) { |
ES6
1 | const shuffle = arr => |
测试代码
1 | // test |
请老铁千万不要这样写,这体现了两个错误:
Why? Check:
https://blog.oldj.net/2017/01/23/shuffle-an-array-in-javascript/
下面来到了第一反应:思考问题。
数组随机化 -> 要用到 Math.random
-> 看来每个元素都要 random 一下 -> 处理 arr.length
的取整要用到 Math.floor
-> 交换数组元素位置需要用到 swap
一切正常的话你的方向应该转向经典的 Fisher–Yates shuffle 算法思路了 :》
由此有了第一版代码:
1 | function shuffle(arr) { |
const
和 let
都没有,连 class
也没有。但是 import
命令具有提升效果,会提升到整个模块的头部,首先执行)return
分开。三段式结构,一目了然的逻辑,使代码更加清晰易维护需要注意的是这里的 randomIndex
处理是 Math.floor(Math.random() * (index + 1))
,index + 1
,看起来好别扭,可以用 Math.ceil
来替换吗:
1 | function shuffle(arr) { |
多谢评论区的 @旅行者2号 大神提醒,这是不行的。因为:
Math.ceil
会将 (0, 1) 范围的数字都化为 1,只有 0 才化为 0。这样会导致 index
为 0 的元素很难被 randomIndex
随机到。什么,JavaScript 中木有这么基础的 swap
函数?
写一个,使逻辑更加清晰 & 重复利用:
1 | function swap(arr, indexA, indexB) { |
一点点小的改动:
1 | function shuffle(arr) { |
用 arr.forEach
替代原本的 for
循环。(我会告诉你 array.forEach
的返回值是 undefined
这一点容易出错嘛)
此外不希望有人质疑:JS 由于函数调用栈空间有限,用 for
循环不是比 forEach
效率更高吗?
拿出这段话压压惊:
”We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.”
– Donald Knuth
JavaScript 天生支持函数式编程(functional programing),放下脑海中的 CPP-OOP,请好好珍惜它。
有了 High-order function & First-class function 的存在,编写代码的逻辑愈发清晰,简洁好维护。
且慢,同学不写一个 ES6 版本的吗?
1 | const shuffle = (arr) => { |
使用 ES6 的箭头函数(arrow function),逻辑的表达更为简洁、清晰、好维护。(我会告诉你箭头函数还因为本身绑定的是外部的 this
,解决了一部分 this
绑定的问题嘛。注意我没有说全部)。
顺便也用 ES6 重写一下 swap
函数把。简介的语法,更强大的表现力,谁用谁喜欢:
1 | const swap = (arr, indexA, indexB) => { |
怎么样,ES6 的对象解构赋值(Destructuring)燃不燃?好用不好用?
其实代码到第三版已然 OK 了,但还是有一处纰漏:
在 arr.forEach((curValue, index) => { ... })
中 index = 0
时,randomIndex
的值也只能为 0,显然这个时候 swap(arr, 0, 0)
的操作是没必要的:
1 | const shuffle = (arr) => { |
那么我们原先的 for
循环语句有木有这种问题呢?ES6 重写一下:
1 | const shuffle = (arr) => { |
其中的循环终止条件是 i > 0
,自动排除掉 i = 0
的情况了,所以在 for
循环中是没有问题的。
既然在循环中用 let
代替了 var
,我们来回顾一下两者的区别吧:
let
相比较 var
有两个不同:
{}
中,不像 var
只有函数才能锁住它的作用域var
有变量提升,let
没有上代码:
1 | for (var i = 0; i < 10; i++){ |
Why?
光说不练假把式,我们来试用一下第四版的 shuffle
把:
1 | // test |
出现调用错误,const
声明的变量没有变量提升,在调用 shuffle
和 swap
的时候他们还木有出生呢~!
So 这样?
1 | const shuffle = (arr) => { |
老铁没毛病。但主要逻辑运行代码放在后,次要逻辑函数定义放在前有没有不妥?
这里只有 shuffle
和 swap
两个函数,或许你会觉得区别不明显,那如果代码更长呢?
没错,或许你可以进行模块拆分,但如果像 underscore 那样的代码呢。如果像博主一样写一个 indexeddb-crud 呢?(不是硬广:-D)
有时候我们需要一次自我审问:每次调用函数时都要确认函数声明在调用之前的工作是必须的吗?
1 | // test |
为啥用 ES5 的方式来写 function,Airbnb 的 ES6 规范建议不是用 const
+ 箭头函数来替代传统的 ES5 function
声明式吗?
我们来看 const
+ 箭头式函数声明带来了什么,失去了什么:
this
绑定子曰:
在这里用传统 ES5 function
是因为:
我想利用它的变量提升实现主逻辑前置,而不用去关心函数的定义位置。
进而从上到下,层层逻辑递进。再一次出现这两个词:逻辑简洁、好维护。
我答:只有好读又简洁,稳定易维护的代码,没有高水平的代码一说。
你问:说好的代码品味呢?
号外:博主为 18 届应届生,目前状态是前端开发补招进行时。如有内推机会,欢迎一波带走 :)
]]>被面试官问到了关于 V8 有哪些了解,索性把之前的做的功课总结起来,一起展示。
V8 是一种 JavaScript 引擎。
JavaScript 引擎是一个专门处理 JavaScript 脚本的虚拟机,一般会附带在网页浏览器之中。
A JavaScript engine is a program or interpreter which executes JavaScript code. A JavaScript engine may be a traditional interpreter, or it may utilize just-in-time compilation to bytecode in some manner.Although there are several uses for a JavaScript engine, it is most commonly used in Web browsers
V8 在运行之前将 JavaScript 编译成了机器码(JIT),而非字节码或是解释执行它,以此提升性能。更进一步,使用了如内联缓存(inline caching)等方法来提高性能。有了这些功能,JavaScript 程序与 V8 引擎的速度媲美二进制编译。
重点:V8 把 JavaScript 代码编译成机器语言。和其他引擎最主要的差别在于,V8 不会生成任何字节码或是中间代码。
V8 compiles JavaScript directly into native assembly.
It’s speed comes from the fact that it compiles JavaScript directly into native assembly.
V8 compiles JavaScript directly to native machine code before executing it, instead of more traditional techniques such as interpreting bytecode or compiling the whole program to machine code and executing it from a filesystem. The compiled code is additionally optimized (and re-optimized) dynamically at runtime, based on heuristics of the code’s execution profile. Optimization techniques used include inlining, elision of expensive runtime properties, and inline caching
对象属性的顺序:永远用相同的顺序为您的对象属性实例化,这样隐藏类和随后的优化代码才能共享。
1 | function Point(x, y) { |
你可能会说对 p1 和 p2 而言,它们会使用相同的隐藏类和类转换。其实不然。 对 “p1” 来说,先是属性 “a” 被添加,然后是属性 “b”。而对 “p2” 来说,先是属性 “b” 被添加,然后才是属性 “a”。这样, “p1” 和 “p2” 就在不同的转换路径作用下,有了不同的隐藏类。在这两种情形下,其实最好是用相同的顺序初始化动态属性,这样隐藏类就可以被复用了。
动态属性:在对象实例化后为其新增属性会导致隐藏类变化
,从而会减慢为旧隐藏类所优化的方法的执行。所以,尽量在构造函数中分配对象的所有属性。
重复执行相同方法的代码会比不同的方法只执行一次的代码运行得更快(由于内联缓存)。
4、数组:避免使用 keys 不是递增数字的稀疏数组(sparse arrays)。并不为每个元素分配内存的稀疏数组实质上是一个 hash 表。这种数组中的元素比通常数组的元素会花销更大才能获取到。此外,避免使用预申请的大型数组。最好随着需要慢慢增加数组的大小。最后,不要删除数组中的元素,因这会使得 keys 变得稀疏。
5、标记值(Tagged values): V8 用 32 个比特来表示对象和数字。它使用 1 个比特来区分是一个对象(flag = 1)还是一个整型(flag = 0)(被称为 SMI 或 SMall Integer,小整型,因其只有 31 比特来表示值)。然后,如果一个数值大于 31 比特,V8 就会给这个数字进行装箱操作(boxing),将其变成 double 型
,并创建一个新的对象将这个 double 型数字放入其中。所以,为了避免代价很高的 boxing 操作,尽量使用 31 比特的有符号数。
Performance advice is addictive, and sometimes focusing on deep advice first can be quite distracting from the real issues.
You need to take a holistic view of the performance of your web application - before focusing on these performance tip, you should probably analyze your code with tools like PageSpeed and get your score up. This will help you avoid premature optimization.
The best basic advice for getting good performance in Web applications is:
Finally, fix what matters
Order of object properties: always instantiate your object properties in the same order so that hidden classes
, and subsequently optimized code, can be shared.
adding properties to an object after instantiation will force a hidden class change and slow down
any methods that were optimized for the previous hidden class. Instead, assign all of an object’s properties in its constructor.inline caching
).are a hash table
. Elements in such arrays are more expensive to access
. Also, try to avoid pre-allocating large arrays. It’s better to grow as you go. Finally, don’t delete elements in arrays. It makes the keys sparse
.v8 除了用在 Chrome 中,还用在 node.js 和 MongoDB(版本 2 以后的)中。
Electron 是一个通过把 Chromium 和 node.js 结合为一个运行时来实现使用 HTML、CSS、JavaScript 构建桌面应用程序的开源库。
代表作品:VS Code, Atom
written by Java ,它旨在用于服务器端,作为默认的 JavaScript 引擎嵌入在 Java SE 6 中,被 Mozilla 基金会作为开源软件管理
Firefox 引擎,第一代引擎
Safari 引擎
Edge 引擎,IE 9 ~ 引擎
用于物联网的轻量级引擎,三星开发
https://en.wikipedia.org/wiki/JavaScript_engine
https://zh.wikipedia.org/wiki/JavaScript%E5%BC%95%E6%93%8E
https://en.wikipedia.org/wiki/Chrome_V8
https://zh.wikipedia.org/wiki/V8_(JavaScript%E5%BC%95%E6%93%8E)
https://blog.sessionstack.com/how-javascript-works-inside-the-v8-engine-5-tips-on-how-to-write-optimized-code-ac089e62b12e
https://www.html5rocks.com/en/tutorials/speed/v8/
我们都知道 CSS 控制了“样式”(presentation layer),也知道布局是 CSS 的重中之重。
那么问题来了,究竟谁才是布局之王?
从:
table
div
+ float
+ 各种各种清除浮动带来的影响position
margin
、新增加一个元素、calc
、min/max height
来实现效果实现各式布局的时代一路走来,经历了各种将本来不用于布局的属性强行来布局后,专为布局而生的 Flexbox 和 grid,仿佛让前端er 们看到了布局的曙光:
考虑浏览器的兼容性?caniuse 一下:
https://caniuse.com/#search=Flexbox
https://caniuse.com/#search=grid
Flexbox 略好,但如果你不用考虑 ie11 的话加上 Autoprefixer 就可以忽略了。这一项 pass。
Flexbox 的关键词是伸缩性和响应式。
伸缩性顾名思义,Flexbox 提供一种更有效的方式来布置,对齐和分配容器中的物品之间的空间,即使它们的尺寸未知(因此 “flexible”)。
Flex 布局背后的主要思想是赋予容器更改其项目的宽度 / 高度(和顺序)以最好地填充可用空间(主要适应各种显示设备和屏幕尺寸)的能力。
需要注意的是,Flexbox 布局与方向无关(main axis 和 corss axis 可以通过 flex-direction
来互换),而不是常规布局(基于垂直方向的块和基于水平方向的内联块)。
Flexbox 可以多简化我们的布局方式呢,举个垂直居中例子:
1 | .container { |
https://css-tricks.com/centering-css-complete-guide/ 中举出来的为了实现垂直居中效果的各种 hack,被 Flexbox 短短的两句代码轻易解决了。
Flexbox 可以多伸缩性(flexible)呢(直接上代码把):
https://github.com/RayJune/JustToDo/blob/81171a39f9/src/styles/main-content.css#L69
几行代码实现 button 的响应式效果(responsive),欢迎在线访问
https://todo.rayjune.me 来查看效果 :)
Grid 的关键词是二维网格和响应式。
依然顾名思义,Grid 通过将页面分割成一个个网格,元素填充到响应表格中完成布局。
与 Flexbox 尤为不同的是,前者专注一维布局(main axis,corss axis 上作用效果次要),grid 可以掌握两个维度的布局。所以只要是 Flexbox 能做到的,grid 几乎都能做到:
1 | /* grid */ |
而且还能做得更多更好(更多 demo 建议查询 cssgrid.io,wesbos 的例子举得很形象,Gird 的强大超出想象)
既然 Flexbox 的特点在于:
我们不难推算出:更适合 Flexbox 的场合:
Grid 的优点在于:
所以更适合 Grid 的场合有:
grid-gap
可以轻松解决minmax()
,repeat()
和 auto-fill
等强大的功能来减少 @media query
软件开发中没有 silver bullet,只有 depends on。根据使用场景选择解决方案才是不变的的正确答案。
P.S. 我会告诉你 Flexbox 和 Grid 一起使用效果更好吗:)
The Flexbox aims at providing a more efficient way to lay out, align and distribute space among items in a container, even when their size is unknown and/or dynamic (thus the word “flex”).
The main idea behind the flex layout is to give the container the ability to alter its items’ width/height (and order) to best fill the available space (mostly to accommodate to all kind of display devices and screen sizes).
A flex container expands items to fill available free space, or shrinks them to prevent overflow.
Most importantly, the Flexbox layout is direction-agnostic as opposed to the regular layouts (block which is vertically-based and inline which is horizontally-based).
While those work well for pages, they lack flexibility to support large or complex applications (especially when it comes to orientation changing, resizing, stretching, shrinking, etc.).
So Flexbox layout is most appropriate to the components of an application, and small-scale layouts, while the Grid layout is intended for larger scale layouts.
css-tricks:
https://css-tricks.com/snippets/css/a-guide-to-Flexbox/
https://css-tricks.com/snippets/css/complete-guide-grid/
https://css-tricks.com/css-grid-replace-Flexbox/
course from Wes Bos:
https://Flexbox.io/
https://cssgrid.io/
jakearchibald:
https://jakearchibald.com/2014/dont-use-Flexbox-for-page-layout/
]]>探索一下,一个简单的斐波那契(Fibonacci)函数的实现能考到 JavaScript 的什么知识?
面试官:熟悉原生 JavaScript 把?写一个 Fibonacci 的实现?
小白:
这还不容易,我闭着眼就能写出五种语言的 Fibonacci 实现,用递归(recursion)实现起来简洁又美观:
1 | function getFibonaccis1(n) { |
面试官:
恩…你用到了递归,你知道用递归的坏处是什么吧?
小白:
比起循环,递归的效率低,但是 Knuth 大神说过:
We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.
也罢,面试官看来想让我写一个简单的循环实现,不如递归高大上,但同样实用:
1 | function getFibonaccis2(n) { |
面试官:恩(并没有想让你写一个循环版本出来)。那我问你递归在 JavaScript 中会出现什么特殊的性能问题吗,有的话要怎么修改递归实现的代码?
小白:敲头~!原来这厮要考我的是 JavaScript 运行栈的问题,如果函数递归调用过多会导致堆栈溢出(stack overflow),还好我码过 JavaScript Cookbook:
1 | var getFibonaccis3 = (function () { |
面试官眼前一亮:(黝黑),可是你这里还是函数迭代调用函数,和之前的有什么不同呢?
小白:这里我的确还是函数迭代调用函数,但是我利用闭包(closure)实现了一个存活的私有变量对象 fib,保存每一次生成的新的值。
由于在 JavaScript 中原始类型放在栈中,object 放在堆中,我这里用空间来换时间,大大减少了函数迭代调用的次数,所以优化了运行栈的问题。
但我还可以写出一个更好的实现(闭包 + 循环):
1 | var getFibonaccis4 = (function () { |
面试官:(这货竟然扯了这么多,不过我想考察的:
的目的达到了)
You got my offer~!
]]>整合了:为什么使用 box-sizing: border-box
,什么时候使用,使用它的好处和注意事项,力求完备的效果
我们都知道盒模型的构建(model box):
由内到外依次是 content, padding, margin, border;
也知道关于它的计算方式的黑历史:
标准盒模型的计算方式是:
1 | width = content |
这样不好吗?十分不好。
因为虽然我们设置的 width/height
直接等于元素的 content
宽高,但是显示出来的元素宽高可是加上了 padding
, border
的(margin
可能会因为 BFC 发生 margin collapsing,不好计算,所以我们认为 margin
是元素之外的元素间间距,没有考虑在内):
实际显示的 height/width
情况:
1 | width = content + padding * 2 + border * 2 // height 同理 |
使用起来别扭吗?十分别扭。每次计算宽高都还要在指定 width/height
的基础上加上 padding * 2 + border * 2
,简单的情况还好,遇到响应式布局等复杂情况数学老师就真的扎心了。
因为 IE 盒模型的计算方式是:
1 | width = content + padding * 2 + border * 2; // height 同理 |
所以有了 IE 盒模型的“复古”推崇,leader 再也不用担心我的数学了。
1 | * { |
是不是差了什么?:before
和 :after
这两个伪元素呢?(伪元素应该用 ::
表示,但目前 :
的适用性更好,所以这里用 :
)
1 | *, |
可是这样全局设置为 IE 盒模型不完全妥当,因为 box-sizing
属性不会默认继承。
如果你想在哪个元素使用标准和模型计算方式 box-sizing: content-box
时,会发现通配符把它的子元素也同意设置为 box-sizing: border-box
了(比如使用 disqus 时)。
为了应对这种情况我们有了以下终极方案:
1 | html { |
其中奥妙,想必读者一看便知。(还是来一行注释把:/* apply a natural box layout model to all elements, but allowing components to change */
)
通配符只有在类似 .foo > *
这样的情况下会速度很慢,普通状态下的通配符 *
和 h1
等元素一样快。
可能会有人担心通配符 *
的性能问题,这里就要辟谣了:
这便是现在通用的解决方案了,CSS 代码起手式,连 Paul Irish 也表示再也离不开这个 gist 了:https://www.paulirish.com/2012/box-sizing-border-box-ftw/。
当有一个绝妙的解决方案出现的时候,作为一个 web 开发者,千万别忘了兼容性:
caniuse 一下,https://caniuse.com/#search=caniuse ,一片飘绿,IE 11 都支持完备。
stackOverFlow 一下: border-box drawback
https://stackoverflow.com/questions/19940459/box-sizing-border-box#answer-19940588
The cons,
IE7 and below have no support, who cares right? Some sadly do.
IE8 and up have only partial support.
看来在 < IE8 的浏览器不支持,不过没关系,我们有万能的 polyfill: https://github.com/Schepp/box-sizing-polyfill
css-tricks 甚至特地宣布每年的二月一号为 International box-sizing Awareness Day,表示了对它的认可。
回到最初的话题,box-sizing: border-box
够完备吗?
现在我们可以自信的说:是的,它够完备。
paulirish:
https://www.paulirish.com/2012/box-sizing-border-box-ftw/
css-tricks:
https://css-tricks.com/international-box-sizing-awareness-day/
https://css-tricks.com/box-sizing/
stackoverflow:
https://stackoverflow.com/questions/19940459/box-sizing-border-box
https://stackoverflow.com/questions/10722841/box-sizing-border-box-to-border-box-or-not-to-border-box-all-elements
caniuse:
https://caniuse.com/#search=caniuse
jeremenichelli:
https://jeremenichelli.io/2015/05/why-nobody-knows-about-box-sizing/
谢谢观看,good day :)
]]>综合了 google 对于 reflow
的优化实践和 stubbornella.org 上对于 reflow
和 repaint
讲解,力求一目了然的效果。
在对某个 DOM 元素做非 layout 修改的时候(如 background-color
,visibility
)会导致这个元素的 repaint
。
性能代价在于浏览器必须验证 DOM 树上其他节点元素的 visibility。
在对某个 DOM 元素做关于 layout 修改的时候(如 width
)会导致:
因此性能消耗很大,有 User blocking 之说,要格外注意这种情况,过多 reflow
很影响用户体验。
因为 reflow
对性能的影响更大,又因为 reflow
和 repaint
不可避免,下面有几种尽量减少 reflow 影响的方法:
postion: absolute
或 position: fixed
来固定,这样可以将大范围的 reflow
变成单一范围的 repaint
<p style="font-weight: border">Another RayJune</p>
),style 应该都被设置在外部的一个 class 中,用修改 class 的方式修改 style 只产生一次 reflowA website can search which attribute will trigger repaint or reflow:
https://csstriggers.com/z-index
A repaint occurs when changes are made to an elements skin that changes visibility, but do not affect its layout. (such as background-color)
Repaint is expensive because the browser must verify the visibility of all other nodes in the DOM tree.
A reflow is even more critical to performance because it involves changes that affect the layout of a portion of the page (or the whole page).
For the purpose of re-rendering part or all of the document.
Reflow of an element causes the subsequent reflow of all child and ancestor elements as well as any elements following it in the DOM.
Reflows can be top-down or bottom-up as reflow information is passed to surrounding nodes.
Reflows are unavoidable, but you can reduce their impact.
Change classes as low in the dom tree as possible and thus limit the scope of the reflow to as few nodes as possible.
减少要操作的 DOM 级别,将回流的范围限制在尽可能小的节点区域。
For example, you should avoid changing a class on wrapper elements to affect the display of child nodes.
Object oriented css always attempts to attach classes to the object (DOM node or nodes) they affect, but in this case it has the added performance benefit of minimizing the impact of reflows.
We all know interacting with the DOM is slow. We try to group changes in an invisible DOM tree fragment and then cause only one reflow when the entire change is applied to the DOM.
Similarly, setting styles via the style attribute cause reflows.
Avoid setting multiple inline styles which would each cause a reflow, the styles should be combined in an external class which would cause only one reflow when the class attribute of the element is manipulated.
Apply animations to elements that are position fixed or absolute.
They don’t affect other elements layout.
So they will only cause a repaint rather than a full reflow. This is much less costly.
Opera also advises that we trade smoothness for speed.
What they mean by this is that you may want to move an animation 1 pixel at a time, but if the animation and subsequent reflows use 100% of the CPU the animation will seem jumpy as the browser struggles to update the flow.
Moving the animated element by 3 pixels at a time may seem slightly less smooth on very fast machines, but it won’t cause CPU thrashing on slower machines and mobile devices.
Even minor changes will cause reflows of all other nodes in the table.
The main reason these expressions are so costly is because they are recalculated each time the document, or part of the document, reflows.
As we have seen from all the many things that trigger a reflow, it can occur thousands and thousands of times per second. Beware!
https://developers.google.com/speed/articles/reflow?csw=1
In many cases, they are equivalent to laying out the entire page again.
Because reflow is a user-blocking operation in the browser, it is useful for developers to understand how to improve reflow time and also to understand the effects of various document properties (DOM depth, CSS rule efficiency, different types of style changes) on reflow time.
At Google, we test the speed of our web pages and applications in a variety of ways - and reflow is a key factor we consider when adding features to our UIs. We strive to deliver lively, interactive and delightful user experiences.
面对外界的嘈杂,有多久没有聆听过内心的声音了?
无法改变外界环境是一种常态,而我们只能去适应它。
多少次你在图书馆等自习场所自习时:
导致原本十二分的投入,变成了只有八分投入。事倍功半,不知如何去办。
这个时候可能你会选择带一个耳机(可以预见大多数人自习戴耳机真的是为了防止被其他噪音打断),调到很大声(长期这样做对耳朵不好),或许你的耳机还有降噪功能。
只为营造一个更专注的学习环境。
多少次晚上在寝室:
导致思维被带偏,主要的精力都拿去对抗噪音。环境聒噪,不知解决之道。
这个时候你可能会选择和其他人一起外放,只不过外放的是你喜欢的歌曲,以此来抵抗外界的噪音,或许你还会和相关同学交涉。
只为一刻内心宁静的感受和宝贵的睡眠。
一味用声音中和噪音亦可解决问题,可也丢失了聆听自我声音的机会。
亲,还记得来自内心的声音是什么样的吗?
其实就是自己最近买耳塞了 :)
以上是自己切身遇到的状况,没想到困扰多时的问题竟然被一对小小的耳塞解决了~!偶买噶,这么好的东西怎能不分享~!
如果你也被以上问题烦扰到的话,买一副安耳悠耳塞吧~!
他会实现
以至于:
最重要的是:它会还给你一个真正安静的,属于你的思考氛围。
如果身处嘈杂的环境,或许你可以尝试戴上耳塞,聆听内心的声音。:)
]]>The more deeply you force your brain to think, the better chance you have of learning and remembering.
This is a learning experience, not a reference book.
Do you
Your brain craves novelty. It’s always searching, scanning, waiting for something unusual. It was built that way, and it helps you stay alive.
crave novelty 渴望新鲜的事物
It doesn’t bother saving the boring things; they never make it past the “this is obviously not important” filter.
How does your brain know what’s important?
Suppose you’re out for a day hike and a tiger jumps in front of you—what happens inside your head and body?
Neurons fire. Emotions crank up. Chemicals surge.
神经元会点火,情绪爆发,释放一些化学物质。
And that’s how your brain knows: This must be important! Don’t forget it!
But imagine you’re at home, or in a library. It’s a safe, warm, tiger-free zone. You’re studying.
Just one problem. Your brain’s trying to make sure that this obviously non-important content doesn’t clutter up scarce resources. Resources that are better spent storing the really big things. Like tigers. Like the danger of fire. Like how you should never again snowboard in shorts.
And there’s no simple way to tell your brain, “Hey brain, thank you very much, but no matter how dull this book is, and how little I’m registering on the emotional Richter scale right now, I really do want you to keep this stuff around.”
So what did this book do?
If you really want to learn, pay attention to how you pay attention. Think about how you think. Learn how you learn.
So how do you get your brain to think HTML & CSS are as important as a tiger?
Don’t just read. Stop and think.
When the book asks you a question, don’t just skip to the answer. Imagine that someone really is asking the question.
The more deeply you force your brain to think, the better chance you have of learning and remembering.
Don’t just look at the exercises. Do it by yourself.
There’s plenty of evidence that physical activity while learning can increase the learning.
Part of the learning (especially the transfer to long-term memory) happens after you put the book down.
Your brain needs time on its own, to do more processing.
If you put in something new during that processing time, some of what you just learned will be lost.
Speaking activates a different part of the brain. If you’re trying to understand something, or increase your chance of remembering it later, say it out loud.
Better still, try to explain it out loud to someone else.
You’ll learn more quickly, and you might uncover ideas you hadn’t known were there when you were reading about it.
Pay attention to whether your brain is getting overloaded.
If you find yourself starting to skim the surface or forget what you just read, it’s time for a break.
Once you go past a certain point, you won’t learn faster by trying to shove more in, and you might even hurt the process.
Your brain needs to know that this matters. Get involved with the stories. Make up your own captions for the photos.
Apply this to something new you’re designing, or rework an older project.
Just do something to get some experience beyond the exercises and activities in this book.
That’s where HTML comes in. HTML tells the browser all about the content and structure of the page.
When the browser reads your HTML, it interprets all the tags that surround your text. Tags are just words or characters in angle brackets, like <head>, <p>, <h1>
, and so on.
The tags tell the browser about the structure and meaning of your text.
So rather than just giving the browser a bunch of text, with HTML you can use tags to tell the browser what text is in a heading, what text is a paragraph, what text needs to be emphasized, or even where images need to be placed.
For starters. Remember that HTML stands for HyperText Markup Language, so HTML gives you a way to “mark up” your text with tags that tell the browser how your text is structured.
But there is also the HyperText aspect of HTML, which we’ll talk about a little later in the book.
Correct, and good catch. Browsers ignore tabs, returns, and most spaces in HTML documents. Instead, they rely on your markup to determine where line and paragraph breaks occur.
<html>
tag? Isn’t it obvious this is an HTML document?The <html>
tag tells the browser your document is actually HTML.
While some browsers will forgive you if you omit it, some won’t, and as we move toward “industrial-strength HTML” later in the book, you’ll see it is quite important to include this tag.
An HTML file is a simple text file. Unlike a word processing file (like .doc for word), there is no special formatting embedded in it.
By convention, we add an “.html” to the end of the filename to give the operating system a better idea of what the file is.
But, as you’ve seen, what really matters is what we put inside the file.
To tell the browser about the structure of your page, use pairs of tags around your content.
Element = Opening Tag + Content + Closing Tag (such as <a href="http://www.rayjune.me">Another RayJune</a>
)
There are a few elements, like <img>
, that are an exception to this rule.
Well, the tags are supposed to match. In general, browsers do a pretty good job of figuring out what you mean if you write incorrect HTML.
But, as you’re going to see, these days there are big benefits to writing totally correct HTML.
While this does mean you need to learn two languages, you’ll discover that because each language is good at what it does.
And this is actually easier than if you had to use one language to do both jobs.
In Chapter 1 we found it to be a nice markup language (the “ML” in HTML) for describing the structure of web pages.
Now we’re going to check out the “HT” in HTML, hypertext, which will let us break free of a single page and link to other pages:
Use the <a>
element to create a hypertext link to another web page.
Attributes are used to customize an element. And with an attribute you can provide additional information about the element.
href: It means “hypertext reference“, but we just call me “href” for short.
A hypertext reference is just another name for a resource that is on the Internet or your computer. Usually the resource is a web page, but I can also point to PDF documents…all kinds of things.
<a>
element for that?Yes, if you put an <img>
element between the <a>
tags, then your image will be clickable just like text.
<a>
tags and it will be clickable? Like, say, a paragraph?You can indeed put a <p>
element inside an <a>
element to link an entire paragraph.
But you’ll mostly be using text and images (or both) within the <a>
element.
The path meanings:
You’ve certainly learned a lot already: tags, elements, links, paths…but it’s all for nothing if you don’t create some killer web pages with that knowledge.
Remember:
In the meantime, you can also think about block versus inline this way:
When you’re designing a page, you typically start with the bigger chunks (the block elements) and then add in the inline elements as you refine the page.
define:
Elements that don’t have any content by design are called void elements. (like
<a>
,<img>
,<br>
)This is a convenient shorthand that reduces the amount of markup in your HTML.
In Chapter 1 we said that an element is an opening tag + content + closing tag.
<br>
an element? It doesn’t have any content, and it doesn’t even have a closing tag.Exactly. It doesn’t have any content. The <br>
element is an element that doesn’t have any content. Why? Because it’s just meant to be a line break, nothing else.
So, when an element doesn’t have any real content by design, we just use a shorthand to represent the element and it ends up looking like <br>
.
After all, if we didn’t have this shorthand, you’d be writing <br></br>
every time you needed a line break, and how much sense does that make?
<br>
, but with <br />
. What does that mean?It means exactly the same thing. The syntax used in <br />
is a more strict syntax that works with XHTML.
Wheneven you see <br />
, just think <br>
, and unless you’re planning on writing pages compliant with XHTML, you should just use <br>
in your HTML.
We always want to choose the HTML element that is closest in meaning to the structure of your content.
If this is a list, let’s use a list element. Doing so gives the browser and you the most power and flexibility to display the content in a useful manner.
<ol>
and <li>
together?Yes. Neither one of these elements really makes sense without the other.
Remember, a list is really a group of items: the <li>
element is used to identify each item, and the <ol>
element is used to group them together.
<ol>
or <ul>
element?No, the <ol>
and <ul>
elements are designed to work only with the <li>
element.
Browsers use <
and >
to begin and end tags, using them in the content of your HTML can cause problems.
But HTML gives you an easy way to specify these and other special characters using a simple abbreviation called a character entity.
For example, the > character’s abbreviation is >
and the < character’s is <
.
So:
1 | The <html> element rocks. |
Another important special character you should know about is the &
(ampersand) character. If you’d like to have an &
in your HTML content, use the character entity &
instead of the &
character itself.
You can look up common ones at this URL: http://www.w3schools.com/tags/ref_entities.asp
or, for a more exhaustive list, use this URL: http://www.unicode.org/charts/
&
is special and I need to use the entity &
in its place, but to type in any entity I have to use a &
. So for, say, the >
entity, do I need to type > ?No, no! The reason &
is special is precisely because it is the first character of any entity. So, it’s perfectly fine to use &
in your entity names, just not by itself.
Just remember to use & anytime you type in an entity, and if you really need an &
in your content, use &
instead.
You can use either the number, like d
or the name of an entity in your HTML (they do the same thing). However, not all entities have names, so in those cases your only choice is to use the number.
A Uniform Resource Locator (URL) is a global address that can be used to locate anything on the Web, including HTML pages, audio, video, and many other forms of web content.
In addition to specifying the location of the resource, a URL also names the protocol that you can use to retrieve that resource(usually HTTP).
In other words, it’s an agreed-upon method (a protocol) for transferring hypertext documents around the Web.
agreed-upon 公认的,一致同意的
While “hypertext documents” are usually just HTML pages, the protocol can also be used to transfer images, or any other file that a web page might need.
So each time you type a URL into your browser’s address bar, the browser asks the server for the corresponding resource using the HTTP protocol.
If the server finds the resource, it returns it to the browser and the browser displays it. What happens if the server doesn’t find it? –’404 Error’
The order of attributes is not important in any element. So, use any ordering you like.
To work consistently with the most browsers, always start your id with a letter (A–Z or a–z) and follow it with any letter, digit, hyphen, underscore, colon, or period.
So, while you can’t use a space and have a name like “RayJune Xue”, that isn’t much of a restriction because you can always have “RayJune-Xue”, “RayJune_Xue”,RayJuneXue, and so on.
Browsers handle <img>
elements a little differently than other elements.
Take an element like an <h1>
or a <p>
. When the browser sees these tags in a page, all it needs to do is display them. Pretty simple.
But when a browser sees an <img>
element, something very different happens: the browser has to retrieve the image before it can be displayed in a page.
For example:
1 | <body> |
Now let’s step through how the browser retrieves and displays this page when it get a request :
Luckily, only three of those formats are commonly used on the Web: JPEG, PNG, and GIF. The only tricky part is deciding which to use when.
Works best for continuous tone images, like photographs.
Can represent images with up to 16 million different colors.
Is a “lossy” format because to reduce the file size, it throws away some information about the image.
Does not support transparency.
Files are smaller for more efficient web pages.
No support for animation.
But JPEG is not perfetc: Looked at lines, logos, small text, solid colors? They don’t look so great with JPEG.
Works best for images with a few solid colors, and images wit lines, like logos, clip art and small text in images.
PNG can represent images with millions of different colors.
And PNG has three different size options: PNG-24 (supports millions of colors), PNG-16 (supports thousands of colors), and PNG-8 (supports 256 colors), depending on your needs.
PNG compresses the file to reduce its size, but doesn’t throw anything way. So, it is a “lossless” format.
support transparency.
Files tend to be larger than their JPEG equivalents, but can be smaller or larger than GIF depending on the number of colors used.
Works best for images with a few solid colors, and images wit lines, like logos, clip art and small text in images.
GIF can represent images with up to 256 different colors.
also a “lossless” format.
GIF also supports transparency, but allows only one color to be set to “transparent.”
Files tend to be larger than their JPEG equivalents.
Supports animation.
<img>
element is void. But doesn’t it have content (the image)?Well, to be more precise, a void element is an element that doesn’t have any content in the HTML page to put the opening and closing tags around.
True, an image is content, but the <img>
element refers to the image.
The image isn’t part of the HTML page itself. Instead, the image replaces the <img>
element when the browser displays the page.
And remember, HTML page are purely text, so the image could never be directly part of the page. It’s always a separate thing.
Browsers often retrieve the images concurrently. That is, the browser makes requests for multiple images at the same time.
Given the speed of computers and networks, this all happens fast enough that you usually see a page display along with its images.
1 | <img src="images/logo.jpg" alt="This is a logo"> |
To handle modern displays, the concept of a CSS pixel has been created. The CSS pixel is 1/96 of an inch (96 ppi).
If you’re placing a transparent image in your web page, make sure the matte color of the image matches the background color of your web page.
Rather than continue to crank out version 6, 7, 8 of HTML, the standards guys (and gals) have turned the specification into a living standard that will document the technology as it evolves.
So, no more version numbers. And you can stop calling it HTML5 because it’s just “HTML” from here on out.
并且 HTML5 是backwards compatibility(向后兼容)的,不用担心你的代码在更新的浏览器中运行不了。
If you’re writing solid HTML today and the spec changes tomorrow to incorporate a new element, then you can just keep on doing what you’re doing.
It’s up to you whether you want to use that new element or not.
The specification is the document that specifies what the HTML standard is; that is, what elements and attributes are in HTML, and more.
This document is maintained by the World Wide Web Consortium (W3C, for short), but anyone can contribute to it and have a say in how the standard is developed.
The <meta>
tag belongs in the <head>
element (remember that the <head>
contains information about your page). Adding a meta tag to specify the character encoding.
‘meta’ means we’re going to tell the browser something about the page.
The charset arrtibute is where we specify the character encoding. Add this line above any other elements in the <head>
element
1 |
|
<meta>
tags that look like this: <meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
. Do I need to use this instead sometimes?No. That is the format for the <meta>
tag in HTML 4.01 and earlier. In HTML5, you can just write <meta charset="utf-8">
.
1 |
|
or linking from “lounge.html” to the external stylesheet
1 |
|
<em>
when I’m overriding the inherited value?With CSS, the most specific rule is always used.
So, if you have a rule for <body>
, and a more specific rule for <em>
elements, it is going to use the more specific rule.
In general, all of the styles that affect the way your text looks, such as font color (the color property), the font-family, as you’ve just seen, and other font-related properties such as font-size, font-weight (for bold text), and font-style (for italics) are inherited.
Other properties, such as border, are not inherited. A lot of the time, you can follow your common sense.
1 | blockquote.greentea, p.greentea { |
elements can be in more than one class.
1 | <p class="greentea raspberry blueberry"> |
You’ve got quite a few choices for specifying font sizes: px
, em
, percentages(%
), and keywords. Here’s a recipe:
Yes, and what those sizes are depends on your browser, and even the version of the browser you are running. But in most cases, the default body font size will be 16 pixels.
Again, it depends on the browser, but in general,
<h1>
is 200%<h2>
is 150%<h3>
is 120%<h4>
is 100%<h5>
is 90% <h6>
is 60%of the default body text font size, if the body font-size change, it change, too.
Notice that by default <h4>
is the same font size as the body font size, and <h5>
and <h6>
are smaller.
每个 font-family
包含一组有共同特征的字体。共有 5 个字体系列:sans-serif
、serif
、monospace
、cursive
和 fantasy
,每个字体系列都包括大量字体,所以我们看到的只是每个字体系列中很少的几个字体例子。
sans-serif
无衬线,清晰、可读性好serif
有衬线,高雅,传统monospace
等宽,适合代码、像打印机打出来的cursive&fantasy
有趣、像手写通常,你指定的 font-family
包含一个候选字体列表(字体优先列表),它们都来自同一个字体系列。而最后总是放一个通用的字体系列名(如 sans-serif
)(如果指定的前几个字体都无法找到,浏览器就会选择一个实际的字体来代替 serif
或 sans-serif
. 取代它的字体是浏览器定义的该字体系列的默认字体)。
1 | body { |
@font-face
,这个规则允许你定义一种字体的名字和位置,然后可以在你的页面中使用。
web 开放字体格式(Web open font format)woff。
@font-face
规则不论看起来还是从表现上讲都不像一个 CSS 规则,我们可以认为 @font-face
是一个内置的 CSS 规则,而不是一个选择器规则。
利用 @font-face
规则可以获取一个 Web 字体,并为它分配一个 font-family
名。最前面的 @ 就是一个很好的线索,说明这不是一个普通的 CSS 规则。
类似的内置 CSS 规则还有:
@import
: 允许导入其他 CSS 文件(而不是 HTML 中通过一个 link 导入)@media
: 允许创建特定于某些”媒体”类型的 CSS 规则,如手机等1 | body { |
1 | body { |
You can also specify the red, green, and blue values as a numeric value between 0 and 255. So:
1 | body { |
Each set of two digits of a hex code just represents the red, green, and blue component of the color.
So the first two digits represent the red, the next two the green, and the last two represent the blue.
1 | body { |
1 | #cc6600 -> cc: red, 66: green, 00: blue |
1 | because c: 12, so cc = 12 * 16 + 12, cc = 204 |
You’re allowed to use shorthand if each two-digit pair shares the same numbers.
So, for instance, #ccbb00
can be abbreviated #cb0
, or #11eeaa
as #1ea
. However, if your hex code is something like #ccbb10
, then you can’t abbreviate it.
You could, but there’s a better way. HTML has an element <del>
that marks content in your HTML as content that should be deleted. There is a similar element called <ins>
that marks content that should be inserted.
By using <del>
and <ins>
, you are marking the meaning of your content in addition to styling it.
最基本的文本颜色搭配原则:对于文本和背景,要使用对比度最大的颜色,这样能帮助提高可读性。
CSS treats every single element as if it were represented by a box.
content
-> padding
-> border
-> margin
padding
and margins
?That’s basically right. Both are used to provide more visual space, and you can’t give the padding
or margin
a direct color or any kind of decoration.
But because they are transparent, they will take on the color of any background colors or background images.
One difference between padding and margins is that the element’s background color (or background image) will extend under the padding, but not the margin. You’ll see how this works in a bit.
content
area determined solely by the size of the content in it?Browsers use several rules to determine the width and height of the content area.
The short answer is that while the content is the primary way the size of an element is determined, you can set the width and height yourself if you need control over the size of the element.
If you need to get that image into your paragraph element, so you’ll be using an <img>
element, right?
There is another way. Using CSS, you can add a background image to any element using the background-image property. Let’s give it a try and see how it works:
1 | .someClass { |
<img>
element?No, the background-image
property has a very specific purpose, which is to set the background image of an element.
It isn’t for placing images in a page—for that, you definitely want to use the <img>
element.
<img>
element, on the other hand, is used to include an image that has a more substantial role in the page, like a photo or a logo.The background-image
property places an image in the background of an element. Two other properties also affect the background image: background-position
and background-repeat
.
By default, background images are repeated, we can use background-repeat: no-repeate
to handle this.
Also, by default, browsers position a background image in the top left of the element which is where we want it, but let’s also add a background-position property just to give it a try.
1 | .someClass { |
1 | <link href="lounge-mobile.css" rel="stylesheet" media="screen and (max-device-width: 480px)"> |
1 | @media screen and (min-device-width: 481px) { |
So, the way this works, only the CSS rules that are specific to a media type are included in an @media
rule. All the rules that are common to all the media types are included in the CSS file below the @media
rules, so that way you don’t have any unnecessarily repeated rules.
And, when a browser loads the page, it determines through the media queries the rules that are appropriate for the page, and ignores any that don’t match.
<link>
or @media
to specify different CSS rules for different media types and characteristics?Either one will work.
But notice that if you put all your rules in one file and split them up using @media
rules, your CSS could get pretty big.
By using different <link>
elements for different media types, you can keep your CSS organized in different files depending on the media type. So, if your CSS files are fairly large, we recommend using <link>
elements to specify different stylesheets.
div
just like a container.
You want to add structure where it has a real purpose, but don’t add structure for structure’s sake.
Always keep your structure as simple as possible to get the job done.
width
meansThe content, only the content.
width
of an element, then where does the width
come from?The default width for a block element is “auto”, which means that it will expand to fill whatever space is available.
You can specify an actual size(200 px
)—or you can specify a percentage(50%
).
If you use a percentage, then the width is calculated as a percentage of the width of the container the element is in (which could be the <body>
, a <div>
, etc.).
In general, the height of an element is left at the default, which is auto, and the browser expands the content area vertically so all of the content is visible.
You can explicitly set a height, but you risk having the bottom of your content overflow into other elements if your height isn’t big enough to contain it.
So in general, leave your element heights unspecified so they default to auto.
The truth is that text-align
will align all the inline content in a block element.
So in this case, we’re setting the property on the <div>
block element, and all its inline content is nicely centered as a result.
Just remember that text-align, despite its name, works on any kind of inline element One other thing to keep in mind: the text-align
property should be set on block elements only. It has no effect if it’s used directly on inline elements (like <img>
).
<div>
is all inside other block elements, like <h2>
, <h3>
, and <p>
. So, if text-align is aligning inline elements in the <div>
block element, how is the text in these nested block elements getting aligned?That’s because these block elements inherit the text-align
property from the <div>
.
So here’s the difference: rather than the <div>
itself aligning the text in the headings and the paragraphs (which it won’t do because these are block elements), the headings and paragraphs are inheriting the text-align value of “center”, and then aligning their own content to center.
This gives you a lot of leverage when you use a <div>
, because you can wrap a section of content in a <div>
and then apply styles to the <div>
rather than each individual element.
Of course, keep in mind that not all properties are inherited by default, so this won’t work for all properties.
1 | #elixirs h2 { |
1 | #elixirs > h2 { |
1 | { |
The border shorthand is even more flexible than margins or padding because you can specify them in any order you like.
1 | { |
You can also use shorthand for backgrounds:
1 | { |
<span>
elements? Actually, what about inline elements in general?You can set the width of inline elements like <span>
, <em>
, and <strong>
, but you won’t notice any effect until you position them.
You can also add margin and padding to these elements, as well as a border. Margins and padding on inline elements work a little differently from block elements—if you add a margin on all sides of an inline element, you’ll only see space added to the left and right.
You can add padding to the top and bottom of an inline element, but the padding doesn’t affect the spacing of the other inline elements around it.
img
?img
are a little different from other inline elements. The width, padding, and margin properties all behave more like they do for a block element.
If you set the width of an image using either the width attribute in the <img>
element or the width property in CSS, the browser scales the image to fit the width you specify.
1 | #elixirs a:link { |
1 | #elixirs a:focus { |
The focus state occurs when the browser focuses on your link.
What does that mean? Some browsers allow you to press your Tab key to rotate through all the links on your page.
When the browser comes to a link, that link has the “focus”.
Setting a value for the focus pseudo-class is helpful for accessibility because those who need to use a keyboard to access a link (as opposed to a mouse) will know when they’ve got the right link selected.
1 | #elixirs a:active { |
The active state occurs when the user first clicks on a link.
They sure can. You determine which style is applied by the ordering of your rules. So, the right ordering is generally considered to be:
Pseudo usually means something that looks like the real thing, but isn’t.
Everyone knows what a CSS class is. It’s a grouping you create to place elements in so you can style them together.
Put “pseudo” and “class” together and you have a pseudo-class: it acts like a class, but it isn’t a real class.
And yet, a:link
, a:visited
, and even a:hover
all allow you to specify style, just like they were classes.
In other words, you can style pseudo-classes, but no one ever types them into their HTML.
The browser goes through and adds all your <a>
elements to the right pseudo-classes.
:visited
pseudo-class. :hover
pseudo-class. Oh, now the user isn’t hovering? The browser yanks it out of the “hover pseudo-class.
Can Pseudo just do links?
No, I do other elements too. Modern browsers already support pseudo-classes like :hover
on other types of elements. And there are some other pseudo-classes, too.
For instance, the pseudo-class :first-child
is assigned to the first child of any element, like the first paragraph in a <blockquote>
. And you can even select the last paragraph of a <blockquote>
with the :last-child
pseudo-class.
Flow is actually what the browser uses to lay out a page of HTML elements.
The browser starts at the top of any HTML file and follows the flow of elements from top to bottom, displaying each element it encounters.
So the first element in a document is displayed first, then a linebreak, followed by the second element, then a linebreak, and so on, from the top of your file to the bottom. That’s flow.
Inline elements are flowed next to each other, horizontally, from top left to bottom right.
Floated elements are ignored by block elements, while inline elements know they are there.
当设置浮动时,该元素会脱离普通文档流,浮上去。这时候其余块元素会忽视掉产生浮动的元素,该怎么排还是怎么排,但内联元素会考虑已浮动元素的外边框,围绕着边框排列。
As you’re going to see, there are many ways to do things in CSS, and each method has its own strengths and weaknesses.
What’s important to you is that you understand the techniques so that you can apply them when and where you need to.
No.
But if you think about it, if you were to float to the center, then the inline content under the floated element would have to be flowed around both sides of your element which would be quite tricky to get to work in a browser.
No, they don’t, and it’s pretty easy to see why.
Unlike block elements that are flowed on the page, floated elements are just, well, floating.
In other words, the margins of floated elements aren’t actually touching the margins of the elements in the normal flow, so they can’t be collapsed.
Yes, you sure can. The best example —and a common one—is to float images.
Give it a try—float an image left or right in a paragraph and you’ll see your text flow around it.
When an element is absolutely positioned, the first thing the browser does is remove it completely from the flow.
The browser then places the element in the position indicated by the top and right properties (you can use bottom and left as well).
Because the sidebar is out of the flow, the other elements don’t even know it is there and they ignore it totally.
Elements that are in the flow don’t even wrap their inline content around an absolutely positioned element. They are totally oblivious to it being on the page.
The default value for positioning is static
.
With static positioning, the element is placed in the normal document flow and isn’t positioned by you—the browser decides where it goes.
You can use the float property to take an element out of the flow, and you can say it should float left or right, but the browser is still ultimately deciding where it goes.
Compare this to the absolute
value for the position property. With absolute positioning, you’re telling the browser exactly where to position elements.
You can absolutely position any element, block or inline.
Just remember that when an element is absolutely positioned, it is removed from the normal flow of the page.
No, you don’t have to specify a width for absolutely positioned elements.
But if you don’t, by default, the block element will take up the entire width
of the browser, minus any offset you specify from the left or right.
This might be exactly what you want, or it might not. So set the value of the width property if you want to change this default behavior.
No. Another common way to position elements is using percentages.
If you use percentages, the positions of your elements may appear to change as you change the width of your browser.
For example, if your browser is 800 pixels wide, and your element’s left position is set to 10%
, then your element will be 80 pixels from the left of the browser window. But if your browser is resized to 400 pixels wide, then the width will be reduced to 10%
of 400 pixels, or 40 pixels from the left of the browser window.
Another common use for percentages is in specifying widths.
If you don’t need specific widths for your elements or margins, then you can use percentages to make both your main content area and your sidebars flexible in size. You’ll see this done a lot in two-column and three-column layouts.
No, z-indexes tend to be used most often for various advanced uses of CSS, especially when web page scripting is involved.
为什么不用表格布局
If you tell me that you can easily do the same with a table-based layout (remember - the HTML isn’t changing) then by all means use tables for layout.
Two other important things are accessibility and SEO.
Both care about in what order information is presented. You cannot easily present your navigation at the top of the page if your table-based layout puts it in the 3rd cell of the 2nd row of the 2nd nested table on the page.
So your answers are maintainability, accessibility and SEO.
It just depends on what you need.
If you really need an element to appear at a precise position in the page, then absolute positioning is the way to go.
But if you want to have text flow around an image, you’ll definitely want to use float.
Use z-index, only work for positioned element.
1 | #div1 { |
Yes, but it’s a very large number, and practically, you’ll never need your z-index values to go that high.
Can any element have a z-index?
No, only elements that have been positioned with CSS using absolute
, relative
, or fixed
positioning.
Only 10–20% of the end user response time is spent downloading the HTML document. The other 80–90% is spent downloading all the components in the page..
This book will change your approach to performance optimization.
When Steve began researching performance for our Platform Engineering group at Yahoo!, I believed performance was mainly a backend issue. But he showed that frontend issues account for 80% of total time.
I thought frontend performance was about optimizing images and keeping CSS and JavaScript external, but the 176 pages and 14 rules you’re holding in your hand right now are proof that it’s much more.
有些人会认为后端更影响网页体验;
In reality, for most web pages, less than 10–20% of the end user response time is spent getting the HTML document from the web server to the browser.
If you want to dramatically reduce the response times of your web pages, you have to focus on the other 80–90% of the end user experience.
What is that 80–90% spent on? How can it be reduced? The chapters that follow lay the groundwork for understanding today’s web and provide 14 rules for making them faster.
Looking at the HTTP traffic in this way, we see that at least 80% of the end user response time is spent on the components in the page.
If we dig deeper into the details of these charts, we start to see how complex the interplay between browsers and HTTP becomes. Earlier, I mentioned how the HTTP status codes and headers affect the browser’s cache. In addition, we can make these observations:
Instead, you can see a blank space with no downloads that occurs immediately following the HTML document’s HTTP request. This is time when the browser is parsing HTML, JavaScript, and CSS, and retrieving components from its cache.
Figure A-2 has a maximum of three HTTP requests happening in parallel, whereas in Figure A-1, there are as many as six or seven simultaneous HTTP requests. This behavior is due to the number of different hostnames being used, and whether they use HTTP/1.0 or HTTP/1.1. Chapter 6 explains these issues in the section “Parallel Downloads.”
That’s because in most situations, browsers block additional HTTP requests while they download scripts. See Chapter 6 to understand why this happens and how to use this knowledge to improve page load times.
Figuring out exactly where the time goes is a challenge. But it’s easy to see where the time does not go—it does not go into downloading the HTML document, including any backend processing.
That’s why frontend performance is important.
In any optimization effort, it’s critical to profile current performance to identify where you can achieve the greatest improvements. It’s clear that the place to focus is frontend performance.
critical 至关重要的,评论的,批评的
profile 简要描述,轮廓
If we were able to cut backend response times in half, the end user response time would decrease only 5–10% overall. If, instead, we reduce the frontend performance by half, we would reduce overall response times by 40–45%.
Reducing backend latency involves projects such as redesigning application architecture and code, finding and optimizing critical code paths, adding or modifying hardware, distributing databases, etc.
These projects take weeks or months.
Most of the frontend performance improvements described in the following chapters involve best practices, such as changing web server configuration files (Chapters 3 and 4); placing scripts and stylesheets in certain places within the page (Chapters 5 and 6); and combining images, scripts, and stylesheets (Chapter 1).
These projects take hours or days—much less than the time required for most backend improvements.
Over 50 teams at Yahoo! have reduced their end user response times by following the best practices described here, many by 25% or more.
In some cases, we’ve had to go beyond these rules and identify improvements more specific to the site being analyzed, but generally, it’s possible to achieve a 25% or greater reduction just by following these best practices.
the Performance Golden Rule:
The rest of this book offers precise guidelines for reducing that 80–90% of end user response time. In demonstrating this, I’ll cover a wide span of technologies: HTTP headers, JavaScript, CSS, Apache, and more.
After that come the 14 rules for faster performance, each in its own chapter.
The rules are listed in general order of priority. A rule’s applicability to your specific web site may vary.
For example, Rule 2 is more appropriate for commercial web sites and less feasible for personal web pages. If you follow all the rules that are applicable to your web site, you’ll make your pages 25–50% faster and improve the user experience.
The last part of the book shows how to analysis the 10 top U.S. web sites from a performance perspective.
HyperText Transfer Protocol (HTTP) is how browsers and servers communicate with each other over the Internet.
The HTTP specification was coordinated by the World Wide Web Consortium (W3C) and Internet Engineering Task Force (IETF), resulting in RFC 2616. HTTP/1.1 is the most common version today, but some browsers and servers still use HTTP/1.0.
HTTP is a client/server protocol made up of requests and responses.
Like many Internet services, the protocol uses a simple, plaintext format. The types of requests are GET, POST, HEAD, PUT, DELETE, OPTIONS, and TRACE. I’m going to focus on the GET request, which is the most common.
A GET request includes a URL followed by headers.
The HTTP response contains a status code, headers, and a body.
The following example shows the possible HTTP headers when requesting the script yahoo_2.0.0-b2.js.
1 | GET /us.js.yimg.com/lib/common/utils/2/yahoo_2.0.0-b2.js HTTP/1.1 |
The size of the response is reduced using compression if both the browser and server support it.
Browsers announce their support of compression using the Accept-Encoding header. Servers identify compressed responses using the Content-Encoding header.
1 | GET /us.js.yimg.com/lib/common/utils/2/yahoo_2.0.0-b2.js HTTP/1.1 |
If the browser has a copy of the component in its cache, but isn’t sure whether it’s still valid, a conditional GET request is made.
If the cached copy is still valid, the browser uses the copy from its cache, resulting in a smaller response and a faster user experience.
Typically, the validity of the cached copy is derived from the date it was last modified.
The browser knows when the component was last modified based on the Last-Modified header in the response. Just like browser is essentially saying, “I have a version of this resource with the following last modified date. May I just use it?”
1 | GET /us.js.yimg.com/lib/common/utils/2/yahoo_2.0.0-b2.js HTTP/1.1 |
If the component has not been modified since the specified date, the server returns a “304 Not Modified” status code and skips sending the body of the response, resulting in a smaller and faster response.
In HTTP/1.1 the ETag and If-None-Match headers are another way to make conditional GET requests. Both approaches are discussed in Chapter 13.
1 | HTTP/1.1 304 Not Modified |
Conditional GET requests and 304 responses help pages load faster, but they still require making a roundtrip between the client and serverto perform the validity check.
The Expires header eliminates the need to check with the server by making it clear whether the browser can use its cached copy of a component.
eliminates 消除,排除
1 | HTTP/1.1 200 OK |
When the browser sees an Expires header in the response, it saves the expiration date with the component in its cache.
As long as the component hasn’t expired, the browser uses the cached version and avoids making any HTTP requests.
Chapter 3 talks about the Expires and Cache-Control headers in more detail.
HTTP is built on top of Transmission Control Protocol (TCP).
In early implementations of HTTP, each HTTP request required opening a new socket connection.
This is inefficient because many HTTP requests in a web page go to the same server.
Persistent Connections (also known as Keep-Alive in HTTP/1.0) was introduced to solve the inefficiency of opening and closing multiple socket connections to the same server.
It lets browsers make multiple requests over a single connection.
Browsers and servers use the Connection header to indicate Keep-Alive support. The Connection header looks the same in the server’s response.
1 | GET /us.js.yimg.com/lib/common/utils/2/yahoo_2.0.0-b2.js HTTP/1.1 |
The browser or server can close the connection by sending a Connection: close header. Technically, the Connection: keep-alive header is not required in HTTP/1.1, but most browsers and servers still include it.
Pipelining, defined in HTTP/1.1, allows for sending multiple requests over a single socket without waiting for a response. Pipelining has better performance than persistent connections.
Unfortunately, pipelining is not supported in Internet Explorer (up to and including version 7), and it’s turned off by default in Firefox through version 2. Until pipelining is more widely adopted, Keep-Alive is the way browsers and servers can more efficiently use socket connections for HTTP.
This is even more important for HTTPS because establishing new secure socket connections is more time consuming.
This chapter contains just an overview of HTTP and focuses only on the aspects that affect performance.
To learn more, read the HTTP specification (http://www.w3.org/ Protocols/rfc2616/rfc2616.html) and HTTP: The Definitive Guide by David Gourley and Brian Totty (O’Reilly; http://www.oreilly.com/catalog/httptdg).
The parts highlighted here are sufficient for understanding the best practices described in the following chapters.
The Performance Golden Rule, reveals that only 10–20% of the end user response time involves retrieving the requested HTML document. The remaining 80–90% of the time is spent making HTTP requests for all the components (images, scripts, stylesheets, Flash, etc.) referenced in the HTML document.
Thus, a simple way to improve response time is to reduce the number of components, and, in turn, reduce the number of HTTP requests.
Suggesting the idea of removing components from the page often creates tension between performance and product design. In this chapter, I describe techniques for eliminating HTTP requests while avoiding the difficult tradeoff decisions between performance and design.
These techniques include using image maps, CSS sprites, inline images, and combined scripts and stylesheets.
If you use multiple hyperlinked images in this way, image maps may be a way to reduce the number of HTTP requests without changing the page’s look and feel.
An image map allows you to associate multiple URLs with a single image. The destination URL is chosen based on where the user clicks on the image.
There are two types of image maps.
Server-side image maps submit all clicks to the same destination URL, passing along the x,y coordinates of where the user clicked. The web application maps the x,y coordinates to the appropriate action.
Client-side image maps are more typical because they map the user’s click to an action without requiring a backend application. The mapping is achieved via HTML’s MAP tag.
1 | <img usemap="#map1" border=0 src="/images/imagemap.gif"> |
No Image Map: http://stevesouders.com/hpws/imagemap-no.php
Image Map: http://stevesouders.com/hpws/imagemap.php
There are drawbacks to using image maps. Defining the area coordinates of the image map, if done manually, is tedious and error-prone, and it is next to impossible for any shape other than rectangles.
Some people do not like image maps because they perceive them as not very accessible or discoverable, and as such there are other markup/css/javascript techniques that work better.
Like image maps, CSS sprites allow you to combine images, but they’re much more flexible.
To use CSS sprites, multiple images are combined into a single image.
The “planchette” is any HTML element that supports background images, such as a SPAN or DIV.
The HTML element is positioned over the desired part of the background image using the CSS background-position property.
For example, each SPAN has a different class that specifies the into the CSS sprite using the background-position property:
1 | <div id="navbar" style="background-color: #F4F5EB; border: 2px ridge #333; width: 180px; height: 32px; padding: 4px 0 4px 0;"> |
1 | #navbar span { |
CSS Sprites: http://stevesouders.com/hpws/sprites.php
It is about as fast as the image map example: 342 milliseconds versus 354 milliseconds, respectively, but this difference is too small to be significant.
Whereas the images in an image map must be contiguous, CSS sprites don’t have that limitation.
More importantly, it is 57% faster than the alternative of using separate images.
In fact, the combined image tends to be smaller than the sum of the separate images as a result of reducing the amount of image overhead (color tables, formatting information, etc.).
If you use a lot of images in your pages for backgrounds, buttons, navbars, links, etc., CSS sprites are an elegant solution that results in clean markup, fewer images to deal with, and faster response times.
It’s possible to include images in your web page without any additional HTTP requests by using the data: URL scheme.
The data: URL scheme was first proposed in 1995. The specification (http://tools.ietf. org/html/rfc2397) says it “allows inclusion of small data items as ‘immediate’ data.” The data is in the URL itself following this format:
1 | data:[<mediatype>][;base64],<data> |
1 | <IMG ALT="Red Star" |
Inline Images: http://stevesouders.com/hpws/inline-images.php
Because data: URLs are embedded in the page, they won’t be cached across different pages. You might not want to inline your company logo, because it would make every page grow by the encoded size of the logo.
A clever way is placing this CSS rule in an external stylesheet means that the data is cached inside the stylesheet. In the following example, the background images used for each link in the navbar are implemented using inline images in an external stylesheet.
Inline CSS Images: http://stevesouders.com/hpws/inline-css-images.php
1 | .home { background-image: url(data:image/gif;base64,R0lGODlhHwAfAPcAAAAAAIxKA...);} .gift { background-image: url(data:image/gif;base64,R0lGODlhHwAfAPcAAAAAAABCp...);} .cart { background-image: url(data:image/gif;base64,R0lGODlhHwAfAPcAAAAAADlCr...);} .settings { background-image: url(data:image/gif;base64,R0lGODlhHwAfAPcAAAAAA...);} .help { background-image: url(data:image/gif;base64,R0lGODlhHwAfAPcAAAAAALW1t...);} |
Comparing this example to the previous examples, we see that it has about the same response time as image maps and CSS sprites.
Putting the inline image in an external stylesheet adds an extra HTTP request, but has the additional benefit of being cached with the stylesheet.
The rules described in later chapters also present guidelines that help reduce the number of HTTP requests, but they focus primarily on subsequent page views.
For components that are not critical to the initial rendering of the page, the post-onload download technique described in Chapter 8 helps by postponing these HTTP requests until after the page is loaded.
随着网页用户规模的增大,你可能要开始考虑访问速度的问题了(服务器的量开始不够了)。这个时候你可以通过重新设计程序架构更好的跑在分布式架构上,但是
The correct first step is found by recalling the Performance Golden Rule:
Only 10–20% of the end user response time is spent downloading the HTML document. The other 80–90% is spent downloading all the components in the page.
If the application web servers are closer to the user, the response time of one HTTP request is improved. On the other hand, if the component web servers are closer to the user, the response times of many HTTP requests are improved.
Rather than starting with the difficult task of redesigning your application in order to disperse the application web servers, it’s better to first disperse the component web servers. This not only achieves a bigger reduction in response times, it’s also easier thanks to content delivery networks.
A content delivery network (CDN) is a collection of web servers distributed across multiple locations to deliver content to users more efficiently.
When optimizing for performance, the server selected for delivering content to a specific user is based on a measure of network proximity. For example, the CDN may choose the server with the fewest network hops or the server with the quickest response time.
In addition to improved response times, CDNs bring other benefits. Their services include backups, extended storage capacity, and caching. A CDN can also help absorb spikes in traffic, for example, 11.11 :)
One drawback to relying on a CDN is that your response times can be affected by traffic from other web sites, possibly even those of your competitors. A CDN service provider typically shares its web servers across all its clients.
Another drawback is the occasional inconvenience of not having direct control of the content servers. For example, modifying HTTP response headers must be done through the service provider rather than directly by your ops team.
Finally, if your CDN service provider’s performance degrades, so does yours.
CDNs are used to deliver static content, such as images, scripts, stylesheets, and Flash.
Serving dynamic HTML pages involves specialized hosting requirements: database connections, state management, authentication, hardware and OS optimizations, etc. These complexities are beyond what a CDN provides.
Static files, on the other hand, are easy to host and have few dependencies. That is why a CDN is easily leveraged to improve the response times for a geographically dispersed user population.
If you conduct your own response time tests to gauge the benefits of using a CDN, it’s important to keep in mind that the location from which you run your test has an impact on the results.
At Yahoo!, this factor threw us off for awhile. Before switching Yahoo! Shopping to Akamai, our preliminary tests were run from a lab at Yahoo! headquarters, located near a Yahoo! data center. The response time improvements gained by switching to Akamai’s CDN—as measured from that lab—were less than 5% (not very impressive).
When we exposed the change to end users, there was an overall 20% reduction in response times on the Yahoo! Shopping site, just from moving all the static components to a CDN.
Fast response time is not your only consideration when designing web pages.
If it were, then we’d all take Rule 1 to an extreme and place no images, scripts, or stylesheets in our pages.
However, we all understand that images, scripts, and stylesheets can enhance the user experience, even if it means that the page will take longer to load.
Rule 3, described in this chapter, shows how you can improve page performance by making sure these components are configured to maximize the browser’s caching capabilities.
code
If it’s short, it’s more likely to actually be used
作者写第三版是因为以下的原因:
比如滴滴打车,AirBnb,飞猪旅行,智能家居等,科技大大便捷了我们的生活,在各个方面。
Web 同样在进步,变的越来越无所不能。如果有些事情不能在 web 上做的话,会令人懊恼(如 网上买火车票)。
针对用户体验的可用性变得非常重要,因此催生了 UX 等职业。
It’s still a book about designing great, usable Web sites.
And it’s also still a book about designing anything that people need to interact with, whether it’s a microwave oven, a mobile app, or an ATM.
The basic principles are the same even if the landscape has changed, because usability is about people and how they understand and use things, not about technology. And while technology often changes quickly, people change very slowly.
The human brain’s capacity doesn’t change from one year to the next, so the insights from studying human behavior have a very long shelf life. What was difficult for users twenty years ago continues to be difficult today.
–Jakob Nielsen
这个世界上有无数多的 Web 站点 (并且有无数多的手机 APP).
I’m not quite sure why Apple brags about this. Having thousands of good apps for a platform is a really good thing. Having millions of mediocre apps just means it’s really hard to find the good ones.
I wrote this book mainly for people who can’t afford to hire (or rent) someone like me (can find and provide solutions about usability).
Knowing some usability principles will help you see the problems yourself—and help keep you from creating them in the first place.
I’ve worked hard to keep this book short—hopefully short enough. I did this for two reasons:
There’s a good usability principle right there: If something requires a large investment of time—or looks like it will—it’s less likely to be used.
As with any field, there’s a lot you could learn about usability. But unless you’re a usability professional, there’s a limit to how much is useful for you to learn.
Dr. Watson is shocked to learn that Sherlock Holmes doesn’t know that the earth travels around the sun. Given the finite capacity of the human brain, Holmes explains, he can’t afford to have useless facts elbowing out the useful ones
I find that the most valuable contributions I make to each project always come from keeping just a few key usability principles in mind.
I’ve tried to boil down the few things I think everybody involved in design should know about usability.
Design is a complicated process and the real answer to most of the questions people ask me is “It depends.”
But I do think that there are a few useful guiding principles it always helps to have in mind, and those are what I’m trying to convey.
Designing, building, and maintaining a great Web site or app isn’t easy. It’s like golf: a handful of ways to get the ball in the hole, a million ways not to. Anyone who gets it even half right has my admiration.
As a result, you’ll find that the examples I use tend to be from excellent products with minor flaws. I think you can learn more from looking at good designs than bad ones.
如果说什么事物(比如一个 Web 站点,一个 App)可用性高的话,那意味着:
A person of average (or even below average) ability and experience can figure out how to use the thing to accomplish something without it being more trouble than it’s worth.
Take my word for it: It’s really that simple.
People often ask me:
“What’s the most important thing I should do if I want to make sure my site or app is easy to use?”
The answer is “DON’T MAKE ME THINK!”
It’s the overriding principle—the ultimate tie breaker when deciding whether a design works or it doesn’t. If you have room in your head for only one usability rule, make this the one.
No question marks. No mental chatter. And no errors.
mental chatter 内心杂乱,心里、脑子里喋喋不休的讨论
I could list dozens of things that users shouldn’t spend their time thinking about, like
The most important thing you can do is to understand the basic principle of eliminating question marks.
eliminate 消除,排除
Eventually you’ll learn to recognize and avoid them in the things you’re building.
Your goal should be for each page or screen to be self-evident, so that just by looking at it the average user will know what it is and how to use it.
In other words, they’ll “get it” without having to think about it.
Here’s the rule: If you can’t make something self-evident, you at least need to make it self-explanatory. (如果你想做一些很创新的设计的话)
What they actually do most of the time (if we’re lucky) is glance at each new page, scan some of the text, and click on the first link that catches their interest or vaguely resembles the thing they’re looking for.
vaguely 有点儿,含糊的
resembles 像,相似
There are almost always large parts of the page that they don’t even look at.
If you want to design effective Web pages, though, you have to learn to live with 3 facts about real-world Web use.
即使在那些专有的网站,如学校教务处网站,银行 app 等,人们也是在 scanning 和 reading 之中切换的。
因为有以下原因
Most Web use involves trying to get something done, and usually done quickly.
On most pages, we’re really only interested in a fraction of what’s on the page. We’re just looking for that.
It’s a basic skill: When you learn to read, you also learn to scan.
We’ve been scanning those to find we’re interested in.
What we see when we look at a page depends on what we have in mind, and it’s usually just a fraction of what’s there.
We tend to focus on words and phrases that seem to match (a) the task at hand or (b) our current or ongoing personal interests. And of course, (c) the trigger words that are hardwired into our nervous systems, like “Free,” “Sale,” and “Sex,” and our own name.
In reality, though, most of the time we don’t choose the best option—we choose the first reasonable option.
As soon as we find a link that seems like it might lead to what we’re looking for, there’s a very good chance that we’ll click it.
Why don’t Web users look for the best choice?
Of course, this is not to say that users never weigh options before they click. It depends on things like their frame of mind, how pressed they are for time, and how much confidence they have in the site.
I’ve seen lots of people use software, Web sites, and consumer products effectively in ways that are nothing like what the designers intended.
Why does this happen?
stumble 绊倒,犯错 stumble across 偶然发现
And it’s a good question: If people manage to muddle through so much, does it really matter whether they “get it”?
The answer is that it matters a great deal because while muddling through may work sometimes, it tends to be inefficient and error-prone.
On the other hand, if users “get it”, there’s a much better chance that:
makes them feel smart.
Faced with the fact that your users are whizzing by, there are some important things you can do:
whiz by 呼啸而过
One of the best ways to make almost anything easier to grasp in a hurry is to follow the existing conventions—the widely used or standardized design patterns.
比如说标题栏一般放在网页正上方这样的经典样式,比如某些图标背后的含义(购物车类图标就代表购物车本身),遵循用户已经习惯的约定俗成的规则,可以降低用户的上手难度。
Conventions have also evolved for different kinds of sites—commerce, colleges, blogs, and many more—since all the sites in each category have to solve the same set of problems.
These conventions didn’t just come out of thin air: They all started life as somebody’s bright idea. If an idea works well enough, other sites imitate it and eventually enough people have seen it in enough places that it needs no explanation.
When applied well, Web conventions make life easier for users because they don’t have to constantly figure out what things are and how they’re supposed to work as they go from site to site.
但是很多设计师不愿意照搬经典设计,而是想要重新造轮子(这点和程序员有些相似),
但真实世界中创新是偶发的,照搬经典才是经常的。
每当你想要抛弃一个经典而要重新发明轮子的时候,请仔细考虑你改善的地方是否增加了足够多的价值,值得用户去学习。(比如当你想要设计一个全新的滚动条的时候,要想想经典进度条的发展过程中已经经过了上千次的微调)。
My recommendation: Innovate when you know you have a better idea, but take advantage of conventions when you don’t.
Don’t get me wrong: I’m not in any way trying to discourage creativity. I love innovative and original Web design.
innovative 创新的,新颖的
innovation 创新,新方法
For instance: Harlem.org . Instead of text links or menus, you use the photo to navigate the site. Not only is it innovative and fun, but it’s easy to understand and use.
And the creators were smart enough to understand that the fun might wear off after a while so they also included a more conventional category-based navigation.
Consistency is always a good thing to strive for within your site or app.
But there will be cases where things will be clearer if you make them slightly inconsistent.
Each page should have a clear visual hierarchy: which things are most important, which things are similar, and which things are part of other things.
hierarchy 层次,等级制度
clear visual hierarchy 清晰的视觉层次
Pages with a clear visual hierarchy have 3 traits:
trait 特质、特性
prominent 突出的、显著的
The most important elements are either larger, bolder, in a distinctive color, set off by more white space, or nearer the top of the page—or some combination of the above.
For instance, you can show that things are similar by grouping them together under a heading, displaying them in the same visual style, or putting them all in a clearly defined area.
一个好的、清晰地视觉层次结构相当于对页面做了预处理,节省了用户许多思考,方便用户去获取他们想要的信息。
但是如果没有的话,体验会很差。
break up 将…分解为,解散,破裂
It is important because it allows users to decide quickly which areas of the page to focus on and which areas they can safely ignore.
Since a large part of what people are doing on the Web is looking for the next thing to click, it’s important to make it easy to tell what’s clickable (or “tappable” on touch screens).
——things like shape (buttons, tabs, etc.), location (in a menu bar, etc.), and formatting (color and underlining).
keep down 抑制,缩减
dull 迟钝的,无趣的
roar 咆哮,轰鸣
One of the great enemies of easy-to-grasp pages is visual noise.
类似这样的视觉噪音有:主次不分的结构、大量抓眼球的东西、混乱的位置摆放等。
When you’re editing your Web pages, it’s probably a good idea to start with the assumption that everything is visual noise (the “presumed guilty until proven innocent” approach) and get rid of anything that’s not making a real contribution.
In the face of limited time and attention, everything that’s not part of the solution must go.
Most of the time—that users spend on your Web pages is spent scanning the text in search of something.
The way your text is formatted can do a lot to make it easier for them.
Here are the most important things you can do to make your pages scan-friendly:
Well-written, thoughtful headings interspersed in the text act as an informal outline or table of contents for a page.
interspersed 点缀,散布
informal 通俗的,随意的,非正式的。所以 formal 也有拘谨的意思
下面有一些关于格式化文本的建议、注意事项:
You can do this by making each higher level larger or by leaving more space above it.
Make sure they’re closer to the section they introduce than to the section they follow.
If you examine a long paragraph, you’ll almost always find that there’s a reasonable place to break it in two. Get in the habit of keeping paragraphs short.
ul better than commas or semicolons
Much page scanning consists of looking for key words and phrases. Formatting the most important ones in bold where they first appear in the text makes them easier to find. And don’t highlight too many things, though, or the technique will lose its effectiveness.
If you really want to learn about making content scannable (or about anything related to writing for screens in general), Ginny Redish’s book Letting Go of the Words will be good for you.
mindless 盲目的,愚蠢的,不需要动脑筋的
What really counts is not the number of clicks it takes me to get to what I want (although there are limits), but rather how hard each click is—the amount of thought required and the amount of uncertainty about whether I’m making the right choice.
Links that clearly and unambiguously identify their target give off a strong scent that assures users that clicking them will bring them nearer to their “prey.” Ambiguous or poorly worded links do not.
unambiguously: 不含糊的,明白的
I think the rule of thumb might be something like
3 mindless, unambiguous clicks == 1 click that requires thought.
Of course, there are exceptions. For instance, if I’m going to have to drill down through the same path in a site repeatedly, or if the pages are going to take a long time to load, then the value of fewer clicks increases.
This problem of giving the user difficult choices and questions that are hard to answer happens all the time in forms. Caroline Jarrett has an entire chapter about it (“Making Questions Easy to Answer”) in her book Forms that Work: Designing Web Forms for Usability.
Life is complicated, though, and some choices really aren’t simple.
When you can’t avoid giving me a difficult choice, you need to go out of your way to give me as much guidance as I need—but no more.
The smallest amount of information that will help me
Placed so I encounter it exactly when I need it
Formatted in a way that ensures that I’ll notice it
Whether you need to offer some help or not, the point is that we face choices all the time on the Web and making those choices mindless is one of the most important things you can do to make a site easy to use.
Get rid of half the words on each page, then get rid of half of what’s left.
— KRUG’S THIRD LAW OF USABILITY
Vigorous writing is concise: A sentence should contain no unnecessary words, a paragraph no unnecessary sentences, for the same reason that a drawing should have no unnecessary lines and a machine no unnecessary parts.
— William Strunk, Jr., and E. B. White, The Elements of Style (Allyn and Bacon, 1979).
vigorous: 有力的,精力充沛的
My Third Law probably sounds excessive, because it’s meant to. Removing half of the words is actually a realistic goal; I find I have no trouble getting rid of half the words on most Web pages without losing anything of value.
excessive: 极端的,过度的
But the idea of removing half of what’s left is just my way of trying to encourage people to be ruthless about it.
ruthless: 无情的,残忍的
We all know happy talk when we see it: It’s the introductory text that’s supposed to welcome us to the site and tell us how great it is or to tell us what we’re about to see in the section we’ve just entered.
Most Web users don’t have time for small talk; they want to get right to the point. You can—and should—eliminate as much happy talk as possible.
The main thing you need to know about instructions is that no one is going to read them—at least not until after repeated attempts at “muddling through” have failed. And even then, if the instructions are wordy, the odds of users finding the information they need are pretty low.
Your objective should always be to eliminate instructions entirely by making everything self-explanatory, or as close to it as possible.
When instructions are absolutely necessary, cut them back to the bare minimum.
Now we’re heading into two chapters that look at how these principles apply to two of the biggest and most important challenges in Web design: navigation and the Home page.
It’s a fact: People won’t use your Web site if they can’t find their way around it.
how do you create the proverbial “clear, simple, and consistent” navigation?
Looking for things on a Web site and looking for them in the “real” world have a lot of similarities.
But the Web experience is missing many of the cues we’ve relied on all our lives to negotiate spaces. Consider these oddities of Web space:
I think we talk about Web navigation because “figuring out where you are” is a much more pervasive problem on the Web than in physical spaces.
Web navigation compensates for this missing sense of place by embodying the site’s hierarchy, creating a sense of “there.”
Two of the purposes of navigation are fairly obvious:
But navigation has some other equally important—and easily overlooked—functions:
Putting them in a standard place lets us locate them quickly, with a minimum of effort; standardizing their appearance makes it easy to distinguish them from everything else.
Done right, persistent navigation should say—preferably in a calm, comforting voice:
“The navigation is over here. Some parts will change a little depending on where you are, but it will always be here, and it will always work the same way.”
Just having the navigation appear in the same place on every page with a consistent look gives you instant confirmation that you’re still in the same site—which is more important than you might think.
And keeping it the same throughout the site means that (hopefully) you only have to figure out how it works once.
I lied. There is one exception to the “follow me everywhere” rule: forms.
On pages where a form needs to be filled in, the persistent navigation can sometimes be an unnecessary distraction. 比如在 登陆的页面、支付宝支付的页面、填写信息的页面,你会只想把当前这个步骤完成,而不是看导航栏。
For these pages, it’s useful to have a minimal version of the persistent navigation with just the Site ID, a link to Home, and any Utilities that might help me fill out the form.
在页面的可视化层次结构中,一般 site ID 放置于页面左上角,并且 site ID 一般由标志性的图片或字体组成,让用户方便辨识。
These are things that either can help me use the site (like Sign in/Register, Help, a Site Map, or a Shopping Cart) or provide information about its publisher (like About Us and Contact Us).
Like the signs for the facilities in a store, the Utilities list should be slightly less prominent than the Sections.
As a rule, the persistent navigation can accommodate only 4 or 5 Utilities—the ones users are likely to need most often. Or it will seems crowd.
The less frequently used leftovers belong in the footer: the small text links at the bottom of each page.
Having a Home button in sight at all times offers reassurance that no matter how lost I may get, I can always start over.
Given the power of searching and the number of people who prefer searching to browsing, unless a site is very small and very well organized, every page should have either a search box or a link to a search page.
搜索框的样式要符合常用规范,让用户一眼就能看出来(如一个放大镜,一个搜索框等等)。而且如果你要加上搜索选项的话,尽可能在用户需要的时候出现,比如淘宝的搜索框:店铺、商品的搜索切换一目了然。
I think this is one of the most common problems in Web design (especially in larger sites): failing to give the lower-level navigation the same attention as the top.
In so many sites, as soon as you get past the second level, the navigation breaks down. The problem is so common that it’s actually hard to find good examples of third-level navigation.
这一点网易严选的首页做得很好,以图标 + 文字的方式形象地展示比较低级别的元素目录(当然也和它本身没有那么大量的低级别目录有关),其他可以参考的还有淘宝和京东首页的低级别元素目录。
所谓细节见差距,做好低级别 / 潜在级别目录的展示同样非常重要。
Page names are the street signs of the Web. When things are going well I may not notice page names at all. But as soon as I start to sense that I may not be headed in the right direction, I need to be able to spot the page name effortlessly so I can get my bearings.
There are four things you need to know about page names:
导航栏应当能够显示用户所在网页的位置,并且应该用明显的颜色加以区分(用户往往看页面非常快,所以避免微妙的颜色差异,选用较大、较明显的颜色差异)。
Like “You are here” indicators, Breadcrumbs show you where you are.
Done right, Breadcrumbs are self-explanatory, they don’t take up much room, and they provide a convenient, consistent way to do two of the things you need to do most often: back up a level or go Home. They’re most useful in a large site with a deep hierarchy.
Here are a few best practices for implementing them:
When you think you’ve covered all the bases, there’s always just one…more…thing.
Think about all the things the Home page has to accommodate:
因为主页是如此的寸土寸金(占据主页多的部分往往能有更大的流量),每个部分都想在主页上多占一些位置。
鉴于这样的局面,我们没法满足每一个网页部分的要求,所以我们必须做出权衡(编程本身也同样需要不断地权衡取舍)。
The one thing you can’t afford to lose in the shuffle—and the thing that most often gets lost—is conveying the big picture.
As quickly and clearly as possible, the Home page needs to answer the four questions I have in my head when I enter a new site for the first time:
I need to be able to answer these questions at a glance, correctly and unambiguously, with very little effort.
If it’s not clear to me what I’m looking at in the first few seconds, the chances are greater that I’ll misinterpret something and get frustrated.
But if I do “get it”, which greatly improves my chances of having a satisfying, successful experience.
This is what I call the Big Bang Theory of Web Design. It’s based on the idea that the first few seconds you spend on a new Web site or Web page are critical.
并不是说人们的第一印象总是正确的,恰恰相反,第一印象总是错的。一旦获得了错误的第一印象,他们接下来的判断都会被错误的第一印象带偏。正因如此给用户一个正确的第一印象非常重要。
This is why it’s so crucial that you get them off on the right foot, making sure that they’re clear on the big picture.
Don’t get me wrong: Everything else is important. You do need to impress me, entice me, direct me, and expose me to your deals. But these things won’t slip through the cracks.
get … across 被理解
There are 3 important places on the page where we expect to find explicit statements of what the site is about.
The point isn’t that everyone will use these 3 elements—or even that everyone will notice them.
Here are a few guidelines for getting the message across:
The best way to keep this from happening is to make the entry points look like entry points (i.e., make the search box look like a search box and the list of sections look like a list of sections). It also helps to label them clearly, with labels like “Search,” “Browse by Category,” “Sign in,” and “Start here” (for a step-by-step process).
i.e. 也就是
Web teams aren’t notoriously successful at making decisions about usability questions. Most teams end up spending a lot of precious time rehashing the same issues over and over.
Unfortunately, there are several forces at work in most Web teams that make these debates almost inevitable. In this chapter, I’ll describe these forces and explain what I think is the best antidote.
antidote 解药
持有某种意见的人往往会认为大多数用户想的和他是一样的,但真的是这样的吗?我们需要明智一些。
The only problem is, there is no Average User.
All web users are unique and all web use is basically idiosyncratic.
idiosyncratic: 特殊的、特质的
The problem is there are no simple “right” answers for most Web design questions (at least not for the important ones). What works is good, integrated design that fills a need—carefully thought out, well executed, and tested.
It’s just that they aren’t the things that Web teams usually argue about.
The point is, it’s not productive to ask questions like “Do most people like pull-down menus?” The right kind of question to ask is Does this pull-down, with these items and this wording in this context on this page reate a good experience for most people who are likely to use this site?“
And there’s really only one way to answer that kind of question: testing.
Usability testing tends to defuse most arguments and break impasses.
作者举出了两个例子:
And while usability testing will sometimes settle these arguments, the main thing it usually ends up doing is revealing that the things they were arguing about weren’t all that important.
For instance, they might discover that it doesn’t make much difference whether you go with cascading menus or mega menus if nobody understands the value proposition of your site.
We need to make usability part of every project right from the beginning.
Sadly, though, this is still how a lot of usability testing gets done: too little, too late, and for all the wrong reasons.
Here’s the difference in a nutshell:
in a nutshell 简而言之
The main difference is that in usability tests, you watch people actually use things, instead of just listening to them talk about them.
Focus groups are best used in the planning stages of a project. Usability tests, on the other hand, should be used through the entire process.
I used to say that the best way to think about testing is that it’s like travel: a broadening experience. It reminds you how different—and the same—people are and gives you a fresh perspective on things. And at the same time, you realize that a lot of things that you take for granted aren’t obvious to everybody.
It’s often not that easy to make changes—especially major changes—to a site once it’s in use. Some percentage of users will resist almost any kind of change, and even apparently simple changes often turn out to have far-reaching effects. Any mistakes you can correct early in the process will save you trouble down the line.
Don’t get me wrong: If you can afford to hire a professional to do your testing, do it. Odds are they’ll be able to do a better job than you can. But if you can’t hire someone, do it yourself.
I believe in the value of this kind of testing so much that I wrote an entire (short) book about how to do it. It’s called Rocket Surgery Made Easy: The Do-It-Yourself Guide to Finding and Fixing Usability Problems.
It covers the topics in this chapter in a lot more detail and gives you step-by-step directions for the whole process.
One morning a month doing usability testing.
If you’re doing Agile development, you’ll be doing testing more frequently, but the principles are still the same.
This is much better than basing your test schedule on milestones and deliverables. because schedules often slip and testing slips along with them.
The ideal number of participants for each round of do-it-yourself testing is three.
They’ll say that it’s too small a sample to prove anything and that it won’t uncover all of the problems. Both of these are true but they just don’t matter, and here’s why:
Proving things requires quantitative testing, with a large sample size, a clearly defined and rigorously followed test protocol, and lots of data gathering and analysis.
quantitative 严格的
而这里的自己动手测试不是一种严格的、覆盖全局的测试,它的目的是通过识别和修复可用性问题来改进正在构建的事物。
You can find more problems in half a day than you can fix in a month.
You’ll always find more problems than you have the resources to fix, so it’s very important that you focus on fixing the most serious ones first. And three users are very likely to encounter many of the most significant problems related to the tasks that you’re testing.
不用特地去挑选最像你的目标用户的的测试者,一方面会增加挑选的成本,一方面因为样本单一,更难发现问题。为此作者提出了建议:
recruit loosely and grade on a curve
即放松挑选测试者的标准。
I like to offer people a little more than the going rate, since it makes it clear that I value their time and improves the chances that they’ll show up.
Remember that even if the session is only an hour, people usually have to spend another hour traveling.
As many people as possible!
One of the most valuable things about doing usability testing is the effect it can have on the observers. For many people, it’s a transformative experience that dramatically changes the way they think about users: They suddenly “get it” that users aren’t all like them.
You should try to do whatever you can to encourage everyone—team members, stakeholders, managers, and even executives—to come and watch the test sessions.
During the break after each test session, observers need to write down the three most serious usability problems they noticed during that session so they can share them in the debriefing.
debrief 盘问
It’s important that they make this short list because, as you’ll see, the purpose of the debriefing is to identify the most serious problems so they get fixed first.
In fact, it’s never too early to start. Even before you begin designing your site.
For instance, it’s a good idea to do a test of competitive sites. They may be actual competitors, or they may just be sites that have the same style, organization, or features that you plan on using.
Bring in three participants and watch them try to do some typical tasks on one or two competitive sites and you’ll learn a lot about what works and doesn’t work without having to design or build anything.
If you’re redesigning an existing site, you’ll also want to test it before you start, so you’ll know what’s not working (and needs to be changed) and what is working (so you don’t break it).
Here are some of the types of problems you’re going to see most often:
They look at the site or a page and either they don’t know what to make of it or they think they do but they’re wrong.
what to make of it 怎么回事
This usually means that either you failed to anticipate what they’d be looking for or the words you’re using to describe things aren’t the words they’d use.
anticipate 预期,预料
In this case, you need to either reduce the overall noise on the page or turn up the volume on the things they need to see so they “pop” out of the visuasl hierarchy more.
一开始手机上也有浏览器,不过用户体验非常差。直到 iPhone 的出现,开创了智能手机的时代,改变了这一切。
One of Apple’s great inventions was the ability to scroll (swiping up and down) and zoom in and out (pinching and…unpinching) very quickly. (It was the very quickly part—the responsiveness of the hardware—that finally made it useful.)
不仅是 Web 功能的便捷,携带一部智能手机意味着很多:一个网页浏览器、一部相机、一个钱包(如支付宝)、一张地图(基于 GPS)。
正如这句话所说:The best camera really is the one you have with you.
And think about the fact that for most people in emerging countries, in the same way they bypassed landlines and went straight to cellphones, the smartphone is their first—and only—computer.
bypassed:绕过,忽视
There’s not much denying that mobile devices are the wave of the future, except for things where you need enormous horsepower (professional video editing, for example, at least for now) or a big playing surface (Photoshop or CAD).
In one sense, the answer is: Not much. The basic principles are still the same. If anything, people are moving faster and reading even less on small screens.
但是 mobile 确实有一些不一样的地方。作者不打算写一些很具体的操作,而是:
What I will do is tell you a few things that I’m sure will continue to be true. And the first one is…
One way to look at design—any kind of design—is that it’s essentially about constraints (things you have to do and things you can’t do) and tradeoffs (the less-than-ideal choices you make to live within the constraints).
Rather than being the negative force that they often feel like, constraints actually make design easier and foster innovation.
foster 培育,培养
If a sofa has to fit in this space and match this color scheme, it’s sometimes easier to find one than if you just go shopping for any sofa.
Having something pinned down can have a focusing effect, where a blank canvas with its unlimited options—while it sounds liberating—can have a paralyzing effect.
pin down 约束,确定,阻止
paralyzing 使…麻痹
Whenever you’re designing, you’re dealing with constraints. And where there are constraints, there are tradeoffs to be made.
Some serious usability problems are the result of a poor decision about a tradeoff.
Most of the challenges in creating good mobile usability boil down to making good tradeoffs.
如果在设计主页的时候你感到寸土寸金的话,那么来感受一下 mobile site 的可怕吧。(假设主页是杭州的房价,mobile 的页面就是北京的房价)
One way to deal with a smaller living space is to leave things out: Create a mobile site that is a subset of the full site. But which parts do you leave out?
One approach was Mobile First. Instead of designing a full-featured (and perhaps bloated) version of your Web site first and then paring it down to create the mobile version, you design the mobile version first based on the features and content that are most important to your users. Then you add on more features and content to create the desktop/full version.
If you’re going to include everything, you have to pay even more attention to prioritizing.
Things I want to use in a hurry or frequently should be close at hand. Everything else can be a few taps away, but there should be an obvious path to get to them.
Smaller screen means that people will be tapping more, but that’s OK.
With small screens it’s inevitable: To see the same amount of information, you’re going to be either tapping or scrolling a lot more. As long as the user continues to feel confident that what they want is further down the screen or behind that link or button, they’ll keep going.
If there are two things I can tell you about scalable design (a/k/a dynamic layout, fluid design, adaptive design, and responsive design), they’re these:
a/k/a or a.k.a 换句话说,又名 (是 also known as 的缩写)
Now that small screens are taking over, everybody cares: If you have a Web site, you have to make it usable on any size screen.
Trying to create separate versions of anything—keeping two sets of books is a surefire path to madness. It doubles the effort (at least) and guarantees that either things won’t be updated as frequently or the versions will be out of sync.
It’s still getting sorted out. This time, the problem has real revenue implications, so there will be technical solutions, but it will take time.
这里作者有个建议
If you don’t have the resources to “mobilize” your site at all and you’re not using responsive design, you should at least make sure that.
There are many situations where people will be willing to zoom in and out through the small viewport of a mobile device in return for access on the go to features they’ve become accustomed to using or need at that moment. Also, some people will prefer to see the desktop pages when using 7″ tablets with high-resolution screens in landscape mode.
affordances 功能可见性
和 Web 端一样,手机端的按钮要长得像一个按钮,输入框要像一个输入框,可以点击的链接要显示出来,而不是要用户猜。
This is not to say that all affordances need to hit you in the face. They just have to be visible enough that people can notice the ones they need to get their tasks done.
Affordances require visual distinctions. But the recent trend in interface design has moved in exactly the opposite direction: removing visual distinctions and “flattening” the appearance of interface elements.
It looks darned good (to some people, anyway), and it can make screens less cluttered-looking. But at what price?
The distinctions required to draw attention to an affordance often need to be multi-dimensional: It’s the position of something (e.g., in the navigation bar) and its formatting (e.g., reversed type, all caps) that tell you it’s a menu item.
By removing a number of these distinctions from the design palette, Flat design makes it harder to differentiate things.
You can do all the Flat design you want (you may have to, it may be forced on you), but make sure you’re using all of the remaining dimensions to compensate for what you lose.
Some people include in their definitions of usability:
Personally, my focus has always been on the three that are central to my definition of usability:
A person of average (or even below average) ability and experience can figure out how to use the thing to accomplish something without it being more trouble than it’s worth.
For now let’s talk about delight, learnability, and memorability and how they apply to mobile apps.
让人快乐的应用通常来自和某个人们希望能实现但没想过真的能实现的想法的结合,再加上一个明朗的想法,使用某些新技术来完成它。
可记忆性可能影响人们是否会经常使用这个应用的重要因素。很久不用之后,还会使用。
Most of this book has been about building clarity into Web sites: making sure that users can understand what it is they’re looking at—and how to use it—without undue effort. Is it clear to people? Do they “get it”?
undue 过度的
But there’s another important component to usability: doing the right thing—being considerate of the user. Besides “Is my site clear?” you also need to be asking, “Does my site behave like a mensch?”
mensch [美国俚语]有道德且受尊敬的人;正人君子
I’ve always found it useful to imagine that every time we enter a Web site, we start out with a reservoir of goodwill. Each problem we encounter on the site lowers the level of that reservoir.
The reservoir is limited, and if you treat users badly enough and exhaust it there’s a good chance that they’ll leave.
但还有比用户离开更严重的后果:他们会在朋友圈、微博之类的地方吐槽,这时候对公司声誉的危害可就大了。
There are a few things worth noting about this reservoir:
Some people have a large, some small; some are more suspicious by nature, or more ornery; others are inherently more patient, trusting, or optimistic. The point is, you can’t count on a very large reserve.
If I’m in a huge hurry, or have just come from a bad experience on another site, my expendable goodwill may already be low when I enter your site, even if I naturally have a large reserve.
Even if you’ve made mistakes that have diminished my goodwill, you can replenish it by doing things that make me feel like you’re looking out for my best interests.
For instance, just opening up a registration form with tons of fields may be enough to cause some people’s reserve to plunge instantly to zero.
The most common things to hide are customer support phone numbers, shipping rates, and prices.
如输入框中要求必须输入 xxx-xxx-xxx(或者其他的格式化),而其中的 - 本可以由代码完成。
Note that while people love to make comments about the appearance of sites—especially about whether they like the colors.
Almost no one is going to leave a site just because it doesn’t look great color. (I tell people to ignore all comments that users make about colors during a user test, unless three out of four people use a word like “puke” to describe the color scheme. Then it’s worth rethinking.
There may be times when you’ll choose to have your site do some of these user-unfriendly things deliberately.
Sometimes it makes business sense not to do exactly what the customer wants.
For instance, uninvited pop-ups almost always annoy people to some extent. But if your statistics show you can get 10 percent more revenue by using pop-ups and you think it’s worth annoying your users, you can do it.
It’s a business decision. Just be sure you do it in an informed way, rather than inadvertently.
“What are the three main things your users want to do?” The problem is, making those things easy doesn’t always become the top priority it should be.
Be upfront about things like shipping costs, hotel daily parking fees, service outages—anything you’d rather not be upfront about.
For instance, instead of giving me the shipping company’s tracking number for my purchase, put a link in my email receipt that opens their site and submits my tracking number when I click it.
My favorite example is the HP technical support site, where it seems like an enormous amount of work has gone into (a) generating the information I need to solve my problems, (b) making sure that it’s accurate and useful, (c) presenting it clearly, and (d) organizing it so I can find it. I’ve had a lot of HP printers, and in almost every case where I’ve had a problem I’ve been able to solve it on my own.
Keep them up to date.
Customer Service and Technical Support can easily give you a list of this week’s five most frequently asked questions. I would always put this list at the top of any site’s Support page.
If you actually do enough user testing, you’ll be able to spare me from many errors before they happen.
But where the potential for errors is unavoidable, always provide a graceful, obvious way for me to recover.
Sometimes you can’t help it: You just don’t have the ability or resources to do what the user wants.
If you can’t do what they want, at least let them know that you know you’re inconveniencing them.
It’s the right thing to do.
How many opportunities do we have to dramatically improve people’s lives just by doing our job a little better?
尽管成为 无障碍访问 专家很难,但我们可以简单的做到以下几点:
The single best thing you can do to improve your site’s accessibility is to test it often, and continually smooth out the parts that confuse everyone.
If you have the time and the motivation, I’d highly recommend locating one or two blind Web users and spending a few hours with them observing how they actually use their screen reader software.
Screen-reader users scan with their ears. Most blind users are just as impatient as most sighted users. They want to get the information they need as quickly as possible. They do not listen to every word on the page—just as sighted users do not read every word. They “scan with their ears,” listening to just enough to decide whether to listen further. Many set the voice to speak at an amazingly rapid rate.
A Web for Everyone: Designing Accessible User Experiences by Sarah Horton and Whitney Quesenbery. (Their approach: “Good UX equals good accessibility. Here’s how to do both.”)
Web Accessibility: Web Standards and Regulatory Compliance by Jim Thatcher et al. (“Here are the laws and regulations, and we’ll help you understand how to meet them.”)
UCD(User Centered Design,以用户为中心的设计)的目标是:设计正确的产品,保证它可用。
UXD(User Experience Design,用户体验设计)是在产品生命周期的每个阶段,都把用户需求考虑进来。
致力于优雅的、可读性好的 JavaScript 排序算法代码。
(转载请署名,优化总结这些代码和知识点消耗 RayJune 大量元气)
或许你会像我一样困惑:为什么我们需要这么多种排序算法呢?
可能这个来自 StackOverFlow 的回答可以为你答疑解惑(自己翻译的,如有错误请尽管提醒):
我们有这么多不同的排序算法是因为他们适用于不同种类的情况(即没有最完美的排序算法,只有适合某种情况的排序算法),比如:
Maybe you will wonder (just like me): Why do we need so many sorting algorithms?
I think this answer from StackOverFlow can handle it:
下面是该回答原文:
We have many different ones because they satisfy different sorting use-cases. Some examples:
https://www.quora.com/Why-do-we-need-so-many-sorting-algorithms
文章中的代码均采用 eslint 规范代码,采用的是 Airbnb 的 ES5 JavaScript 编程规范。
其中额外遵守的编程规范有:
preIndex
, temp
, size
本文中常使用 swap
函数,在这里提前列出来,以下就省略了。
1 | function swap(arr, indexA, indexB) { |
通过依次比较、交换相邻的元素(按照由小到大的顺序,如果符合这个顺序就不用交换),一次这样的循环可以得到一个最大值,n - 1 次这样的循环可以排序完毕。
关于 but not better than Insertion sort:
Bubble sort has many of the same properties as insertion sort, but has slightly higher overhead. In the case of nearly sorted data, bubble sort takes O(n) time, but requires at least 2 passes through the data (whereas insertion sort requires something more like 1 pass).
1 | function bubbleSort(arr) { |
设置一标志性变量 pos ,用于记录每趟排序中最后一次进行交换的位置。
由于 pos 位置之后的记录均已交换到位,故在进行下一趟排序时 只要扫描到 pos 位置即可
1 | function bubbleSort2(arr) { |
传统冒泡排序中每一趟排序操作只能找到一个最大值或最小值,
我们可以 在每趟排序中进行正向和反向两遍冒泡 ,
一次可以得到两个最终值(最大和最小) , 从而使外排序趟数几乎减少了一半。
1 | function bubbleSort3(arr) { |
前两种优化方式(缓存 pos、双向遍历)的结合:
1 | function bubbleSort4(arr) { |
来自于蚂蚁金服的一道面试题:
对于冒泡排序来说,能不能传入第二个参数(参数为函数),来控制升序和降序?(联想一下 array.sort() )
1 | function bubbleSort(arr, compareFun) { |
如果你像我一样理解错了意思的话(理解成了,如何在冒泡排序中传入一个函数参数,并使用 array.sort() 方法来排序)的话,就有了下面的方法:
1 | function bubbleSort(arr, compareFun) { |
每一次内循环遍历寻找最小的数,记录下 minIndex,并在这次内循环结束后交换 minIndex 和 i 的位置,重复这样的循环 n - 1 次即得到结果。
关于 Θ(n) swaps:
Selection sort has the property of minimizing the number of swaps. In applications where the cost of swapping items is high, selection sort very well may be the algorithm of choice.
即就算是我们觉得最慢的选择排序,也有它的用武之地。
1 | function selectionSort(arr) { |
如果你想在每次内循环中找到最大值并把其交换到数组的末尾(相比较 minIndex 有点麻烦),以下是实现的代码:
1 | function selectionSort2(arr) { |
默认 a[0] 为已排序数组中的元素,从 arr[1] 开始逐渐往已排序数组中插入元素,从后往前一个个比较,如果待插入元素小于已排序元素,则已排序元素往后移动一位,直到待插入元素找到合适的位置并插入已排序数组。经过 n - 1 次这样的循环插入后排序完毕。
For its advantages (adaptive, low overhead, stable, O(n) time when nearly sorted), insertion sort is often used as the recursive base case (when the problem size is small) for higher overhead divide-and-conquer sorting algorithms, such as shell sort or quick sort.
1 | function insertionSort(arr) { |
因为对于插入排序的优化方法是:二分查找优化,这里补充一下二分查找的算法的实现。
核心概念是:折半。
1 | function binarySearch(arr, value) { |
查找插入位置时使用二分查找的方式来优化性能:
1 | function binaryInsertionSort(arr) { |
希尔排序是插入排序的改进版,它克服了插入排序只能移动一个相邻位置的缺陷(希尔排序可以一次移动 gap 个距离),利用了插入排序在排序几乎已经排序好的数组的非常快的优点。
使用可以动态定义的 gap 来渐进式排序,先排序距离较远的元素,再逐渐递进,而实际上排序中元素最终位置距离初始位置远的概率是很大的,所以希尔排序大大提升了性能(尤其是 reverse 的时候非常快,想象一下这时候冒泡排序和插入排序的速度)。
而且希尔排序不仅效率较高(比冒泡和插入高),它的代码相对要简短,低开销(继承插入排序的优点),追求这些特点(效率要求过得去就好,代码简短,开销低,且数据量较小)的时候希尔排序是好的 O(n·log(n)) 算法的替代品。
总而言之:希尔排序的性能优化来自增量队列的输入和 gap 的设定。
关于 not stable:
我们知道, 单次直接插入排序是稳定的,它不会改变相同元素之间的相对顺序,但在多次不同的插入排序过程中,
相同的元素可能在各自的插入排序中移动,可能导致相同元素相对顺序发生变化。因此, 希尔排序并不稳定。
关于 worse-case time 有一点复杂:
The worse-case time complexity of shell sort depends on the increment sequence. For the increments 1 4 13 40 121…, which is what is used here, the time complexity is O(n3/2). For other increments, time complexity is known to be O(n4/3) and even O(n·log2(n)).
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
其中 gap(增量)的选择是希尔排序的重要部分。只要最终 gap 为 1 任何 gap 序列都可以工作。算法最开始以一定的 gap 进行排序。然后会继续以一定 gap 进行排序,直到 gap = 1 时,算法变为插入排序。
Donald Shell 最初建议 gap 选择为 n / 2 并且对 gap 取半直到 gap 达到 1 。虽然这样取可以比 O(n²) 类的算法(插入排序、冒泡排序)更好,但这样仍然有减少平均时间和最差时间的余地。
(关于优化 gap 的细节涉及到复杂的数学知识,我们这里不做深究,详细可以参考 wikipedia 上的页面)
Donald Shell 的最初建议(gap = n / 2)版代码(方便理解):
1 | function shellSort(arr) { |
常见的、易生成的、优化 gap 的序列方法(来自 Algorithms (4th Edition) ,有些更快的方法但序列不容易生成,因为用到了比较深奥的数学公式):
1 | function shellSort(arr) { |
归并排序使用分而治之的思想,以折半的方式来递归/迭代排序元素,利用空间来换时间,做到了时间复杂度 O(n·log(n)) 的同时保持了排序元素的 stable,这让它在一些更考虑排序效率和稳定性,次考虑存储空间的场合非常适用(如数据库内排序,和堆排序相比,归并排序的 stable 是优点)。并且归并排序非常适合于列表排序。
If using Θ(n) extra space is of no concern, then merge sort is an excellent choice: It is simple to implement, and it is the only stable O(n·lg(n)) sorting algorithm. Note that when sorting linked lists, merge sort requires only Θ(log(n)) extra space (for recursion).
Merge sort is the algorithm of choice for a variety of situations: when stability is required, when sorting linked lists, and when random access is much more expensive than sequential access (for example, external sorting on tape).
There do exist linear time in-place merge algorithms for the last step of the algorithm, but they are both expensive and complex. The complexity is justified for applications such as external sorting when Θ(n) extra space is not available.
以迭代的方式来实现(但要注意防止函数调用过深导致 JavaScript 的运行栈溢出):
1 | function mergeSort(arr) { // recursion |
二叉堆是一种特殊的堆,二叉堆是完全二叉树或者是近似完全二叉树。二叉堆满足堆特性:父节点的键值总是大于或等于任何一个子节点的键,且每个节点的左子树和右子树都是一个二叉堆。 当父节点的键值总是大于或等于任何一个子节点的键值时为最大堆。当父节点的键值总是小于或等于任何一个子节点的键值时为最小堆。
堆排序可以认为是选择排序的改进版,像选择排序一样将输入划分为已排序和待排序,不一样的是堆排序利用堆这种近似完全二叉树的良好的数据结构来实现排序,本质上使用了二分的思想。先将所有的数据堆化,然后移动 arr[0] 到数组末尾(已排序区域),再重新堆化,依次这样循环来排序。
利用堆这种良好的数据结构,它在拥有良好的可预测性的同时(不管输入什么都是 O(n·log(n)) time ),但它的缺点也有:即不稳定,而且 O(n·log(n) 的平均效率决定了它的效率不如快速排序。适用于数据库内引擎排序(需要这样的可预测性性能)。
1 | function heapSort(arr) { |
wikipedia 上给出的方法于 basic code 基本实现的区别在于维护堆性质时采用的方式不同,本质是一样的:
1 | function heapSort(arr) { |
When implemented well, it can be about two or three times faster than its main competitors, merge sort and heapsort
1 | function quickSort(arr) { |
use array.forEach(), functional programming
1 | function quickSort(arr) { |
1 | function quickSort(arr) { |
use array.forEach(), functional programming
1 | function quickSort(arr) { |
上面简单版本的缺点是,它需要Ω(n)的额外存储空间,也就跟归并排序一样不好。额外需要的内存空间配置,在实际上的实现,也会极度影响速度和缓存的性能。有一个比较复杂使用原地(in-place)分区算法的版本,且在好的基准选择上,平均可以达到O(log n)空间的使用复杂度。
1 |
好了,现在终于到了各个算法大 PK 的时候了:
插入排序不解释
性能大小:希尔排序 > 插入排序 > 冒泡排序 > 选择排序
堆排序
性能大小: 快速排序 > 堆排序 > 归并排序
因为虽然堆排序做到了 O(n·log(n) time,而快速排序的最差情况是 O(n²),但是快速排序的绝大部分时间的效率比 O(n·log(n) 还要快,所以快速排序真的无愧于它的名字。(十分快速)
正如开头所说,世界上没有最好的算法(《人月神话》:没有银弹),只有最适合某种情况的算法。
算法代有人才出,各领风骚数十载。领悟经典算法其中的精髓才是王道:
缓存位置、双向遍历、二分、分而治之、利用良好的数据结构、利用高深的数学技巧…这些算法背后的思想所带给我们的远比代码本身更有价值。
最后引用 + 改编一下陈立杰的话:
现在是计算机科学的黄金时代,也是全人类的黄金时代,能够站在这样的黄金时代里,我感到无比的荣幸,我们都梦想能够成为黄金时代大潮中的一朵浪花,为人类智慧添砖加瓦。
加瓦把骚年~
Collect some RegExp concepts and demos from MDN.
(Some of these demos modified by myself).
1 | var re = new RegExp("Shelley\s+Powers"); |
Returns true or false
1 | var demo = 'abc rayjune'; |
If the regex has the global flag set, test() will advance the lastIndex of the regex.
1 | var regex = /foo/g; |
The exec() method executes a search for a match in a specified string. Returns a result array, or null.
1 | var str = 'hello -rayjune'; |
once use ‘\g’
1 | var reg = /hello/g; |
and the re has lastIndex property
1 | var myRe = /ab*/g; |
The index of the first match between the regular expression and the given string;
if not found, -1.
1 | var str = "hey JudE"; |
An Array containing the entire match result and any parentheses-captured matched results;
null if there were no matches.
1 | var str = 'hello -rayjune'; |
once use ‘\g’
1 | var reg = /hello/g; |
1 | var a = 'abc de'; |
Switching words in a string
1 | var re = /(\w+)\s(\w+)/; |
1 | var re = /like/; |
1 | var re = /Shelley\s+Powers/; |
matches any single character except the newline character.
1 | var re = /.n/; |
not match na
Matches ‘x’ and remembers the match, as the following example shows. The parentheses are called capturing parentheses.
1 | var re = /(a)(b)/; |
Matches ‘x’ but does not remember the match.
1 | var re = /(?:a)(?:b)/; |
And let you define subexpressions for regular expression operators to work with.
1 | var re1 = /foo{1,2}/; |
Matches ‘x’ only if ‘x’ is not followed by ‘y’
1 | var re = /ray(?!june)/; |
This pattern type matches any one of the characters in the brackets, including escape sequences.
1 | console.log(/[\/]/.test('/')); // true |
It matches anything that is not enclosed in the brackets
1 | console.log('abcdef'.match(/[^a-c]/g)); // (3) ["d", "e", "f"] |
Matches a word boundary.
1 | console.log('moon'.match(/\bm/)); // ["m", index: 0, input: "moon"] |
Matches a non-word boundary.
1 | console.log('possibly yesterday.'.match(/y\B./)); // ["ye", index: 9, input: "possibly yesterday."] |
Matches a digit character. Equivalent to [0-9].
Matches a non-digit character. Equivalent to [^0-9].
Matches a carriage return
Matches a single white space character, including space, tab, form feed, line feed.
Matches any alphanumeric character including the underscore. Equivalent to [A-Za-z0-9_]
1 | console.log('ray_june'.match(/\w/g)); (8) ["r", "a", "y", "_", "j", "u", "n", "e"] |
Matches any non-word character. Equivalent to [^A-Za-z0-9_].
]]>Just for self review.
The (*) section means it’s come from Internet (stackOverFlow, MDN or Medium).
It’s not a complete encyclopedia of JavaScript use today—no one book can cover all there is to cover. But hopefully, you’ll come away with an appreciation of all you can do with JavaScript.
This book does consist of two rather general sections: the first focuses on existing JavaScript functionality and objects(1-10); the second focuses more on JavaScript used within environments, such as a browser.
1 | var city = new String("St. Louis"); // String object |
If you do need to access a String object method on a string literal, you can. What happens is the JavaScript engine creates a String object, wraps it around the string literal, performs the method call, and then discards the String object.
The valueOf method is available for all JavaScript objects, and returns the primitive value of whatever the object is: for Number, String, and boolean, their primitive values; for Function, the function text, and so on.
1 | var a = new Number(1); |
1 | if (typeof String.trim == "undefined") { |
trim the unwanted whitespace from around a string.
1 | var str = 'abc def'; |
Regular expressions are search patterns that can be used to find text that matches a given pattern.
1 | // Look for #a0b1c2 |
Though the regular expressions seem complex, they’re really nothing more than a way to describe a pattern.
1 | function leftTrim(str) { |
1 | var intervalId = null; |
1 | console.log(Math.floor(1.6)); // 1 |
Convert a number to a hexadecimal string with:
1 | hexString = yourNumber.toString(16); |
and reverse the process with:
1 | yourNumber = parseInt(hexString, 16); |
from https://stackoverflow.com/questions/57803/how-to-convert-decimal-to-hex-in-javascript#answer-57805
The Math.random() function returns a floating-point, pseudo-random number in the range [0, 1)
1 | window.onload = function() { |
range [0, 254] === [0, 255)
1 | window.onload = function() { |
even this
1 | window.onload = function() { |
parseInt() & parseFloat()
An array is an ordered collection of elements.
To create an array of several undefined elements, you can provide an array length when creating an array:
1 | var largeCollection = new Array(100); // a new array with 100 undefined elements |
1 | var animals = new Array("dog","cat","seal","elephant","walrus","lion"); |
Use the Array methods indexOf and splice to find and remove/replace array elements:
1 | var animals = ['dog', 'cat', 'seal', 'walrus', 'lion', 'cat']; |
If the index is negative, the elements will be spliced from the end, not from the beginning of the array
1 | var animals = ["cat","walrus","lion", "cat"]; |
When we use an Array object to create an associative array, what we’re really doing is adding new properties to the array object, rather than adding new array elements.
1 | obj[propName] = "somevalue"; |
what you’re really doing is adding a new object property:
1 | obj.propName = "somevalue"; |
Instead of using an Array object to create the associative array, use the JavaScript Object directly.
JavaScript functions have Function objects:
1 | var fn = new Function (arg1, arg2, ..., argn, functionbody); |
However, using this syntax is not as efficient as using the function statement, because using a function constructor requires that the function be parsed each time it’s called.
Functions defined with the function statement are parsed once, when the code is loaded.
Variable names can be any combination of characters, numbers, and underscores, as long as the variable name starts with a character or underscore and case-sensitivity is preserved.
You need to create a function, but you won’t know its structure until runtime.
Use an anonymous function, created using the Function object constructor:
1 | // two parameters and one function body string |
Anonymous functions are parsed at runtime, which makes them inefficient for general purposes.
However, they allow us to define both parameters and function body at runtime, which is handy if you’re not sure what the function body is going to be until runtime.
e.g.
1 | window.onload = function() { |
In JavaScript, there is one scope that is created for the outermost application environment. All global variables, functions, and objects are contained within this outer scope.
When you create a function, you create a new scope that exists as long as the function exists. The function has access to all variables in its scope, as well as all of the variables from the outer scope, but the outer scope does not have access to the variables in the function.
Because of these scoping rules, we can access window and document objects in all of our browser applications, and the inner function in the solution can also access the data passed to, or originating in, the outer function that wraps it.
However, the outer function cannot access the inner function’s arguments or local data, because they exist in a different scope.
So even though the outer function’s application scope no longer exists, the inner function’s scope exists at the time the function was returned, including a snapshot of the outer function’s data. It will continue to exist until the application is finished, and the outer, global scope is released.
1 | function outerFunction() { |
The problem with this circular reference is exacerbated in earlier versions of IE, because IE does not release memory associated with DOM objects (such as the doc element) if application scope is released. Even leaving the page does not reclaim the memory: you have to close the browser.
Luckily, newer versions of IE don’t have this problem. However, function closures should be deliberate, rather than accidental.
from https://www.sitepoint.com/currying-in-functional-javascript/
1 | // no currying |
1 | var curryIt = function(uncurried) { |
instance from cookbook:
1 | function curry(fn) { |
When you want to curry a function:
1 | function diffPoint (x1, y1, x2, y2) { |
Adding currying to your coding practice will encourage the use of partially applied functions throughout your code, avoiding a lot of potential repetition, and may help get you into better habits about naming and dealing with function arguments.
You want to optimize your JavaScript applications and libraries by reducing the need to repeat complex and CPU-intensive computations.
1 | var fibonacci = (function lazyDef() { |
nonmemoized function
1 | function fib(n) { |
calculate time consume
1 | // run nonmemo function, with timer |
You can also remove event listeners, as well as cancel the events themselves.
You can also prevent the event from propagating if the element receiving the event is nested in another element.
Canceling an event is helpful when dealing with form validation, and preventing event propagation is helpful when processing click events.
It’s up to you to decide which level of event handling meets your needs.
1 | function listenEvent(eventTarget, eventType, eventHandler) { |
Luckily, most JavaScript libraries already provide the cross-browser event handling functions.
1 | function stopListening(eventTarget, eventType, eventHandler) { |
Canceling an Event Based on Changed Circumstance
You need to cancel an event, such as a form submission, before the event propagates to other elements.
Preventing an Event from Propagating Through a Set of Nested Elements
1 | var answer = confirm('Are you sure you want to do that?'); |
1 | var newWindow = window.open("http://oreilly.com", "namedWindow"); |
We don’t want to indiscriminately throw up pop ups, or intervene with links or people going about their business, but there are times when we want to ensure that people know that when they click a link, type in a new domain, or even close the browser, they’re leaving the current site.
You want people to be aware of the fact that they’re leaving the previously secure website and going somewhere that may be less than secure.
With the advent of JavaScript, form elements could be validated before the data was sent to the server, saving the reader time and the website extra processing.
JavaScript can also be used to modify form elements based on the data the web reader provides, such as filling a selection list with the names of cities when a certain state is selected.
1 | <form id="picker"> |
DOM Level 0 form collections:
1 | document.forms['picker'].elements["intext"].value |
you can also use an array index:
1 | var txtValue = document.forms[0].elements[1].value; |
Using an array index is tricky, since it may be difficult to determine the location of a specific form and element.
However, it’s also a simple way to process all form elements in a loop:
1 | while (var i = 0; i < document.forms[0].elements.length; i++) { |
Whenever you’re accessing data from a text or other field where the user can input whatever value he wants, before sending to the database or displaying in the page, you will want to strip or encode any harmful SQL, markup, or script that may be embedded in the value. You can use encodeURI and encodeURIComponent in JavaScript for encoding.
1 | <body> |
Note: HTML5 Constraint validation doesn’t remove the need for validation on the server side. Even though far fewer invalid form requests are to be expected, invalid ones can still be sent by non-compliant browsers (for instance, browsers without HTML5 and without JavaScript) or by bad guys trying to trick your web application. Therefore, like with HTML4, you need to also validate input constraints on the server side, in a way that is consistent with what is done on the client side.
In the form event handler function, you can access both the event and the element to get information about both. How you do this depends on your browser, and also how you assign the events.