Java充电社
专辑
博文
联系我
本人继续续收门徒,亲手指导
正则表达式专题(JS版)
-> 正则表达式编程
1、JS正则表达式完整教程
2、正则表达式字符匹配攻略
3、正则表达式位置匹配攻略
4、正则表达式括号的作用
5、正则表达式回溯法原理
6、正则表达式的拆分
7、正则表达式的构建
8、正则表达式编程
9、下载PDF版
上一篇:正则表达式的构建
下一篇:下载PDF版
<div style="display:none"></div> 什么叫知识,能指导我们实践的东西才叫知识。 学习一样东西,如果不能使用,最多只能算作纸上谈兵。正则表达式的学习,也不例外。 掌握了正则表达式的语法后,下一步,也是关键的一步,就是在真实世界中使用它。 那么如何使用正则表达式呢?有哪些关键的点呢?本章就解决这个问题。 ## 内容包括 1. 正则表达式的四种操作 2. 相关API注意要点 3. 真实案例 ## 1. 正则表达式的四种操作 正则表达式是匹配模式,不管如何使用正则表达式,万变不离其宗,都需要先“匹配”。 有了匹配这一基本操作后,才有其他的操作:验证、切分、提取、替换。 进行任何相关操作,也需要宿主引擎相关API的配合使用。当然,在JS中,相关API也不多。 ### 1.1 验证 验证是正则表达式最直接的应用,比如表单验证。 在说验证之前,先要说清楚匹配是什么概念。 所谓匹配,就是看目标字符串里是否有满足匹配的子串。因此,“匹配”的本质就是“查找”。 有没有匹配,是不是匹配上,判断是否的操作,即称为“验证”。 这里举一个例子,来看看如何使用相关API进行验证操作的。 比如,判断一个字符串中是否有数字。 - 使用`search` ```javascript var regex = /\d/; var string = "abc123"; console.log( !!~string.search(regex) ); // => true ``` - 使用`test` ```javascript var regex = /\d/; var string = "abc123"; console.log( regex.test(string) ); // => true ``` - 使用`match` ```javascript var regex = /\d/; var string = "abc123"; console.log( !!string.match(regex) ); // => true ``` - 使用`exec` ```javascript var regex = /\d/; var string = "abc123"; console.log( !!regex.exec(string) ); // => true ``` 其中,最常用的是`test`。 ### 1.2 切分 匹配上了,我们就可以进行一些操作,比如切分。 所谓“切分”,就是把目标字符串,切成一段一段的。在JS中使用的是`split`。 比如,目标字符串是"html,css,javascript",按逗号来切分: ```javascript var regex = /,/; var string = "html,css,javascript"; console.log( string.split(regex) ); // => ["html", "css", "javascript"] ``` 又比如,如下的日期格式: > 2017/06/26 > > 2017.06.26 > > 2017-06-26 可以使用`split`“切出”年月日: ```javascript var regex = /\D/; console.log( "2017/06/26".split(regex) ); console.log( "2017.06.26".split(regex) ); console.log( "2017-06-26".split(regex) ); // => ["2017", "06", "26"] // => ["2017", "06", "26"] // => ["2017", "06", "26"] ``` ### 1.3 提取 虽然整体匹配上了,但有时需要提取部分匹配的数据。 此时正则通常要使用分组引用(分组捕获)功能,还需要配合使用相关API。 这里,还是以日期为例,提取出年月日。注意下面正则中的括号: - `match` ```javascript var regex = /^(\d{4})\D(\d{2})\D(\d{2})$/; var string = "2017-06-26"; console.log( string.match(regex) ); // =>["2017-06-26", "2017", "06", "26", index: 0, input: "2017-06-26"] ``` - `exec` ```javascript var regex = /^(\d{4})\D(\d{2})\D(\d{2})$/; var string = "2017-06-26"; console.log( regex.exec(string) ); // =>["2017-06-26", "2017", "06", "26", index: 0, input: "2017-06-26"] ``` - `test` ```javascript var regex = /^(\d{4})\D(\d{2})\D(\d{2})$/; var string = "2017-06-26"; regex.test(string); console.log( RegExp.$1, RegExp.$2, RegExp.$3 ); // => "2017" "06" "26" ``` - `search` ```javascript var regex = /^(\d{4})\D(\d{2})\D(\d{2})$/; var string = "2017-06-26"; string.search(regex); console.log( RegExp.$1, RegExp.$2, RegExp.$3 ); // => "2017" "06" "26" ``` - `replace` ```javascript var regex = /^(\d{4})\D(\d{2})\D(\d{2})$/; var string = "2017-06-26"; var date = []; string.replace(regex, function(match, year, month, day) { date.push(year, month, day); }); console.log(date); // => ["2017", "06", "26"] ``` 其中,最常用的是`match`。 ### 1.4 替换 找,往往不是目的,通常下一步是为了替换。在JS中,使用`replace`进行替换。 比如把日期格式,从yyyy-mm-dd替换成yyyy/mm/dd: ```javascript var string = "2017-06-26"; var today = new Date( string.replace(/-/g, "/") ); console.log( today ); // => Mon Jun 26 2017 00:00:00 GMT+0800 (中国标准时间) ``` 这里只是简单地应用了一下`replace`。但,`replace`方法是强大的,是需要重点掌握的。 ## 2. 相关API注意要点 从上面可以看出用于正则操作的方法,共有6个,字符串实例4个,正则实例2个: > String#search > > String#split > > String#match > > String#replace > > RegExp#test > > RegExp#exec 本文不打算详细地讲解它们的方方面面细节,具体可以参考《JavaScript权威指南》的第三部分。本文重点列出一些容易忽视的地方,以飨读者。 ### 2.1 search和match的参数问题 我们知道字符串实例的那4个方法参数都支持正则和字符串。 但`search`和`match`,会把字符串转换为正则的。 ```javascript var string = "2017.06.27"; console.log( string.search(".") ); // => 0 //需要修改成下列形式之一 console.log( string.search("\\.") ); console.log( string.search(/\./) ); // => 4 // => 4 console.log( string.match(".") ); // => ["2", index: 0, input: "2017.06.27"] //需要修改成下列形式之一 console.log( string.match("\\.") ); console.log( string.match(/\./) ); // => [".", index: 4, input: "2017.06.27"] // => [".", index: 4, input: "2017.06.27"] console.log( string.split(".") ); // => ["2017", "06", "27"] console.log( string.replace(".", "/") ); // => "2017/06.27" ``` ### 2.2 match返回结果的格式问题 `match`返回结果的格式,与正则对象是否有修饰符`g`有关。 ```javascript var string = "2017.06.27"; var regex1 = /\b(\d+)\b/; var regex2 = /\b(\d+)\b/g; console.log( string.match(regex1) ); console.log( string.match(regex2) ); // => ["2017", "2017", index: 0, input: "2017.06.27"] // => ["2017", "06", "27"] ``` 没有`g`,返回的是标准匹配格式,即,数组的第一个元素是整体匹配的内容,接下来是分组捕获的内容,然后是整体匹配的第一个下标,最后是输入的目标字符串。 有`g`,返回的是所有匹配的内容。 当没有匹配时,不管有无`g`,都返回`null`。 ### 2.3 exec比match更强大 当正则没有`g`时,使用`match`返回的信息比较多。但是有`g`后,就没有关键的信息`index`了。 而`exec`方法就能解决这个问题,它能接着上一次匹配后继续匹配: ```javascript var string = "2017.06.27"; var regex2 = /\b(\d+)\b/g; console.log( regex2.exec(string) ); console.log( regex2.lastIndex); console.log( regex2.exec(string) ); console.log( regex2.lastIndex); console.log( regex2.exec(string) ); console.log( regex2.lastIndex); console.log( regex2.exec(string) ); console.log( regex2.lastIndex); // => ["2017", "2017", index: 0, input: "2017.06.27"] // => 4 // => ["06", "06", index: 5, input: "2017.06.27"] // => 7 // => ["27", "27", index: 8, input: "2017.06.27"] // => 10 // => null // => 0 ``` 其中正则实例`lastIndex`属性,表示下一次匹配开始的位置。 比如第一次匹配了“2017”,开始下标是0,共4个字符,因此这次匹配结束的位置是3,下一次开始匹配的位置是4。 从上述代码看出,在使用`exec`时,经常需要配合使用`while`循环: ```javascript var string = "2017.06.27"; var regex2 = /\b(\d+)\b/g; var result; while ( result = regex2.exec(string) ) { console.log( result, regex2.lastIndex ); } // => ["2017", "2017", index: 0, input: "2017.06.27"] 4 // => ["06", "06", index: 5, input: "2017.06.27"] 7 // => ["27", "27", index: 8, input: "2017.06.27"] 10 ``` ### 2.4 修饰符g,对exex和test的影响 上面提到了正则实例的`lastIndex`属性,表示尝试匹配时,从字符串的`lastIndex`位开始去匹配。 字符串的四个方法,每次匹配时,都是从0开始的,即`lastIndex`属性始终不变。 而正则实例的两个方法`exec`、`test`,当正则是全局匹配时,每一次匹配完成后,都会修改`lastIndex`。下面让我们以`test`为例,看看你是否会迷糊: ```javascript var regex = /a/g; console.log( regex.test("a"), regex.lastIndex ); console.log( regex.test("aba"), regex.lastIndex ); console.log( regex.test("ababc"), regex.lastIndex ); // => true 1 // => true 3 // => false 0 ``` 注意上面代码中的第三次调用`test`,因为这一次尝试匹配,开始从下标`lastIndex`即3位置处开始查找,自然就找不到了。 如果没有`g`,自然都是从字符串第0个字符处开始尝试匹配: ```javascript var regex = /a/; console.log( regex.test("a"), regex.lastIndex ); console.log( regex.test("aba"), regex.lastIndex ); console.log( regex.test("ababc"), regex.lastIndex ); // => true 0 // => true 0 // => true 0 ``` ### 2.5 test整体匹配时需要使用^和$ 这个相对容易理解,因为`test`是看目标字符串中是否有子串匹配正则,即有部分匹配即可。 如果,要整体匹配,正则前后需要添加开头和结尾: ```javascript console.log( /123/.test("a123b") ); // => true console.log( /^123$/.test("a123b") ); // => false console.log( /^123$/.test("123") ); // => true ``` ### 2.6 split相关注意事项 `split`方法看起来不起眼,但要注意的地方有两个的。 第一,它可以有第二个参数,表示结果数组的最大长度: ```javascript var string = "html,css,javascript"; console.log( string.split(/,/, 2) ); // =>["html", "css"] ``` 第二,正则使用分组时,结果数组中是包含分隔符的: ```javascript var string = "html,css,javascript"; console.log( string.split(/(,)/) ); // =>["html", ",", "css", ",", "javascript"] ``` ### 2.7 replace是很强大的 《JavaScript权威指南》认为`exec`是这6个API中最强大的,而我始终认为`replace`才是最强大的。因为它也能拿到该拿到的信息,然后可以假借替换之名,做些其他事情。 总体来说`replace`有两种使用形式,这是因为它的第二个参数,可以是字符串,也可以是函数。 当第二个参数是字符串时,如下的字符有特殊的含义: > `$1`,`$2`,...,`$99 `匹配第1~99个分组里捕获的文本 > `$&` 匹配到的子串文本 > `$`` 匹配到的子串的左边文本 > `$'` 匹配到的子串的右边文本 > `$$` 美元符号 例如,把"2,3,5",变成"5=2+3": ```javascript var result = "2,3,5".replace(/(\d+),(\d+),(\d+)/, "$3=$1+$2"); console.log(result); // => "5=2+3" ``` 又例如,把"2,3,5",变成"222,333,555": ```javascript var result = "2,3,5".replace(/(\d+)/g, "$&$&$&"); console.log(result); // => "222,333,555" ``` 再例如,把"2+3=5",变成"2+3=2+3=5=5": ```javascript var result = "2+3=5".replace(/=/, "$&$`$&$'$&"); console.log(result); // => "2+3=2+3=5=5" ``` 当第二个参数是函数时,我们需要注意该回调函数的参数具体是什么: ```javascript "1234 2345 3456".replace(/(\d)\d{2}(\d)/g, function(match, $1, $2, index, input) { console.log([match, $1, $2, index, input]); }); // => ["1234", "1", "4", 0, "1234 2345 3456"] // => ["2345", "2", "5", 5, "1234 2345 3456"] // => ["3456", "3", "6", 10, "1234 2345 3456"] ``` 此时我们可以看到`replace`拿到的信息,并不比`exec`少。 ### 2.8 使用构造函数需要注意的问题 一般不推荐使用构造函数生成正则,而应该优先使用字面量。因为用构造函数会多写很多`\`。 ```javascript var string = "2017-06-27 2017.06.27 2017/06/27"; var regex = /\d{4}(-|\.|\/)\d{2}\1\d{2}/g; console.log( string.match(regex) ); // => ["2017-06-27", "2017.06.27", "2017/06/27"] regex = new RegExp("\\d{4}(-|\\.|\\/)\\d{2}\\1\\d{2}", "g"); console.log( string.match(regex) ); // => ["2017-06-27", "2017.06.27", "2017/06/27"] ``` ### 2.9 修饰符 ES5中修饰符,共3个: > `g` 全局匹配,即找到所有匹配的,单词是global > > `i` 忽略字母大小写,单词ingoreCase > > `m` 多行匹配,只影响`^`和`$`,二者变成行的概念,即行开头和行结尾。单词是multiline 当然正则对象也有相应的只读属性: ```javascript var regex = /\w/img; console.log( regex.global ); console.log( regex.ignoreCase ); console.log( regex.multiline ); // => true // => true // => true ``` ### 2.10 source属性 正则实例对象属性,除了`global`、`ingnoreCase`、`multiline`、`lastIndex`属性之外,还有一个`source`属性。 它什么时候有用呢? 比如,在构建动态的正则表达式时,可以通过查看该属性,来确认构建出的正则到底是什么: ```javascript var className = "high"; var regex = new RegExp("(^|\\s)" + className + "(\\s|$)"); console.log( regex.source ) // => (^|\s)high(\s|$) 即字符串"(^|\\s)high(\\s|$)" ``` ### 2.11 构造函数属性 构造函数的静态属性基于所执行的最近一次正则操作而变化。除了是`$1`,...,`$9`之外,还有几个不太常用的属性(有兼容性问题): > `RegExp.input` 最近一次目标字符串,简写成`RegExp["$_"]` > `RegExp.lastMatch` 最近一次匹配的文本,简写成`RegExp["$&"]` > `RegExp.lastParen` 最近一次捕获的文本,简写成`RegExp["$+"]` > `RegExp.leftContext` 目标字符串中`lastMatch`之前的文本,简写成RegExp["$\`"] > `RegExp.rightContext `目标字符串中`lastMatch`之后的文本,简写成`RegExp["$'"]` 测试代码如下: ```javascript var regex = /([abc])(\d)/g; var string = "a1b2c3d4e5"; string.match(regex); console.log( RegExp.input ); console.log( RegExp["$_"]); // => "a1b2c3d4e5" console.log( RegExp.lastMatch ); console.log( RegExp["$&"] ); // => "c3" console.log( RegExp.lastParen ); console.log( RegExp["$+"] ); // => "3" console.log( RegExp.leftContext ); console.log( RegExp["$`"] ); // => "a1b2" console.log( RegExp.rightContext ); console.log( RegExp["$'"] ); // => "d4e5" ``` ## 3. 真实案例 ### 3.1 使用构造函数生成正则表达式 我们知道要优先使用字面量来创建正则,但有时正则表达式的主体是不确定的,此时可以使用构造函数来创建。模拟`getElementsByClassName`方法,就是很能说明该问题的一个例子。 这里`getElementsByClassName`函数的实现思路是: - 比如要获取className为"high"的dom元素; - 首先生成一个正则:`/(^|\s)high(\s|$)/`; - 然后再用其逐一验证页面上的所有dom元素的类名,拿到满足匹配的元素即可。 代码如下(可以直接复制到本地查看运行效果): ```javascript <p class="high">1111</p> <p class="high">2222</p> <p>3333</p> <script> function getElementsByClassName(className) { var elements = document.getElementsByTagName("*"); var regex = new RegExp("(^|\\s)" + className + "(\\s|$)"); var result = []; for (var i = 0; i < elements.length; i++) { var element = elements[i]; if (regex.test(element.className)) { result.push(element) } } return result; } var highs = getElementsByClassName('high'); highs.forEach(function(item) { item.style.color = 'red'; }); </script> ``` ### 3.2 使用字符串保存数据 一般情况下,我们都愿意使用数组来保存数据。但我看到有的框架中,使用的却是字符串。 使用时,仍需要把字符串切分成数组。虽然不一定用到正则,但总感觉酷酷的,这里分享如下: ```javascript var utils = {}; "Boolean|Number|String|Function|Array|Date|RegExp|Object|Error".split("|").forEach(function(item) { utils["is" + item] = function(obj) { return {}.toString.call(obj) == "[object " + item + "]"; }; }); console.log( utils.isArray([1, 2, 3]) ); // => true ``` ### 3.3 if语句中使用正则替代&& 比如,模拟`ready`函数,即加载完毕后再执行回调(不兼容ie的): ```javascript var readyRE = /complete|loaded|interactive/; function ready(callback) { if (readyRE.test(document.readyState) && document.body) { callback() } else { document.addEventListener( 'DOMContentLoaded', function () { callback() }, false ); } }; ready(function() { alert("加载完毕!") }); ``` ### 3.4 使用强大的replace 因为`replace`方法比较强大,有时用它根本不是为了替换,只是拿其匹配到的信息来做文章。 这里以查询字符串(querystring)压缩技术为例,注意下面`replace`方法中,回调函数根本没有返回任何东西。 ```javascript function compress(source) { var keys = {}; source.replace(/([^=&]+)=([^&]*)/g, function(full, key, value) { keys[key] = (keys[key] ? keys[key] + ',' : '') + value; }); var result = []; for (var key in keys) { result.push(key + '=' + keys[key]); } return result.join('&'); } console.log( compress("a=1&b=2&a=3&b=4") ); // => "a=1,3&b=2,4" ``` ### 3.5 综合运用 最后这里再做个简单实用的正则测试器。 具体效果如下: ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/177/21ecfad3-f629-4de9-b037-b307073db99f.jpg) 代码,直接贴了,相信你能看得懂: ```javascript <section> <div id="err"></div> <input id="regex" placeholder="请输入正则表达式"> <input id="text" placeholder="请输入测试文本"> <button id="run">测试一下</button> <div id="result"></div> </section> <style> section{ display:flex; flex-direction:column; justify-content:space-around; height:300px; padding:0 200px; } section *{ min-height:30px; } #err { color:red; } #result{ line-height:30px; } .info { background:#00c5ff; padding:2px; margin:2px; display:inline-block; } </style> <script> (function() { // 获取相应dom元素 var regexInput = document.getElementById("regex"); var textInput = document.getElementById("text"); var runBtn = document.getElementById("run"); var errBox = document.getElementById("err"); var resultBox = document.getElementById("result"); // 绑定点击事件 runBtn.onclick = function() { // 清除错误和结果 errBox.innerHTML = ""; resultBox.innerHTML = ""; // 获取正则和文本 var text = textInput.value; var regex = regexInput.value; if (regex == "") { errBox.innerHTML = "请输入正则表达式"; } else if (text == "") { errBox.innerHTML = "请输入测试文本"; } else { regex = createRegex(regex); if (!regex) return; var result, results = []; // 没有修饰符g的话,会死循环 if (regex.global) { while(result = regex.exec(text)) { results.push(result); } } else { results.push(regex.exec(text)); } if (results[0] == null) { resultBox.innerHTML = "匹配到0个结果"; return; } // 倒序是有必要的 for (var i = results.length - 1; i >= 0; i--) { var result = results[i]; var match = result[0]; var prefix = text.substr(0, result.index); var suffix = text.substr(result.index + match.length); text = prefix + '<span class="info">' + match + '</span>' + suffix; } resultBox.innerHTML = "匹配到" + results.length + "个结果:<br>" + text; } }; // 生成正则表达式,核心函数 function createRegex(regex) { try { if (regex[0] == "/") { regex = regex.split("/"); regex.shift(); var flags = regex.pop(); regex = regex.join("/"); regex = new RegExp(regex, flags); } else { regex = new RegExp(regex, "g"); } return regex; } catch(e) { errBox.innerHTML = "无效的正则表达式"; return false; } } })(); </script> ``` ## 第七章小结 相关API的注意点,本章基本上算是一网打尽了。 至于文中的例子,都是点睛之笔,没有详细解析。如有理解不透的,建议自己敲一敲。 ## 后记 其实本文首发于:[正则表达式系列总结 - 知乎专栏](https://link.juejin.im?target=https%3A%2F%2Fzhuanlan.zhihu.com%2Fp%2F27653434) 原文是一个系列。一直等到老姚成为掘金的专栏作者,经过仔细考虑,在掘金平台没有采用系列形式,而是合成为了一篇文章。这样既便于读者阅读,最起码能一气呵成地阅读。同时也便于作者统一回复留言。 文章要结束了,最后还要有几点说明。 ### 1. 需要注意的地方 本文主要讨论的是JavaScript的正则表达式,更精确地说是ES5的正则表达式。 JavaScript的正则表达式引擎是传统型NFA的,因此本系列的讨论是适合任何一门正则引擎是传统型NFA的编程语言。当然,市面上大部分语言的正则引擎都是这种的。而JS里正则涉及到的所有语法要点,是这种引擎支持的核心子集。也就是说,要学正则表达式,不妨以JS正则为出发点。 ### 2. 参考资料 当然本文不是无本之末。主要参考的是几本书籍。 以下书籍中核心章节都认真阅读过,甚至阅读多遍。 [《JavaScript权威指南》](https://link.juejin.im?target=http%3A%2F%2Flink.zhihu.com%2F%3Ftarget%3Dhttps%3A%2F%2Fbook.douban.com%2Fsubject%2F10549733%2F),看完本系列,再去看书中的第10章,你就知道了什么叫字字珠玑。 [《精通正则表达式》](https://link.juejin.im?target=http%3A%2F%2Flink.zhihu.com%2F%3Ftarget%3Dhttps%3A%2F%2Fbook.douban.com%2Fsubject%2F2154713%2F),权威且比较杂乱,我阅读的第一本正则表达式书籍。 [《正则表达式必知必会》](https://link.juejin.im?target=http%3A%2F%2Flink.zhihu.com%2F%3Ftarget%3Dhttps%3A%2F%2Fbook.douban.com%2Fsubject%2F26285406%2F),这是我看的第二本正则,看完后,确定自己算是入门了。 [《正则指引》](https://link.juejin.im?target=http%3A%2F%2Flink.zhihu.com%2F%3Ftarget%3Dhttps%3A%2F%2Fbook.douban.com%2Fsubject%2F10591096%2F),《精通正则表达式》的译者写的,相对清晰。 [《正则表达式入门》](https://link.juejin.im?target=http%3A%2F%2Flink.zhihu.com%2F%3Ftarget%3Dhttps%3A%2F%2Fbook.douban.com%2Fsubject%2F22182383%2F),我看的是英文版的,对于已经入门的我,基本没多少收获了。 [《正则表达式经典实例》](https://link.juejin.im?target=http%3A%2F%2Flink.zhihu.com%2F%3Ftarget%3Dhttps%3A%2F%2Fbook.douban.com%2Fsubject%2F25986599%2F),除了第3章,比较杂外,也有收获,以实例为主导的一本书。 [《JavaScript Regular Expressions》](https://link.juejin.im?target=http%3A%2F%2Flink.zhihu.com%2F%3Ftarget%3Dhttps%3A%2F%2Fbook.douban.com%2Fsubject%2F26630579%2F),为数不多转讲JS正则的。页数不多,也有收获。 [《高性能JavaScript 》](https://link.juejin.im?target=https%3A%2F%2Fbook.douban.com%2Fsubject%2F5362856%2F)第5章,我看的是英文版的。第5章,讲了回溯和优化。 [《JavaScript忍者秘籍》](https://link.juejin.im?target=https%3A%2F%2Fbook.douban.com%2Fsubject%2F26638316%2F)第7章,大概讲了一下正则的用法,几个例子还不错。 [《JavaScript高级程序设计》](https://link.juejin.im?target=https%3A%2F%2Fbook.douban.com%2Fsubject%2F10546125%2F)第5.4节,比较简短的介绍。 使用的工具: **Regulex,一款可视化工具ProcessOn - 免费在线作图,实时协作LICEcap – 灵活好用,GIF 屏幕录制工具** ### 3. 个人感悟 **要多写文章的** 首先,我十分感谢读者。读者能在信息泛滥的网络里,点击我的文章进来瞧两眼,这都是对其注意力的消费。更何况,还有很多童鞋都认真读了,甚至给我挑毛病,这都是对我的帮助。不知有多少童鞋是从头读到这里的,不妨留言打卡,让我知道你是用心的读者,而并非简简单单地收藏一下,然后就再也不曾看过了。 说到要写文章,其目的是以教为学。看似为了教,其实是为了学**。**能教会别人才算自己真正学会了,最起码形成了文字,通过了自己的语言逻辑这一关。如果还能有人指出你的错误认知,那样收获就更大了,何乐而不为呢? 很多书中都提到类似的观点,例如《知道做到》《好好学习》《与时间做朋友》《暗时间》等。 **以教为学的其他手段** 当然,以教为学的手段还有很多,比如**翻译一本书**。我私下已经翻译了好几本(窃喜^_^)。 可以从薄点的书籍开始,比如100页左右的。基本上使用有道就可以了,也不用要求自己一词一句的翻译,能用自己的话说明白就行了。说到这里,不得不提起,我们的阮一峰大神,在我看来,他就是成功地应用这种模式的。看完外文的文章,理解明白了,用自己的话说一说,再形成自己的简练风格。 恐怕你可能说自己的英文水平不够,没信心尝试。相信我,熟悉了常用词汇(比如literal翻译成字面量)后,配合有道翻译,薄点的书,一天翻译一章是没问题的。当然前提是你懂相关领域,不然是没办法意译的。 最后一种以教为学的手段是,**写一本书**。写文章是基础,文章多了,自然而言就可以写成一本书。当然,写书强调的是整体架构,所以文章最好成体系。 你看看那些国内专业书籍的作者,一般都事先翻译过几本书的。最起码在前端领域,我就看到了好几位是这么干的。翻译明白了,学会了,用自己的角度去弄出一本书还是相对很容易的。 虽然,本人并未曾写过书,但上述方法,我始终相信是可行的。 最后,我们该想到,陆游诗人对前端界做出的最大贡献是: 纸上得来终觉浅,绝知此事要躬行。 本文完。 ```html 作者:老姚 链接:https://juejin.im/post/5965943ff265da6c30653879 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 ``` <a style="display:none" target="_blank" href="https://mp.weixin.qq.com/s/_S1DD2JADnXvpexxaBwLLg" style="color:red; font-size:20px; font-weight:bold">继续收门徒,亲手带,月薪 4W 以下的可以来找我</a> ## 最新资料 1. <a href="https://mp.weixin.qq.com/s?__biz=MzkzOTI3Nzc0Mg==&mid=2247484964&idx=2&sn=c81bce2f26015ee0f9632ddc6c67df03&scene=21#wechat_redirect" target="_blank">尚硅谷 Java 学科全套教程(总 207.77GB)</a> 2. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484192&idx=1&sn=505f2faaa4cc911f553850667749bcbb&scene=21#wechat_redirect" target="_blank">2021 最新版 Java 微服务学习线路图 + 视频</a> 3. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484573&idx=1&sn=7f3d83892186c16c57bc0b99f03f1ffd&scene=21#wechat_redirect" target="_blank">阿里技术大佬整理的《Spring 学习笔记.pdf》</a> 4. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484544&idx=2&sn=c1dfe907cfaa5b9ae8e66fc247ccbe84&scene=21#wechat_redirect" target="_blank">阿里大佬的《MySQL 学习笔记高清.pdf》</a> 5. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247485167&idx=1&sn=48d75c8e93e748235a3547f34921dfb7&scene=21#wechat_redirect" target="_blank">2021 版 java 高并发常见面试题汇总.pdf</a> 6. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247485664&idx=1&sn=435f9f515a8f881642820d7790ad20ce&scene=21#wechat_redirect" target="_blank">Idea 快捷键大全.pdf</a> ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/1/2883e86e-3eff-404a-8943-0066e5e2b454.png)
#custom-toc-container