├── 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 | // 创建