├── translation
├── LICENSE
├── 如何成为一个JavaScript 大牛?【译】.md
├── 7 个基本的 JS 函数[译].md
├── 其实闭包并不高深莫测.md
├── Web应用上线之前,每个程序员应该了解的技术细节.md
├── 脱离jQuery,使用原生Ajax.md
├── JavaScript 模块【Part 2】:模块打包.md
├── 用Mocha和Chai对JavaScript进行单元测试.md
└── JavaScript 模块【Part 1】:初学者指南.md
├── posts
├── 实现类似 QQ音乐网页版 的单页面总结.md
├── white-space:nowrap的妙用.md
├── 关于 Glob (gulp) 的学习.md
├── jQuery 的 attr 与 prop 的区别.md
├── Flex 学习.md
├── 关于JavaScript单线程的一些事.md
├── 《CSS 揭秘》读书笔记.md
├── 再次阅读《精通CSS-高级Web标准解决方案(第二版)》.md
├── 《图解HTTP》读书笔记.md
└── 《JavaScript模式》读书笔记.md
└── README.md
/translation/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/posts/实现类似 QQ音乐网页版 的单页面总结.md:
--------------------------------------------------------------------------------
1 | # 实现类似 QQ音乐网页版 的单页面总结
2 |
3 | 标签: iframe javascript hash
4 |
5 | ---
6 |
7 | 最近需要对创业团队的网站进行改版,而我负责前端设计和实现。
8 | 下面是一些总结与体会:
9 | 当设计完成之前,我就跟和我配合的Java 后台说用iframe实现,结果说麻烦不肯,到最后突然对我说还是用iframe吧,说他以前也用过,很简单--!...其实我之间也基本没用iframe,对它比较陌生,但是 QQmusic 网页版就是用iframe 做的,印象比较深刻!
10 |
11 | 我设计的页面总体结构是与QQmusic网页版类似,网页头部和脚部都是固定,中间内容是通过iframe来展示。
12 |
13 | 用iframe之前,我想到要解决的问题有:
14 |
15 | 1. iframe虽然有height这个属性,但是每次加载到里面的内容都是不同的,而且我实现的部分页面是需要动态加载能容的。
16 | 我的解决办法是:
17 | iframe 首次加载成功后和 `iframe` 页面内有动态增加内容时(导致整体高度有变化)都调用下面这个函数,来设置 `iframe` 高度
18 |
19 | function iframeLoaded() {
20 | var contentFrame = document.getElementById('contentFrame');
21 | if(contentFrame) {
22 | contentFrame.height = contentFrame.contentWindow.document.documentElement.scrollHeight + "px";
23 | }
24 | }
25 |
26 |
27 | 2. 因为是做成像QQmusic网页版的单页面,所以我也利用hash变化来欺骗浏览器,让浏览器为我的页面跳转生成历史记录,但是后来发现,每次点击链接加载不用iframe时,都会生成两条相同的历史记录。这是为什么呢?后来发现,hash值改变会导致一次,iframe的src改变也会生成一次历史记录(包括hash的改变)。然后我又去看看QQmusic 是怎么实现只产生一次历史记录的,惊奇的发现,它的iframe的src一直没变(一直是 about:blank)。
28 |
29 |
30 |
31 | 因此发现我之前对iframe有些误解,之前认为iframe只能通过src来获取内容,其实个人认为正确的是:iframe中的内容不一定是通过设置src后获取的,也可以是通过其它方式(例如通过ajax获取html后替换原视图而成);所以对于QQmusic来说,iframe只是一块渲染视图的容器,它里面显示的内容是由另外的逻辑来控制的。这样无须改变iframe的src(也就不会产生历史记录),从而可以动态修改iframe的内容了。如:
32 |
33 | window.onload = function(){
34 | var iframe = document.getElementById("iframe")
35 | var newDiv = document.createElement("div")
36 | newDiv.innerHTML = "我要跑到iframe里"
37 | iframe.contentWindow.document.body.appendChild(newDiv)
38 | }
39 |
40 | 对于整体页面(用jQuery发出异步请求)
41 |
42 | $.ajax({
43 | url: "原本iframe的src值", // 改为异步请求加载
44 | type: "GET"
45 | })
46 | .done(function(data){
47 | var iframe = document.getElementById("iframe")
48 | iframe.contentWindow.document.documentElement.innerHTML = data; // 获取后直接插到iframe
49 | })
50 |
51 | 所以,iframe的内容一直在改变,而它的src却一直是about:blank没变。因此也不会产生新的历史记录。
52 | 此时此刻,我心情是很开心的,然而,当我与iframe内的元素交互时,发现除了 CSS 的交互效果,和写在内的js代码都是不执行的(测试后发现直接添加到元素的onclick事件可以执行),而且在测试的过程中发现有时候CSS加载比较慢,导致HTML裸露出来,不知道为什么。这个要继续查查。
53 |
54 | 所以,最后我不采用通过ajax获取内容,再添加到iframe的做法。
55 | 而是采用移除原来iframe,再新建一个iframe插入的方式,这种方式也是不会产生新的历史记录。
56 |
57 | 解决了产生两条历史记录的问题后,剩下的问题就是iframe内的链接跳转,因为整体是通过主页面的hash值来路由的,所以iframe内的链接跳转是不能直接跳转的,他的跳转需要一定处理的流程:
58 |
59 | 处理由iframe内发送的请求:
60 | ①首先接收iframe的参数
61 | ②根据参数生成对应的hash,并修改main_frame 的hash值
62 | ③根据hash值,修改iframe的src(我是通过删除原来的iframe,再添加新iframe的做法)
63 |
64 | 如:主页面的全局有一个接收iframe内a标签的data-hash的函数:
65 |
66 | function handleIframeRequst( iframeHash){
67 | window.location.hash = iframeHash;
68 | }
69 |
70 | 假设iframe内的一个a标签 :
71 | 点击这个标签时,就会调用主页面的一个处理该data-hash的函数
72 | parent.handleIframeRequst($(this).data("hash")); // 通过parent调用主页面的函数
73 |
74 | 主页面接收参数后,修改自身的hash值,然后解析hash值,生成相应的 iframe src值。
75 |
76 | 这样基本就可以将网站做成 类似 QQmusic 那样的单页面网站啦。 满足感 Up!Up!Up!
77 |
--------------------------------------------------------------------------------
/posts/white-space:nowrap的妙用.md:
--------------------------------------------------------------------------------
1 | # white-space:nowrap 的妙用
2 |
3 | 标签: CSS white-space
4 |
5 | ---
6 |
7 | 对于多个元素同在同一行的布局,如比较常见的是轮播。下面我将探讨这这一布局的做法:
8 | 首先约定`html`结果如下:
9 |
10 | div.row
11 | div.col
12 | div.col
13 | div.col
14 | ...
15 |
16 | ### 做法一:
17 | 设定`div.row`的宽度为`div.col宽度*div.col的个数`,然后设置`div.col`为`float:left`或`display:inline-block`
18 | 对于 `float:left`, `div.row` 需要清除浮动。
19 | 对于 `display:inline-block`,需要压缩html或者为`div.row`设置 `font-size:0` 以去除 `div.col` 之间的水平间隙,后者也顺便去除了垂直方向的间隙(line-height为相对单位时,其最终值为line-height值*font-size)。对于前者,还有垂直方面的间隙未去除,我们可以为`div.col`设置 `vertical-align:top` 或为`div.row`设置 `line-height:0`。推荐前者(即vertical-align),因为当 `div.col` 高度不相等时,会按顶部对齐,当然你也可以`bottom`或`middle`。而且,如果`div.col`内含有行内元素或inline-block元素时,`div.col`会按其子元素最后一行`inline/inline-block`元素的基线进行垂直方向上的对齐(vertical-align默认值是baseline)。因此最好显式设置`div.col`的垂直方向上的对齐。
20 | ![baseline基线][1]
21 | baseline基线
22 |
23 | ![水平与竖直方向上的间隙][2]
24 | 水平与竖直方向上的间隙
25 |
26 | ![按其子元素最后一行inline/inline-block元素的基线进行垂直方向上的对齐][3]
27 | 按其子元素最后一行`inline/inline-block`元素的基线进行垂直方向上的对齐
28 | > 这也符合张鑫旭老师的《[CSS深入理解vertical-align和line-height的基友关系][4]》这篇文章讲到的:一个inline-block元素,如果里面没有inline内联元素,或者overflow不是visible,则该元素的基线就是其margin底边缘,否则,其基线就是元素里面最后一行内联元素的基线。
29 |
30 |
31 | 补充知识:line-height的值为**数字**与**百分比**的区别
32 | > 百分比是当前元素的字体大小`*`百分比,算出的值让后代元素继承(固定值,后代元素均用此值);而数字是让后代元素的字体大小`*`数值(相对值,后代元素根据自身字体大小算出适合的行高)。具体可以看 《[深入了解css的行高Line Height属性][5]》。
33 |
34 | 当然,如果`div.row`内有行内元素或inline-block元素,它们会继承父元素的font-size与line-height,因此需要重新设置font-size和line-height,以覆盖`div.row`对应的值。
35 |
36 | 做法一的案例有:淘宝首页的主轮播(通过子元素浮动,父元素清除浮动)。
37 | 这种做法的好处有:①兼容性好,无须清除`div.col`直接的间隙,因为浮动后的元素会一直与当前行框(line box)顶部对齐,vertical-align对齐无效。
38 | 不好的地方:要计算`div.row`的宽度。
39 |
40 |
41 | ### 做法二(这也是我想讲的巧妙)
42 | 直接上代码:
43 |
44 | *{
45 | margin: 0;
46 | padding: 0;
47 | }
48 | .row{
49 | white-space: nowrap; // 让div.col放置在同一行
50 | background-color: rgb(0,0,0); // 背景色,以方便观察
51 | font-size: 0; // 去除水平+垂直间隙
52 | }
53 | .col{
54 | display: inline-block;
55 | *display: inline; // 兼容IE 6/7,模拟inline-block效果
56 | *zoom: 1; // 兼容IE 6/7,模拟inline-block效果
57 | width: 20%;
58 | margin-right: 30px;
59 | height: 100px;
60 | background-color: red;
61 | font-size: 14px; // 覆盖父元素的font-size
62 | vertical-align: top; // 向上对齐,同时去除垂直间隙
63 | }
64 |
65 | ![此处输入图片的描述][6]
66 | 黑色背景是`div.row`,红色背景是 `div.col`。
67 |
68 | 可看出这与与应用了`white-space:nowrap`的文本容器效果一样。
69 |
70 | ####做法二的好处有:
71 | ①兼容性好(IE5都正常),无须计算宽度,可任意放多个 `div.col`,而 `div.row` 的宽度等于其父元素的宽度(但IE6则会将div.row撑大,在IE6中,`width`如同`min-width`效果,`height`也是)。
72 | ![IE5/6效果][7]
73 | IE5上的效果,IE6应该也一样。
74 |
75 | ---
76 |
77 | 如果你还有其它想法,欢迎大家在评论处告诉我哦。
78 |
79 | [github-JChehe][8]。
80 | [静态博客][9] <- 小心这心机婊
81 |
82 |
83 |
84 | [1]: https://blog-1251477229.cos.ap-chengdu.myqcloud.com/others/nowrap-baseline.jpg
85 | [2]: https://blog-1251477229.cos.ap-chengdu.myqcloud.com/others/nowrap-jianxi.jpg
86 | [3]: https://blog-1251477229.cos.ap-chengdu.myqcloud.com/others/nowrap-inlineORinline-block.jpg
87 | [4]: http://www.zhangxinxu.com/wordpress/2015/08/css-deep-understand-vertical-align-and-line-height/
88 | [5]: http://www.cnblogs.com/fengzheng126/archive/2012/05/18/2507632.html
89 | [6]: https://blog-1251477229.cos.ap-chengdu.myqcloud.com/others/nowrap-GIF.gif
90 | [7]: https://blog-1251477229.cos.ap-chengdu.myqcloud.com/others/nowrap-GIF-IE56.gif
91 | [8]: https://github.com/JChehe/blog
92 | [9]: http://jchehe.github.io/resume/
93 |
--------------------------------------------------------------------------------
/posts/关于 Glob (gulp) 的学习.md:
--------------------------------------------------------------------------------
1 | 参考资料:https://github.com/isaacs/node-glob
2 |
3 | 下文是关于 Gulp 的 `gulp.src(globs[, options])` 方法的第一个参数 `globs` 的学习。
4 |
5 | 需要注意的是:
6 | 当该参数 `globs` 为数组时,其包含的多个 glob 会**按顺序进行解析**,这意味着以下意图是可以实现的:
7 |
8 | // 排除所有以字母 b 开头的 js 文件,但不排除 bad.js
9 | gulp.src(['*.js', '!b*.js', 'bad.js'])
10 |
11 | ---
12 |
13 | ## Glob
14 | 使用 shell 里的 patterns 匹配文件,如 `*` 等。
15 |
16 | ## 用法
17 | ### 用 npm 安装 glob
18 |
19 | npm i glob
20 |
21 | 编写js代码:
22 |
23 | var glob = require("glob");
24 |
25 | // options 是可选参数
26 | glob("**/*.js", options, function (er, files) {
27 | // files 参数是一个文件名数组。
28 | // 若参数 options 的 `nonull` 属性为 true,则在匹配不到文件时, files 参数则为 ["**/*.js"]。
29 | //( 若 `nonull` 为 false 时, files 为空数组)。
30 | // er 是一个 error 对象或 null。
31 | })
32 |
33 | ## Glob 初级
34 | "Globs" 是你通过在命令行输入字符后完成某些操作时的 pattern。如 `ls *.js`,或将 `build/*` 放在 `.gitignore`。
35 |
36 | 在解析路径段的 patterns 前,braced sections 会展开为一个集合。braced sections 以 `{` 开头,`}` 为结尾,中间部分以英文逗号 `,` 分隔。braced sections 可以含有斜杠符号 `/`。因此,`a{/b/c,bcd}` 会展开为 `a/b/c` 和 `abcd`。
37 |
38 | 以下字符用在路径段时,会拥有特别的含义:
39 |
40 | - `*` : 匹配0或多个字符。
41 |
42 | glob("js/*.js", function(err, files){
43 | console.log(files);
44 | });
45 | 获取js目录下的所有js文件(不包括以`.`开头的文件,下文有方法解决:对 glob 方法的 options 参数的属性 `dot:true`)。
46 |
47 |
48 | - `?` : 匹配一个字符(不能为空)。
49 |
50 | glob("js/a?.js", function(err, files){
51 | console.log(files);
52 | }
53 | 获取js目录下所有文件名长度为1字符的js文件。例如:能匹配 js/ab.js,不能匹配 js/a.js。
54 |
55 |
56 | - `[...]` : 匹配该路径段中在指定范围内的一个字符。
57 | 注意:不能组合,只能匹配其中**一个**字符。另外,如果指定范围的首字符是 `!` 或 `^`,则匹配**不在指定范围内**的**一个**字符。
58 |
59 | glob("js/a[0-3].js", function(err, files){
60 | console.log(files);
61 | })
62 | 获取js目录下以`a`开头,第二个字符为0-3之间(包括0和3)的js文件。若改为 `["js/[^ab].js"]`,则匹配 js/c.js,不匹配 js/cd.js、js/ac.js。
63 |
64 |
65 | - `!(pattern|pattern|pattern)` : 匹配(完全且精确地匹配,且不可组合)不符合任何模型之一的字符。注意 `|` 前后不能有空格,下同。
66 |
67 | glob("js/!(a|b).js", function(err, files){
68 | console.log(files);
69 | });
70 | 匹配 js 目录下的 aa.js、ab.js、ba.js、c.js 不匹配 a.js、b.js。
71 |
72 |
73 |
74 | - `?(pattern|pattern|pattern)`:匹配多个 pattern 中 0 或 1 个(精确匹配,不可以组合)。
75 |
76 | glob("js/?(a|b).js", function(err, files){
77 | console.log(files);
78 | });
79 | 匹配 js 目录下的 a.js、b.js,不匹配 ab.js
80 |
81 |
82 | - `+(pattern|pattern|pattern)` : 至少匹配多个 pattern 中的一个。与`*(pattern|pattern|pattern)` 不用的是,它必须1个及以上,不能为空。
83 |
84 | glob("js/+(a|b)b.js", function(err, files){
85 | console.log(files);
86 | });
87 | 匹配 js 目录下的 ab.js、bb.js、ababab.js,不能匹配 abcd.js(也就是说:只允许匹配出现在范围内的字符) ,也不能像 `js/*(a|b)b.js` 那样匹配 b.js。
88 |
89 |
90 | - `*(a|b|c)` : 匹配括号中多个 pattern 中0或任意多个(pattern可相互组合)。
91 |
92 | glob("js/*(a|b|c).js", function(err, files){
93 | console.log(files);
94 | });
95 | 匹配 js 目录下的 a.js、ab.js、abc.js、ba.js,不匹配 abcd.js(也就是说:只允许匹配出现在范围内的字符)。
96 |
97 |
98 | - `@(pattern|pattern|pattern)` 匹配多个 pattern 中的任意一个(即不可以组合,且不能为空或大于1个)。与 `?(pattern|pattern|pattern)` 区别是不可为空。
99 |
100 | glob("js/@(a|b)b.js", function(err, files){
101 | console.log(files);
102 | });
103 | 匹配 js 目录下的 ab.js、bb.js,不匹配 b.js、abb.js、abc.js。
104 |
105 |
106 | - `**` 与 `*` 类似,可以匹配任何内容(可匹配空),但 `**` 不仅能匹配路径中的特定一段,还能匹配后代所有目录(即多段路径段)。
107 |
108 | glob("js/**/*.js", function(err, files){
109 | console.log(files);
110 | });
111 | 匹配 js 目录下所有js文件,如 js/a.js 或 js/a/b/c/d.js。
112 |
113 | ## Dots(即 `.`)
114 | 如果文件或目录的某路径段以 `.` 作为首字符,那么该路径段不会符合任何 glob pattern,除非该 pattern 的相应路径段同样以 `.` 作为首字符。
115 |
116 | 例如,pattern `a/.*/c` 会匹配文件 `a/.b/c`,而 pattern `a/*/c` 则不会匹配该文件,因为 `*` 不会匹配以 `.` 字符开头的文件。
117 |
118 | 可通过在 options 设置 `dot: true`,让 glob 将 `.` 视为普通字符。
119 |
120 | ## Basename 匹配
121 | 如果在 options 设置 `matchBase: true`,且 pattern 不含有 `/`,那么将会寻找任何匹配 basename 的文件,即在当前路径下的文件树进行搜索。例如,`*.js` 会匹配 `test/simple.basic.js`。
122 |
123 | ## 空集
124 | 如果不匹配任何文件,则会返回空数组。这点与 shell 不同,shell 会返回自身 pattern。
125 |
126 | $echo echo a*s*d*f
127 | a*s*d*f
128 |
129 | 若想得到 bash 那样的行为,可对 options 参数设置 `nonull:true`。
130 |
131 | 若发现文中有任何错误,或有任何好的建议,欢迎评论。
132 |
133 | -------
134 |
135 | GitHub:[关于 Glob (gulp) 的学习](https://github.com/JChehe/blog/blob/master/posts/%E5%85%B3%E4%BA%8E%20Glob%20%E7%9A%84%E5%AD%A6%E4%B9%A0.md)
136 |
--------------------------------------------------------------------------------
/translation/如何成为一个JavaScript 大牛?【译】.md:
--------------------------------------------------------------------------------
1 | # 如何成为一个JavaScript 大牛?【译】
2 |
3 | 标签: JavaScript translation
4 |
5 | ---
6 |
7 | 在成长的过程中,我的兴趣点不断发散,而且都是看似不相关的领域。我喜欢数学正如我喜欢历史一样。我的目标是成为一个 多才多艺的人 – 博学者-,能在多个领域成为优秀人才。这证实是一项艰巨的任务,我忽然面临着行行皆通,样样稀松的危险。
8 |
9 | 我开始考虑专注于某些领域,这样即使不能成为像文艺复兴时期的通才,但至少能精通某些方面。那我怎么样才能专注于某一领域的同时,掌握软件开发所需的庞大的知识体系呢?
10 |
11 | 本帖内容是基于我过去 5 年经验编写的,概述了我成为一个优秀的 JavaScript 开发者所用到的技术和资源。
12 |
13 | 当今大多数 web 开发者都面临着同样的问题:他们不得不擅长多个不同领域,从数据库到后端架构,再到前端的用户界面,用所精通的 CSS 知识去修改 UI 。
14 |
15 | ## 看书
16 | 为了达到精通,专注与努力是首要条件。如果不投入全身心工作,最后你只会一知半解。例如通过阅读一些博客文章,因为初期时间投入较低,所以看起来会比较简单。但从长远来看,这种学习模式将会比专注于学习精髓的过程花费更多的时间。解决这个难题的方法很简单:看书。
17 |
18 | 书籍让我们站在文明的肩膀上。而精炼的文字让我们的知识代代相传。而对于如何成为 web 技术专家这个问题,你在学习的过程中就要与 web 本身保持一定距离。因为 web 对于学习来说,其本身就是一个混杂且分散的媒介,所以我的第一个建议是阅读相关专业的书籍。
19 |
20 | 对于 JavaScript,从 [《JavaScript 语言精髓》](http://shop.oreilly.com/product/9780596517748.do) 这本被称为 JavaScript 圣经的书开始。这本书虽然比较旧,但非常适合入门。[《JavaScript权威指南》](http://shop.oreilly.com/product/9780596805531.do) 也是必备的,尽管你可能会将它作为一个参考书籍。另外,jQuery 作者 John Resig 的 [《JavaScript 忍者禁术》](http://blog.ustunozgur.com/javascript/programming/books/videos/2015/06/17/www.manning.com/resig/) 也是不容错过的。如果你在寻找好(在线免费的)书,可以看看 [《JavaScript Allongé》](https://leanpub.com/javascript-allonge/) 、[《You Don’t Know JS》](https://github.com/getify/You-Dont-Know-JS) 和 [《Eloquent JavaScript》](http://eloquentjavascript.net/)([点击这里](https://watchandcode.com/courses/eloquent-javascript-the-annotated-version) 可以看它的注释版本)。这些都能以电子书或印刷版的形式购买。另外,Mozilla’s Developer Network 也有很好的 “[JavaScript 指南](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide)”。
21 |
22 | ## 学习、使用并阅读库
23 | 接下来最重要的一步是了解库。如果书籍教会你如何理解语言,则库教你如何表达它。对于库,你有两个重要的事情要做:使用它们并阅读它们的源代码。
24 |
25 | 通过使用库,开始知道:jQuery、Backbone、underscore 和 React、Angular 、Ember 中的一个。当然,这不是说你必须使用这些库,但称职的 JavaScript 开发者都应该至少有这些库的使用经验(不管好坏)。
26 |
27 | 对于提高 JavaScript 技能,第二重要的是阅读这些库的源代码。其中,我特别推荐 Backbone 和 underscore 的源代码,因为它们的代码写得特别漂亮。通过阅读和理解 underscore,你的函数编程能力将会得到提高。另一个是其他几个开发者推荐给我的库是 mootools (我个人没有 mootools 的使用和阅读经验,仅仅是传达信息。)
28 |
29 | 理解上述列表里的其它库,如 React、Ember 等,可能有点难,但值得付出努力。至少略读其它库的源代码,看看它们是如何组织基础代码并尽量发现一些模式。其它一些值得使用和阅读源代码的库还有 d3、 highcharts 和 moment.js。
30 |
31 | ## 练习与问自己问题
32 | 成为优秀 JavaScript 开发者的下一步是做大量的实践。理论上,这些实践的重点不在 DOM,而是语言,所以确保有测试工具能在 node.js 上运行。在 node.js 上做大量小练习。通过不同的方式使用 JavaScript 的闭包、原型、array-extras (map, filter) 等。当你经过大量练习后,头脑里就会对 JavaScript 有基本的想法。
33 |
34 | 我朋友 Armagan 是一名杰出的 JavaScript 程序员兼老师,他在课堂里使用的课本 [《JavaScript 设计模式》](http://www.apress.com/9781590599082) 也是值得一看的。
35 |
36 | 试着回答诸如:原型继承是如何工作的?闭包的定义是什么?this 关键字是如何改变的?如何使用 apply/bind/map/filter/call?收集一些 JavaScript 开发者常见问题并尝试用自己的语言解释它。用书面或口头的方式向别人解释这些概念,能极大地提高能力。在做实践的同时,尝试做“假设分析”。例如,“如果使用两次 bind,this 将会代表什么?jQuery 是如何确保 this 关键字是引用 jQuery 对象,而不是全局对象?这个库如何完成某个特性?”这些都是值得思考的常见问题。
37 |
38 | ## 学习标准
39 | 下一步是学习更多关于 EcmaScript 标准。找到一份最新的 EcmaScript 标准并尝试阅读它。除了这些,也要尝试学习即将推出的 JavaScript 特性,如 ES 6 和 ES 7 新增的。最近有一些新特性如:promises、modules、generators、comprehensions 和 again。可以通过专门的书来学习标准,如 Zakas 的 ( [Understanding EcmaScript 6](https://leanpub.com/understandinges6) ) 或 Dr. Axel Rauschmayer 的 ES6 书 ( [Exploring JS](http://exploringjs.com/) ) 。阅读标准是获取专业知识和发现语言新特性的主要来源。
40 |
41 | ## 使用 web 上的资源
42 | 我之前提到使用 web 获取 web 知识的危险性,所以最后的建议是具体如何在 web 中获取最好的资源。Hacker News 是一个很好的资源,然而如果时刻关注它的话,将会花费较多时间,因为信噪比较低(表示 JavaScript 文章比例较低)。取而代之的是,关注 [JavaScript Weekly](http://javascriptweekly.com/) 之类的每周文摘。随着时间的推移,你会看到哪些库或技术是备受关注的。在 Twitter,尝试去关注那些有影响力的 JavaScript 开发者。这里是 Tutsplus 列出的 [33 个值得关注的 JavaScript 开发者](http://code.tutsplus.com/articles/33-developers-you-must-subscribe-to-as-a-javascript-junkie--net-18151)。其它在 web 上的资源还包括一些博客,如 [Toptal Blogs](http://www.toptal.com/section/front-end)、[Rebecca Murphey’s blog](http://rmurphey.com/) (如果你对这个博客的帖子感兴趣,也可以看看 [A Baseline for Front-End [JS] Developers: 2015](http://rmurphey.com/blog/2015/03/23/a-baseline-for-front-end-developers-2015/))和 [Nicholas Zakas’ blog](http://www.nczonline.net/)。(如果你有其它好博客,请 Email 我,我会将它添加到该列表里。)
43 |
44 | 另一个重要资源是大会视频和教育视频。对于大会,JSConf 系列都是高质量的。对于教育视频,我强烈建议 Pluralsight,因为他们拥有经验丰富的开发者准备的高质量课程。(我与 Pluralsgiht 没有隶属关系)
45 |
46 | ## 浓缩版
47 | - 从阅读书籍开始,因为书籍能为你提供精华信息。
48 | - 学习主要的库,如 jQuery、underscore、Backbone,并阅读它们的源代码。
49 | - 多实践并尝试用自己的话解释“继承”之类的常见 JavaScript 概念。对上述主题进行演讲和交流。
50 | - 仔细阅读最新标准,并开始使用该语言的最新特性。
51 | - 关注 web 资源,每周关注一次文摘或博客,或观看会议视频和视频教程。
52 |
53 | ## 总结
54 | 一直反复这些并完成大量项目,将会极大地提高你的 JavaScript 编程能力。只有努力不懈,才有希望在几年后成为一名专家。我觉得自己是一名优秀的 JavaScript 程序员,离专家仍有一大段路要走,有很多技术需要在我接下来的学习生涯中学到。另外,随时可以通过 [atustun@ustunozgur.com]() 向我提出反馈和修正。
55 |
56 | 本文由 [伯乐在线](http://web.jobbole.com/) - [刘健超-J.c](http://www.jobbole.com/members/q574805242) 翻译,[shutear](http://www.jobbole.com/members/shutear) 校稿。未经许可,禁止转载!
57 | 英文出处:[Ustun Ozgur](http://blog.ustunozgur.com/javascript/programming/books/videos/2015/06/17/how_to_be_a_great_javascript_software_developer.html)。
58 |
59 | 感谢您的阅读。
60 |
--------------------------------------------------------------------------------
/posts/jQuery 的 attr 与 prop 的区别.md:
--------------------------------------------------------------------------------
1 | ## jQuery 的 attr 与 prop 的区别
2 |
3 | 标签: JavaScript jQuery
4 |
5 | ---
6 |
7 | 先提出问题:对于 checked 这类值是 true/false 的属性,用 jQuery 的 attr 或 prop 方法进行 读取或设置值是有区别的。
8 |
9 | 在看 jQuery 文档前,我们先看看 attribute 与 property 是什么:
10 |
11 | ### 先搞懂 attribute 与 property
12 |
13 | 当编写 HTML 源码时,你能在 HTML 元素里定义 attributes。然后,一旦浏览器解析你的代码,该 HTML 元素相应的 DOM 节点就会被创建。该节点是一个对象,因此它就拥有 properties。
14 | 因此,我们知道:attributes 是 HTML 元素(标签)的属性,而 properties 是 DOM 对象的属性。
15 |
16 | 例如,下面这个 HTML 元素:
17 |
18 |
19 |
20 | 拥有两个 attributes。
21 |
22 | 一旦浏览器解析该代码,HTMLInputElement 对象就会被创建,并且该对象会拥有很多 properties,如:accept、accessKey、align、alt、attributes、autofocus、baseURI、checked、childElementCount、ChildNodes、children、classList、className、clientHeight 等等。
23 |
24 | 对于某个 DOM 节点对象,properties 是该对象的所有属性,而 attributes 是该对象对应元素(标签)的属性。
25 |
26 | 当一个 DOM 节点为某个 HTML 元素所创建时,其大多数 properties 与对应 attributes 拥有相同或相近的名字,但这并不是一对一的关系。例如,下面这个 HTML 元素:
27 |
28 |
29 |
30 | 其对应 DOM 节点会拥有如下properties: id、type 和 value:
31 |
32 | - `id` property是 `id` attribute 的映射:获取该 property 即等于读取其对应的 attribute 值,而设置该 property 即为 attribute 赋值。`id` 是一个纯粹的映射 property,它不会修改或限制其值。
33 | - `type` property 是 `type` attribute 的映射:获取该 property 即等于读取其对应的 attribute 值,而设置该 property 即为 attribute 赋值。但 `type` 并不是一个纯粹的映射 property,因为它的值被限制在已知值(即 input 的合法类型,如:text、password)。如果你有 ``,然后 `theInput.getAttribute("type")` 会返回 `"foo"`,而 `theInput.type` 会返回 `"text"`。
34 | - 相比之下,`value` property 并不会映射 `value` attribute。取而代之的是 input 的当前值。当用户手动更改输入框的值,`value` property 会反映该改变。所以,如果用户在 input 输入 `John`,然后:
35 |
36 | theInput.value // 返回 "John"
37 | 然而:
38 | theInput.getAttribute('value') // 返回 "Name:"
39 |
40 | `value` property 反映了 input 的**当前**文本内容,而 `value` attribute 则是在 HTML 源码 value 属性所指定的**初始**文本内容。
41 |
42 | 因此,如果你想知道文本框的当前值,则读取 property。而如果你想知道文本框的初始值,则读取 attribute。或者你也可以利用 defaultValue property,它是 value attribute 的纯粹映射。
43 |
44 | theInput.value // returns "John"
45 | theInput.getAttribute('value') // returns "Name:"
46 | theInput.defaultValue // returns "Name:"
47 |
48 | 有几个 properties 是直接反映它们 attribute(rel、id),而有一些则用稍微不同的名字进行直接映射(`htmlFor` 映射 `for` attribute,`className` 映射 `class` attribute)。很多 property 所映射的 attribute 是带有限制/变动的(src、href、disabled、multiple)。该 [规范][1] 涵盖了各种各样的映射。
49 |
50 |
51 | ### 再看看 attr() 与 prop() 的区别
52 |
53 |
54 | 上述能让我们理清了 attribute 与 property 之间的区别,下面根据 [jQuery 文档][2] 对 attr() 与 prop() 方法进行比较:
55 |
56 | 自 jQuery 1.6 版本起,`attr()` 方法对于未设置的 attributes (即标签中没写该 attributes)都会返回 `undefined`。对于检索和改变 DOM 的 properties,如表单元素的 checked、selected 或 disabled 状态,应使用 `.prop()` 方法。
57 |
58 | Attributes vs. Properties
59 |
60 | attributes 与 properties 之间的差异在特定情况下会变得尤为重要。在 jQuery 1.6 前,`.attr()` 方法在检索一些 attributes 时,有时会把 property 考虑进去,这会导致不一致的行为。在 jQuery 1.6 版本之后,`.prop()` 方法提供了一种明确检索 property 值的方式,而 `.attr` 只会检索 attributes。
61 |
62 | 例如,selectedIndex、tagName、nodeName、nodeType、ownerDocument、defaultChecked 和 defaultSelected 能被 `.prop()` 检索与设置。在 jQuery 1.6 之前,这些 properties 都是通过 `.attr()` 检索的,但检索这些属性并不应属于 attr 方法职责内 。这些属性并没有对应的 attributes,只有 properties 本身。
63 |
64 | 对于值为布尔值的 attributes ,考虑到一个 DOM 元素是通过 HTML 标签 ` | auto; /* default value */
147 | }
148 | ```
149 | > 如果同时设置flex-basis和width,那么width属性会被覆盖,也就是说flex-basis的优先级比width高。有一点需要注意的是:如果flex-basis和width其中有一个是auto,那么另外一个非auto的属性优先级会更高。
150 |
151 |
152 | #### flex属性
153 | flex属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。
154 | ```css
155 | .item {
156 | flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
157 | }
158 | ```
159 |
160 | 该属性有两个关键字:`auto` (`1 1 auto`) 和 `none` (`0 0 auto`)。
161 |
162 | #### align-self属性
163 | 允许单个项目有与其他项目不一样的对齐(交叉轴上)方式,即覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。
164 | ```css
165 | .item {
166 | align-self: auto | flex-start | flex-end | center | baseline | stretch;
167 | }
168 | ```
169 | 除了auto,其余与align-items 一样。
170 |
171 | 希望能尽快应用到项目中。
172 |
173 |
174 | [1]: http://caniuse.com/#search=flex
175 | [2]: http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html
176 | [3]: http://www.ruanyifeng.com/blog/2015/07/flex-examples.html
177 | [4]: http://zhoon.github.io/css3/2014/08/23/flex.html
178 | [5]: https://blog-1251477229.cos.ap-chengdu.myqcloud.com/others/flex.png
179 | [6]: https://blog-1251477229.cos.ap-chengdu.myqcloud.com/others/justify-content.png
180 | [7]: https://blog-1251477229.cos.ap-chengdu.myqcloud.com/others/align-content.png
181 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 一切以官方文档为准!
2 |
3 | ### 前端
4 |
5 | - [XCel 项目总结 - Electron 与 Vue 的性能优化][1]
6 | - [我的第一次移动端页面制作 — 总结与思考][2]
7 | - [我的第一次小程序制作 — 总结与思考][3]
8 | - [try-catch-finally][4]
9 | - [【译】前端开发者们,快带上 Tensorflow.js 拥抱机器学习吧][5]
10 | - [【译】基于 Vue-router 实现用户认证][6]
11 | - [【译】如何更好地组织 React 项目][7]
12 | - [【译】Electron 自动更新的完整教程(Windows 和 OSX)][8]
13 | - [【译】Electron 的本质][9]
14 | - [【译】以案例阐述 Debounce 和 Throttle][10]
15 | - [【译】使用 Fullscreen API 全屏展示内容][11]
16 | - [【译】Grid 完整指南][12]
17 |
18 |
19 | ### 后端
20 |
21 | - [Redis 知识积累][13]
22 | - [《深入浅出 Node.js》读书笔记][14]
23 | - [《Nginx 高性能 Web 服务器详解》读书笔记][15]
24 | - [《Web API 的设计与开发》读书笔记][16]
25 | - [【译】MySQL 数据类型【8.0 中文版】][17]
26 |
27 | ### 动效动画
28 |
29 | - [《HTML5 + JavaScript 动画基础》读书笔记][18]
30 | - [“等一下,我碰!”——常见的2D碰撞检测][19]
31 | - [曲线(路径)运动的那些事][20]
32 | - [正态分布 — 更真实地还原动画][21]
33 | - [动画:从 AE 到 Web][22]
34 | - [Three.js 现学现卖][23]
35 | - [CSS 3D Panorama - 淘宝造物节技术剖析][24]
36 | - [这里有你对 Web 游戏的疑问吗?][25]
37 | - [用 Web 技术实现移动监测][26]
38 | - [实现一个简单但有趣的AR效果(Web)][27]
39 | - [浅谈 WebVR][28]
40 | - [【译】使用 CSS 分层动画实现曲线运动][29]
41 | - [【译】探索基于 WebGL 的动画与交互(案例学习)][30]
42 | - [【译】基于 Three.js 实现了交互式 3D 人物][31]
43 | - [【译】基于 Three.js 实现 3D 模型换肤][32]
44 | - [【译】隧道动画][33]
45 | - [【译】叶子——可互动的 Web 玩具][34]
46 |
47 |
48 | ### 其他
49 |
50 | - [《JavaScript 设计模式与开发实践》读书笔记][35]
51 | - [看懂「测试覆盖率报告」][36]
52 | - [《Pro Git 2》思维导图][37]
53 | - [《啊哈!算法》速读笔记][38]
54 |
55 | ## 关于版权
56 |
57 | 版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章**原始出处、作者信息和本声明**。否则将追究法律责任。
58 |
59 | ---
60 |
61 | ## 之前的记录
62 |
63 | 主要是原创文章和翻译技术文章。
64 |
65 | ## 原创文章
66 |
67 | 更多原创文章,可关注 <[博客园 刘健超-J.c][39]> or <[segmentfault 刘健超_Jc][40]>
68 | - [Flex 学习][41]
69 | - [《CSS 揭秘》读书笔记][42]
70 | - [《JavaScript模式》读书笔记][43]
71 | - [white-space:nowrap 的妙用][44]
72 | - [《图解HTTP》读书笔记][45]
73 | - [jQuery 的 attr 与 prop 的区别][46]
74 | - [关于 Glob(gulp) 的学习][47]
75 | - [《JavaScript(ES5)的面向对象精要》读书笔记][48]
76 | - [关于JavaScript单线程的一些事][49]
77 | - [再次阅读《精通CSS-高级Web标准解决方案(第二版)》][50]
78 | - [实现类似 QQ音乐网页版 的单页面总结][51]
79 |
80 | ## 翻译文章
81 |
82 | 更多翻译文章,可关注 [伯乐在线 刘健超-J.c][52]。
83 |
84 | > 注:之前在伯乐在线翻译了 28 篇文章,但目前伯乐在线已不运营。
85 |
86 | - [JavaScript 模块【Part 1】:初学者指南][53]
87 | - [JavaScript 模块【Part 2】:模块打包][54]
88 | - [用Mocha和Chai对JavaScript进行单元测试][55]
89 | - [7 个基本的 JS 函数][56]
90 | - [Web应用上线之前,每个程序员应该了解的技术细节][57]
91 | - [其实闭包并不高深莫测][58]
92 | - [如何成为一个JavaScript 大牛?][59]
93 | - [脱离jQuery,使用原生Ajax][60]
94 |
95 |
96 | [1]: https://github.com/JChehe/blog/issues/7
97 | [2]: https://github.com/JChehe/blog/issues/4
98 | [3]: https://github.com/JChehe/blog/issues/36
99 | [4]: https://github.com/JChehe/blog/issues/38
100 | [5]: https://github.com/JChehe/blog/issues/41
101 | [6]: https://github.com/JChehe/blog/issues/20
102 | [7]: https://github.com/JChehe/blog/issues/19
103 | [8]: https://github.com/JChehe/blog/issues/6
104 | [9]: https://github.com/JChehe/blog/issues/5
105 | [10]: https://github.com/JChehe/blog/issues/34
106 | [11]: https://github.com/JChehe/blog/issues/17
107 | [12]: https://github.com/JChehe/blog/issues/16
108 | [13]: https://github.com/JChehe/blog/issues/48
109 | [14]: https://github.com/JChehe/blog/issues/51
110 | [15]: https://github.com/JChehe/blog/issues/50
111 | [16]: https://github.com/JChehe/blog/issues/10
112 | [17]: https://jchehe.gitbook.io/mysql_data_types_cn/
113 | [18]: https://github.com/JChehe/blog/issues/40
114 | [19]: https://github.com/JChehe/blog/issues/8
115 | [20]: https://github.com/JChehe/blog/issues/33
116 | [21]: https://github.com/JChehe/blog/issues/29
117 | [22]: https://github.com/JChehe/blog/issues/18
118 | [23]: https://github.com/JChehe/blog/issues/14
119 | [24]: https://github.com/JChehe/blog/issues/2
120 | [25]: https://github.com/JChehe/blog/issues/13
121 | [26]: https://github.com/JChehe/blog/issues/12
122 | [27]: https://github.com/JChehe/blog/issues/9
123 | [28]: https://github.com/JChehe/blog/issues/3
124 | [29]: https://github.com/JChehe/blog/issues/27
125 | [30]: https://github.com/JChehe/blog/issues/11
126 | [31]: https://github.com/JChehe/blog/issues/45
127 | [32]: https://github.com/JChehe/blog/issues/44
128 | [33]: https://github.com/JChehe/blog/issues/15
129 | [34]: https://github.com/JChehe/blog/issues/28
130 | [35]: https://github.com/JChehe/blog/issues/35
131 | [36]: https://github.com/JChehe/blog/issues/49
132 | [37]: https://github.com/JChehe/blog/issues/42
133 | [38]: https://github.com/JChehe/blog/issues/32
134 | [39]: http://www.cnblogs.com/Jccc/
135 | [40]: https://segmentfault.com/u/jc
136 | [41]: https://github.com/JChehe/blog/blob/master/posts/Flex%20%E5%AD%A6%E4%B9%A0.md
137 | [42]: https://github.com/JChehe/blog/blob/master/posts/%E3%80%8ACSS%20%E6%8F%AD%E7%A7%98%E3%80%8B%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0.md
138 | [43]: https://github.com/JChehe/blog/blob/master/posts/%E3%80%8AJavaScript%E6%A8%A1%E5%BC%8F%E3%80%8B%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0.md
139 | [44]: https://github.com/JChehe/blog/blob/master/posts/white-space:nowrap%E7%9A%84%E5%A6%99%E7%94%A8.md
140 | [45]: https://github.com/JChehe/blog/blob/master/posts/%E3%80%8A%E5%9B%BE%E8%A7%A3HTTP%E3%80%8B%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0.md
141 | [46]: https://github.com/JChehe/blog/blob/master/posts/jQuery%20%E7%9A%84%20attr%20%E4%B8%8E%20prop%20%E7%9A%84%E5%8C%BA%E5%88%AB.md
142 | [47]: https://github.com/JChehe/blog/blob/master/posts/%E5%85%B3%E4%BA%8E%20Glob%20%28gulp%29%20%E7%9A%84%E5%AD%A6%E4%B9%A0.md
143 | [48]: https://github.com/JChehe/blog/blob/master/posts/%E3%80%8AJavaScript%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%B2%BE%E8%A6%81%E3%80%8B%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0.md
144 | [49]: https://github.com/JChehe/blog/blob/master/posts/%E5%85%B3%E4%BA%8EJavaScript%E5%8D%95%E7%BA%BF%E7%A8%8B%E7%9A%84%E4%B8%80%E4%BA%9B%E4%BA%8B.md
145 | [50]: https://github.com/JChehe/blog/blob/master/posts/%E5%86%8D%E6%AC%A1%E9%98%85%E8%AF%BB%E3%80%8A%E7%B2%BE%E9%80%9ACSS-%E9%AB%98%E7%BA%A7Web%E6%A0%87%E5%87%86%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88%EF%BC%88%E7%AC%AC%E4%BA%8C%E7%89%88%EF%BC%89%E3%80%8B.md
146 | [51]: https://github.com/JChehe/blog/blob/master/posts/%E5%AE%9E%E7%8E%B0%E7%B1%BB%E4%BC%BC%20QQ%E9%9F%B3%E4%B9%90%E7%BD%91%E9%A1%B5%E7%89%88%20%E7%9A%84%E5%8D%95%E9%A1%B5%E9%9D%A2%E6%80%BB%E7%BB%93.md
147 | [52]: http://www.jobbole.com/members/q574805242/
148 | [53]: https://github.com/JChehe/blog/blob/master/translation/JavaScript%20%E6%A8%A1%E5%9D%97%E3%80%90Part%201%E3%80%91%EF%BC%9A%E5%88%9D%E5%AD%A6%E8%80%85%E6%8C%87%E5%8D%97.md
149 | [54]: https://github.com/JChehe/blog/blob/master/translation/JavaScript%20%E6%A8%A1%E5%9D%97%E3%80%90Part%202%E3%80%91%EF%BC%9A%E6%A8%A1%E5%9D%97%E6%89%93%E5%8C%85.md
150 | [55]: https://github.com/JChehe/blog/blob/master/translation/%E7%94%A8Mocha%E5%92%8CChai%E5%AF%B9JavaScript%E8%BF%9B%E8%A1%8C%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95.md
151 | [56]: https://github.com/JChehe/blog/blob/master/translation/7%20%E4%B8%AA%E5%9F%BA%E6%9C%AC%E7%9A%84%20JS%20%E5%87%BD%E6%95%B0%5B%E8%AF%91%5D.md
152 | [57]: https://github.com/JChehe/blog/blob/master/translation/Web%E5%BA%94%E7%94%A8%E4%B8%8A%E7%BA%BF%E4%B9%8B%E5%89%8D%EF%BC%8C%E6%AF%8F%E4%B8%AA%E7%A8%8B%E5%BA%8F%E5%91%98%E5%BA%94%E8%AF%A5%E4%BA%86%E8%A7%A3%E7%9A%84%E6%8A%80%E6%9C%AF%E7%BB%86%E8%8A%82.md
153 | [58]: https://github.com/JChehe/blog/blob/master/translation/%E5%85%B6%E5%AE%9E%E9%97%AD%E5%8C%85%E5%B9%B6%E4%B8%8D%E9%AB%98%E6%B7%B1%E8%8E%AB%E6%B5%8B.md
154 | [59]: https://github.com/JChehe/blog/blob/master/translation/%E5%A6%82%E4%BD%95%E6%88%90%E4%B8%BA%E4%B8%80%E4%B8%AAJavaScript%20%E5%A4%A7%E7%89%9B%EF%BC%9F%E3%80%90%E8%AF%91%E3%80%91.md
155 | [60]: https://github.com/JChehe/blog/blob/master/translation/%E8%84%B1%E7%A6%BBjQuery%EF%BC%8C%E4%BD%BF%E7%94%A8%E5%8E%9F%E7%94%9FAjax.md
156 |
--------------------------------------------------------------------------------
/translation/7 个基本的 JS 函数[译].md:
--------------------------------------------------------------------------------
1 | # 7 个基本的 JS 函数
2 |
3 | 标签: JavaScript translation
4 |
5 | ---
6 |
7 | 我记得早期的 JavaScript ,要完成任何事情几乎都绕不开一些简单的函数,因为浏览器提供商实现功能有所差异,而且不只是边缘功能,基础功能也一样,如 `addEventListener` 和 `attachEvent`。虽然时代变了,但仍有一些函数是每个开发者都应该掌握的,以便于完成某些功能和提高性能。
8 |
9 | ### [debounce](http://davidwalsh.name/javascript-debounce-function)
10 |
11 | 对于高耗能事件,debounce 函数是一种不错解决方案。如果你不对 `scroll`、`resize`、和 `key*` 事件使用 debounce 函数,那么你几乎等同于犯了错误。下面的 `debounce` 函数能让你的代码保持高效:
12 |
13 | // 返回一个函数,如果它被不间断地调用,它将不会得到执行。该函数在停止调用 N 毫秒后,再次调用它才会得到执行。如果有传递 ‘immediate’ 参数,会马上将函数安排到执行队列中,而不会延迟。
14 | function debounce(func, wait, immediate) {
15 | var timeout;
16 | return function() {
17 | var context = this, args = arguments;
18 | var later = function() {
19 | timeout = null;
20 | if (!immediate) func.apply(context, args);
21 | };
22 | var callNow = immediate && !timeout;
23 | clearTimeout(timeout);
24 | timeout = setTimeout(later, wait);
25 | if (callNow) func.apply(context, args);
26 | };
27 | };
28 |
29 | // 用法
30 | var myEfficientFn = debounce(function() {
31 | // 所有繁重的操作
32 | }, 250);
33 | window.addEventListener('resize', myEfficientFn);
34 | `debounce` 函数不允许回调函数在指定时间内执行多于一次。当为一个会频繁触发的事件分配一个回调函数时,该函数显得尤为重要。
35 |
36 | ### [poll](http://davidwalsh.name/javascript-polling)
37 | 尽管上面我提及了 `debounce` 函数,但如果事件不存在时,你就不能插入一个事件以判断所需的状态,那么就需要每隔一段时间去检查状态是否达到你的要求。
38 |
39 | function poll(fn, callback, errback, timeout, interval) {
40 | var endTime = Number(new Date()) + (timeout || 2000);
41 | interval = interval || 100;
42 |
43 | (function p() {
44 | // 如果条件满足,则执行!
45 | if (fn()) {
46 | callback();
47 | }
48 | // 如果条件不满足,但并未超时,再来一次
49 | else if (Number(new Date()) < endTime) {
50 | setTimeout(p, interval);
51 | }
52 | // 不匹配且时间消耗过长,则拒绝!
53 | else {
54 | errback(new Error('timed out for ' + fn + ': ' + arguments));
55 | }
56 | })();
57 | }
58 |
59 | // 用法:确保元素可见
60 | poll(
61 | function() {
62 | return document.getElementById('lightbox').offsetWidth > 0;
63 | },
64 | function() {
65 | // 执行,成功的回调函数
66 | },
67 | function() {
68 | // 错误,失败的回调函数
69 | }
70 | );
71 | Polling 在 web 中已被应用很长时间了,并在将来仍会被使用。
72 |
73 | ### [once](http://davidwalsh.name/javascript-once)
74 | 有时候,你想让一个给定的功能只发生一次,类似于 `onload` 事件。下面的代码提供了你所说的功能:
75 |
76 | function once(fn, context) {
77 | var result;
78 |
79 | return function() {
80 | if (fn) {
81 | result = fn.apply(context || this, arguments);
82 | fn = null;
83 | }
84 |
85 | return result;
86 | };
87 | }
88 |
89 | // 用法
90 | var canOnlyFireOnce = once(function() {
91 | console.log('Fired!');
92 | });
93 |
94 | canOnlyFireOnce(); // "Fired!"
95 | canOnlyFireOnce(); // // 没有执行指定函数
96 | `once` 函数确保给定函数只能被调用一次,从而防止重复初始化!
97 |
98 | ### [getAbsoluteUrl](http://davidwalsh.name/get-absolute-url)
99 | 从一个字符串变量得到一个绝对 URL,并不是你想象中这么简单。对于某些 `URL` 构造器,如果你不提供必要的参数就会出问题(而有时候你真的不知道提供什么参数)。下面有一个优雅的技巧,只需要你传递一个字符串就能得到相应的绝对 URL。
100 |
101 | var getAbsoluteUrl = (function() {
102 | var a;
103 | return function(url) {
104 | if (!a) a = document.createElement('a');
105 | a.href = url;
106 |
107 | return a.href;
108 | };
109 | })();
110 |
111 | // 用法
112 | getAbsoluteUrl('/something'); // http://davidwalsh.name/something
113 |
114 | a 元素的 `href` 处理和 url 处理看似无意义,而 return 语句返回了一个可靠的绝对 URL。
115 |
116 | ### [isNative](http://davidwalsh.name/detect-native-function)
117 | 如果你想知道一个指定函数是否是原生的,或者能不能通过声明来覆盖它。下面这段便于使用的代码能给你答案:
118 |
119 | ;(function() {
120 |
121 | // Used to resolve the internal `[[Class]]` of values
122 | var toString = Object.prototype.toString;
123 |
124 | // Used to resolve the decompiled source of functions
125 | var fnToString = Function.prototype.toString;
126 |
127 | // Used to detect host constructors (Safari > 4; really typed array specific)
128 | var reHostCtor = /^\[object .+?Constructor\]$/;
129 |
130 | // Compile a regexp using a common native method as a template.
131 | // We chose `Object#toString` because there's a good chance it is not being mucked with.
132 | var reNative = RegExp('^' +
133 | // Coerce `Object#toString` to a string
134 | String(toString)
135 | // Escape any special regexp characters
136 | .replace(/[.*+?^${}()|[\]\/\\]/g, '\\$&')
137 | // Replace mentions of `toString` with `.*?` to keep the template generic.
138 | // Replace thing like `for ...` to support environments like Rhino which add extra info
139 | // such as method arity.
140 | .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
141 | );
142 |
143 | function isNative(value) {
144 | var type = typeof value;
145 | return type == 'function'
146 | // Use `Function#toString` to bypass the value's own `toString` method
147 | // and avoid being faked out.
148 | ? reNative.test(fnToString.call(value))
149 | // Fallback to a host object check because some environments will represent
150 | // things like typed arrays as DOM methods which may not conform to the
151 | // normal native pattern.
152 | : (value && type == 'object' && reHostCtor.test(toString.call(value))) || false;
153 | }
154 |
155 | // export however you want
156 | module.exports = isNative;
157 | }());
158 | 这个函数虽不完美,但它能完成任务!
159 |
160 | ### [insertRule](http://davidwalsh.name/add-rules-stylesheets)
161 | 我们都知道能通过选择器(通过 `document.querySelectorAll` )获取一个 NodeList ,并可为每个元素设置样式,但有什么更高效的方法为选择器设置样式呢(例如你可以在样式表里完成):
162 |
163 | var sheet = (function() {
164 | // 创建