├── README.md ├── analysis_jq ├── README.md ├── demo.html ├── jquerMey-1.0.1.js ├── jquery-3.3.1.js ├── sizzle.js └── sizzle.min.js ├── git_mindMap ├── git.md ├── git命令思维导图.xmind ├── git思维导图.xmind ├── images │ ├── git命令思维导图.png │ └── git终端vim常用操作.png └── readme.md ├── images ├── SQL.png ├── blog.png ├── home.png ├── ice.png ├── source(1).png ├── source(2).gif ├── source(3).png ├── source(4).png ├── source(5).gif ├── source(6).gif ├── source_2 (1).png ├── source_2 (2).png ├── source_2 (4).png └── source_2 (5).png └── packages ├── ESLint_rules ├── readme.md └── unclutter.md ├── antd-table └── README.md ├── background └── readme.md ├── basic_theory ├── images │ └── React.png └── readme.md ├── collect ├── 2019.02.28 │ └── readme.md ├── 2019.03.06 │ └── readme.md └── good_net │ └── readme.md ├── filter&&map&&reduce └── readme.md ├── h5 ├── h5_adaptation │ └── readme.md ├── h5_drap │ ├── index.js │ ├── mobile_drap.html │ ├── mobile_jq.html │ └── readme.md └── h5_problem │ └── readme.md ├── leetcode └── readme.md ├── live-miniprogram └── live-miniprogram.md ├── node └── node.md ├── promise-mini ├── dologin.md ├── map.md ├── pullload.md └── we-request.md ├── ts └── ts-detail.md ├── vue-tag ├── README.md └── tag.vue └── whistle-for-miniprogram └── 小程序使用whistle代理.md /README.md: -------------------------------------------------------------------------------- 1 | ### github blog地址(持续输出ing) 2 | 近期动态 3 | - [助你效率翻倍的vscode插件](https://github.com/mtonhuang/blog/issues/43) 4 | - [大文件上传demo](https://github.com/mtonhuang/blog/issues/42) 5 | - [微信社招算法面经](https://github.com/mtonhuang/blog/issues/36) 6 | - [浅尝websocket](https://github.com/mtonhuang/blog/issues/37) 7 | 8 |
小程序开发 9 |

10 | 11 | - [小程序“微前端”的一些想法](https://github.com/mtonhuang/blog/issues/25) 12 | - [小程序重大改动灰度方案](https://github.com/mtonhuang/blog/issues/32) 13 | - [小程序底层原理汇总:fire:](https://github.com/mtonhuang/blog/issues/30) 14 | - [小程序登录态管理dologin组件](https://github.com/mtonhuang/blog/issues/31) 15 | - [如何使小程序请求优雅化](https://github.com/mtonhuang/blog/issues/14) 16 | - [小程序使用whistle代理](https://github.com/mtonhuang/blog/issues/15) 17 | - [小程序滑动分页加载动效](https://github.com/mtonhuang/blog/issues/33) 18 | - [小程序封装地图授权函数](https://github.com/mtonhuang/blog/issues/34) 19 | - [小程序gulp相关配置](https://github.com/mtonhuang/blog/issues/35) 20 | - [多样化自定义小程序导航栏:fire:](https://github.com/mtonhuang/blog/issues/16) 21 | - [如何使用小程序直播插件](https://github.com/mtonhuang/blog/issues/22) 22 | 23 |

24 |
25 | 26 |
深入JS/剖析源码系列 27 |

28 | 29 | - [JS实现apply方法](https://github.com/mtonhuang/blog/issues/29) 30 | - [一步步分析JQ源码:fire:](https://github.com/mtonhuang/blog/issues/18) 31 | - [如何实现一个filter,map函数](https://github.com/mtonhuang/blog/issues/12) 32 | - [实现一个简易的axios](https://github.com/mtonhuang/blog/issues/26) 33 | - [用Promise封装XMLHttpRequest](https://github.com/mtonhuang/blog/issues/38) 34 | - [实现Promise.all()、race()、any()](https://github.com/mtonhuang/blog/issues/40) 35 | 36 |

37 |
38 | 39 |
前端开发效能工具 40 |

41 | 42 | - [助你效率翻倍的vscode插件](https://github.com/mtonhuang/blog/issues/43) 43 | - [loupe可视化工具](http://latentflip.com/loupe/?code=ZnVuY3Rpb24gYSgpIHsNCiAgICBiKCk7DQogICAgY29uc29sZS5sb2coJ2EnKTsNCn0NCmZ1bmN0aW9uIGIoKSB7DQogICAgY29uc29sZS5sb2coJ2InKQ0KfQ0KYSgpOw0K!!!PGJ1dHRvbj5DbGljayBtZSE8L2J1dHRvbj4%3D) 44 | - [SQL实用命令](https://github.com/mtonhuang/blog/blob/master/images/SQL.png) 45 | - [ESLint常用rules总结:fire:](https://github.com/mtonhuang/blog/issues/21) 46 | - [手撸webpack4.0配置](https://github.com/mtonhuang/Multiple-page-boilerplate) 47 | - [node版本切换——nvm](https://github.com/mtonhuang/blog/issues/23) 48 | - [json2ts——导入json自动识别生成d.ts类型声明](http://json2ts.com/) 49 | - [git思维导图:fire:](https://github.com/mtonhuang/bolg/tree/master/git_mindMap) 50 | - [git 协同开发,需要注意的几个小点](https://github.com/mtonhuang/blog/issues/13) 51 | 52 |

53 |
54 | 55 |
算法 56 |

57 | 58 | - [leetcode](https://github.com/mtonhuang/blog/issues/24) 59 | - [代码随想录](https://www.programmercarl.com/%E9%93%BE%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html#%E5%BE%AA%E7%8E%AF%E9%93%BE%E8%A1%A8) 60 |

61 | 62 |
63 | 64 |
TypeScript 65 |

66 | 67 | - [ts效能开发](https://github.com/mtonhuang/blog/issues/17) 68 | 69 |

70 |
71 | 72 |
h5c3 73 |

74 | 75 | - [h5开发坑点小总结:fire:](https://github.com/mtonhuang/blog/issues/19) 76 | - [h5适配](https://github.com/mtonhuang/blog/issues/20) 77 | 78 |

79 |
80 | 81 |
自己捣鼓的小玩意 82 |

83 | 84 | - [wechatApp-template](https://github.com/mtonhuang/wechatApp-template) 85 | - [refactor-boilerplate](https://github.com/mtonhuang/refactor-boilerplate) 86 | - [omim-tag](https://github.com/Tencent/omi/tree/master/packages/omim/src/tag) 87 | 88 |

89 |
90 | 91 |
其他 92 |

93 | 94 | - [杂乱复习](https://github.com/mtonhuang/blog/issues/39) 95 | - [修改vscode背景图](https://github.com/mtonhuang/blog/tree/master/vscode/background) 96 | - [前端开源项目收集 -> 2019.03.06刊](https://github.com/mtonhuang/bolg/tree/master/collect) 97 | - [Docker 部署 vue 项目](https://juejin.cn/post/6844903837774397447#comment) 98 | 99 |

100 |
101 | 102 | 103 | ### 写在后面 104 | 105 | 我是mtonhuang,~~23~~25year射手男,base深圳,程序员/斜杠青年/篮球爱好者/投资爱好者/小程序开发爱好者 106 | 107 | > _Written at 16:02 on Oct 31, 2019. 108 | 109 | -------------------------------------------------------------------------------- /analysis_jq/README.md: -------------------------------------------------------------------------------- 1 | [掘金](https://juejin.im/post/5c20cdcc6fb9a049d5198299)同步更新,欢迎给一个star!!! 2 | 3 | 首先,我们先去官网把JQ的js相关文件download到本地,随意浏览一下源码,尝试理解jq的实现原理。 4 | 5 | 接着我们创建一个属于自己的js文件(取名为jquerMey-1.0.1js)。 6 | 7 | **这里先说一下解析源码的几个步骤:** 8 | 9 | 1. 学会分析组成及架构 => 10 | (JQ通过选择器(字符串)来检索所有匹配的DOM,并且进行批量操作,同时能够帮我们解决浏览器的兼容问题。) 11 | 12 | 2. 学会看英文注释(不懂多用腾讯翻译君[手动滑稽]) 13 | 14 | 3. 先减后删 15 | 16 | 4. 阅读思考作者的语义 17 | 18 | 5. 尝试补全 19 | 好的,开搞吧! 20 | 21 | ### 一、创立一个html文件 22 | 23 | ```html 24 | 25 | 26 | 27 | 28 | jQuery源码解析 29 | 30 | 31 |
这是一个div
32 | 这是一个span 33 | 34 | 35 | 36 | 42 | 43 | 44 | ``` 45 | ![](https://user-gold-cdn.xitu.io/2018/12/24/167e02557ae6790d?w=558&h=118&f=png&s=13077) 46 | 可以看到,这边jQuery.fn.init 输出的是一个数组,还有一系列方法。我们一步步来。 47 | 48 | ### 二、删源码 49 | 50 | 这边先把JQ源码的所有东西都先删一下,可以看到,定义一个匿名函数,创建 **闭包**。 51 | 52 | ```js 53 | // 定义一个匿名函数,马上调用它,包起来调用的时候可以创建闭包 54 | (function(global,factory) { 55 | //内存中动态开辟了一块空间来执行这个里面的代码,对外是封闭的,可以访问外面的变量 56 | }(typeof window !== "undefined" ? window : this, function (window, noGlobal) { 57 | /*这里的三元判断,除了BOM浏览器的运行环境还能运行在什么环境中? =>node环境 (node运行在V8引擎中,主要用来做中间件) 58 | 中间件很多,架构与部署方面的中间件:webpack,grunt,gulp;功能方面的中间件:node.js(页面静态化) */ 59 | })); 60 | ``` 61 | 好,接着分析 62 | 63 | ```js 64 | // 定义一个匿名函数,马上调用它,包起来调用的时候可以创建闭包 65 | (function (global, factory) { 66 | //内存中动态开辟了一块空间来执行这个里面的代码,对外是封闭的,可以访问外面的变量 67 | /*那么除了BOM浏览器的运行环境还能运行在什么环境中? => 68 | node环境 (node运行在V8引擎中,主要用来做中间件) 中间件很多, 69 | 架构与部署方面的中间件:webpack,grunt,gulp;功能方面的中间件:node.js(页面静态化) */ 70 | if (typeof module === "object" && typeof module.exports === "object") { 71 | // For CommonJS and CommonJS-like environments where a proper `window` 72 | module.exports = global.document ? 73 | factory(global, true) : 74 | function (w) { 75 | if (!w.document) { 76 | throw new Error("jQuery requires a window with a document"); 77 | } 78 | return factory(w); 79 | }; 80 | } 81 | else { 82 | factory(global); 83 | } 84 | }(typeof window !== "undefined" ? window : this, function (window, noGlobal) { 85 | })); 86 | ``` 87 | 写到这里,那么这里注释说的CommonJS是什么呢?这就涉及到了上面说的node了。 88 | 89 | ### 三、何为CommonJS 90 | 91 | CommonJS是nodejs也就是服务器端广泛使用的模块化机制。 该规范的主要内容是,模块必须通过module.exports 导出对外的变量或接口,通过 require() 来导入其他模块的输出到当前模块作用域中。 92 | 93 | ![](https://user-gold-cdn.xitu.io/2018/12/24/167e02a678b1792f?w=763&h=493&f=png&s=80800) 94 | 95 | ### 四、JQuery的本质 96 | 97 | 可以看到,这里并没有给factory()传入第二个参数,默认为false,则会执行下面if的代码(即为BOM环境)。在if语句中,可以看到jQuery一定是核心代码,那么jQuery到底是什么呢?继续看。 98 | 99 | 100 | ![](https://user-gold-cdn.xitu.io/2018/12/24/167e02aa290fc9e7?w=746&h=410&f=png&s=54772) 101 | 102 | 这里的jQuery本质就是一个函数,jQuery有一个fn对象,并且fn有一个init函数。这里的makeArrray本质是返回一个数组。 103 | 104 | 105 | ![](https://user-gold-cdn.xitu.io/2018/12/24/167e02ac9abb5719?w=525&h=611&f=png&s=57864) 106 | 107 | 往下看,可以看到这里jQuery的fn对象其实就是jQuery的原型对象;接着我们找到init方法。 108 | 109 | 110 | ``` 111 | jQuery.fn = jQuery.prototype = { 112 | init : function (selector, context) { 113 | return jQuery.makeArray( selector, context ); 114 | } 115 | }; 116 | jQuery.makeArray = function(selector, context){ 117 | var $eles = new Sizzle(selector, context); 118 | return $eles; 119 | } 120 | ``` 121 | 分析完jQuery.fn,我们看看makeArray。Sizzle.js文件里面有很多算法方面的代码,我们先跳过,继续分析代码。此时,我们用Chrome打开html代码,可以看到,输出如图:(此时还没有写addClass函数所以报错了) 122 | 123 | 124 | ![](https://user-gold-cdn.xitu.io/2018/12/24/167e02dd96637903?w=562&h=117&f=png&s=12216) 125 | 126 | 127 | ```js 128 | jQuery.fn = jQuery.prototype = { 129 | init : function (selector, context) { 130 | return jQuery.makeArray( selector, context ); 131 | }, 132 | each: function (func) { 133 | 134 | }, 135 | addClass : function (className) { 136 | 137 | }, 138 | removeClass: function (className) { 139 | 140 | } 141 | }; 142 | jQuery.makeArray = function(selector, context){ 143 | var $eles = new Sizzle(selector, context); 144 | $eles.prevObject = arguments.callee; 145 | $eles.__proto__ = jQuery.fn 146 | return $eles; 147 | } 148 | ``` 149 | ### 五、补全添加方法 150 | 151 | 继续补全,这样jQuery的 整体架构 就ok了,之后就是往里面添加东西。 152 | 153 | (比如往里面添加addClass,removeClass,each方法) 154 | 155 | 156 | ```js 157 | jQuery.fn = jQuery.prototype = { 158 | init : function (selector, context) { 159 | return jQuery.makeArray( selector, context ); 160 | }, 161 | each: function (func) { 162 | for (var i=0;i 187 | 188 | 189 | 190 | jQuery源码解析 191 | 192 | 207 | 208 |
这是一个div
209 | 这是一个span 210 | 211 | 212 | 213 | 214 | 223 | 224 | 225 | ``` 226 | 结果如图: 227 | 228 | 229 | 230 | ![](https://user-gold-cdn.xitu.io/2018/12/25/167e2f749d2fea47?w=594&h=272&f=gif&s=4446) 231 | 232 | 附上全部代码: 233 | 234 | 235 | ```js 236 | /*! 237 | * jqueMey JavaScript Library v1.0.1 238 | * 239 | * Includes Sizzle.js 240 | * https://sizzlejs.com/ 241 | * 242 | * Copyright JS Foundation and other contributors 243 | * Released under the MIT license 244 | * Email: huangmiantong@126.com 245 | * 246 | * Date: 2018-12-11T22:04Z 247 | */ 248 | 249 | // 定义一个匿名函数,马上调用它,包起来调用的时候可以创建闭包 250 | (function (global, factory) { 251 | //在BOM浏览器的运行环境 252 | /*那么除了BOM浏览器的运行环境还能运行在什么环境中? => 253 | node环境 (node运行在V8引擎中,主要用来做中间件) 中间件很多, 254 | 架构与部署方面的中间件:webpack,grunt,gulp;功能方面的中间件:node.js(页面静态化) */ 255 | //内存中动态开辟了一块空间来执行这个里面的代码 256 | if (typeof module === "object" && typeof module.exports === "object") { 257 | module.exports = global.document ? 258 | factory(global, true) : 259 | function (w) { 260 | if (!w.document) { 261 | throw new Error("jQuery requires a window with a document"); 262 | } 263 | return factory(w); 264 | }; 265 | } else { 266 | factory(global); 267 | } 268 | }(typeof window !== "undefined" ? window : this, function (window, noGlobal) { 269 | var 270 | version = "1.0.1", 271 | 272 | // Define a local copy of jQuery 273 | jQuery = function( selector, context ) { 274 | 275 | // The jQuery object is actually just the init constructor 'enhanced' 276 | // Need init if jQuery is called (just allow error to be thrown if not included) 277 | return new jQuery.fn.init( selector, context ); 278 | }; 279 | jQuery.fn = jQuery.prototype = { 280 | init : function (selector, context) { 281 | return jQuery.makeArray( selector, context ); 282 | }, 283 | each: function (func) { 284 | for (var i=0;i 2 | 3 | 4 | 5 | jQuery源码解析 6 | 7 | 22 | 23 |
这是一个div
24 | 这是一个span 25 | 26 | 27 | 28 | 29 | 38 | 39 | -------------------------------------------------------------------------------- /analysis_jq/jquerMey-1.0.1.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jqueMey JavaScript Library v1.0.1 3 | * 4 | * Includes Sizzle.js 5 | * https://sizzlejs.com/ 6 | * 7 | * Copyright JS Foundation and other contributors 8 | * Released under the MIT license 9 | * Email: huangmiantong@126.com || v_mtonhuang@tencent.com 10 | * 11 | * Date: 2018-12-11T22:04Z 12 | */ 13 | 14 | // 定义一个匿名函数,马上调用它,包起来调用的时候可以创建闭包 15 | (function (global, factory) { 16 | //在BOM浏览器的运行环境 17 | /*那么除了BOM浏览器的运行环境还能运行在什么环境中? => 18 | node环境 (node运行在V8引擎中,主要用来做中间件) 中间件很多, 19 | 架构与部署方面的中间件:webpack,grunt,gulp;功能方面的中间件:node.js(页面静态化) */ 20 | //内存中动态开辟了一块空间来执行这个里面的代码 21 | if (typeof module === "object" && typeof module.exports === "object") { 22 | module.exports = global.document ? 23 | factory(global, true) : 24 | function (w) { 25 | if (!w.document) { 26 | throw new Error("jQuery requires a window with a document"); 27 | } 28 | return factory(w); 29 | }; 30 | } else { 31 | factory(global); 32 | } 33 | }(typeof window !== "undefined" ? window : this, function (window, noGlobal) { 34 | var 35 | version = "1.0.1", 36 | 37 | // Define a local copy of jQuery 38 | jQuery = function( selector, context ) { 39 | 40 | // The jQuery object is actually just the init constructor 'enhanced' 41 | // Need init if jQuery is called (just allow error to be thrown if not included) 42 | return new jQuery.fn.init( selector, context ); 43 | }; 44 | jQuery.fn = jQuery.prototype = { 45 | init : function (selector, context) { 46 | return jQuery.makeArray( selector, context ); 47 | }, 48 | each: function (func) { 49 | for (var i=0;i+~]|"+z+")"+z+"*"),V=new RegExp(z+"|>"),X=new RegExp(F),J=new RegExp("^"+H+"$"),K={ID:new RegExp("^#("+H+")"),CLASS:new RegExp("^\\.("+H+")"),TAG:new RegExp("^("+H+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+z+"*(even|odd|(([+-]|)(\\d*)n|)"+z+"*(?:([+-]|)"+z+"*(\\d+)|))"+z+"*\\)|)","i"),bool:new RegExp("^(?:"+P+")$","i"),needsContext:new RegExp("^"+z+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+z+"*((?:-\\d)?\\d*)"+z+"*\\)|)(?=[^-]|$)","i")},Q=/^(?:input|select|textarea|button)$/i,W=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,ee=new RegExp("\\\\([\\da-f]{1,6}"+z+"?|("+z+")|.)","ig"),te=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},ne=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,re=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},ie=function(){d()},oe=ye(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{R.apply(I=$.call(N.childNodes),N.childNodes),I[N.childNodes.length].nodeType}catch(e){R={apply:I.length?function(e,t){B.apply(e,$.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function ue(e,t,r,i){var o,l,c,s,f,h,y,w=t&&t.ownerDocument,x=t?t.nodeType:9;if(r=r||[],"string"!=typeof e||!e||1!==x&&9!==x&&11!==x)return r;if(!i&&((t?t.ownerDocument||t:N)!==p&&d(t),t=t||p,g)){if(11!==x&&(f=Z.exec(e)))if(o=f[1]){if(9===x){if(!(c=t.getElementById(o)))return r;if(c.id===o)return r.push(c),r}else if(w&&(c=w.getElementById(o))&&v(t,c)&&c.id===o)return r.push(c),r}else{if(f[2])return R.apply(r,t.getElementsByTagName(e)),r;if((o=f[3])&&n.getElementsByClassName&&t.getElementsByClassName)return R.apply(r,t.getElementsByClassName(o)),r}if(n.qsa&&!A[e+" "]&&(!m||!m.test(e))&&(1!==x||"object"!==t.nodeName.toLowerCase())){if(y=e,w=t,1===x&&V.test(e)){(s=t.getAttribute("id"))?s=s.replace(ne,re):t.setAttribute("id",s=b),l=(h=u(e)).length;while(l--)h[l]="#"+s+" "+me(h[l]);y=h.join(","),w=_.test(e)&&he(t.parentNode)||t}try{return R.apply(r,w.querySelectorAll(y)),r}catch(t){A(e,!0)}finally{s===b&&t.removeAttribute("id")}}}return a(e.replace(j,"$1"),t,r,i)}function le(){var e=[];function t(n,i){return e.push(n+" ")>r.cacheLength&&delete t[e.shift()],t[n+" "]=i}return t}function ae(e){return e[b]=!0,e}function ce(e){var t=p.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function se(e,t){var n=e.split("|"),i=n.length;while(i--)r.attrHandle[n[i]]=t}function fe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(e){return function(t){return"form"in t?t.parentNode&&!1===t.disabled?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&oe(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function pe(e){return ae(function(t){return t=+t,ae(function(n,r){var i,o=e([],n.length,t),u=o.length;while(u--)n[i=o[u]]&&(n[i]=!(r[i]=n[i]))})})}function he(e){return e&&void 0!==e.getElementsByTagName&&e}n=ue.support={},o=ue.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},d=ue.setDocument=function(e){var t,i,u=e?e.ownerDocument||e:N;return u!==p&&9===u.nodeType&&u.documentElement?(p=u,h=p.documentElement,g=!o(p),N!==p&&(i=p.defaultView)&&i.top!==i&&(i.addEventListener?i.addEventListener("unload",ie,!1):i.attachEvent&&i.attachEvent("onunload",ie)),n.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ce(function(e){return e.appendChild(p.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=Y.test(p.getElementsByClassName),n.getById=ce(function(e){return h.appendChild(e).id=b,!p.getElementsByName||!p.getElementsByName(b).length}),n.getById?(r.filter.ID=function(e){var t=e.replace(ee,te);return function(e){return e.getAttribute("id")===t}},r.find.ID=function(e,t){if(void 0!==t.getElementById&&g){var n=t.getElementById(e);return n?[n]:[]}}):(r.filter.ID=function(e){var t=e.replace(ee,te);return function(e){var n=void 0!==e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}},r.find.ID=function(e,t){if(void 0!==t.getElementById&&g){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),r.find.TAG=n.getElementsByTagName?function(e,t){return void 0!==t.getElementsByTagName?t.getElementsByTagName(e):n.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},r.find.CLASS=n.getElementsByClassName&&function(e,t){if(void 0!==t.getElementsByClassName&&g)return t.getElementsByClassName(e)},y=[],m=[],(n.qsa=Y.test(p.querySelectorAll))&&(ce(function(e){h.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&m.push("[*^$]="+z+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||m.push("\\["+z+"*(?:value|"+P+")"),e.querySelectorAll("[id~="+b+"-]").length||m.push("~="),e.querySelectorAll(":checked").length||m.push(":checked"),e.querySelectorAll("a#"+b+"+*").length||m.push(".#.+[+~]")}),ce(function(e){e.innerHTML="";var t=p.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&m.push("name"+z+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&m.push(":enabled",":disabled"),h.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&m.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),m.push(",.*:")})),(n.matchesSelector=Y.test(w=h.matches||h.webkitMatchesSelector||h.mozMatchesSelector||h.oMatchesSelector||h.msMatchesSelector))&&ce(function(e){n.disconnectedMatch=w.call(e,"*"),w.call(e,"[s!='']:x"),y.push("!=",F)}),m=m.length&&new RegExp(m.join("|")),y=y.length&&new RegExp(y.join("|")),t=Y.test(h.compareDocumentPosition),v=t||Y.test(h.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},T=t?function(e,t){if(e===t)return f=!0,0;var r=!e.compareDocumentPosition-!t.compareDocumentPosition;return r||(1&(r=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!n.sortDetached&&t.compareDocumentPosition(e)===r?e===p||e.ownerDocument===N&&v(N,e)?-1:t===p||t.ownerDocument===N&&v(N,t)?1:s?k(s,e)-k(s,t):0:4&r?-1:1)}:function(e,t){if(e===t)return f=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,u=[e],l=[t];if(!i||!o)return e===p?-1:t===p?1:i?-1:o?1:s?k(s,e)-k(s,t):0;if(i===o)return fe(e,t);n=e;while(n=n.parentNode)u.unshift(n);n=t;while(n=n.parentNode)l.unshift(n);while(u[r]===l[r])r++;return r?fe(u[r],l[r]):u[r]===N?-1:l[r]===N?1:0},p):p},ue.matches=function(e,t){return ue(e,null,null,t)},ue.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&d(e),n.matchesSelector&&g&&!A[t+" "]&&(!y||!y.test(t))&&(!m||!m.test(t)))try{var r=w.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(e){A(t,!0)}return ue(t,p,null,[e]).length>0},ue.contains=function(e,t){return(e.ownerDocument||e)!==p&&d(e),v(e,t)},ue.attr=function(e,t){(e.ownerDocument||e)!==p&&d(e);var i=r.attrHandle[t.toLowerCase()],o=i&&L.call(r.attrHandle,t.toLowerCase())?i(e,t,!g):void 0;return void 0!==o?o:n.attributes||!g?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null},ue.escape=function(e){return(e+"").replace(ne,re)},ue.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},ue.uniqueSort=function(e){var t,r=[],i=0,o=0;if(f=!n.detectDuplicates,s=!n.sortStable&&e.slice(0),e.sort(T),f){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return s=null,e},i=ue.getText=function(e){var t,n="",r=0,o=e.nodeType;if(o){if(1===o||9===o||11===o){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=i(e)}else if(3===o||4===o)return e.nodeValue}else while(t=e[r++])n+=i(t);return n},(r=ue.selectors={cacheLength:50,createPseudo:ae,match:K,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(ee,te),e[3]=(e[3]||e[4]||e[5]||"").replace(ee,te),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||ue.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&ue.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return K.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=u(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(ee,te).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=E[e+" "];return t||(t=new RegExp("(^|"+z+")"+e+"("+z+"|$)"))&&E(e,function(e){return t.test("string"==typeof e.className&&e.className||void 0!==e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=ue.attr(r,e);return null==i?"!="===t:!t||(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i.replace(O," ")+" ").indexOf(n)>-1:"|="===t&&(i===n||i.slice(0,n.length+1)===n+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),u="last"!==e.slice(-4),l="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,a){var c,s,f,d,p,h,g=o!==u?"nextSibling":"previousSibling",m=t.parentNode,y=l&&t.nodeName.toLowerCase(),w=!a&&!l,v=!1;if(m){if(o){while(g){d=t;while(d=d[g])if(l?d.nodeName.toLowerCase()===y:1===d.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[u?m.firstChild:m.lastChild],u&&w){v=(p=(c=(s=(f=(d=m)[b]||(d[b]={}))[d.uniqueID]||(f[d.uniqueID]={}))[e]||[])[0]===x&&c[1])&&c[2],d=p&&m.childNodes[p];while(d=++p&&d&&d[g]||(v=p=0)||h.pop())if(1===d.nodeType&&++v&&d===t){s[e]=[x,p,v];break}}else if(w&&(v=p=(c=(s=(f=(d=t)[b]||(d[b]={}))[d.uniqueID]||(f[d.uniqueID]={}))[e]||[])[0]===x&&c[1]),!1===v)while(d=++p&&d&&d[g]||(v=p=0)||h.pop())if((l?d.nodeName.toLowerCase()===y:1===d.nodeType)&&++v&&(w&&((s=(f=d[b]||(d[b]={}))[d.uniqueID]||(f[d.uniqueID]={}))[e]=[x,v]),d===t))break;return(v-=i)===r||v%r==0&&v/r>=0}}},PSEUDO:function(e,t){var n,i=r.pseudos[e]||r.setFilters[e.toLowerCase()]||ue.error("unsupported pseudo: "+e);return i[b]?i(t):i.length>1?(n=[e,e,"",t],r.setFilters.hasOwnProperty(e.toLowerCase())?ae(function(e,n){var r,o=i(e,t),u=o.length;while(u--)e[r=k(e,o[u])]=!(n[r]=o[u])}):function(e){return i(e,0,n)}):i}},pseudos:{not:ae(function(e){var t=[],n=[],r=l(e.replace(j,"$1"));return r[b]?ae(function(e,t,n,i){var o,u=r(e,null,i,[]),l=e.length;while(l--)(o=u[l])&&(e[l]=!(t[l]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),t[0]=null,!n.pop()}}),has:ae(function(e){return function(t){return ue(e,t).length>0}}),contains:ae(function(e){return e=e.replace(ee,te),function(t){return(t.textContent||t.innerText||i(t)).indexOf(e)>-1}}),lang:ae(function(e){return J.test(e||"")||ue.error("unsupported lang: "+e),e=e.replace(ee,te).toLowerCase(),function(t){var n;do{if(n=g?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return(n=n.toLowerCase())===e||0===n.indexOf(e+"-")}while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===h},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:de(!1),disabled:de(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!r.pseudos.empty(e)},header:function(e){return W.test(e.nodeName)},input:function(e){return Q.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:pe(function(){return[0]}),last:pe(function(e,t){return[t-1]}),eq:pe(function(e,t,n){return[n<0?n+t:n]}),even:pe(function(e,t){for(var n=0;nt?t:n;--r>=0;)e.push(r);return e}),gt:pe(function(e,t,n){for(var r=n<0?n+t:n;++r1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function ve(e,t,n){for(var r=0,i=t.length;r-1&&(o[c]=!(u[c]=f))}}else y=be(y===u?y.splice(h,y.length):y),i?i(null,u,y,a):R.apply(u,y)})}function xe(e){for(var t,n,i,o=e.length,u=r.relative[e[0].type],l=u||r.relative[" "],a=u?1:0,s=ye(function(e){return e===t},l,!0),f=ye(function(e){return k(t,e)>-1},l,!0),d=[function(e,n,r){var i=!u&&(r||n!==c)||((t=n).nodeType?s(e,n,r):f(e,n,r));return t=null,i}];a1&&we(d),a>1&&me(e.slice(0,a-1).concat({value:" "===e[a-2].type?"*":""})).replace(j,"$1"),n,a0,i=e.length>0,o=function(o,u,l,a,s){var f,h,m,y=0,w="0",v=o&&[],b=[],N=c,C=o||i&&r.find.TAG("*",s),E=x+=null==N?1:Math.random()||.1,D=C.length;for(s&&(c=u===p||u||s);w!==D&&null!=(f=C[w]);w++){if(i&&f){h=0,u||f.ownerDocument===p||(d(f),l=!g);while(m=e[h++])if(m(f,u||p,l)){a.push(f);break}s&&(x=E)}n&&((f=!m&&f)&&y--,o&&v.push(f))}if(y+=w,n&&w!==y){h=0;while(m=t[h++])m(v,b,u,l);if(o){if(y>0)while(w--)v[w]||b[w]||(b[w]=q.call(a));b=be(b)}R.apply(a,b),s&&!o&&b.length>0&&y+t.length>1&&ue.uniqueSort(a)}return s&&(x=E,c=N),v};return n?ae(o):o}l=ue.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=u(e)),n=t.length;while(n--)(o=xe(t[n]))[b]?r.push(o):i.push(o);(o=S(e,Ce(i,r))).selector=e}return o},a=ue.select=function(e,t,n,i){var o,a,c,s,f,d="function"==typeof e&&e,p=!i&&u(e=d.selector||e);if(n=n||[],1===p.length){if((a=p[0]=p[0].slice(0)).length>2&&"ID"===(c=a[0]).type&&9===t.nodeType&&g&&r.relative[a[1].type]){if(!(t=(r.find.ID(c.matches[0].replace(ee,te),t)||[])[0]))return n;d&&(t=t.parentNode),e=e.slice(a.shift().value.length)}o=K.needsContext.test(e)?0:a.length;while(o--){if(c=a[o],r.relative[s=c.type])break;if((f=r.find[s])&&(i=f(c.matches[0].replace(ee,te),_.test(a[0].type)&&he(t.parentNode)||t))){if(a.splice(o,1),!(e=i.length&&me(a)))return R.apply(n,i),n;break}}}return(d||l(e,p))(i,t,!g,n,!t||_.test(e)&&he(t.parentNode)||t),n},n.sortStable=b.split("").sort(T).join("")===b,n.detectDuplicates=!!f,d(),n.sortDetached=ce(function(e){return 1&e.compareDocumentPosition(p.createElement("fieldset"))}),ce(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||se("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ce(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||se("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ce(function(e){return null==e.getAttribute("disabled")})||se(P,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null});var Ee=e.Sizzle;ue.noConflict=function(){return e.Sizzle===ue&&(e.Sizzle=Ee),ue},"function"==typeof define&&define.amd?define(function(){return ue}):"undefined"!=typeof module&&module.exports?module.exports=ue:e.Sizzle=ue}(window); 3 | //# sourceMappingURL=sizzle.min.map -------------------------------------------------------------------------------- /git_mindMap/git.md: -------------------------------------------------------------------------------- 1 | ### git 协同开发,需要注意的几个小点 2 | 3 | 最近两个月,负责“xxxx”小程序的相关迭代,该项目从16年开发迭代到现在,git操作十分频繁,小小总结了一下该注意的点,希望对你大大有用。 4 | 5 | #### 切换现有分支需注意 6 | 我们都知道使用 `git checkout branch` 即可去到你想去的分支,这个情况在你当前分支没有修改代码的前提是可以行得通的,但是呢,如果一旦你修改了,`git` 会提示你并不能切换,此时我们有两种方法: 7 | 8 | 1. commit 我们的相关代码; 9 | 2. stash 暂存我们的代码。 10 | 11 | 第1种方法适用于开发完一个模块,可以提交远程仓库的情况。 12 | 第2种方法适用于开发到一半不想提交的情况,但后面在重新切回来时需要 `git stash apply` 恢复暂存区的内容。 13 | 14 | #### 创建并且切换分支需注意 15 | 16 | 在开发过程中,往往有 n 多个分支,每个模块需求都有一个独立的分支,当我在 a 分支开发到一半时,此时有一个新的模块需求,那么我需要创建并且切换一个新分支 b 进行开发,此时要注意: 17 | 18 | 先 checkout 到 master,而后习惯的先 `git pull` 拉取 master 上最新的代码(往往会没同步到,造成后面 merge 冲突问题)再 `git checkout -b branch`。 19 | 20 | 有些同学会忽略以上操作,在 a 分支就创建并且切换一个新分支 b ,但此时 b 的代码是继承来自 a 分支,这往往不是我们想要的。 21 | 22 | #### commit 习惯 23 | 24 | 在各个团队内,也许并没有严格要求 commit 的 message 规范,平时你可能会这样commit:`git commit -m "哈哈哈"`。这样就造成了一个问题,我知道你这次提交是在笑,但是我并不知道你为什么笑。 25 | 26 | 当然有些团队内部也有自定义的规范,比如 `git commit -m "[fix]我这次是修改 xx bug"` ,这样也是非常好的,一目了然。下面我推荐linkxiao大佬给我的一款插件 `vsc-commitizen`。直接看操作: 27 | 28 | 安装完这个插件后,按“ctrl+shift+p”,输入“vsc-commitizen”(下次会直接出现在窗口,如下图), 29 | 30 | ![](https://act.weixin.qq.com/static/images/201912/e6c31060155fac00bafe1b8ef9906049.png) 31 | 32 | 而后,选择我们这次提交的修改类型和填写相关message即可,方便快捷。 33 | 34 | ![](https://act.weixin.qq.com/static/images/201912/8f025754852def4aa4a1eeb8eae3d596.png) 35 | 36 | #### 合并分支需注意 37 | 38 | 在当前分支 a 开发完后,我们需要先 checkout 到 master,`git pull` 后确保拉取到 master 最新的代码之后,再切回 a 分支,如果 master 有更新,则执行 `git merge master` 合并分支,有冲突则解决冲突,之后再提交 push ,确保后续提 MR 39 | 40 | #### 提交MR/PR需注意 41 | 42 | 打开xxx,在相应的项目仓库,选择Merge Request,选择你修改的分支,后面选择checkout的老板,提交你的MR即可。 -------------------------------------------------------------------------------- /git_mindMap/git命令思维导图.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtonhuang/blog/f5c42844a71529ec8752f79ef1963ce7db205886/git_mindMap/git命令思维导图.xmind -------------------------------------------------------------------------------- /git_mindMap/git思维导图.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtonhuang/blog/f5c42844a71529ec8752f79ef1963ce7db205886/git_mindMap/git思维导图.xmind -------------------------------------------------------------------------------- /git_mindMap/images/git命令思维导图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtonhuang/blog/f5c42844a71529ec8752f79ef1963ce7db205886/git_mindMap/images/git命令思维导图.png -------------------------------------------------------------------------------- /git_mindMap/images/git终端vim常用操作.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtonhuang/blog/f5c42844a71529ec8752f79ef1963ce7db205886/git_mindMap/images/git终端vim常用操作.png -------------------------------------------------------------------------------- /git_mindMap/readme.md: -------------------------------------------------------------------------------- 1 | ## git思维导图(03/07 update) 2 | 3 | 本人整理了git常用的命令,做成了思维导图,并附上了vim常用命令。 4 | 5 | 如果想要更深入的理解git,或者完成更加复杂的操作,还需要系统性的学习。 6 | 7 | 有需要请download高清图,喜欢的请给个star ^_^ 8 | 9 | ![](https://github.com/mtonhuang/bolg/blob/master/git_mindMap/images/git%E5%91%BD%E4%BB%A4%E6%80%9D%E7%BB%B4%E5%AF%BC%E5%9B%BE.png) 10 | 11 | ![](https://github.com/mtonhuang/bolg/blob/master/git_mindMap/images/git%E7%BB%88%E7%AB%AFvim%E5%B8%B8%E7%94%A8%E6%93%8D%E4%BD%9C.png) 12 | -------------------------------------------------------------------------------- /images/SQL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtonhuang/blog/f5c42844a71529ec8752f79ef1963ce7db205886/images/SQL.png -------------------------------------------------------------------------------- /images/blog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtonhuang/blog/f5c42844a71529ec8752f79ef1963ce7db205886/images/blog.png -------------------------------------------------------------------------------- /images/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtonhuang/blog/f5c42844a71529ec8752f79ef1963ce7db205886/images/home.png -------------------------------------------------------------------------------- /images/ice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtonhuang/blog/f5c42844a71529ec8752f79ef1963ce7db205886/images/ice.png -------------------------------------------------------------------------------- /images/source(1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtonhuang/blog/f5c42844a71529ec8752f79ef1963ce7db205886/images/source(1).png -------------------------------------------------------------------------------- /images/source(2).gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtonhuang/blog/f5c42844a71529ec8752f79ef1963ce7db205886/images/source(2).gif -------------------------------------------------------------------------------- /images/source(3).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtonhuang/blog/f5c42844a71529ec8752f79ef1963ce7db205886/images/source(3).png -------------------------------------------------------------------------------- /images/source(4).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtonhuang/blog/f5c42844a71529ec8752f79ef1963ce7db205886/images/source(4).png -------------------------------------------------------------------------------- /images/source(5).gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtonhuang/blog/f5c42844a71529ec8752f79ef1963ce7db205886/images/source(5).gif -------------------------------------------------------------------------------- /images/source(6).gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtonhuang/blog/f5c42844a71529ec8752f79ef1963ce7db205886/images/source(6).gif -------------------------------------------------------------------------------- /images/source_2 (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtonhuang/blog/f5c42844a71529ec8752f79ef1963ce7db205886/images/source_2 (1).png -------------------------------------------------------------------------------- /images/source_2 (2).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtonhuang/blog/f5c42844a71529ec8752f79ef1963ce7db205886/images/source_2 (2).png -------------------------------------------------------------------------------- /images/source_2 (4).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtonhuang/blog/f5c42844a71529ec8752f79ef1963ce7db205886/images/source_2 (4).png -------------------------------------------------------------------------------- /images/source_2 (5).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtonhuang/blog/f5c42844a71529ec8752f79ef1963ce7db205886/images/source_2 (5).png -------------------------------------------------------------------------------- /packages/ESLint_rules/readme.md: -------------------------------------------------------------------------------- 1 | [掘金](https://juejin.im/post/5c5560f16fb9a049b07dcad0)同步更新,欢迎给个star! 2 | 3 | # ESLint 推荐的rules 4 | 5 | ### no-compare-neg-zero 6 | 7 | > 禁止与 -0 进行比较 8 | 9 | **Rule Details** 10 | 11 |  该规则对试图与 -0 进行比较的代码发出警告,因为并不会达到预期。也就是说像 x === -0 的代码对于 +0 和 -0 都有效。作者可能想要用 Object.is(x, -0)。 12 | 13 | 14 | **错误** 代码示例: 15 | ```javascript 16 | if (x === -0) { 17 | // doSomething()... 18 | } 19 | ``` 20 | **正确** 代码示例: 21 | 22 | ```javascript 23 | if (x === 0) { 24 | //a doSomething()... 25 | } 26 | ``` 27 | ```javascript 28 | if (Object.is(x, -0)) { 29 | // doSomething()... 30 | } 31 | ``` 32 | 33 | ### no-cond-assign 34 | 35 | > 禁止条件表达式中出现赋值操作符 36 | 37 | **Rule Details** 38 | 39 |  该规则禁止在 if、for、while 和 do...while 语句中出现模棱两可的赋值操作符。 40 | 41 | **options** 42 | 43 | 该规则有一个字符串选项: 44 | - "except-parens" (默认) 允许条件语句中出现赋值操作符,前提是它们被圆括号括起来 (例如,在 while 或 do...while 循环条件中,允许赋值给一个变量) 45 | - "always" 禁止条件语句中出现赋值语句 46 | 47 | 48 | 默认选项 "except-parens" 的 **错误** 代码示例: 49 | ```javascript 50 | /*eslint no-cond-assign: "error"*/ 51 | 52 | // Unintentional assignment 53 | var x; 54 | if (x = 0) { 55 | var b = 1; 56 | } 57 | 58 | // Practical example that is similar to an error 59 | function setHeight(someNode) { 60 | "use strict"; 61 | do { 62 | someNode.height = "100px"; 63 | } while (someNode = someNode.parentNode); 64 | } 65 | ``` 66 | 默认选项 "except-parens" 的 **正确** 代码示例: 67 | 68 | ```javascript 69 | /*eslint no-cond-assign: "error"*/ 70 | 71 | // Assignment replaced by comparison 72 | var x; 73 | if (x === 0) { 74 | var b = 1; 75 | } 76 | 77 | // Practical example that wraps the assignment in parentheses 78 | function setHeight(someNode) { 79 | "use strict"; 80 | do { 81 | someNode.height = "100px"; 82 | } while ((someNode = someNode.parentNode)); 83 | } 84 | 85 | // Practical example that wraps the assignment and tests for 'null' 86 | function setHeight(someNode) { 87 | "use strict"; 88 | do { 89 | someNode.height = "100px"; 90 | } while ((someNode = someNode.parentNode) !== null); 91 | } 92 | ``` 93 | 94 | 选项 "always" 的 **错误** 代码示例: 95 | ```javascript 96 | /*eslint no-cond-assign: ["error", "always"]*/ 97 | 98 | // Unintentional assignment 99 | var x; 100 | if (x = 0) { 101 | var b = 1; 102 | } 103 | 104 | // Practical example that is similar to an error 105 | function setHeight(someNode) { 106 | "use strict"; 107 | do { 108 | someNode.height = "100px"; 109 | } while (someNode = someNode.parentNode); 110 | } 111 | 112 | // Practical example that wraps the assignment in parentheses 113 | function setHeight(someNode) { 114 | "use strict"; 115 | do { 116 | someNode.height = "100px"; 117 | } while ((someNode = someNode.parentNode)); 118 | } 119 | 120 | // Practical example that wraps the assignment and tests for 'null' 121 | function setHeight(someNode) { 122 | "use strict"; 123 | do { 124 | someNode.height = "100px"; 125 | } while ((someNode = someNode.parentNode) !== null); 126 | } 127 | ``` 128 | 129 | 选项 "always" 的 **正确** 代码示例: 130 | 131 | ```javascript 132 | /*eslint no-cond-assign: ["error", "always"]*/ 133 | 134 | // Assignment replaced by comparison 135 | var x; 136 | if (x === 0) { 137 | var b = 1; 138 | } 139 | ``` 140 | 141 | ### no-console 142 | 143 | > 禁用 console 144 | 145 | **Rule Details** 146 | 147 |  该规则禁止调用 console 对象的方法。 148 | 149 | 150 | **错误** 代码示例: 151 | ```javascript 152 | /*eslint no-console: "error"*/ 153 | 154 | console.log("Log a debug level message."); 155 | console.warn("Log a warn level message."); 156 | console.error("Log an error level message."); 157 | ``` 158 | **正确** 代码示例: 159 | 160 | ```javascript 161 | /*eslint no-console: "error"*/ 162 | 163 | // custom console 164 | Console.log("Hello world!"); 165 | ``` 166 | 167 | **options** 168 | 169 |  该规则有例外情况,是个对象: 170 | 171 | - "allow" 是个字符串数组,包含允许使用的console 对象的方法 172 | 173 | 选项 { "allow": ["warn", "error"] } 的 **正确** 代码示例: 174 | 175 | ```javascript 176 | /*eslint no-console: ["error", { allow: ["warn", "error"] }] */ 177 | 178 | console.warn("Log a warn level message."); 179 | console.error("Log an error level message."); 180 | ``` 181 | 182 | **When Not To Use It** 183 | 184 |  如果你在使用 Node.js,然后,console 主要用来向用户输出信息,所以不是严格用于调试目的。如果你正在做 Node.js 开发,那么你很可能不想启用此规则。 185 | 186 |  另一个可能不使用此规则的情况是,如果你想执行控制台调用,而不是控制台重写。例如: 187 | 188 | ```javascript 189 | /*eslint no-console: ["error", { allow: ["warn"] }] */ 190 | console.error = function (message) { 191 | throw new Error(message); 192 | }; 193 | ``` 194 | 195 |  在上面使用 no-console 规则的示例中,ESLint 将报告一个错误。对于上面的例子,你可以禁用该规则: 196 | 197 | ```javascipt 198 | // eslint-disable-next-line no-console 199 | console.error = function (message) { 200 | throw new Error(message); 201 | }; 202 | 203 | // or 204 | 205 | console.error = function (message) { // eslint-disable-line no-console 206 | throw new Error(message); 207 | }; 208 | ``` 209 | 210 |  然而,你可能不希望手动添加 eslint-disable-next-line 或 eslint-disable-line。你可以使用 no-restricted-syntax 规则来实现控制台调用仅接收错误的效果: 211 | 212 | ```javascript 213 | { 214 | "rules": { 215 | "no-restricted-syntax": [ 216 | "error", 217 | { 218 | "selector": "CallExpression[callee.object.name='console'][callee.property.name=/^(log|warn|error|info|trace)$/]", 219 | "message": "Unexpected property on console object was called" 220 | } 221 | ] 222 | } 223 | } 224 | ``` 225 | 226 | ### no-constant-condition 227 | 228 | > 禁止在条件中使用常量表达式 229 | 230 | **Rule Details** 231 | 232 |  该规则禁止在以下语句的条件中出现常量表达式: 233 | 234 | - if、for、while 或 do...while 语句 235 | - ?: 三元表达式 236 | 237 | 238 | **错误** 代码示例: 239 | ```javascript 240 | /*eslint no-constant-condition: "error"*/ 241 | 242 | if (false) { 243 | doSomethingUnfinished(); 244 | } 245 | 246 | if (void x) { 247 | doSomethingUnfinished(); 248 | } 249 | 250 | for (;-2;) { 251 | doSomethingForever(); 252 | } 253 | 254 | while (typeof x) { 255 | doSomethingForever(); 256 | } 257 | 258 | do { 259 | doSomethingForever(); 260 | } while (x = -1); 261 | 262 | var result = 0 ? a : b; 263 | ``` 264 | **正确** 代码示例: 265 | 266 | ```javascript 267 | /*eslint no-constant-condition: "error"*/ 268 | 269 | if (x === 0) { 270 | doSomething(); 271 | } 272 | 273 | for (;;) { 274 | doSomethingForever(); 275 | } 276 | 277 | while (typeof x === "undefined") { 278 | doSomething(); 279 | } 280 | 281 | do { 282 | doSomething(); 283 | } while (x); 284 | 285 | var result = x !== 0 ? a : b; 286 | ``` 287 | 288 | **options** 289 | 290 | checkLoops 291 | 292 |  默认为 true。设置该选项为 false 允许在循环中使用常量表达式。 293 | 294 | 当 checkLoops 为 false 时的 **正确** 代码示例: 295 | 296 | ```js 297 | /*eslint no-constant-condition: ["error", { "checkLoops": false }]*/ 298 | 299 | while (true) { 300 | doSomething(); 301 | if (condition()) { 302 | break; 303 | } 304 | }; 305 | 306 | for (;true;) { 307 | doSomething(); 308 | if (condition()) { 309 | break; 310 | } 311 | }; 312 | 313 | do { 314 | doSomething(); 315 | if (condition()) { 316 | break; 317 | } 318 | } while (true) 319 | ``` 320 | 321 | ### no-control-regex 322 | 323 | > 禁止在正则表达式中使用控制字符 324 | 325 | **Rule Details** 326 | 327 |  该规则禁止在正则表达式中出现控制字符。 328 | 329 | 330 | **错误** 代码示例: 331 | ```js 332 | /*eslint no-control-regex: "error"*/ 333 | 334 | var pattern1 = /\x1f/; 335 | var pattern2 = new RegExp("\x1f"); 336 | ``` 337 | 338 | **正确** 代码示例: 339 | 340 | ```javascript 341 | /*eslint no-control-regex: "error"*/ 342 | 343 | var pattern1 = /\x20/; 344 | var pattern2 = new RegExp("\x20"); 345 | ``` 346 | 347 | **When Not To Use It** 348 | 349 |  如果你需要使用控制字符进行模式匹配,你应该关闭该规则。 350 | 351 | ### no-debugger 352 | 353 | > 禁用 debugger 354 | 355 | **Rule Details** 356 | 357 |  该规则禁止 debugger 语句。 358 | 359 | 360 | **错误** 代码示例: 361 | ```js 362 | /*eslint no-debugger: "error"*/ 363 | 364 | function isTruthy(x) { 365 | debugger; 366 | return Boolean(x); 367 | } 368 | ``` 369 | **正确** 代码示例: 370 | ```js 371 | /*eslint no-debugger: "error"*/ 372 | 373 | function isTruthy(x) { 374 | return Boolean(x); // set a breakpoint at this line 375 | } 376 | ``` 377 | 378 | **When Not To Use It** 379 | 380 |  如果你的代码在很大程度上仍处于开发阶段,不想担心剥离 debugger 语句,那么就关闭此规则。通常在部署测试代码之前,你会想重新开启此规则。 381 | 382 | ### no-dupe-args 383 | 384 | > 禁止 function 定义中出现重名参数 385 | 386 | **Rule Details** 387 | 388 |  该规则禁止在函数定义或表达中出现重名参数。该规则并不适用于箭头函数或类方法,因为解析器会报告这样的错误。 389 | 390 |  如果 ESLint 在严格模式下解析代码,解析器(不是该规则)将报告这样的错误。 391 | 392 | 393 | **错误** 代码示例: 394 | ```js 395 | /*eslint no-dupe-args: "error"*/ 396 | 397 | function foo(a, b, a) { 398 | console.log("value of the second a:", a); 399 | } 400 | 401 | var bar = function (a, b, a) { 402 | console.log("value of the second a:", a); 403 | }; 404 | ``` 405 | **正确** 代码示例: 406 | 407 | ```js 408 | /*eslint no-dupe-args: "error"*/ 409 | 410 | function foo(a, b, c) { 411 | console.log(a, b, c); 412 | } 413 | 414 | var bar = function (a, b, c) { 415 | console.log(a, b, c); 416 | }; 417 | ``` 418 | 419 | ### no-dupe-keys 420 | 421 | > 禁止对象字面量中出现重复的 key 422 | 423 | **Rule Details** 424 | 425 |  该规则禁止在对象字面量中出现重复的键。 426 | 427 | 428 | **错误** 代码示例: 429 | ```js 430 | /*eslint no-dupe-keys: "error"*/ 431 | 432 | var foo = { 433 | bar: "baz", 434 | bar: "qux" 435 | }; 436 | 437 | var foo = { 438 | "bar": "baz", 439 | bar: "qux" 440 | }; 441 | 442 | var foo = { 443 | 0x1: "baz", 444 | 1: "qux" 445 | }; 446 | ``` 447 | **正确** 代码示例: 448 | 449 | ```js 450 | /*eslint no-dupe-keys: "error"*/ 451 | 452 | var foo = { 453 | bar: "baz", 454 | quxx: "qux" 455 | }; 456 | ``` 457 | 458 | ### no-duplicate-case 459 | 460 | > 禁止出现重复的 case 标签 461 | 462 | **Rule Details** 463 | 464 |  该规则禁止在 switch 语句中的 case 子句中出现重复的测试表达式。 465 | 466 | 467 | **错误** 代码示例: 468 | ```js 469 | /*eslint no-duplicate-case: "error"*/ 470 | 471 | var a = 1, 472 | one = 1; 473 | 474 | switch (a) { 475 | case 1: 476 | break; 477 | case 2: 478 | break; 479 | case 1: // duplicate test expression 480 | break; 481 | default: 482 | break; 483 | } 484 | 485 | switch (a) { 486 | case one: 487 | break; 488 | case 2: 489 | break; 490 | case one: // duplicate test expression 491 | break; 492 | default: 493 | break; 494 | } 495 | 496 | switch (a) { 497 | case "1": 498 | break; 499 | case "2": 500 | break; 501 | case "1": // duplicate test expression 502 | break; 503 | default: 504 | break; 505 | } 506 | ``` 507 | **正确** 代码示例: 508 | 509 | ```js 510 | /*eslint no-duplicate-case: "error"*/ 511 | 512 | var a = 1, 513 | one = 1; 514 | 515 | switch (a) { 516 | case 1: 517 | break; 518 | case 2: 519 | break; 520 | case 3: 521 | break; 522 | default: 523 | break; 524 | } 525 | 526 | switch (a) { 527 | case one: 528 | break; 529 | case 2: 530 | break; 531 | case 3: 532 | break; 533 | default: 534 | break; 535 | } 536 | 537 | switch (a) { 538 | case "1": 539 | break; 540 | case "2": 541 | break; 542 | case "3": 543 | break; 544 | default: 545 | break; 546 | } 547 | ``` 548 | 549 | ### no-empty 550 | 551 | > 禁止出现空语句块 552 | 553 | **Rule Details** 554 | 555 |  该规则禁止空语句块出现。该规则忽略包含一个注释的语句块(例如,在 try 语句中,一个空的 catch 或 finally 语句块意味着程序应该继续执行,无论是否出现错误)。 556 | 557 | 558 | **错误** 代码示例: 559 | ```js 560 | /*eslint no-empty: "error"*/ 561 | 562 | if (foo) { 563 | } 564 | 565 | while (foo) { 566 | } 567 | 568 | switch(foo) { 569 | } 570 | 571 | try { 572 | doSomething(); 573 | } catch(ex) { 574 | 575 | } finally { 576 | 577 | } 578 | ``` 579 | **正确** 代码示例: 580 | 581 | ```js 582 | /*eslint no-empty: "error"*/ 583 | 584 | if (foo) { 585 | // empty 586 | } 587 | 588 | while (foo) { 589 | /* empty */ 590 | } 591 | 592 | try { 593 | doSomething(); 594 | } catch (ex) { 595 | // continue regardless of error 596 | } 597 | 598 | try { 599 | doSomething(); 600 | } finally { 601 | /* continue regardless of error */ 602 | } 603 | ``` 604 | 605 | **Options** 606 | 607 |  该规则有例外情况,是个对象: 608 | 609 | - "allowEmptyCatch": true 允许出现空的 catch 子句 (也就是说,不包含注释) 610 | 611 | **allowEmptyCatch** 612 | 613 | 选项 { "allowEmptyCatch": true } 的 **正确** 代码示例: 614 | 615 | ```js 616 | /* eslint no-empty: ["error", { "allowEmptyCatch": true }] */ 617 | try { 618 | doSomething(); 619 | } catch (ex) {} 620 | 621 | try { 622 | doSomething(); 623 | } 624 | catch (ex) {} 625 | finally { 626 | /* continue regardless of error */ 627 | } 628 | ``` 629 | **When Not To Use It** 630 | 631 |  如果你打算使用空语句块,那么你可以禁用此规则。 632 | 633 | ### no-empty-character-class 634 | 635 | > 禁止在正则表达式中使用空字符集 636 | 637 | **Rule Details** 638 | 639 |  该规则禁止在正则表达式中出现空字符集。 640 | 641 | 642 | **错误** 代码示例: 643 | ```js 644 | /*eslint no-empty-character-class: "error"*/ 645 | 646 | /^abc[]/.test("abcdefg"); // false 647 | "abcdefg".match(/^abc[]/); // null 648 | ``` 649 | **正确** 代码示例: 650 | 651 | ```js 652 | /*eslint no-empty-character-class: "error"*/ 653 | 654 | /^abc/.test("abcdefg"); // true 655 | "abcdefg".match(/^abc/); // ["abc"] 656 | 657 | /^abc[a-z]/.test("abcdefg"); // true 658 | "abcdefg".match(/^abc[a-z]/); // ["abcd"] 659 | ``` 660 | 661 | **Known Limitations** 662 | 663 |  该规则不会报告 RegExp 构造函数的字符串参数中空字符集的使用情况。 664 | 665 | 当该规则报告了正确代码时,漏报的示例: 666 | 667 | ```js 668 | /*eslint no-empty-character-class: "error"*/ 669 | 670 | var abcNeverMatches = new RegExp("^abc[]"); 671 | ``` 672 | 673 | ### no-ex-assign 674 | 675 | > 禁止对 catch 子句的参数重新赋值 676 | 677 | **Rule Details** 678 | 679 |  该规则禁止对 catch 子句中的异常重新赋值。 680 | 681 | 682 | **错误** 代码示例: 683 | ```js 684 | /*eslint no-ex-assign: "error"*/ 685 | 686 | try { 687 | // code 688 | } catch (e) { 689 | e = 10; 690 | } 691 | ``` 692 | **正确** 代码示例: 693 | 694 | ```js 695 | /*eslint no-ex-assign: "error"*/ 696 | 697 | try { 698 | // code 699 | } catch (e) { 700 | var foo = 10; 701 | } 702 | ``` 703 | 704 | **Further Reading** 705 | 706 | - [The “catch” with try…catch](https://bocoup.com/blog/the-catch-with-try-catch) by Ben Alman explains how the exception identifier can leak into the outer scope in IE 6-8 707 | 708 | ### no-extra-boolean-cast 709 | 710 | > 禁止不必要的布尔转换 711 | 712 | **Rule Details** 713 | 714 |  该规则禁止不必要的布尔类型转换。 715 | 716 | 717 | **错误** 代码示例: 718 | ```js 719 | /*eslint no-extra-boolean-cast: "error"*/ 720 | 721 | var foo = !!!bar; 722 | 723 | var foo = !!bar ? baz : bat; 724 | 725 | var foo = Boolean(!!bar); 726 | 727 | var foo = new Boolean(!!bar); 728 | 729 | if (!!foo) { 730 | // ... 731 | } 732 | 733 | if (Boolean(foo)) { 734 | // ... 735 | } 736 | 737 | while (!!foo) { 738 | // ... 739 | } 740 | 741 | do { 742 | // ... 743 | } while (Boolean(foo)); 744 | 745 | for (; !!foo; ) { 746 | // ... 747 | } 748 | ``` 749 | **正确** 代码示例: 750 | 751 | ```js 752 | /*eslint no-extra-boolean-cast: "error"*/ 753 | 754 | var foo = !!bar; 755 | var foo = Boolean(bar); 756 | 757 | function foo() { 758 | return !!bar; 759 | } 760 | 761 | var foo = bar ? !!baz : !!bat; 762 | ``` 763 | 764 | ### no-extra-semi 765 | 766 | > 禁止不必要的分号 767 | 768 | **Rule Details** 769 | 770 | 该规则禁用不必要的分号。 771 | 772 | 773 | **错误** 代码示例: 774 | ```js 775 | /*eslint no-extra-semi: "error"*/ 776 | 777 | var x = 5;; 778 | 779 | function foo() { 780 | // code 781 | }; 782 | 783 | ``` 784 | **正确** 代码示例: 785 | 786 | ```js 787 | /*eslint no-extra-semi: "error"*/ 788 | 789 | var x = 5; 790 | 791 | var foo = function() { 792 | // code 793 | }; 794 | 795 | ``` 796 | 797 | **When Not To Use It** 798 | 799 | 如果你有意使用额外的分号,那么你可以禁用此规则。 800 | 801 | ### no-func-assign 802 | 803 | > 禁止对 function 声明重新赋值 804 | 805 | **Rule Details** 806 | 807 | 该规则禁止对 function 声明重新赋值。 808 | 809 | 810 | **错误** 代码示例: 811 | ```js 812 | /*eslint no-func-assign: "error"*/ 813 | 814 | function foo() {} 815 | foo = bar; 816 | 817 | function foo() { 818 | foo = bar; 819 | } 820 | ``` 821 | 822 | 与 JSHint 中对应的规则不同,该规则的 **错误** 代码示例: 823 | 824 | ```js 825 | /*eslint no-func-assign: "error"*/ 826 | 827 | foo = bar; 828 | function foo() {} 829 | ``` 830 | **正确** 代码示例: 831 | 832 | ```js 833 | /*eslint no-func-assign: "error"*/ 834 | 835 | var foo = function () {} 836 | foo = bar; 837 | 838 | function foo(foo) { // `foo` is shadowed. 839 | foo = bar; 840 | } 841 | 842 | function foo() { 843 | var foo = bar; // `foo` is shadowed. 844 | } 845 | ``` 846 | 847 | ### no-inner-declarations 848 | 849 | > 禁止在嵌套的块中出现变量声明或 function 声明 850 | 851 | **Rule Details** 852 | 853 | 该规则要求函数声明和变量声明(可选的)在程序或函数体的顶部。 854 | 855 | **Options** 856 | 857 | 该规则有一个字符串选项: 858 | 859 | - "functions" (默认) 禁止 function 声明出现在嵌套的语句块中 860 | - "both" 禁止 function 和 var 声明出现在嵌套的语句块中 861 | 862 | **functions** 863 | 864 | 默认选项 "functions" 的 **错误** 代码示例: 865 | ```js 866 | /*eslint no-inner-declarations: "error"*/ 867 | 868 | if (test) { 869 | function doSomething() { } 870 | } 871 | 872 | function doSomethingElse() { 873 | if (test) { 874 | function doAnotherThing() { } 875 | } 876 | } 877 | ``` 878 | 默认选项 "functions" 的 **正确** 代码示例: 879 | 880 | ```js 881 | /*eslint no-inner-declarations: "error"*/ 882 | 883 | function doSomething() { } 884 | 885 | function doSomethingElse() { 886 | function doAnotherThing() { } 887 | } 888 | 889 | if (test) { 890 | asyncCall(id, function (err, data) { }); 891 | } 892 | 893 | var fn; 894 | if (test) { 895 | fn = function fnExpression() { }; 896 | } 897 | ``` 898 | 899 | **both** 900 | 901 | 选项 "both" 的 **错误** 代码示例: 902 | 903 | ```js 904 | 905 | /*eslint no-inner-declarations: ["error", "both"]*/ 906 | 907 | if (test) { 908 | var foo = 42; 909 | } 910 | 911 | function doAnotherThing() { 912 | if (test) { 913 | var bar = 81; 914 | } 915 | } 916 | 917 | ``` 918 | 919 | 选项 "both" 的 **正确** 代码示例: 920 | 921 | ```js 922 | /*eslint no-inner-declarations: "error"*/ 923 | /*eslint-env es6*/ 924 | 925 | var bar = 42; 926 | 927 | if (test) { 928 | let baz = 43; 929 | } 930 | 931 | function doAnotherThing() { 932 | var baz = 81; 933 | } 934 | ``` 935 | 936 | **When Not To Use It** 937 | 938 | 当 [block-scoped functions](https://bugzilla.mozilla.org/show_bug.cgi?id=585536) 出现在 ES6 中时,函数声明的部分规则将被废弃,但在那之前,它应该是行之有效的。当使用 [block-scoped-var](https://cn.eslint.org/docs/rules/block-scoped-var) 规则时或者在嵌套块中声明变量是可以接受的(尽管有变量声明提升)时候,可以不再检测变量声明。 939 | 940 | 941 | ### no-invalid-regexp 942 | 943 | > 禁止 RegExp 构造函数中存在无效的正则表达式字符串 944 | 945 | **Rule Details** 946 | 947 | 该规则禁止在 RegExp 构造函数中出现无效的正则表达式。 948 | 949 | 950 | **错误** 代码示例: 951 | ```js 952 | /*eslint no-invalid-regexp: "error"*/ 953 | 954 | RegExp('[') 955 | 956 | RegExp('.', 'z') 957 | 958 | new RegExp('\\') 959 | ``` 960 | **正确** 代码示例: 961 | 962 | ```js 963 | /*eslint no-invalid-regexp: "error"*/ 964 | 965 | RegExp('.') 966 | 967 | new RegExp 968 | 969 | this.RegExp('[') 970 | ``` 971 | 972 | **Environments** 973 | 974 | ECMAScript 6 为 RegExp 构造函数增加了以下标志参数: 975 | 976 | - "u" (unicode) 977 | - "y" (sticky) 978 | 你可以在你的 ESLint 配置 中通过设置 ECMAScript 为 6 ,来使这些标志被有效地识别。 979 | 980 | 如果你想允许使用额外的标志,也不论出于什么目的,你可以在 .eslintrc 使用 allowConstructorFlags 选项指定它们。这样,不管是否有 ecmaVersion 设置,这些标记将会被该规则忽略。 981 | 982 | **Options** 983 | 984 | 该规则有例外情况,是个对象: 985 | 986 | - "allowConstructorFlags" 是个标志的数组 987 | 988 | **allowConstructorFlags** 989 | 990 | 选项 { "allowConstructorFlags": ["u", "y"] } 的 **正确** 代码示例: 991 | 992 | ```js 993 | /*eslint no-invalid-regexp: ["error", { "allowConstructorFlags": ["u", "y"] }]*/ 994 | 995 | new RegExp('.', 'y') 996 | 997 | new RegExp('.', 'yu') 998 | 999 | ``` 1000 | Further Reading 1001 | - [Annotated ES5 §7.8.5 - Regular Expression Literals](https://es5.github.io/#x7.8.5) 1002 | 1003 | 1004 | ### no-irregular-whitespace 1005 | 1006 | > 禁止在字符串和注释之外不规则的空白 1007 | 1008 | **Rule Details** 1009 | 1010 | 该规则旨在捕获无效的不是正常的tab和空格的空白。这些字符有的会在现代浏览器中引发问题,其它的会引起调试问题。 1011 | 1012 | 该规则禁止出现以下字符,除非该规则选项允许: 1013 | 1014 | ``` 1015 | \u000B - Line Tabulation (\v) - 1016 | \u000C - Form Feed (\f) - 1017 | \u00A0 - No-Break Space - 1018 | \u0085 - Next Line 1019 | \u1680 - Ogham Space Mark 1020 | \u180E - Mongolian Vowel Separator - 1021 | \ufeff - Zero Width No-Break Space - 1022 | \u2000 - En Quad 1023 | \u2001 - Em Quad 1024 | \u2002 - En Space - 1025 | \u2003 - Em Space - 1026 | \u2004 - Tree-Per-Em 1027 | \u2005 - Four-Per-Em 1028 | \u2006 - Six-Per-Em 1029 | \u2007 - Figure Space 1030 | \u2008 - Punctuation Space - 1031 | \u2009 - Thin Space 1032 | \u200A - Hair Space 1033 | \u200B - Zero Width Space - 1034 | \u2028 - Line Separator 1035 | \u2029 - Paragraph Separator 1036 | \u202F - Narrow No-Break Space 1037 | \u205f - Medium Mathematical Space 1038 | \u3000 - Ideographic Space 1039 | ``` 1040 | **Options** 1041 | 1042 | 该规则有例外情况,是个对象: 1043 | 1044 | - "skipStrings": true (默认) 允许在字符串字面量中出现任何空白字符 1045 | - "skipComments": true 允许在注释中出现任何空白字符 1046 | - "skipRegExps": true 允许在正则表达式中出现任何空白字符 1047 | - "skipTemplates": true 允许在模板字面量中出现任何空白字符 1048 | 1049 | **skipStrings** 1050 | 1051 | 默认选项 { "skipStrings": true } 的 **错误** 代码示例: 1052 | ```js 1053 | /*eslint no-irregular-whitespace: "error"*/ 1054 | 1055 | function thing() /**/{ 1056 | return 'test'; 1057 | } 1058 | 1059 | function thing( /**/){ 1060 | return 'test'; 1061 | } 1062 | 1063 | function thing /**/(){ 1064 | return 'test'; 1065 | } 1066 | 1067 | function thing᠎/**/(){ 1068 | return 'test'; 1069 | } 1070 | 1071 | function thing() { 1072 | return 'test'; /**/ 1073 | } 1074 | 1075 | function thing() { 1076 | return 'test'; /**/ 1077 | } 1078 | 1079 | function thing() { 1080 | // Description : some descriptive text 1081 | } 1082 | 1083 | /* 1084 | Description : some descriptive text 1085 | */ 1086 | 1087 | function thing() { 1088 | return / regexp/; 1089 | } 1090 | 1091 | /*eslint-env es6*/ 1092 | function thing() { 1093 | return `template string`; 1094 | } 1095 | ``` 1096 | 默认选项 { "skipStrings": true } **正确** 代码示例: 1097 | 1098 | ```js 1099 | /*eslint no-irregular-whitespace: "error"*/ 1100 | 1101 | function thing() { 1102 | return ' thing'; 1103 | } 1104 | 1105 | function thing() { 1106 | return '​thing'; 1107 | } 1108 | 1109 | function thing() { 1110 | return 'th ing'; 1111 | } 1112 | ``` 1113 | 1114 | **skipComments** 1115 | 1116 | 选项 { "skipComments": true } 的 **正确** 代码示例: 1117 | ```js 1118 | /*eslint no-irregular-whitespace: ["error", { "skipComments": true }]*/ 1119 | 1120 | function thing() { 1121 | // Description : some descriptive text 1122 | } 1123 | 1124 | /* 1125 | Description : some descriptive text 1126 | */ 1127 | ``` 1128 | 1129 | **skipRegExps** 1130 | 1131 | 选项 { "skipRegExps": true } 的 **正确** 代码示例: 1132 | 1133 | ```js 1134 | /*eslint no-irregular-whitespace: ["error", { "skipRegExps": true }]*/ 1135 | 1136 | function thing() { 1137 | return / regexp/; 1138 | } 1139 | ``` 1140 | 1141 | **skipTemplates** 1142 | 1143 | 选项 { "skipTemplates": true } 的 **正确** 代码示例: 1144 | ```js 1145 | /*eslint no-irregular-whitespace: ["error", { "skipTemplates": true }]*/ 1146 | /*eslint-env es6*/ 1147 | 1148 | function thing() { 1149 | return `template string`; 1150 | } 1151 | ``` 1152 | **When Not To Use It** 1153 | 1154 | 如果你想在你的应用中使用 tab 和空格之外的空白字符,可以关闭此规则。 1155 | 1156 | ### no-obj-calls 1157 | 1158 | > 禁止把全局对象作为函数调用 1159 | 1160 | **Rule Details** 1161 | 1162 | 该规则禁止将 Math、JSON 和 Reflect 对象当作函数进行调用。 1163 | 1164 | 1165 | **错误** 代码示例: 1166 | ```js 1167 | /*eslint no-obj-calls: "error"*/ 1168 | 1169 | var math = Math(); 1170 | var json = JSON(); 1171 | var reflect = Reflect(); 1172 | ``` 1173 | **正确** 代码示例: 1174 | 1175 | ```js 1176 | /*eslint no-obj-calls: "error"*/ 1177 | 1178 | function area(r) { 1179 | return Math.PI * r * r; 1180 | } 1181 | var object = JSON.parse("{}"); 1182 | var value = Reflect.get({ x: 1, y: 2 }, "x"); 1183 | ``` 1184 | 1185 | ### no-regex-spaces 1186 | 1187 | > 禁止正则表达式字面量中出现多个空格 1188 | 1189 | **Rule Details** 1190 | 1191 | 该规则禁止在正则表达式字面量中出现多个空格。 1192 | 1193 | **错误** 代码示例: 1194 | ```javascript 1195 | /*eslint no-regex-spaces: "error"*/ 1196 | 1197 | var re = /foo bar/; 1198 | var re = new RegExp("foo bar"); 1199 | ``` 1200 | **正确** 代码示例: 1201 | 1202 | ``` 1203 | /*eslint no-regex-spaces: "error"*/ 1204 | 1205 | var re = /foo {3}bar/; 1206 | var re = new RegExp("foo {3}bar"); 1207 | ``` 1208 | 1209 | ### no-sparse-arrays 1210 | 1211 | > 禁用稀疏数组 1212 | 1213 | **Rule Details** 1214 | 1215 | 该规则禁止使用稀疏数组,也就是逗号之前没有任何元素的数组。该规则不适用于紧随最后一个元素的拖尾逗号的情况。 1216 | 1217 | **错误** 代码示例: 1218 | ```javascript 1219 | /*eslint no-sparse-arrays: "error"*/ 1220 | 1221 | var items = [,]; 1222 | var colors = [ "red",, "blue" ]; 1223 | ``` 1224 | **正确** 代码示例: 1225 | 1226 | ``` 1227 | /*eslint no-sparse-arrays: "error"*/ 1228 | 1229 | var items = []; 1230 | var items = new Array(23); 1231 | 1232 | // trailing comma (after the last element) is not a problem 1233 | var colors = [ "red", "blue", ]; 1234 | ``` 1235 | 1236 | 1237 | ### no-unexpected-multiline 1238 | 1239 | > 禁止出现令人困惑的多行表达式 1240 | 1241 | **Rule Details** 1242 | 1243 | 该规则禁止使用令人困惑的多行表达式。 1244 | 1245 | **错误** 代码示例: 1246 | ```javascript 1247 | /*eslint no-unexpected-multiline: "error"*/ 1248 | 1249 | var foo = bar 1250 | (1 || 2).baz(); 1251 | 1252 | var hello = 'world' 1253 | [1, 2, 3].forEach(addNumber); 1254 | 1255 | let x = function() {} 1256 | `hello` 1257 | 1258 | let x = function() {} 1259 | x 1260 | `hello` 1261 | 1262 | let x = foo 1263 | /regex/g.test(bar) 1264 | ``` 1265 | **正确** 代码示例: 1266 | 1267 | ``` 1268 | /*eslint no-unexpected-multiline: "error"*/ 1269 | 1270 | var foo = bar; 1271 | (1 || 2).baz(); 1272 | 1273 | var foo = bar 1274 | ;(1 || 2).baz() 1275 | 1276 | var hello = 'world'; 1277 | [1, 2, 3].forEach(addNumber); 1278 | 1279 | var hello = 'world' 1280 | void [1, 2, 3].forEach(addNumber); 1281 | 1282 | let x = function() {}; 1283 | `hello` 1284 | 1285 | let tag = function() {} 1286 | tag `hello` 1287 | ``` 1288 | 1289 | 1290 | ### no-unreachable 1291 | 1292 | > 禁止在return、throw、continue 和 break 语句之后出现不可达代码 1293 | 1294 | **Rule Details** 1295 | 1296 | 该规则禁止在 return、throw、continue 和 break 语句后出现不可达代码。 1297 | 1298 | **错误** 代码示例: 1299 | ```javascript 1300 | /*eslint no-unreachable: "error"*/ 1301 | 1302 | function foo() { 1303 | return true; 1304 | console.log("done"); 1305 | } 1306 | 1307 | function bar() { 1308 | throw new Error("Oops!"); 1309 | console.log("done"); 1310 | } 1311 | 1312 | while(value) { 1313 | break; 1314 | console.log("done"); 1315 | } 1316 | 1317 | throw new Error("Oops!"); 1318 | console.log("done"); 1319 | 1320 | function baz() { 1321 | if (Math.random() < 0.5) { 1322 | return; 1323 | } else { 1324 | throw new Error(); 1325 | } 1326 | console.log("done"); 1327 | } 1328 | 1329 | for (;;) {} 1330 | console.log("done"); 1331 | ``` 1332 | **正确** 代码示例,因为 JavaScript 函数和变量提升: 1333 | 1334 | ``` 1335 | /*eslint no-unreachable: "error"*/ 1336 | 1337 | function foo() { 1338 | return bar(); 1339 | function bar() { 1340 | return 1; 1341 | } 1342 | } 1343 | 1344 | function bar() { 1345 | return x; 1346 | var x; 1347 | } 1348 | 1349 | switch (foo) { 1350 | case 1: 1351 | break; 1352 | var x; 1353 | } 1354 | ``` 1355 | 1356 | 1357 | ### no-unsafe-finally 1358 | 1359 | > 禁止在 finally 语句块中出现控制流语句 1360 | 1361 | **Rule Details** 1362 | 1363 | 该规则禁止在 finally 语句块中出现 return、throw、break 和 continue 语句。它允许间接使用,比如在 function 或 class 的定义中。 1364 | 1365 | **错误** 代码示例: 1366 | ```javascript 1367 | /*eslint no-unsafe-finally: "error"*/ 1368 | let foo = function() { 1369 | try { 1370 | return 1; 1371 | } catch(err) { 1372 | return 2; 1373 | } finally { 1374 | return 3; 1375 | } 1376 | }; 1377 | ``` 1378 | ```javascript 1379 | /*eslint no-unsafe-finally: "error"*/ 1380 | let foo = function() { 1381 | try { 1382 | return 1; 1383 | } catch(err) { 1384 | return 2; 1385 | } finally { 1386 | throw new Error; 1387 | } 1388 | }; 1389 | ``` 1390 | **正确** 代码示例: 1391 | 1392 | ``` 1393 | /*eslint no-unsafe-finally: "error"*/ 1394 | let foo = function() { 1395 | try { 1396 | return 1; 1397 | } catch(err) { 1398 | return 2; 1399 | } finally { 1400 | console.log("hola!"); 1401 | } 1402 | }; 1403 | ``` 1404 | ``` 1405 | /*eslint no-unsafe-finally: "error"*/ 1406 | let foo = function() { 1407 | try { 1408 | return 1; 1409 | } catch(err) { 1410 | return 2; 1411 | } finally { 1412 | let a = function() { 1413 | return "hola!"; 1414 | } 1415 | } 1416 | }; 1417 | ``` 1418 | ``` 1419 | /*eslint no-unsafe-finally: "error"*/ 1420 | let foo = function(a) { 1421 | try { 1422 | return 1; 1423 | } catch(err) { 1424 | return 2; 1425 | } finally { 1426 | switch(a) { 1427 | case 1: { 1428 | console.log("hola!") 1429 | break; 1430 | } 1431 | } 1432 | } 1433 | }; 1434 | ``` 1435 | 1436 | 1437 | ### no-unsafe-negation 1438 | 1439 | > 禁止对关系运算符的左操作数使用否定操作符 1440 | 1441 | **Rule Details** 1442 | 1443 | 该规则禁止对关系运算符的左操作数使用否定操作符。 1444 | 1445 | 关系运算符有: 1446 | 1447 | - in 运算符. 1448 | - instanceof 运算符. 1449 | 1450 | **错误** 代码示例: 1451 | ```javascript 1452 | /*eslint no-unsafe-negation: "error"*/ 1453 | 1454 | if (!key in object) { 1455 | // operator precedence makes it equivalent to (!key) in object 1456 | // and type conversion makes it equivalent to (key ? "false" : "true") in object 1457 | } 1458 | 1459 | if (!obj instanceof Ctor) { 1460 | // operator precedence makes it equivalent to (!obj) instanceof Ctor 1461 | // and it equivalent to always false since boolean values are not objects. 1462 | } 1463 | ``` 1464 | **正确** 代码示例: 1465 | 1466 | ``` 1467 | /*eslint no-unsafe-negation: "error"*/ 1468 | 1469 | if (!(key in object)) { 1470 | // key is not in object 1471 | } 1472 | 1473 | if (!(obj instanceof Ctor)) { 1474 | // obj is not an instance of Ctor 1475 | } 1476 | 1477 | if(("" + !key) in object) { 1478 | // make operator precedence and type conversion explicit 1479 | // in a rare situation when that is the intended meaning 1480 | } 1481 | ``` 1482 | Options 1483 | 无。 1484 | 1485 | 1486 | ### use-isnan 1487 | 1488 | > 该规则禁止与 ‘NaN’ 的比较。 1489 | 1490 | **Rule Details** 1491 | 1492 | 该规则禁止在正则表达式字面量中出现多个空格。 1493 | 1494 | **错误** 代码示例: 1495 | ```javascript 1496 | /*eslint use-isnan: "error"*/ 1497 | 1498 | if (foo == NaN) { 1499 | // ... 1500 | } 1501 | 1502 | if (foo != NaN) { 1503 | // ... 1504 | } 1505 | ``` 1506 | **正确** 代码示例: 1507 | 1508 | ``` 1509 | /*eslint use-isnan: "error"*/ 1510 | 1511 | if (isNaN(foo)) { 1512 | // ... 1513 | } 1514 | 1515 | if (!isNaN(foo)) { 1516 | // ... 1517 | } 1518 | ``` 1519 | 1520 | 1521 | ### valid-typeof 1522 | 1523 | > 强制 typeof 表达式与有效的字符串进行比较 1524 | 1525 | **Rule Details** 1526 | 1527 | 该规则强制 typeof 表达式与有效的字符串进行比较。 1528 | 1529 | Options 1530 | 1531 | 该规则有一个对象选项: 1532 | 1533 | - "requireStringLiterals": true 要求 typeof 表达式只与字符串字面量或其它 typeof 表达式 进行比较,禁止与其它值进行比较。 1534 | 1535 | **错误** 代码示例: 1536 | ```javascript 1537 | /*eslint valid-typeof: "error"*/ 1538 | 1539 | typeof foo === "strnig" 1540 | typeof foo == "undefimed" 1541 | typeof bar != "nunber" 1542 | typeof bar !== "function" 1543 | ``` 1544 | **正确** 代码示例: 1545 | 1546 | ```js 1547 | /*eslint valid-typeof: "error"*/ 1548 | 1549 | typeof foo === "string" 1550 | typeof bar == "undefined" 1551 | typeof foo === baz 1552 | typeof bar === typeof qux 1553 | ``` 1554 | 选项 { "requireStringLiterals": true } 的 **错误** 代码示例: 1555 | ```javascript 1556 | typeof foo === undefined 1557 | typeof bar == Object 1558 | typeof baz === "strnig" 1559 | typeof qux === "some invalid type" 1560 | typeof baz === anotherVariable 1561 | typeof foo == 5 1562 | ``` 1563 | 选项 { "requireStringLiterals": true } 的 **正确** 代码示例: 1564 | 1565 | ```js 1566 | typeof foo === "undefined" 1567 | typeof bar == "object" 1568 | typeof baz === "string" 1569 | typeof bar === typeof qux 1570 | ``` 1571 | ### no-case-declarations 1572 | 1573 | > 不允许在 case 子句中使用词法声明 1574 | 1575 | **Rule Details** 1576 | 1577 | 该规则旨在避免访问未经初始化的词法绑定以及跨 case 语句访问被提升的函数。 1578 | 1579 | 1580 | **错误** 代码示例: 1581 | ```javascript 1582 | /*eslint no-case-declarations: "error"*/ 1583 | /*eslint-env es6*/ 1584 | 1585 | switch (foo) { 1586 | case 1: 1587 | let x = 1; 1588 | break; 1589 | case 2: 1590 | const y = 2; 1591 | break; 1592 | case 3: 1593 | function f() {} 1594 | break; 1595 | default: 1596 | class C {} 1597 | } 1598 | ``` 1599 | **正确** 代码示例: 1600 | 1601 | ```js 1602 | /*eslint no-case-declarations: "error"*/ 1603 | /*eslint-env es6*/ 1604 | 1605 | // Declarations outside switch-statements are valid 1606 | const a = 0; 1607 | 1608 | switch (foo) { 1609 | // The following case clauses are wrapped into blocks using brackets 1610 | case 1: { 1611 | let x = 1; 1612 | break; 1613 | } 1614 | case 2: { 1615 | const y = 2; 1616 | break; 1617 | } 1618 | case 3: { 1619 | function f() {} 1620 | break; 1621 | } 1622 | case 4: 1623 | // Declarations using var without brackets are valid due to function-scope hoisting 1624 | var z = 4; 1625 | break; 1626 | default: { 1627 | class C {} 1628 | } 1629 | } 1630 | ``` 1631 | 1632 | ### no-empty-pattern 1633 | 1634 | > 禁止使用空解构模式 1635 | 1636 | **Rule Details** 1637 | 1638 | 此规则目的在于标记出在解构对象和数组中的任何的空模式,每当遇到一个这样的空模式,该规则就会报告一个问题。 1639 | 1640 | 1641 | **错误** 代码示例: 1642 | ```javascript 1643 | /*eslint no-empty-pattern: "error"*/ 1644 | 1645 | var {} = foo; 1646 | var [] = foo; 1647 | var {a: {}} = foo; 1648 | var {a: []} = foo; 1649 | function foo({}) {} 1650 | function foo([]) {} 1651 | function foo({a: {}}) {} 1652 | function foo({a: []}) {} 1653 | ``` 1654 | **正确** 代码示例: 1655 | 1656 | ```js 1657 | /*eslint no-empty-pattern: "error"*/ 1658 | 1659 | var {a = {}} = foo; 1660 | var {a = []} = foo; 1661 | function foo({a = {}}) {} 1662 | function foo({a = []}) {} 1663 | ``` 1664 | 1665 | 1666 | ### no-fallthrough 1667 | 1668 | > 禁止 case 语句落空 1669 | 1670 | **Rule Details** 1671 | 1672 | 该规则旨在消除非故意 case 落空行为。因此,它会标记处没有使用注释标明的落空情况。 1673 | 1674 | **错误** 代码示例: 1675 | ```javascript 1676 | /*eslint no-fallthrough: "error"*/ 1677 | 1678 | switch(foo) { 1679 | case 1: 1680 | doSomething(); 1681 | 1682 | case 2: 1683 | doSomething(); 1684 | } 1685 | ``` 1686 | **正确** 代码示例: 1687 | 1688 | ```js 1689 | /*eslint no-fallthrough: "error"*/ 1690 | 1691 | switch(foo) { 1692 | case 1: 1693 | doSomething(); 1694 | break; 1695 | 1696 | case 2: 1697 | doSomething(); 1698 | } 1699 | 1700 | function bar(foo) { 1701 | switch(foo) { 1702 | case 1: 1703 | doSomething(); 1704 | return; 1705 | 1706 | case 2: 1707 | doSomething(); 1708 | } 1709 | } 1710 | 1711 | switch(foo) { 1712 | case 1: 1713 | doSomething(); 1714 | throw new Error("Boo!"); 1715 | 1716 | case 2: 1717 | doSomething(); 1718 | } 1719 | 1720 | switch(foo) { 1721 | case 1: 1722 | case 2: 1723 | doSomething(); 1724 | } 1725 | 1726 | switch(foo) { 1727 | case 1: 1728 | doSomething(); 1729 | // falls through 1730 | 1731 | case 2: 1732 | doSomething(); 1733 | } 1734 | ``` 1735 | 1736 | 注意,在上面的例子中,最后的 case 语句,不会引起警告,因为没有可落空的语句了。 1737 | 1738 | **Options** 1739 | 1740 | 该规则接受单个选项参数: 1741 | 1742 | - 设置 commentPattern 选项为一个正则表达式字符串,来改变对有意为之的落空注释的检索 1743 | 1744 | commentPattern 1745 | 1746 | 选项 { "commentPattern": "break[\\s\\w]*omitted" } 的 **正确** 代码示例: 1747 | 1748 | ```javascript 1749 | /*eslint no-fallthrough: ["error", { "commentPattern": "break[\\s\\w]*omitted" }]*/ 1750 | 1751 | switch(foo) { 1752 | case 1: 1753 | doSomething(); 1754 | // break omitted 1755 | 1756 | case 2: 1757 | doSomething(); 1758 | } 1759 | 1760 | switch(foo) { 1761 | case 1: 1762 | doSomething(); 1763 | // caution: break is omitted intentionally 1764 | 1765 | default: 1766 | doSomething(); 1767 | } 1768 | ``` 1769 | 1770 | 1771 | ### no-global-assign 1772 | 1773 | >禁止对原生对象或只读的全局对象进行赋值 1774 | 1775 | **Rule Details** 1776 | 1777 | 该规则禁止修改只读的全局变量。 1778 | 1779 | ESLint 可以配置全局变量为只读。 1780 | 1781 | - Specifying Environments 1782 | - Specifying Globals 1783 | 1784 | 1785 | **错误** 代码示例: 1786 | ```javascript 1787 | /*eslint no-global-assign: "error"*/ 1788 | 1789 | Object = null 1790 | undefined = 1 1791 | ``` 1792 | ``` 1793 | /*eslint no-global-assign: "error"*/ 1794 | /*eslint-env browser*/ 1795 | 1796 | window = {} 1797 | length = 1 1798 | top = 1 1799 | ``` 1800 | ``` 1801 | /*eslint no-global-assign: "error"*/ 1802 | /*globals a:false*/ 1803 | 1804 | a = 1 1805 | ``` 1806 | **正确** 代码示例: 1807 | 1808 | ```js 1809 | /*eslint no-global-assign: "error"*/ 1810 | 1811 | a = 1 1812 | var b = 1 1813 | b = 2 1814 | ``` 1815 | ```js 1816 | /*eslint no-global-assign: "error"*/ 1817 | /*eslint-env browser*/ 1818 | 1819 | onload = function() {} 1820 | ``` 1821 | ```js 1822 | /*eslint no-global-assign: "error"*/ 1823 | /*globals a:true*/ 1824 | 1825 | a = 1 1826 | ``` 1827 | **Options** 1828 | 1829 | 该规则接受一个 exceptions 选项,可以用来指定允许进行赋值的内置对象列表: 1830 | 1831 | ```js 1832 | { 1833 | "rules": { 1834 | "no-global-assign": ["error", {"exceptions": ["Object"]}] 1835 | } 1836 | } 1837 | ``` 1838 | 1839 | ### no-octal 1840 | 1841 | > 禁用八进制字面量 1842 | 1843 | **Rule Details** 1844 | 1845 | 该规则禁用八进制字面量。 1846 | 1847 | 如果 ESLint 是在严格模式下解析代码,解析器(而不是该规则)会报告错误。 1848 | 1849 | 1850 | **错误** 代码示例: 1851 | ```javascript 1852 | /*eslint no-octal: "error"*/ 1853 | 1854 | var num = 071; 1855 | var result = 5 + 07; 1856 | ``` 1857 | **正确** 代码示例: 1858 | 1859 | ```js 1860 | /*eslint no-octal: "error"*/ 1861 | 1862 | var num = "071"; 1863 | ``` 1864 | 1865 | ### no-redeclare 1866 | 1867 | > 禁止多次声明同一变量 1868 | 1869 | **Rule Details** 1870 | 1871 | 此规则目旨在消除同一作用域中多次声明同一变量。 1872 | 1873 | **错误** 代码示例: 1874 | ```javascript 1875 | /*eslint no-redeclare: "error"*/ 1876 | 1877 | var a = 3; 1878 | var a = 10; 1879 | ``` 1880 | **正确** 代码示例: 1881 | 1882 | ```js 1883 | /*eslint no-redeclare: "error"*/ 1884 | 1885 | var a = 3; 1886 | // ... 1887 | a = 10; 1888 | ``` 1889 | 1890 | **Options** 1891 | 1892 | 该规则有一个选项参数,是个对象,该对象有个布尔属性为 "builtinGlobals"。默认为false。 1893 | 1894 | 如果设置为 true,该规则也会检查全局内建对象,比如Object、Array、Number… 1895 | 1896 | **builtinGlobals** 1897 | 1898 | "builtinGlobals" 选项将会在全局范围检查被重新声明的内置全局变量。 1899 | 1900 | 选项 { "builtinGlobals": true } 的 **错误** 代码示例: 1901 | 1902 | ```js 1903 | /*eslint no-redeclare: ["error", { "builtinGlobals": true }]*/ 1904 | 1905 | var Object = 0; 1906 | ``` 1907 | 1908 | 在 browser 环境下,选项 {"builtinGlobals": true} 的 **错误** 代码示例: 1909 | 1910 | ```js 1911 | /*eslint no-redeclare: ["error", { "builtinGlobals": true }]*/ 1912 | /*eslint-env browser*/ 1913 | 1914 | var top = 0; 1915 | ``` 1916 | browser 环境有很多内建的全局变量(例如,top)。一些内建的全局变量不能被重新声明。 1917 | 1918 | 注意,当使用 node 或 commonjs 环境 (或 ecmaFeatures.globalReturn,如果使用默认解析器)时,则程序的最大作用域不是实际的全局作用域,而是一个模块作用域。当出现这种情况时,声明一个以内置的全局变量命令的变量,不算是重声明,只是遮蔽了全局变量。在这种情况下,应该使用 no-shadow 规则的 "builtinGlobals" 选项。 1919 | 1920 | 1921 | ### no-self-assign 1922 | 1923 | > 禁止自我赋值 1924 | 1925 | **Rule Details** 1926 | 1927 | 该规则旨在消除自身赋值的情况。 1928 | 1929 | **错误** 代码示例: 1930 | ```javascript 1931 | /*eslint no-self-assign: "error"*/ 1932 | 1933 | foo = foo; 1934 | 1935 | [a, b] = [a, b]; 1936 | 1937 | [a, ...b] = [x, ...b]; 1938 | 1939 | ({a, b} = {a, x}); 1940 | ``` 1941 | **正确** 代码示例: 1942 | 1943 | ```js 1944 | /*eslint no-self-assign: "error"*/ 1945 | 1946 | foo = bar; 1947 | [a, b] = [b, a]; 1948 | 1949 | // This pattern is warned by the `no-use-before-define` rule. 1950 | let foo = foo; 1951 | 1952 | // The default values have an effect. 1953 | [foo = 1] = [foo]; 1954 | ``` 1955 | 1956 | **Options** 1957 | 1958 | 该规则也有可以检查属性的选项。 1959 | 1960 | ```js 1961 | { 1962 | "no-self-assign": ["error", {"props": false}] 1963 | } 1964 | ``` 1965 | 1966 | - props - 如果为 true,no-self-assign 规则将对属性的自我赋值发出警告。默认为 false. 1967 | 1968 | **props** 1969 | 1970 | 选项 { "props": true } 的 **错误** 代码示例: 1971 | 1972 | ```js 1973 | /*eslint no-self-assign: [error, {props: true}]*/ 1974 | 1975 | // self-assignments with properties. 1976 | obj.a = obj.a; 1977 | obj.a.b = obj.a.b; 1978 | obj["a"] = obj["a"]; 1979 | obj[a] = obj[a]; 1980 | ``` 1981 | 1982 | 选项 { "props": true } 的 **正确** 代码示例: 1983 | 1984 | ```js 1985 | /*eslint no-self-assign: [error, {props: true}]*/ 1986 | 1987 | // non-self-assignments with properties. 1988 | obj.a = obj.b; 1989 | obj.a.b = obj.c.b; 1990 | obj.a.b = obj.a.c; 1991 | obj[a] = obj["a"] 1992 | 1993 | // This ignores if there is a function call. 1994 | obj.a().b = obj.a().b 1995 | a().b = a().b 1996 | 1997 | // Known limitation: this does not support computed properties except single literal or single identifier. 1998 | obj[a + b] = obj[a + b]; 1999 | obj["a" + "b"] = obj["a" + "b"]; 2000 | ``` 2001 | 2002 | ### no-unused-labels 2003 | 2004 | > 禁用出现未使用过的标 2005 | 2006 | **Rule Details** 2007 | 2008 | 该规则旨在消除未使用过的标签。 2009 | 2010 | 2011 | **错误** 代码示例: 2012 | ```javascript 2013 | /*eslint no-unused-labels: "error"*/ 2014 | 2015 | A: var foo = 0; 2016 | 2017 | B: { 2018 | foo(); 2019 | } 2020 | 2021 | C: 2022 | for (let i = 0; i < 10; ++i) { 2023 | foo(); 2024 | } 2025 | ``` 2026 | **正确** 代码示例: 2027 | 2028 | ```js 2029 | /*eslint no-unused-labels: "error"*/ 2030 | 2031 | A: { 2032 | if (foo()) { 2033 | break A; 2034 | } 2035 | bar(); 2036 | } 2037 | 2038 | B: 2039 | for (let i = 0; i < 10; ++i) { 2040 | if (foo()) { 2041 | break B; 2042 | } 2043 | bar(); 2044 | } 2045 | ``` 2046 | 2047 | 2048 | ### no-useless-escape 2049 | 2050 | > 禁用不必要的转义字符 2051 | 2052 | **Rule Details** 2053 | 2054 | 该规则标记在不改变代码行为的情况下可以安全移除的转义。 2055 | 2056 | 2057 | **错误** 代码示例: 2058 | ```javascript 2059 | /*eslint no-useless-escape: "error"*/ 2060 | 2061 | "\'"; 2062 | '\"'; 2063 | "\#"; 2064 | "\e"; 2065 | `\"`; 2066 | `\"${foo}\"`; 2067 | `\#{foo}`; 2068 | /\!/; 2069 | /\@/; 2070 | ``` 2071 | **正确** 代码示例: 2072 | 2073 | ```js 2074 | /*eslint no-useless-escape: "error"*/ 2075 | 2076 | "\""; 2077 | '\''; 2078 | "\x12"; 2079 | "\u00a9"; 2080 | "\371"; 2081 | "xs\u2111"; 2082 | `\``; 2083 | `\${${foo}}`; 2084 | `$\{${foo}}`; 2085 | /\\/g; 2086 | /\t/g; 2087 | /\w\$\*\^\./; 2088 | ``` 2089 | 2090 | 2091 | ### no-delete-var 2092 | 2093 | > 禁用不必要的转义字符 2094 | 2095 | **Rule Details** 2096 | 2097 | 该规则禁止对变量使用 delete 操作符。 2098 | 2099 | 如果 ESLint 是在严格模式下解析代码,解析器(而不是该规则)会报告错误。 2100 | 2101 | **错误** 代码示例: 2102 | ```javascript 2103 | /*eslint no-delete-var: "error"*/ 2104 | 2105 | var x; 2106 | delete x; 2107 | ``` 2108 | 2109 | 2110 | ### no-undef 2111 | 2112 | > 禁用未声明的变量,除非它们在 /*global */ 注释中被提到 2113 | 2114 | **Rule Details** 2115 | 2116 | 对任何未声明的变量的引用都会引起一个警告,除非显式地在 /*global ...*/ 注释中指定,或在 globals key in the configuration file 中指定。另一个常见的用例是,你有意使用定义在其他地方的全局变量(例如来自 HTML 的脚本)。 2117 | 2118 | 2119 | **错误** 代码示例: 2120 | ```javascript 2121 | /*eslint no-undef: "error"*/ 2122 | 2123 | var a = someFunction(); 2124 | b = 10; 2125 | ``` 2126 | 有 global 声明时,该规则的 **正确** 代码示例: 2127 | 2128 | ```js 2129 | /*global someFunction b:true*/ 2130 | /*eslint no-undef: "error"*/ 2131 | 2132 | var a = someFunction(); 2133 | b = 10; 2134 | ``` 2135 | 有 global 声明时,该规则的 **错误** 代码示例: 2136 | 2137 | ```js 2138 | /*global b*/ 2139 | /*eslint no-undef: "error"*/ 2140 | 2141 | b = 10; 2142 | ``` 2143 | 默认情况下,/*global */ 中声明的变量是只读的,因此对其进行赋值是错误的。 2144 | 2145 | **Options** 2146 | 2147 | - typeof 设置为 true,将对 typeof 中用到的变量发出警告(默认为false)。 2148 | 2149 | **typeof** 2150 | 2151 | 默认选项 { "typeof": false } 的 **正确** 代码示例: 2152 | ```js 2153 | /*eslint no-undef: "error"*/ 2154 | 2155 | if (typeof UndefinedIdentifier === "undefined") { 2156 | // do something ... 2157 | } 2158 | ``` 2159 | 如果想阻止在 typeof 运算中有未申明的变量导致的警告,可以用此项。 2160 | 2161 | 选项 { "typeof": true } 的 **错误** 代码示例: 2162 | ```js 2163 | /*eslint no-undef: ["error", { "typeof": true }] */ 2164 | 2165 | if(typeof a === "string"){} 2166 | ``` 2167 | 有 global 声明时,选项 { "typeof": true } 的 **正确** 代码示例: 2168 | ```js 2169 | /*global a*/ 2170 | /*eslint no-undef: ["error", { "typeof": true }] */ 2171 | 2172 | if(typeof a === "string"){} 2173 | ``` 2174 | **Environments** 2175 | 2176 | 为了方便,ESlint 提供了预定义流行类库和运行时环境暴露的全局变量的快捷方式。该规则支持这些环境,如 指定 Environments 中列出的。使用如下: 2177 | 2178 | **browser** 2179 | 2180 | browser 环境下的 **正确** 代码示例: 2181 | ```js 2182 | /*eslint no-undef: "error"*/ 2183 | /*eslint-env browser*/ 2184 | 2185 | setTimeout(function() { 2186 | alert("Hello"); 2187 | }); 2188 | ``` 2189 | **Node.js** 2190 | 2191 | node 环境下的 **正确** 代码示例: 2192 | ```js 2193 | /*eslint no-undef: "error"*/ 2194 | /*eslint-env node*/ 2195 | 2196 | var fs = require("fs"); 2197 | module.exports = function() { 2198 | console.log(fs); 2199 | }; 2200 | ``` 2201 | 2202 | ### no-unused-vars 2203 | 2204 | > 禁止出现未使用过的变量 2205 | 2206 | **Rule Details** 2207 | 2208 | 此规则旨在消除未使用过的变量,方法和方法中的参数名,当发现这些存在,发出警告。 2209 | 2210 | 符合下面条件的变量被认为是可以使用的: 2211 | 2212 | - 作为回调函数 2213 | - 被读取 (var y = x) 2214 | - 传入函数中作为argument对象(doSomething(x)) 2215 | - 在传入到另一个函数的函数中被读取 2216 | 2217 | 一个变量仅仅是被赋值为 (var x = 5) 或者是被声明过,则认为它是没被考虑使用。 2218 | 2219 | 2220 | **错误** 代码示例: 2221 | ```javascript 2222 | /*eslint no-unused-vars: "error"*/ 2223 | /*global some_unused_var*/ 2224 | 2225 | // It checks variables you have defined as global 2226 | some_unused_var = 42; 2227 | 2228 | var x; 2229 | 2230 | // Write-only variables are not considered as used. 2231 | var y = 10; 2232 | y = 5; 2233 | 2234 | // A read for a modification of itself is not considered as used. 2235 | var z = 0; 2236 | z = z + 1; 2237 | 2238 | // By default, unused arguments cause warnings. 2239 | (function(foo) { 2240 | return 5; 2241 | })(); 2242 | 2243 | // Unused recursive functions also cause warnings. 2244 | function fact(n) { 2245 | if (n < 2) return 1; 2246 | return n * fact(n - 1); 2247 | } 2248 | 2249 | // When a function definition destructures an array, unused entries from the array also cause warnings. 2250 | function getY([x, y]) { 2251 | return y; 2252 | } 2253 | ``` 2254 | **正确** 代码示例: 2255 | 2256 | ```js 2257 | /*eslint no-unused-vars: "error"*/ 2258 | 2259 | var x = 10; 2260 | alert(x); 2261 | 2262 | // foo is considered used here 2263 | myFunc(function foo() { 2264 | // ... 2265 | }.bind(this)); 2266 | 2267 | (function(foo) { 2268 | return foo; 2269 | })(); 2270 | 2271 | var myFunc; 2272 | myFunc = setTimeout(function() { 2273 | // myFunc is considered used 2274 | myFunc(); 2275 | }, 50); 2276 | 2277 | // Only the second argument from the descructured array is used. 2278 | function getY([, y]) { 2279 | return y; 2280 | } 2281 | ``` 2282 | **exported** 2283 | 2284 | 在 CommonJS 或者 ECMAScript 模块外部,可用 var创建一个被其他模块代码引用的变量。你也可以用 /* exported variableName */ 注释快表明此变量已导出,因此此变量不会被认为是未被使用过的。 2285 | 2286 | 需要注意的是 /* exported */ 在下列情况下是无效的: 2287 | 2288 | - node 或 commonjs 环境 2289 | - parserOptions.sourceType 是 module 2290 | - ecmaFeatures.globalReturn 为 true 2291 | 2292 | 行注释 // exported variableName 将不起作用,因为 exported 不是特定于行的。 2293 | 2294 | 选项 /* exported variableName */ 的 **正确** 代码示例: 2295 | ```js 2296 | /* exported global_var */ 2297 | 2298 | var global_var = 42; 2299 | ``` 2300 | **Options** 2301 | 2302 | 该规则接受一个字符串或者对像类型的参数。字符串设置正如同 vars 一样(如下所示)。 2303 | 2304 | 配置项的默认值,变量选项是 all,参数的选项是 after-used 。 2305 | ```js 2306 | { 2307 | "rules": { 2308 | "no-unused-vars": ["error", { "vars": "all", "args": "after-used", "ignoreRestSiblings": false }] 2309 | } 2310 | } 2311 | ``` 2312 | **vars** 2313 | 2314 | 此配置项有两个值: 2315 | 2316 | - all 检测所有变量,包括全局环境中的变量。这是默认值。 2317 | - local 仅仅检测本作用域中声明的变量是否使用,允许不使用全局环境中的变量。 2318 | 2319 | **vars: local** 2320 | 2321 | 选项 { "vars": "local" } 的 正确 代码示例: 2322 | ```js 2323 | /*eslint no-unused-vars: ["error", { "vars": "local" }]*/ 2324 | /*global some_unused_var */ 2325 | 2326 | some_unused_var = 42; 2327 | ``` 2328 | **varsIgnorePattern** 2329 | 2330 | 这个 varsIgnorePattern 选项指定了不需要检测的异常:变量名称匹配正则模式。例如,变量的名字包含 ignored 或者 Ignored。 2331 | 2332 | 选项 { "varsIgnorePattern": "[iI]gnored" } 的 **正确** 代码示例: 2333 | 2334 | ```js 2335 | /*eslint no-unused-vars: ["error", { "varsIgnorePattern": "[iI]gnored" }]*/ 2336 | 2337 | var firstVarIgnored = 1; 2338 | var secondVar = 2; 2339 | console.log(secondVar); 2340 | ``` 2341 | 2342 | **args** 2343 | 2344 | args 选项有三个值: 2345 | 2346 | - after-used - 最后一个参数必须使用。如:一个函数有两个参数,你使用了第二个参数,ESLint 不会报警告。 2347 | - all - 所有命名参数必须使用。 2348 | - none - 不检查参数。 2349 | 2350 | **args: after-used** 2351 | 2352 | 选项 { "args": "after-used" } 的 **错误** 代码示例: 2353 | ```js 2354 | /*eslint no-unused-vars: ["error", { "args": "after-used" }]*/ 2355 | 2356 | // 1 error 2357 | // "baz" is defined but never used 2358 | (function(foo, bar, baz) { 2359 | return bar; 2360 | })(); 2361 | ``` 2362 | 选项 { "args": "after-used" } 的 正确 代码示例: 2363 | ``` 2364 | /*eslint no-unused-vars: ["error", {"args": "after-used"}]*/ 2365 | 2366 | (function(foo, bar, baz) { 2367 | return baz; 2368 | })(); 2369 | ``` 2370 | **args: all** 2371 | 2372 | 选项 { "args": "all" } 的 错误 代码示例: 2373 | ```js 2374 | /*eslint no-unused-vars: ["error", { "args": "all" }]*/ 2375 | 2376 | // 2 errors 2377 | // "foo" is defined but never used 2378 | // "baz" is defined but never used 2379 | (function(foo, bar, baz) { 2380 | return bar; 2381 | })(); 2382 | ``` 2383 | **args: none** 2384 | 2385 | 选项 { "args": "none" } 的 正确 代码示例: 2386 | ```js 2387 | /*eslint no-unused-vars: ["error", { "args": "none" }]*/ 2388 | 2389 | (function(foo, bar, baz) { 2390 | return bar; 2391 | })(); 2392 | ``` 2393 | **ignoreRestSiblings** 2394 | 2395 | ignoreRestSiblings 选项是个布尔类型 (默认: false)。使用 Rest 属性 可能会“省略”对象中的属性,但是默认情况下,其兄弟属性被标记为 “unused”。使用该选项可以使 rest 属性的兄弟属性被忽略。 2396 | 2397 | 选项 { "ignoreRestSiblings": true } 的 **正确** 代码示例: 2398 | ```js 2399 | /*eslint no-unused-vars: ["error", { "ignoreRestSiblings": true }]*/ 2400 | // 'type' is ignored because it has a rest property sibling. 2401 | var { type, ...coords } = data; 2402 | ``` 2403 | **argsIgnorePattern** 2404 | 2405 | argsIgnorePattern 选项指定排除不需要检测:这些参数的名字符合正则匹配。例如,下划线开头的变量。 2406 | 2407 | 选项 { "argsIgnorePattern": "^_" } 的 **正确** 代码示例: 2408 | ```js 2409 | /*eslint no-unused-vars: ["error", { "argsIgnorePattern": "^_" }]*/ 2410 | 2411 | function foo(x, _y) { 2412 | return x + 1; 2413 | } 2414 | foo(); 2415 | ``` 2416 | **caughtErrors** 2417 | 2418 | caughtErrors 选项被用来验证 catch 块的参数。 2419 | 2420 | 它有两个设置: 2421 | 2422 | - none - 不检查错误对象。这是默认设置。 2423 | - all - 所有参数必须被使用。 2424 | 2425 | caughtErrors: none 2426 | 没有指定该规则,相当于将它赋值为 none。 2427 | 2428 | 选项 { "caughtErrors": "none" } 的 **正确** 代码示例: 2429 | ```js 2430 | /*eslint no-unused-vars: ["error", { "caughtErrors": "none" }]*/ 2431 | 2432 | try { 2433 | //... 2434 | } catch (err) { 2435 | console.error("errors"); 2436 | } 2437 | ``` 2438 | **caughtErrors: all** 2439 | 2440 | 选项 { "caughtErrors": "all" } 的 **错误** 代码示例: 2441 | ```js 2442 | /*eslint no-unused-vars: ["error", { "caughtErrors": "all" }]*/ 2443 | 2444 | // 1 error 2445 | // "err" is defined but never used 2446 | try { 2447 | //... 2448 | } catch (err) { 2449 | console.error("errors"); 2450 | } 2451 | ``` 2452 | **caughtErrorsIgnorePattern** 2453 | 2454 | caughtErrorsIgnorePattern 选项指定例外情况,不会检查匹配正则表达式 catch 参数。例如,名字以 ‘ignore’ 开头的变量。 2455 | 2456 | 选项 { "caughtErrorsIgnorePattern": "^ignore" } 的 正确 代码示例: 2457 | ```js 2458 | /*eslint no-unused-vars: ["error", { "caughtErrorsIgnorePattern": "^ignore" }]*/ 2459 | 2460 | try { 2461 | //... 2462 | } catch (ignoreErr) { 2463 | console.error("errors"); 2464 | } 2465 | ``` 2466 | 2467 | ### no-mixed-spaces-and-tabs 2468 | 2469 | > 禁止空格和 tab 的混合缩进 2470 | 2471 | **Rule Details** 2472 | 2473 | 该规则禁止使用 空格 和 tab 混合缩进。 2474 | 2475 | 2476 | **错误** 代码示例: 2477 | ```javascript 2478 | /*eslint no-mixed-spaces-and-tabs: "error"*/ 2479 | 2480 | function add(x, y) { 2481 | // --->..return x + y; 2482 | 2483 | return x + y; 2484 | } 2485 | 2486 | function main() { 2487 | // --->var x = 5, 2488 | // --->....y = 7; 2489 | 2490 | var x = 5, 2491 | y = 7; 2492 | } 2493 | ``` 2494 | **正确** 代码示例: 2495 | 2496 | ```js 2497 | /*eslint no-mixed-spaces-and-tabs: "error"*/ 2498 | 2499 | function add(x, y) { 2500 | // --->return x + y; 2501 | return x + y; 2502 | } 2503 | ``` 2504 | **Options** 2505 | 2506 | 该规则有一个字符串选项。 2507 | 2508 | - "smart-tabs" 当 tab 是为了对齐,允许混合使用空格和 tab。 2509 | 2510 | **smart-tabs** 2511 | 2512 | 选项 "smart-tabs" 的 正确 代码示例: 2513 | ```js 2514 | /*eslint no-mixed-spaces-and-tabs: ["error", "smart-tabs"]*/ 2515 | 2516 | function main() { 2517 | // --->var x = 5, 2518 | // --->....y = 7; 2519 | 2520 | var x = 5, 2521 | y = 7; 2522 | } 2523 | ``` 2524 | 2525 | ### constructor-super 2526 | 2527 | > 要求在构造函数中有 super() 的调用 2528 | 2529 | **Rule Details** 2530 | 2531 | 该规则旨在标记无效或缺失的 super() 调用。 2532 | 2533 | **错误** 代码示例: 2534 | ```javascript 2535 | /*eslint constructor-super: "error"*/ 2536 | /*eslint-env es6*/ 2537 | 2538 | class A { 2539 | constructor() { 2540 | super(); // This is a SyntaxError. 2541 | } 2542 | } 2543 | 2544 | class A extends B { 2545 | constructor() { } // Would throw a ReferenceError. 2546 | } 2547 | 2548 | // Classes which inherits from a non constructor are always problems. 2549 | class A extends null { 2550 | constructor() { 2551 | super(); // Would throw a TypeError. 2552 | } 2553 | } 2554 | 2555 | class A extends null { 2556 | constructor() { } // Would throw a ReferenceError. 2557 | } 2558 | ``` 2559 | **正确** 代码示例: 2560 | 2561 | ```js 2562 | /*eslint constructor-super: "error"*/ 2563 | /*eslint-env es6*/ 2564 | 2565 | class A { 2566 | constructor() { } 2567 | } 2568 | 2569 | class A extends B { 2570 | constructor() { 2571 | super(); 2572 | } 2573 | } 2574 | ``` 2575 | 2576 | 2577 | ### no-class-assign 2578 | 2579 | > 禁止修改类声明的变量 2580 | 2581 | **Rule Details** 2582 | 2583 | 该规则旨在标记类声明中变量的修改情况。 2584 | 2585 | 2586 | **错误** 代码示例: 2587 | ```javascript 2588 | /*eslint no-class-assign: "error"*/ 2589 | /*eslint-env es6*/ 2590 | 2591 | class A { } 2592 | A = 0; 2593 | ``` 2594 | ```javascript 2595 | /*eslint no-class-assign: "error"*/ 2596 | /*eslint-env es6*/ 2597 | 2598 | A = 0; 2599 | class A { } 2600 | ``` 2601 | ```javascript 2602 | /*eslint no-class-assign: "error"*/ 2603 | /*eslint-env es6*/ 2604 | 2605 | class A { 2606 | b() { 2607 | A = 0; 2608 | } 2609 | } 2610 | ``` 2611 | ```javascript 2612 | /*eslint no-class-assign: "error"*/ 2613 | /*eslint-env es6*/ 2614 | 2615 | let A = class A { 2616 | b() { 2617 | A = 0; 2618 | // `let A` is shadowed by the class name. 2619 | } 2620 | } 2621 | ``` 2622 | **正确** 代码示例: 2623 | 2624 | ```js 2625 | /*eslint no-class-assign: "error"*/ 2626 | /*eslint-env es6*/ 2627 | 2628 | let A = class A { } 2629 | A = 0; // A is a variable. 2630 | ``` 2631 | ```js 2632 | /*eslint no-class-assign: "error"*/ 2633 | /*eslint-env es6*/ 2634 | 2635 | let A = class { 2636 | b() { 2637 | A = 0; // A is a variable. 2638 | } 2639 | } 2640 | ``` 2641 | ```js 2642 | /*eslint no-class-assign: 2*/ 2643 | /*eslint-env es6*/ 2644 | 2645 | class A { 2646 | b(A) { 2647 | A = 0; // A is a parameter. 2648 | } 2649 | } 2650 | ``` 2651 | 2652 | 2653 | ### no-const-assign 2654 | 2655 | > 禁止修改 const 声明的变量 2656 | 2657 | **Rule Details** 2658 | 2659 | 该规则旨在标记修改用const关键字声明的变量。 2660 | 2661 | 2662 | **错误** 代码示例: 2663 | ```javascript 2664 | /*eslint no-const-assign: "error"*/ 2665 | /*eslint-env es6*/ 2666 | 2667 | const a = 0; 2668 | a = 1; 2669 | ``` 2670 | ```javascript 2671 | /*eslint no-const-assign: "error"*/ 2672 | /*eslint-env es6*/ 2673 | 2674 | const a = 0; 2675 | a += 1; 2676 | ``` 2677 | ```javascript 2678 | /*eslint no-const-assign: "error"*/ 2679 | /*eslint-env es6*/ 2680 | 2681 | const a = 0; 2682 | ++a; 2683 | ``` 2684 | **正确** 代码示例: 2685 | 2686 | ```js 2687 | /*eslint no-const-assign: "error"*/ 2688 | /*eslint-env es6*/ 2689 | 2690 | const a = 0; 2691 | console.log(a); 2692 | ``` 2693 | ```js 2694 | /*eslint no-const-assign: "error"*/ 2695 | /*eslint-env es6*/ 2696 | 2697 | for (const a in [1, 2, 3]) { // `a` is re-defined (not modified) on each loop step. 2698 | console.log(a); 2699 | } 2700 | ``` 2701 | ```js 2702 | /*eslint no-const-assign: "error"*/ 2703 | /*eslint-env es6*/ 2704 | 2705 | for (const a of [1, 2, 3]) { // `a` is re-defined (not modified) on each loop step. 2706 | console.log(a); 2707 | } 2708 | ``` 2709 | 2710 | 2711 | ### no-dupe-class-members 2712 | 2713 | > 禁止类成员中出现重复的名称 2714 | 2715 | **Rule Details** 2716 | 2717 | 该规则旨在标记类成员中重复名称的使用。 2718 | 2719 | 2720 | **错误** 代码示例: 2721 | ```javascript 2722 | /*eslint no-dupe-class-members: "error"*/ 2723 | /*eslint-env es6*/ 2724 | 2725 | class Foo { 2726 | bar() { } 2727 | bar() { } 2728 | } 2729 | 2730 | class Foo { 2731 | bar() { } 2732 | get bar() { } 2733 | } 2734 | 2735 | class Foo { 2736 | static bar() { } 2737 | static bar() { } 2738 | } 2739 | ``` 2740 | **正确** 代码示例: 2741 | 2742 | ```js 2743 | /*eslint no-dupe-class-members: "error"*/ 2744 | /*eslint-env es6*/ 2745 | 2746 | class Foo { 2747 | bar() { } 2748 | qux() { } 2749 | } 2750 | 2751 | class Foo { 2752 | get bar() { } 2753 | set bar(value) { } 2754 | } 2755 | 2756 | class Foo { 2757 | static bar() { } 2758 | bar() { } 2759 | } 2760 | ``` 2761 | 2762 | 2763 | ### no-new-symbol 2764 | 2765 | > 禁止 Symbolnew 操作符和 new 一起使用 2766 | 2767 | **Rule Details** 2768 | 2769 | 该规则旨在阻止使用 new 操作符调用 Symbol。 2770 | 2771 | 2772 | **错误** 代码示例: 2773 | ```javascript 2774 | /*eslint no-new-symbol: "error"*/ 2775 | /*eslint-env es6*/ 2776 | 2777 | var foo = new Symbol('foo'); 2778 | ``` 2779 | **正确** 代码示例: 2780 | 2781 | ```js 2782 | /*eslint no-new-symbol: "error"*/ 2783 | /*eslint-env es6*/ 2784 | 2785 | var foo = Symbol('foo'); 2786 | 2787 | 2788 | // Ignores shadowed Symbol. 2789 | function bar(Symbol) { 2790 | const baz = new Symbol("baz"); 2791 | } 2792 | ``` 2793 | 2794 | 2795 | ### no-this-before-super 2796 | 2797 | > 禁止在构造函数中,在调用 super() 之前使用 this 或 super 2798 | 2799 | **Rule Details** 2800 | 2801 | 该规则旨在标记出在调用 super() 之前使用 this 或 super 的情况。 2802 | 2803 | **错误** 代码示例: 2804 | ```javascript 2805 | /*eslint no-this-before-super: "error"*/ 2806 | /*eslint-env es6*/ 2807 | 2808 | class A extends B { 2809 | constructor() { 2810 | this.a = 0; 2811 | super(); 2812 | } 2813 | } 2814 | 2815 | class A extends B { 2816 | constructor() { 2817 | this.foo(); 2818 | super(); 2819 | } 2820 | } 2821 | 2822 | class A extends B { 2823 | constructor() { 2824 | super.foo(); 2825 | super(); 2826 | } 2827 | } 2828 | 2829 | class A extends B { 2830 | constructor() { 2831 | super(this.foo()); 2832 | } 2833 | } 2834 | ``` 2835 | **正确** 代码示例: 2836 | 2837 | ```js 2838 | /*eslint no-this-before-super: "error"*/ 2839 | /*eslint-env es6*/ 2840 | 2841 | class A { 2842 | constructor() { 2843 | this.a = 0; // OK, this class doesn't have an `extends` clause. 2844 | } 2845 | } 2846 | 2847 | class A extends B { 2848 | constructor() { 2849 | super(); 2850 | this.a = 0; // OK, this is after `super()`. 2851 | } 2852 | } 2853 | 2854 | class A extends B { 2855 | foo() { 2856 | this.a = 0; // OK. this is not in a constructor. 2857 | } 2858 | } 2859 | ``` 2860 | -------------------------------------------------------------------------------- /packages/ESLint_rules/unclutter.md: -------------------------------------------------------------------------------- 1 | # ESLint 补充 2 | 3 | ### no-duplicate-imports 4 | 5 | > 禁止重复模块导入 6 | 7 | **Rule Details** 8 | 9 | 该规则要求单个模块的所有的导入都在同一个 import 语句中。 10 | 11 | 12 | **错误** 代码示例: 13 | ``` 14 | /*eslint no-duplicate-imports: "error"*/ 15 | 16 | import { merge } from 'module'; 17 | import something from 'another-module'; 18 | import { find } from 'module'; 19 | ``` 20 | **正确** 代码示例: 21 | 22 | ``` 23 | /*eslint no-duplicate-imports: "error"*/ 24 | 25 | import { merge, find } from 'module'; 26 | import something from 'another-module'; 27 | ``` 28 | 29 | **Options** 30 | 31 | 该规则有一个对象选项,只有一个布尔属性 includeExports。默认为 false。 32 | 33 | 如果一个导入的模块又被导出,你应该把这些导入加到 import 语句中,然后直接导出,不要使用 export ... from。 34 | 35 | 选项 { "includeExports": true } 的 **错误** 代码示例: 36 | 37 | ``` 38 | /*eslint no-duplicate-imports: ["error", { "includeExports": true }]*/ 39 | 40 | import { merge } from 'module'; 41 | 42 | export { find } from 'module'; 43 | ``` 44 | 选项 { "includeExports": true } 的 **正确** 代码示例: 45 | 46 | ``` 47 | /*eslint no-duplicate-imports: ["error", { "includeExports": true }]*/ 48 | 49 | import { merge, find } from 'module'; 50 | 51 | export { find }; 52 | ``` 53 | 54 | 55 | ### no-useless-constructor 56 | 57 | > 禁用不必要的构造函数 58 | 59 | **Rule Details** 60 | 61 | 该规则标记可以被安全移除但又不改变类的行为的构造函数。 62 | 63 | 64 | **错误** 代码示例: 65 | ``` 66 | /*eslint no-useless-constructor: "error"*/ 67 | /*eslint-env es6*/ 68 | 69 | class A { 70 | constructor () { 71 | } 72 | } 73 | 74 | class A extends B { 75 | constructor (...args) { 76 | super(...args); 77 | } 78 | } 79 | ``` 80 | **正确** 代码示例: 81 | 82 | ``` 83 | /*eslint no-useless-constructor: "error"*/ 84 | 85 | class A { } 86 | 87 | class A { 88 | constructor () { 89 | doSomething(); 90 | } 91 | } 92 | 93 | class A extends B { 94 | constructor() { 95 | super('foo'); 96 | } 97 | } 98 | 99 | class A extends B { 100 | constructor() { 101 | super(); 102 | doSomething(); 103 | } 104 | } 105 | ``` 106 | 107 | ### no-var 108 | 109 | > 要求使用 let 或 const 而不是 var 110 | 111 | **Rule Details** 112 | 113 | 该规则旨在阻止 var 的使用,推荐使用 const 或 let。 114 | 115 | 116 | **错误** 代码示例: 117 | ``` 118 | /*eslint no-var: "error"*/ 119 | 120 | var x = "y"; 121 | var CONFIG = {}; 122 | ``` 123 | **正确** 代码示例: 124 | 125 | ``` 126 | /*eslint no-var: "error"*/ 127 | /*eslint-env es6*/ 128 | 129 | let x = "y"; 130 | const CONFIG = {}; 131 | ``` 132 | 133 | ### camelcase 134 | 135 | > 强制使用骆驼拼写法命名约定 136 | 137 | **Rule Details** 138 | 139 | 此规则在源码中查找下划线 (_)。它忽略前导和尾部的下划线,只检查在变量名称中间的下划线。如果 ESLint 判断定某个变量是个常量(全部大写),将不会发出警告。否则会发出警告。该规则仅仅标记定义和赋值,不适用于方法调用。在 ES6 import 语句中,该规则只针对将引入到本地模块作用域的变量名。 140 | 141 | **Options** 142 | 143 | 该规则有一个对象选项: 144 | 145 | - "properties": "always" (默认) 强制属性名称为驼峰风格 146 | - "properties": "never" 不检查属性名称 147 | 148 | **always** 149 | 150 | 默认选项 { "properties": "always" } 的**错误** 代码示例: 151 | ``` 152 | /*eslint camelcase: "error"*/ 153 | 154 | import { no_camelcased } from "external-module" 155 | 156 | var my_favorite_color = "#112C85"; 157 | 158 | function do_something() { 159 | // ... 160 | } 161 | 162 | obj.do_something = function() { 163 | // ... 164 | }; 165 | 166 | function foo({ no_camelcased }) { 167 | // ... 168 | }; 169 | 170 | function foo({ isCamelcased: no_camelcased }) { 171 | // ... 172 | } 173 | 174 | function foo({ no_camelcased = 'default value' }) { 175 | // ... 176 | }; 177 | 178 | var obj = { 179 | my_pref: 1 180 | }; 181 | 182 | var { category_id = 1 } = query; 183 | 184 | var { foo: no_camelcased } = bar; 185 | 186 | var { foo: bar_baz = 1 } = quz; 187 | ``` 188 | 默认选项 { "properties": "always" } 的 **正确** 代码示例: 189 | 190 | ``` 191 | /*eslint camelcase: "error"*/ 192 | 193 | import { no_camelcased as camelCased } from "external-module"; 194 | 195 | var myFavoriteColor = "#112C85"; 196 | var _myFavoriteColor = "#112C85"; 197 | var myFavoriteColor_ = "#112C85"; 198 | var MY_FAVORITE_COLOR = "#112C85"; 199 | var foo = bar.baz_boom; 200 | var foo = { qux: bar.baz_boom }; 201 | 202 | obj.do_something(); 203 | do_something(); 204 | new do_something(); 205 | 206 | var { category_id: category } = query; 207 | 208 | function foo({ isCamelCased }) { 209 | // ... 210 | }; 211 | 212 | function foo({ isCamelCased: isAlsoCamelCased }) { 213 | // ... 214 | } 215 | 216 | function foo({ isCamelCased = 'default value' }) { 217 | // ... 218 | }; 219 | 220 | var { categoryId = 1 } = query; 221 | 222 | var { foo: isCamelCased } = bar; 223 | 224 | var { foo: isCamelCased = 1 } = quz; 225 | 226 | ``` 227 | 228 | **never** 229 | 230 | 选项 { "properties": "never" } 的 **正确** 代码示例: 231 | 232 | ``` 233 | /*eslint camelcase: ["error", {properties: "never"}]*/ 234 | 235 | var obj = { 236 | my_pref: 1 237 | }; 238 | ``` 239 | 240 | ### comma-dangle 241 | 242 | > 要求或禁止末尾逗号 243 | 244 | **Rule Details** 245 | 246 | 这个规则强制在对象和数组字面量中使用一致的拖尾逗号。 247 | 248 | **Options** 249 | 250 | 该规则有一个字符串选项或一个对象选项: 251 | 252 | ``` 253 | { 254 | "comma-dangle": ["error", "never"], 255 | // or 256 | "comma-dangle": ["error", { 257 | "arrays": "never", 258 | "objects": "never", 259 | "imports": "never", 260 | "exports": "never", 261 | "functions": "ignore" 262 | }] 263 | } 264 | ``` 265 | 266 | - "never" (默认) 禁用拖尾逗号 267 | - "always" 要求使用拖尾逗号 268 | - "always-multiline" 当最后一个元素或属性与闭括号 ] 或 } 在 不同的行时,要求使用拖尾逗- 号;当在 同一行时,禁止使用拖尾逗号。 269 | - "only-multiline" 当最后一个元素或属性与闭括号 ] 或 } 在 不同的行时,允许(但不要求)- 使用拖尾逗号;当在 同一行时,禁止使用拖尾逗号。 270 | 271 | 从ECMAScript 2017开始,拖尾逗号在函数声明和函数调用中是有效的语法;然而,字符串选项不会检查这种情况以向后兼容。 272 | 273 | 你也可以使用一个对象选项针对每种类型的语法来配置该规则规则。 274 | 275 | 以下每个选项可以设置为 "never"、"always"、"always-multiline"、"only-multiline" 或 "ignore"。 276 | 277 | 每个选项默认为 "never",除非额外指定。 278 | 279 | - arrays 针对数组字面量和解构赋值的数组模式。(比如 let [a,] = [1,];) 280 | - objects 针对对象字面量和解构赋值的对象模式。(比如 let {a,} = {a: 1};) 281 | - imports 针对 ES 模块的 import 声明。 (比如 import {a,} from "foo";) 282 | - exports 针对 ES 模块的 export 声明。 (比如 export {a,};) 283 | - functions 针对函数声明和函数调用。 (比如 (function(a,){ })(b,);) 284 | 285 | functions 默认设置为 "ignore" 以与字符串选项保持一致。 286 | 287 | **never** 288 | 289 | 默认选项 "never" 的 **错误** 代码示例: 290 | ``` 291 | /*eslint comma-dangle: ["error", "never"]*/ 292 | 293 | var foo = { 294 | bar: "baz", 295 | qux: "quux", 296 | }; 297 | 298 | var arr = [1,2,]; 299 | 300 | foo({ 301 | bar: "baz", 302 | qux: "quux", 303 | }); 304 | ``` 305 | 默认选项 "never" 的 **正确** 代码示例: 306 | ``` 307 | /*eslint comma-dangle: ["error", "never"]*/ 308 | 309 | var foo = { 310 | bar: "baz", 311 | qux: "quux" 312 | }; 313 | 314 | var arr = [1,2]; 315 | 316 | foo({ 317 | bar: "baz", 318 | qux: "quux" 319 | }); 320 | ``` 321 | **always** 322 | 323 | 选项 "always" 的 **错误** 代码示例: 324 | ``` 325 | /*eslint comma-dangle: ["error", "always"]*/ 326 | 327 | var foo = { 328 | bar: "baz", 329 | qux: "quux" 330 | }; 331 | 332 | var arr = [1,2]; 333 | 334 | foo({ 335 | bar: "baz", 336 | qux: "quux" 337 | }); 338 | ``` 339 | 选项 "always" 的 **正确** 代码示例: 340 | 341 | ``` 342 | 343 | /*eslint comma-dangle: ["error", "always"]*/ 344 | 345 | var foo = { 346 | bar: "baz", 347 | qux: "quux", 348 | }; 349 | 350 | var arr = [1,2,]; 351 | 352 | foo({ 353 | bar: "baz", 354 | qux: "quux", 355 | }); 356 | ``` 357 | **always-multiline** 358 | 359 | 选项 "always-multiline" 的 **错误** 代码示例: 360 | ``` 361 | /*eslint comma-dangle: ["error", "always-multiline"]*/ 362 | 363 | var foo = { 364 | bar: "baz", 365 | qux: "quux" 366 | }; 367 | 368 | var foo = { bar: "baz", qux: "quux", }; 369 | 370 | var arr = [1,2,]; 371 | 372 | var arr = [1, 373 | 2,]; 374 | 375 | var arr = [ 376 | 1, 377 | 2 378 | ]; 379 | 380 | foo({ 381 | bar: "baz", 382 | qux: "quux" 383 | }); 384 | ``` 385 | 选项 "always-multiline" 的 **正确** 代码示例: 386 | 387 | ``` 388 | /*eslint comma-dangle: ["error", "always-multiline"]*/ 389 | 390 | var foo = { 391 | bar: "baz", 392 | qux: "quux", 393 | }; 394 | 395 | var foo = {bar: "baz", qux: "quux"}; 396 | var arr = [1,2]; 397 | 398 | var arr = [1, 399 | 2]; 400 | 401 | var arr = [ 402 | 1, 403 | 2, 404 | ]; 405 | 406 | foo({ 407 | bar: "baz", 408 | qux: "quux", 409 | }); 410 | ``` 411 | **only-multiline** 412 | 413 | 选项 "only-multiline" 的 **错误** 代码示例: 414 | 415 | ``` 416 | /*eslint comma-dangle: ["error", "only-multiline"]*/ 417 | 418 | var foo = { bar: "baz", qux: "quux", }; 419 | 420 | var arr = [1,2,]; 421 | 422 | var arr = [1, 423 | 2,]; 424 | ``` 425 | 选项 "only-multiline" 的 **正确** 代码示例: 426 | ``` 427 | /*eslint comma-dangle: ["error", "only-multiline"]*/ 428 | 429 | var foo = { 430 | bar: "baz", 431 | qux: "quux", 432 | }; 433 | 434 | var foo = { 435 | bar: "baz", 436 | qux: "quux" 437 | }; 438 | 439 | var foo = {bar: "baz", qux: "quux"}; 440 | var arr = [1,2]; 441 | 442 | var arr = [1, 443 | 2]; 444 | 445 | var arr = [ 446 | 1, 447 | 2, 448 | ]; 449 | 450 | var arr = [ 451 | 1, 452 | 2 453 | ]; 454 | 455 | foo({ 456 | bar: "baz", 457 | qux: "quux", 458 | }); 459 | 460 | foo({ 461 | bar: "baz", 462 | qux: "quux" 463 | }); 464 | ``` 465 | **functions** 466 | 467 | 选项 {"functions": "never"} 的 **错误** 代码示例: 468 | ``` 469 | /*eslint comma-dangle: ["error", {"functions": "never"}]*/ 470 | 471 | function foo(a, b,) { 472 | } 473 | 474 | foo(a, b,); 475 | new foo(a, b,); 476 | ``` 477 | 选项 {"functions": "never"} 的 **正确** 代码示例: 478 | ``` 479 | 480 | /*eslint comma-dangle: ["error", {"functions": "never"}]*/ 481 | 482 | function foo(a, b) { 483 | } 484 | 485 | foo(a, b); 486 | new foo(a, b); 487 | ``` 488 | 选项 {"functions": "always"} 的 **错误** 代码示例: 489 | ``` 490 | 491 | /*eslint comma-dangle: ["error", {"functions": "always"}]*/ 492 | 493 | function foo(a, b) { 494 | } 495 | 496 | foo(a, b); 497 | new foo(a, b); 498 | ``` 499 | 选项 {"functions": "always"} 的 **正确** 代码示例: 500 | ``` 501 | 502 | /*eslint comma-dangle: ["error", {"functions": "always"}]*/ 503 | 504 | function foo(a, b,) { 505 | } 506 | 507 | foo(a, b,); 508 | new foo(a, b,); 509 | ``` 510 | 511 | ### computed-property-spacing 512 | 513 | > 强制在计算的属性的方括号中使用一致的空格 514 | 515 | **Rule Details** 516 | 517 | 该规则旨在保持计算属性内空格的一致性。 518 | 519 | 它要求或禁止括号和其内部值之间的空格。括号内相邻的值出现折行的情况,不适用于此规则。 520 | 521 | 522 | **Options** 523 | 524 | 该规则有一个字符串选项: 525 | 526 | - "never" (默认) 禁止在计算属性内使用空格 527 | - "always" 要求在计算属性内使用一个或多个空格 528 | **never** 529 | 530 | 默认选项 "never" 的 **错误** 代码示例: 531 | ``` 532 | /*eslint computed-property-spacing: ["error", "never"]*/ 533 | /*eslint-env es6*/ 534 | 535 | obj[foo ] 536 | obj[ 'foo'] 537 | var x = {[ b ]: a} 538 | obj[foo[ bar ]] 539 | ``` 540 | 默认选项 "never" 的 **正确** 代码示例: 541 | ``` 542 | /*eslint computed-property-spacing: ["error", "never"]*/ 543 | /*eslint-env es6*/ 544 | 545 | obj[foo] 546 | obj['foo'] 547 | var x = {[b]: a} 548 | obj[foo[bar]] 549 | ``` 550 | **always** 551 | 552 | 选项 "always" 的 **错误** 代码示例: 553 | ``` 554 | /*eslint computed-property-spacing: ["error", "always"]*/ 555 | /*eslint-env es6*/ 556 | 557 | obj[foo] 558 | var x = {[b]: a} 559 | obj[ foo] 560 | obj['foo' ] 561 | obj[foo[ bar ]] 562 | var x = {[ b]: a} 563 | ``` 564 | 选项 "always" 的 **正确** 代码示例: 565 | ``` 566 | /*eslint computed-property-spacing: ["error", "always"]*/ 567 | /*eslint-env es6*/ 568 | 569 | obj[ foo ] 570 | obj[ 'foo' ] 571 | var x = {[ b ]: a} 572 | obj[ foo[ bar ] ] 573 | ``` 574 | 575 | ### consistent-this 576 | 577 | > 当获取当前执行环境的上下文时,强制使用一致的命名 578 | 579 | **Rule Details** 580 | 581 | 该规则指定一个变量作为 this 的别名。它将强制两件事情: 582 | 583 | - 如果一个变量声明为一个指定的名称,它 必须 初始化(在声明语句中)或被赋值(与声明语句在同一范围内)为 this。 584 | - 如果一个变量初始化或被赋值为 this,那么该变量 必须 是指定的别名。 585 | 586 | 587 | **Options** 588 | 589 | 该规则有一个到两个字符串选项: 590 | 591 | - 为 this 指定别名 (默认 "that") 592 | 593 | 594 | 默认选项 "that" 的 **错误** 代码示例: 595 | ``` 596 | /*eslint consistent-this: ["error", "that"]*/ 597 | 598 | var that = 42; 599 | 600 | var self = this; 601 | 602 | that = 42; 603 | 604 | self = this; 605 | ``` 606 | 默认选项 "that" 的 **正确** 代码示例: 607 | ``` 608 | /*eslint consistent-this: ["error", "that"]*/ 609 | 610 | var that = this; 611 | 612 | var self = 42; 613 | 614 | var self; 615 | 616 | that = this; 617 | 618 | foo.bar = this; 619 | ``` 620 | 如果指定的变量没有初始化,默认选项 "that" 的 **错误** 代码示例: 621 | ``` 622 | /*eslint consistent-this: ["error", "that"]*/ 623 | 624 | var that; 625 | function f() { 626 | that = this; 627 | } 628 | ``` 629 | 如果指定的变量没有初始化,默认选项 "that" 的 **正确** 代码示例: 630 | ``` 631 | /*eslint consistent-this: ["error", "that"]*/ 632 | 633 | var that; 634 | that = this; 635 | 636 | var foo, that; 637 | foo = 42; 638 | that = this; 639 | ``` 640 | 641 | ### func-call-spacing 642 | 643 | > 要求或禁止在函数标识符和其调用之间有空格 644 | 645 | **Rule Details** 646 | 647 | 该规则要求或禁止在函数名和开括号之间有空格。 648 | 649 | **options** 650 | 651 | 该规则有一个字符串选项: 652 | 653 | - "never" (默认) 禁止在函数名和开括号之间有空格 654 | - "always" 要求在函数名和开括号之间有空格 655 | 656 | 657 | 未来,在 "always" 模式中,可以有第二个选项,是个对象,包含一个布尔类型的 allowNewlines 属性。 658 | 659 | **never** 660 | 661 | 默认选项 "never" 的 **错误** 代码示例: 662 | ``` 663 | /*eslint func-call-spacing: ["error", "never"]*/ 664 | 665 | fn (); 666 | 667 | fn 668 | (); 669 | ``` 670 | 默认选项 "never" 的 **正确** 代码示例: 671 | ``` 672 | /*eslint func-call-spacing: ["error", "never"]*/ 673 | 674 | fn(); 675 | ``` 676 | **always** 677 | 678 | 选项 "always" 的 **错误** 代码示例: 679 | ``` 680 | /*eslint func-call-spacing: ["error", "always"]*/ 681 | 682 | fn(); 683 | 684 | fn 685 | (); 686 | ``` 687 | 选项 "always" 的 **正确** 代码示例: 688 | ``` 689 | /*eslint func-call-spacing: ["error", "always"]*/ 690 | 691 | fn (); 692 | ``` 693 | **allowNewlines** 694 | 695 | 默认情况下,"always" 不允许换行。在 "always" 模式中,设置 allowNewlines 选项为 true 来允许换行。换行从来就不是必须的。 696 | 697 | 选项 { "allowNewlines": true } 的 **错误** 代码示例: 698 | ``` 699 | /*eslint func-call-spacing: ["error", "always", { "allowNewlines": true }]*/ 700 | 701 | fn(); 702 | ``` 703 | 选项 { "allowNewlines": true } 的 **正确** 代码示例: 704 | ``` 705 | /*eslint func-call-spacing: ["error", "always", { "allowNewlines": true }]*/ 706 | 707 | fn (); // Newlines are never required. 708 | 709 | fn 710 | (); 711 | ``` 712 | ### indent 713 | 714 | > 强制使用一致的缩进 715 | 716 | **Rule Details** 717 | 718 | 该规则旨在强制使用一致的缩进风格。默认是 4个空格。 719 | 720 | **Options** 721 | 722 | 该规则有一个混合选项: 723 | 724 | 例如,2 个空格缩进: 725 | ``` 726 | { 727 | "indent": ["error", 2] 728 | } 729 | ``` 730 | 或 tab 缩进: 731 | ``` 732 | { 733 | "indent": ["error", "tab"] 734 | } 735 | ``` 736 | 默认选项的 错误 代码示例: 737 | ``` 738 | /*eslint indent: "error"*/ 739 | 740 | if (a) { 741 | b=c; 742 | function foo(d) { 743 | e=f; 744 | } 745 | } 746 | ``` 747 | 默认选项的 正确 代码示例: 748 | ``` 749 | /*eslint indent: "error"*/ 750 | 751 | if (a) { 752 | b=c; 753 | function foo(d) { 754 | e=f; 755 | } 756 | } 757 | ``` 758 | 该规则有一个对象选项: 759 | 760 | - "SwitchCase" (默认:0) 强制 switch 语句中的 case 子句的缩进级别 761 | - "VariableDeclarator" (默认:1) 强制 var 声明的缩进级别;也可以使用一个对象为 var、let 和 const 声明分别定义。 762 | - "outerIIFEBody" (默认: 1) 强制文件级别的 IIFE 的缩进 763 | - "MemberExpression" (默认: 1) 强制多行属性链的缩进 (除了在变量声明和赋值语句中)也可以设置为 "off" 以禁止检查成员表达式的缩进。 764 | - "FunctionDeclaration" 使用一个对象定义函数声明的缩进规则。 765 | - parameters (默认: 1) 强制函数声明中参数的缩进。可以是一个数字来表示缩进级别,或字符串 "first" 表示声明中的所有参数必须与第一个参数对齐。也可以设置为 "off" 以禁止检查函数声明的参数的缩进。 766 | - body (默认: 1) 强制函数声明的函数体的缩进级别。 767 | - "FunctionExpression" 使用一个对象定义函数表达式的缩进规则。 768 | - parameters (默认: 1) 强制函数表达式中参数的缩进。可以是一个数字来表示缩进级别,或字符串 "first" 表示表达式中的所有参数必须与第一个参数对齐。也可以设置为 "off" 以禁止检查函数表达式的参数的缩进。 769 | - body (默认: 1) 强制函数表达式的函数体的缩进级别。 770 | - "CallExpression" 使用一个对象定义函数调用表达式的缩进规则。 771 | - arguments (默认: 1) 强制函数调用表达式中参数的缩进。可以是一个数字来表示缩进级别,或字符串 "first" 表示表达式中的所有参数必须先与第一个参数对齐。也可以设置为 "off" 以禁止检查函数调用的参数的缩进。 772 | - "ArrayExpression" (默认: 1) 强制数组中的元素的缩进。可以是一个数字来表示缩进级别,或字符串 "first" 表示数组中的所有元素必须与第一个元素对齐。也可以设置为 "off" 以禁止检查数组元素的缩进。 773 | - "ObjectExpression" (默认: 1) 强制对象中的属性的缩进。可以是一个数字来表示缩进级别,或字符串 "first" 表示对象中的所有属性必须与第一个属性对齐。也可以设置为 "off" 以禁止检查对象属性的缩进。 774 | - "ImportDeclaration" (默认: 1) 强制 import 语句的缩进。可以设置为 "first",表示从一个模块中导入的成员要与第一个成员对齐。也可以设置为 "off" 以禁止检查导入的模块成员的缩进。 775 | - "flatTernaryExpressions": true (默认 false) 要求三元表达式内的三元表达式不能有缩进。 776 | - "ignoredNodes" 接受一组 selectors。如果任何选择器匹配了一个 AST 节点,其子节点的 token 的缩进将被忽略。如果你不同意它为特定的语法模式强制执行缩进,可以将此选项作为规避该规则的选项。 777 | - "ignoreComments" (默认: false) 当主食不需要与前一行或下一行的注释对齐,可以使用此选项。 778 | 779 | 780 | 缩进级别表示指定的多个缩进。例如: 781 | 782 | - 如果缩进设置为 4 个空格,VariableDeclarator 设置为 2,多行变量声明将会缩进 8 个空格。 783 | - 如果缩进设置为 2 个空格,VariableDeclarator 设置为 2,多行变量声明将会缩进 4 个空格。 784 | - 如果缩进设置为 2 个空格,VariableDeclarator 设置为 {"var": 2, "let": 2, "const": 3},多行变量声明将会分别为 var 和 let 语句缩进 4 个空格,const 语句缩进 6 个空格语句。 785 | - 如果缩进设置为 tab 缩进,VariableDeclarator 设置为 2,多行变量声明将会缩进 2 个 tab。 786 | - 如果缩进设置为 2 个空格,SwitchCase 设置为 0,case将不会缩进。 787 | - 如果缩进设置为 2 个空格,SwitchCase 设置为 1,case 子句将相对于 switch 语句缩进 2 个空格。 788 | - 如果缩进设置为 2 个空格,SwitchCase 设置为 2,case 子句将相对于 switch 语句缩进 4 个空格。 789 | - 如果缩进设置为 tab 缩进,SwitchCase 设置为 2,case 子句将相对于 switch 语句缩进 2 个 tab。 790 | - 如果缩进设置为 2 个空格, MemberExpression 设置为 0,多行属性将不对缩进。 791 | - 如果缩进设置为 2 个空格, MemberExpression 设置为 1,多行属性将缩进 2 个空格。 792 | - 如果缩进设置为 2 个空格, MemberExpression 设置为 2,多行属性将缩进 4 个空格。 793 | - 如果缩进设置为 4 个空格, MemberExpression 设置为 0,多行属性将不会缩进。 794 | - 如果缩进设置为 4 个空格, MemberExpression 设置为 1,多行属性将将缩进 4 个空格。 795 | - 如果缩进设置为 4 个空格, MemberExpression 设置为 2,多行属性将将缩进 8 个空格。 796 | 797 | 798 | **tab** 799 | 800 | 选项 "tab" 的 **错误** 代码示例: 801 | ``` 802 | /*eslint indent: ["error", "tab"]*/ 803 | 804 | if (a) { 805 | b=c; 806 | function foo(d) { 807 | e=f; 808 | } 809 | } 810 | ``` 811 | 选项 "tab" 的 **正确** 代码示例: 812 | ``` 813 | /*eslint indent: ["error", "tab"]*/ 814 | 815 | if (a) { 816 | /*tab*/b=c; 817 | /*tab*/function foo(d) { 818 | /*tab*//*tab*/e=f; 819 | /*tab*/} 820 | } 821 | ``` 822 | **SwitchCase** 823 | 824 | 选项 2, { "SwitchCase": 1 } 的 **错误** 代码示例: 825 | ``` 826 | /*eslint indent: ["error", 2, { "SwitchCase": 1 }]*/ 827 | 828 | switch(a){ 829 | case "a": 830 | break; 831 | case "b": 832 | break; 833 | } 834 | ``` 835 | 选项 2, { "SwitchCase": 1 } 的 **正确** 代码示例: 836 | ``` 837 | /*eslint indent: ["error", 2, { "SwitchCase": 1 }]*/ 838 | 839 | switch(a){ 840 | case "a": 841 | break; 842 | case "b": 843 | break; 844 | } 845 | ``` 846 | **VariableDeclarator** 847 | 848 | 选项 2, { "VariableDeclarator": 1 } 的 **错误** 代码示例: 849 | ``` 850 | /*eslint indent: ["error", 2, { "VariableDeclarator": 1 }]*/ 851 | /*eslint-env es6*/ 852 | 853 | var a, 854 | b, 855 | c; 856 | let a, 857 | b, 858 | c; 859 | const a = 1, 860 | b = 2, 861 | c = 3; 862 | ``` 863 | 选项 2, { "VariableDeclarator": 1 } 的 **正确** 代码示例: 864 | ``` 865 | /*eslint indent: ["error", 2, { "VariableDeclarator": 1 }]*/ 866 | /*eslint-env es6*/ 867 | 868 | var a, 869 | b, 870 | c; 871 | let a, 872 | b, 873 | c; 874 | const a = 1, 875 | b = 2, 876 | c = 3; 877 | ``` 878 | 选项 2, { "VariableDeclarator": 2 } 的 **正确** 代码示例: 879 | ``` 880 | /*eslint indent: ["error", 2, { "VariableDeclarator": 2 }]*/ 881 | /*eslint-env es6*/ 882 | 883 | var a, 884 | b, 885 | c; 886 | let a, 887 | b, 888 | c; 889 | const a = 1, 890 | b = 2, 891 | c = 3; 892 | ``` 893 | 选项 2, { "VariableDeclarator": { "var": 2, "let": 2, "const": 3 } } 的 **正确** 代码示例: 894 | ``` 895 | /*eslint indent: ["error", 2, { "VariableDeclarator": { "var": 2, "let": 2, "const": 3 } }]*/ 896 | /*eslint-env es6*/ 897 | 898 | var a, 899 | b, 900 | c; 901 | let a, 902 | b, 903 | c; 904 | const a = 1, 905 | b = 2, 906 | c = 3; 907 | ``` 908 | **outerIIFEBody** 909 | 910 | 选项 2, { "outerIIFEBody": 0 } 的 **错误** 代码示例: 911 | ``` 912 | /*eslint indent: ["error", 2, { "outerIIFEBody": 0 }]*/ 913 | 914 | (function() { 915 | 916 | function foo(x) { 917 | return x + 1; 918 | } 919 | 920 | })(); 921 | 922 | 923 | if(y) { 924 | console.log('foo'); 925 | } 926 | ``` 927 | 选项 2, {"outerIIFEBody": 0} 的 **正确** 代码示例: 928 | ``` 929 | /*eslint indent: ["error", 2, { "outerIIFEBody": 0 }]*/ 930 | 931 | (function() { 932 | 933 | function foo(x) { 934 | return x + 1; 935 | } 936 | 937 | })(); 938 | 939 | 940 | if(y) { 941 | console.log('foo'); 942 | } 943 | ``` 944 | **MemberExpression** 945 | ``` 946 | 选项 2, { "MemberExpression": 1 } 的 **错误** 代码示例: 947 | 948 | /*eslint indent: ["error", 2, { "MemberExpression": 1 }]*/ 949 | 950 | foo 951 | .bar 952 | .baz() 953 | ``` 954 | 选项 2, { "MemberExpression": 1 } 的 **正确** 代码示例: 955 | ``` 956 | /*eslint indent: ["error", 2, { "MemberExpression": 1 }]*/ 957 | 958 | foo 959 | .bar 960 | .baz(); 961 | 962 | // Any indentation is permitted in variable declarations and assignments. 963 | var bip = aardvark.badger 964 | .coyote; 965 | ``` 966 | **FunctionDeclaration** 967 | 968 | 选项 2, { "FunctionDeclaration": {"body": 1, "parameters": 2} } 的 **错误** 代码示例: 969 | ``` 970 | /*eslint indent: ["error", 2, { "FunctionDeclaration": {"body": 1, "parameters": 2} }]*/ 971 | 972 | function foo(bar, 973 | baz, 974 | qux) { 975 | qux(); 976 | } 977 | ``` 978 | 选项 2, { "FunctionDeclaration": {"body": 1, "parameters": 2} } 的 **正确** 代码示例: 979 | ``` 980 | /*eslint indent: ["error", 2, { "FunctionDeclaration": {"body": 1, "parameters": 2} }]*/ 981 | 982 | function foo(bar, 983 | baz, 984 | qux) { 985 | qux(); 986 | } 987 | ``` 988 | 选项 2, { "FunctionDeclaration": {"parameters": "first"} } 的 **错误** 代码示例: 989 | ``` 990 | /*eslint indent: ["error", 2, {"FunctionDeclaration": {"parameters": "first"}}]*/ 991 | 992 | function foo(bar, baz, 993 | qux, boop) { 994 | qux(); 995 | } 996 | ``` 997 | 选项 2, { "FunctionDeclaration": {"parameters": "first"} } 的 **正确** 代码示例: 998 | ``` 999 | /*eslint indent: ["error", 2, {"FunctionDeclaration": {"parameters": "first"}}]*/ 1000 | 1001 | function foo(bar, baz, 1002 | qux, boop) { 1003 | qux(); 1004 | } 1005 | ``` 1006 | **FunctionExpression** 1007 | 1008 | 选项 2, { "FunctionExpression": {"body": 1, "parameters": 2} } 的 **错误** 代码示例: 1009 | ``` 1010 | /*eslint indent: ["error", 2, { "FunctionExpression": {"body": 1, "parameters": 2} }]*/ 1011 | 1012 | var foo = function(bar, 1013 | baz, 1014 | qux) { 1015 | qux(); 1016 | } 1017 | ``` 1018 | 选项 2, { "FunctionExpression": {"body": 1, "parameters": 2} } 的 **正确** 代码示例: 1019 | ``` 1020 | /*eslint indent: ["error", 2, { "FunctionExpression": {"body": 1, "parameters": 2} }]*/ 1021 | 1022 | var foo = function(bar, 1023 | baz, 1024 | qux) { 1025 | qux(); 1026 | } 1027 | ``` 1028 | 选项 2, { "FunctionExpression": {"parameters": "first"} } 的 **错误** 代码示例: 1029 | ``` 1030 | /*eslint indent: ["error", 2, {"FunctionExpression": {"parameters": "first"}}]*/ 1031 | 1032 | var foo = function(bar, baz, 1033 | qux, boop) { 1034 | qux(); 1035 | } 1036 | ``` 1037 | 选项 2, { "FunctionExpression": {"parameters": "first"} } 的 **正确** 代码示例: 1038 | ``` 1039 | /*eslint indent: ["error", 2, {"FunctionExpression": {"parameters": "first"}}]*/ 1040 | 1041 | var foo = function(bar, baz, 1042 | qux, boop) { 1043 | qux(); 1044 | } 1045 | ``` 1046 | **CallExpression** 1047 | 1048 | 选项 2, { "CallExpression": {"arguments": 1} } 的 错误 代码示例: 1049 | ``` 1050 | /*eslint indent: ["error", 2, { "CallExpression": {"arguments": 1} }]*/ 1051 | 1052 | foo(bar, 1053 | baz, 1054 | qux 1055 | ); 1056 | ``` 1057 | 选项 2, { "CallExpression": {"arguments": 1} } 的 **正确** 代码示例: 1058 | ``` 1059 | /*eslint indent: ["error", 2, { "CallExpression": {"arguments": 1} }]*/ 1060 | 1061 | foo(bar, 1062 | baz, 1063 | qux 1064 | ); 1065 | ``` 1066 | 选项 2, { "CallExpression": {"arguments": "first"} } 的 **错误** 代码示例: 1067 | ``` 1068 | /*eslint indent: ["error", 2, {"CallExpression": {"arguments": "first"}}]*/ 1069 | 1070 | foo(bar, baz, 1071 | baz, boop, beep); 1072 | ``` 1073 | 选项 2, { "CallExpression": {"arguments": "first"} } 的 **正确** 代码示例: 1074 | ``` 1075 | /*eslint indent: ["error", 2, {"CallExpression": {"arguments": "first"}}]*/ 1076 | 1077 | foo(bar, baz, 1078 | baz, boop, beep); 1079 | ``` 1080 | **ArrayExpression** 1081 | 1082 | 选项 2, { "ArrayExpression": 1 } 的 **错误** 代码示例: 1083 | ``` 1084 | /*eslint indent: ["error", 2, { "ArrayExpression": 1 }]*/ 1085 | 1086 | var foo = [ 1087 | bar, 1088 | baz, 1089 | qux 1090 | ]; 1091 | ``` 1092 | 选项 2, { "ArrayExpression": 1 } 的 **正确** 代码示例: 1093 | ``` 1094 | /*eslint indent: ["error", 2, { "ArrayExpression": 1 }]*/ 1095 | 1096 | var foo = [ 1097 | bar, 1098 | baz, 1099 | qux 1100 | ]; 1101 | ``` 1102 | 选项 2, { "ArrayExpression": "first" } 的 **错误** 代码示例: 1103 | ``` 1104 | /*eslint indent: ["error", 2, {"ArrayExpression": "first"}]*/ 1105 | 1106 | var foo = [bar, 1107 | baz, 1108 | qux 1109 | ]; 1110 | ``` 1111 | 选项 2, { "ArrayExpression": "first" } 的 **正确** 代码示例: 1112 | ``` 1113 | /*eslint indent: ["error", 2, {"ArrayExpression": "first"}]*/ 1114 | 1115 | var foo = [bar, 1116 | baz, 1117 | qux 1118 | ]; 1119 | ``` 1120 | **ObjectExpression** 1121 | 1122 | 选项 2, { "ObjectExpression": 1 } 的 **错误** 代码示例: 1123 | ``` 1124 | /*eslint indent: ["error", 2, { "ObjectExpression": 1 }]*/ 1125 | 1126 | var foo = { 1127 | bar: 1, 1128 | baz: 2, 1129 | qux: 3 1130 | }; 1131 | ``` 1132 | 选项 2, { "ObjectExpression": 1 } 的 **正确** 代码示例: 1133 | ``` 1134 | /*eslint indent: ["error", 2, { "ObjectExpression": 1 }]*/ 1135 | 1136 | var foo = { 1137 | bar: 1, 1138 | baz: 2, 1139 | qux: 3 1140 | }; 1141 | ``` 1142 | 选项 2, { "ObjectExpression": "first" } 的 **错误** 代码示例: 1143 | ``` 1144 | /*eslint indent: ["error", 2, {"ObjectExpression": "first"}]*/ 1145 | 1146 | var foo = { bar: 1, 1147 | baz: 2 }; 1148 | ``` 1149 | 选项 2, { "ObjectExpression": "first" } 的 **正确** 代码示例: 1150 | ``` 1151 | /*eslint indent: ["error", 2, {"ObjectExpression": "first"}]*/ 1152 | 1153 | var foo = { bar: 1, 1154 | baz: 2 }; 1155 | ``` 1156 | **ImportDeclaration** 1157 | ``` 1158 | /*eslint indent: ["error", 4, { ImportDeclaration: 1 }]*/ 1159 | 1160 | import { foo, 1161 | bar, 1162 | baz, 1163 | } from 'qux'; 1164 | 1165 | import { 1166 | foo, 1167 | bar, 1168 | baz, 1169 | } from 'qux'; 1170 | ``` 1171 | Examples of incorrect code for this rule with the 4, { ImportDeclaration: "first" } option: 1172 | ``` 1173 | /*eslint indent: ["error", 4, { ImportDeclaration: "first" }]*/ 1174 | 1175 | import { foo, 1176 | bar, 1177 | baz, 1178 | } from 'qux'; 1179 | /*eslint indent: ["error", 4, { ImportDeclaration: "first" }]*/ 1180 | 1181 | import { foo, 1182 | bar, 1183 | baz, 1184 | } from 'qux'; 1185 | ``` 1186 | **flatTernaryExpressions** 1187 | 1188 | Examples of incorrect code for this rule with the default 4, { "flatTernaryExpressions": false } option: 1189 | ``` 1190 | /*eslint indent: ["error", 4, { "flatTernaryExpressions": false }]*/ 1191 | 1192 | var a = 1193 | foo ? bar : 1194 | baz ? qux : 1195 | boop; 1196 | /*eslint indent: ["error", 4, { "flatTernaryExpressions": false }]*/ 1197 | 1198 | var a = 1199 | foo ? bar : 1200 | baz ? qux : 1201 | boop; 1202 | ``` 1203 | Examples of incorrect code for this rule with the 4, { "flatTernaryExpressions": true } option: 1204 | ``` 1205 | /*eslint indent: ["error", 4, { "flatTernaryExpressions": true }]*/ 1206 | 1207 | var a = 1208 | foo ? bar : 1209 | baz ? qux : 1210 | boop; 1211 | /*eslint indent: ["error", 4, { "flatTernaryExpressions": true }]*/ 1212 | 1213 | var a = 1214 | foo ? bar : 1215 | baz ? qux : 1216 | boop; 1217 | ``` 1218 | **ignoredNodes** 1219 | 1220 | The following configuration ignores the indentation of ConditionalExpression (“ternary expression”) nodes: 1221 | ``` 1222 | /*eslint indent: ["error", 4, { "ignoredNodes": ["ConditionalExpression"] }]*/ 1223 | 1224 | var a = foo 1225 | ? bar 1226 | : baz; 1227 | 1228 | var a = foo 1229 | ? bar 1230 | : baz; 1231 | ``` 1232 | The following configuration ignores indentation in the body of IIFEs. 1233 | ``` 1234 | /*eslint indent: ["error", 4, { "ignoredNodes": ["CallExpression > FunctionExpression.callee > BlockStatement.body"] }]*/ 1235 | 1236 | (function() { 1237 | 1238 | foo(); 1239 | bar(); 1240 | 1241 | }) 1242 | ``` 1243 | **ignoreComments** 1244 | 1245 | Examples of additional correct code for this rule with the 4, { "ignoreComments": true } option: 1246 | 1247 | ``` 1248 | /*eslint indent: ["error", 4, { "ignoreComments": true }] */ 1249 | 1250 | if (foo) { 1251 | doSomething(); 1252 | 1253 | // comment intentionally de-indented 1254 | doSomethingElse(); 1255 | } 1256 | ``` 1257 | 1258 | ### quotes 1259 | 1260 | > 强制使用一致的反勾号、双引号或单引号 1261 | 1262 | **Rule Details** 1263 | 1264 | 该规则强制使用一致的反勾号、双引号或单引号。 1265 | 1266 | **Options** 1267 | 1268 | 该规则有两个选项,一个是字符串,一个是对象。 1269 | 1270 | 字符串选项: 1271 | 1272 | - "double" (默认) 要求尽可能地使用双引号 1273 | - "single" 要求尽可能地使用单引号 1274 | - "backtick" 要求尽可能地使用反勾号 1275 | 1276 | 1277 | 对象选项: 1278 | 1279 | - "avoidEscape": true 允许字符串使用单引号或双引号,只要字符串中包含了一个其它引号,否则需要转义 1280 | - "allowTemplateLiterals": true 允许字符串使用反勾号 1281 | 弃用:avoid-escape选项已被弃用;请使用 avoidEscape。 1282 | 1283 | **double** 1284 | 1285 | 默认选项 "double" 的 **错误** 代码示例: 1286 | ``` 1287 | /*eslint quotes: ["error", "double"]*/ 1288 | 1289 | var single = 'single'; 1290 | var unescaped = 'a string containing "double" quotes'; 1291 | var backtick = `back\ntick`; // you can use \n in single or double quoted strings 1292 | ``` 1293 | 默认选项 "double" 的 **正确** 代码示例: 1294 | ``` 1295 | /*eslint quotes: ["error", "double"]*/ 1296 | /*eslint-env es6*/ 1297 | 1298 | var double = "double"; 1299 | var backtick = `back 1300 | tick`; // backticks are allowed due to newline 1301 | var backtick = tag`backtick`; // backticks are allowed due to tag 1302 | ``` 1303 | **single** 1304 | 选项 "single" 的 **错误** 代码示例: 1305 | ``` 1306 | /*eslint quotes: ["error", "single"]*/ 1307 | 1308 | var double = "double"; 1309 | var unescaped = "a string containing 'single' quotes"; 1310 | ``` 1311 | 选项 "single" 的 **正确** 代码示例: 1312 | ``` 1313 | /*eslint quotes: ["error", "single"]*/ 1314 | /*eslint-env es6*/ 1315 | 1316 | var single = 'single'; 1317 | var backtick = `back${x}tick`; // backticks are allowed due to substitution 1318 | ``` 1319 | **backticks** 1320 | 1321 | 选项 "backtick" 的 **错误** 代码示例: 1322 | ``` 1323 | /*eslint quotes: ["error", "backtick"]*/ 1324 | 1325 | var single = 'single'; 1326 | var double = "double"; 1327 | var unescaped = 'a string containing `backticks`'; 1328 | ``` 1329 | 选项 "backtick" 的 **正确** 代码示例: 1330 | ``` 1331 | /*eslint quotes: ["error", "backtick"]*/ 1332 | /*eslint-env es6*/ 1333 | 1334 | var backtick = `backtick`; 1335 | ``` 1336 | **avoidEscape** 1337 | 1338 | 选项呢 "double", { "avoidEscape": true } 的 **正确** 代码示例: 1339 | ``` 1340 | /*eslint quotes: ["error", "double", { "avoidEscape": true }]*/ 1341 | 1342 | var single = 'a string containing "double" quotes'; 1343 | ``` 1344 | 选项 "single", { "avoidEscape": true } 的 **正确** 代码示例: 1345 | ``` 1346 | /*eslint quotes: ["error", "single", { "avoidEscape": true }]*/ 1347 | 1348 | var double = "a string containing 'single' quotes"; 1349 | ``` 1350 | 选项 "backtick", { "avoidEscape": true } 的 **正确** 代码示例: 1351 | ``` 1352 | /*eslint quotes: ["error", "backtick", { "avoidEscape": true }]*/ 1353 | 1354 | var double = "a string containing `backtick` quotes" 1355 | ``` 1356 | **allowTemplateLiterals** 1357 | 1358 | 选项 "double", { "allowTemplateLiterals": true } 的 **正确** 代码示例: 1359 | ``` 1360 | /*eslint quotes: ["error", "double", { "allowTemplateLiterals": true }]*/ 1361 | 1362 | var double = "double"; 1363 | var double = `double`; 1364 | ``` 1365 | 选项 "single", { "allowTemplateLiterals": true } 的 **正确** 代码示例: 1366 | ``` 1367 | /*eslint quotes: ["error", "single", { "allowTemplateLiterals": true }]*/ 1368 | 1369 | var single = 'single'; 1370 | var single = `single`; 1371 | ``` 1372 | 1373 | ### space-infix-ops 1374 | 1375 | > 要求操作符周围有空格 1376 | 1377 | **Rule Details** 1378 | 1379 | 此规则旨在确保中缀运算符周围有空格。 1380 | 1381 | **Options** 1382 | 1383 | 该规则接收唯一一个可选项参数,具有以下默认值: 1384 | ``` 1385 | "space-infix-ops": ["error", {"int32Hint": false}] 1386 | ``` 1387 | **int32Hint** 1388 | 1389 | 设置 int32Hint 选项为 true (默认 false) 允许 a|0 不带空格. 1390 | ``` 1391 | var foo = bar|0; // `foo` is forced to be signed 32 bit integer 1392 | ``` 1393 | **错误** 代码示例: 1394 | ``` 1395 | /*eslint space-infix-ops: "error"*/ 1396 | /*eslint-env es6*/ 1397 | 1398 | a+b 1399 | 1400 | a+ b 1401 | 1402 | a +b 1403 | 1404 | a?b:c 1405 | 1406 | const a={b:1}; 1407 | 1408 | var {a=0}=bar; 1409 | 1410 | function foo(a=0) { } 1411 | ``` 1412 | **正确** 代码示例: 1413 | ``` 1414 | /*eslint space-infix-ops: "error"*/ 1415 | /*eslint-env es6*/ 1416 | 1417 | a + b 1418 | 1419 | a + b 1420 | 1421 | a ? b : c 1422 | 1423 | const a = {b:1}; 1424 | 1425 | var {a = 0} = bar; 1426 | 1427 | function foo(a = 0) { } 1428 | ``` 1429 | 1430 | ### space-unary-ops 1431 | 1432 | > 强制在一元操作符前后使用一致的空格 1433 | 1434 | **Rule Details** 1435 | 1436 | 该规则强制 words 一元操作符后空格和 nonwords 一元操作符之前或之后的空格的一致性。 1437 | 1438 | 一元 words 操作符的例子: 1439 | ``` 1440 | // new 1441 | var joe = new Person(); 1442 | 1443 | // delete 1444 | var obj = { 1445 | foo: 'bar' 1446 | }; 1447 | delete obj.foo; 1448 | 1449 | // typeof 1450 | typeof {} // object 1451 | 1452 | // void 1453 | void 0 // undefined 1454 | ``` 1455 | 一元 nonwords 操作符的例子: 1456 | ``` 1457 | if ([1,2,3].indexOf(1) !== -1) {}; 1458 | foo = --foo; 1459 | bar = bar++; 1460 | baz = !foo; 1461 | qux = !!baz; 1462 | ``` 1463 | **Options** 1464 | 1465 | 该规则有三个可选项: 1466 | 1467 | - words - 适用于单词类一元操作符,例如:new、delete、typeof、void、yield 1468 | - nonwords - 适用于这些一元操作符: -、+、--、++、!、!! 1469 | - overrides - 覆盖操作符周围空格的用法。默认为空,但可用来强制或禁止操作符周围有空格。例如: 1470 | 1471 | ``` 1472 | "space-unary-ops": [ 1473 | 2, { 1474 | "words": true, 1475 | "nonwords": false, 1476 | "overrides": { 1477 | "new": false, 1478 | "++": true 1479 | } 1480 | }] 1481 | ``` 1482 | 在这个例子中,new 操作符之后禁用空格,++ 操作左右要求有空格。 1483 | 1484 | 选项 {"words": true, "nonwords": false} 的 **错误** 代码示例: 1485 | ``` 1486 | /*eslint space-unary-ops: "error"*/ 1487 | 1488 | typeof!foo; 1489 | 1490 | void{foo:0}; 1491 | 1492 | new[foo][0]; 1493 | 1494 | delete(foo.bar); 1495 | 1496 | ++ foo; 1497 | 1498 | foo --; 1499 | 1500 | - foo; 1501 | 1502 | + "3"; 1503 | /*eslint space-unary-ops: "error"*/ 1504 | /*eslint-env es6*/ 1505 | 1506 | function *foo() { 1507 | yield(0) 1508 | } 1509 | /*eslint space-unary-ops: "error"*/ 1510 | 1511 | async function foo() { 1512 | await(bar); 1513 | } 1514 | ``` 1515 | 选项 {"words": true, "nonwords": false} 的 **正确** 代码示例: 1516 | ``` 1517 | /*eslint space-unary-ops: "error"*/ 1518 | 1519 | // Word unary operator "delete" is followed by a whitespace. 1520 | delete foo.bar; 1521 | 1522 | // Word unary operator "new" is followed by a whitespace. 1523 | new Foo; 1524 | 1525 | // Word unary operator "void" is followed by a whitespace. 1526 | void 0; 1527 | 1528 | // Unary operator "++" is not followed by whitespace. 1529 | ++foo; 1530 | 1531 | // Unary operator "--" is not preceded by whitespace. 1532 | foo--; 1533 | 1534 | // Unary operator "-" is not followed by whitespace. 1535 | -foo; 1536 | 1537 | // Unary operator "+" is not followed by whitespace. 1538 | +"3"; 1539 | /*eslint space-unary-ops: "error"*/ 1540 | /*eslint-env es6*/ 1541 | 1542 | function *foo() { 1543 | yield (0) 1544 | } 1545 | /*eslint space-unary-ops: "error"*/ 1546 | 1547 | async function foo() { 1548 | await (bar); 1549 | } 1550 | ``` 1551 | ### brace-style 1552 | 1553 | > 强制在代码块中使用一致的大括号风格 1554 | 1555 | **Rule Details** 1556 | 1557 | 该规则旨在强制在Javascript中使用特定的括号风格。因此,如果某条语句或声明没有遵守该该风格,该规则将发出警告。 1558 | 1559 | **Options** 1560 | 1561 | 该规则有一个字符串选项: 1562 | 1563 | - "1tbs" (默认) 强制 one true brace style 1564 | - "stroustrup" 强制 Stroustrup style 1565 | - "allman" 强制 Allman style 1566 | 1567 | 该规则可以有例外情况,用对象表示: 1568 | 1569 | "allowSingleLine": true (默认 false) 允许块的开括号和闭括号在 同一行 1570 | 1571 | **1tbs** 1572 | 1573 | 选项"1tbs"的 **错误** 代码示例: 1574 | ``` 1575 | /*eslint brace-style: "error"*/ 1576 | 1577 | function foo() 1578 | { 1579 | return true; 1580 | } 1581 | 1582 | if (foo) 1583 | { 1584 | bar(); 1585 | } 1586 | 1587 | try 1588 | { 1589 | somethingRisky(); 1590 | } catch(e) 1591 | { 1592 | handleError(); 1593 | } 1594 | 1595 | if (foo) { 1596 | bar(); 1597 | } 1598 | else { 1599 | baz(); 1600 | } 1601 | ``` 1602 | 选项"1tbs"的 **正确** 代码示例: 1603 | ``` 1604 | /*eslint brace-style: "error"*/ 1605 | 1606 | function foo() { 1607 | return true; 1608 | } 1609 | 1610 | if (foo) { 1611 | bar(); 1612 | } 1613 | 1614 | if (foo) { 1615 | bar(); 1616 | } else { 1617 | baz(); 1618 | } 1619 | 1620 | try { 1621 | somethingRisky(); 1622 | } catch(e) { 1623 | handleError(); 1624 | } 1625 | 1626 | // when there are no braces, there are no problems 1627 | if (foo) bar(); 1628 | else if (baz) boom(); 1629 | ``` 1630 | 选项"1tbs", { "allowSingleLine": true }的 **正确** 代码示例: 1631 | ``` 1632 | /*eslint brace-style: ["error", "1tbs", { "allowSingleLine": true }]*/ 1633 | 1634 | function nop() { return; } 1635 | 1636 | if (foo) { bar(); } 1637 | 1638 | if (foo) { bar(); } else { baz(); } 1639 | 1640 | try { somethingRisky(); } catch(e) { handleError(); } 1641 | ``` 1642 | **stroustrup** 1643 | 1644 | 选项"stroustrup"的 **错误** 代码示例: 1645 | ``` 1646 | /*eslint brace-style: ["error", "stroustrup"]*/ 1647 | 1648 | function foo() 1649 | { 1650 | return true; 1651 | } 1652 | 1653 | if (foo) 1654 | { 1655 | bar(); 1656 | } 1657 | 1658 | try 1659 | { 1660 | somethingRisky(); 1661 | } catch(e) 1662 | { 1663 | handleError(); 1664 | } 1665 | 1666 | if (foo) { 1667 | bar(); 1668 | } else { 1669 | baz(); 1670 | } 1671 | ``` 1672 | 选项"stroustrup"的 **正确** 代码示例: 1673 | ``` 1674 | /*eslint brace-style: ["error", "stroustrup"]*/ 1675 | 1676 | function foo() { 1677 | return true; 1678 | } 1679 | 1680 | if (foo) { 1681 | bar(); 1682 | } 1683 | 1684 | if (foo) { 1685 | bar(); 1686 | } 1687 | else { 1688 | baz(); 1689 | } 1690 | 1691 | try { 1692 | somethingRisky(); 1693 | } 1694 | catch(e) { 1695 | handleError(); 1696 | } 1697 | 1698 | // when there are no braces, there are no problems 1699 | if (foo) bar(); 1700 | else if (baz) boom(); 1701 | ``` 1702 | 选项"stroustrup", { "allowSingleLine": true }的 **正确** 代码示例: 1703 | ``` 1704 | /*eslint brace-style: ["error", "stroustrup", { "allowSingleLine": true }]*/ 1705 | 1706 | function nop() { return; } 1707 | 1708 | if (foo) { bar(); } 1709 | 1710 | if (foo) { bar(); } 1711 | else { baz(); } 1712 | 1713 | try { somethingRisky(); } 1714 | catch(e) { handleError(); } 1715 | ``` 1716 | **allman** 1717 | 1718 | 选项"allman"的 **错误** 代码示例: 1719 | ``` 1720 | /*eslint brace-style: ["error", "allman"]*/ 1721 | 1722 | function foo() { 1723 | return true; 1724 | } 1725 | 1726 | if (foo) 1727 | { 1728 | bar(); } 1729 | 1730 | try 1731 | { 1732 | somethingRisky(); 1733 | } catch(e) 1734 | { 1735 | handleError(); 1736 | } 1737 | 1738 | if (foo) { 1739 | bar(); 1740 | } else { 1741 | baz(); 1742 | } 1743 | ``` 1744 | 选项"allman"的 **正确** 代码示例: 1745 | ``` 1746 | /*eslint brace-style: ["error", "allman"]*/ 1747 | 1748 | function foo() 1749 | { 1750 | return true; 1751 | } 1752 | 1753 | if (foo) 1754 | { 1755 | bar(); 1756 | } 1757 | 1758 | if (foo) 1759 | { 1760 | bar(); 1761 | } 1762 | else 1763 | { 1764 | baz(); 1765 | } 1766 | 1767 | try 1768 | { 1769 | somethingRisky(); 1770 | } 1771 | catch(e) 1772 | { 1773 | handleError(); 1774 | } 1775 | 1776 | // when there are no braces, there are no problems 1777 | if (foo) bar(); 1778 | else if (baz) boom(); 1779 | ``` 1780 | 选项"allman", { "allowSingleLine": true }的 **正确** 代码示例: 1781 | ``` 1782 | /*eslint brace-style: ["error", "allman", { "allowSingleLine": true }]*/ 1783 | 1784 | function nop() { return; } 1785 | 1786 | if (foo) { bar(); } 1787 | 1788 | if (foo) { bar(); } 1789 | else { baz(); } 1790 | 1791 | try { somethingRisky(); } 1792 | catch(e) { handleError(); } 1793 | ``` 1794 | 1795 | ### space-before-blocks 1796 | 1797 | > 强制在块之前使用一致的空格 1798 | 1799 | **Rule Details** 1800 | 1801 | 该规则将强制块之前的空格的一致性。它只在非行首的块上起作用。 1802 | 1803 | - 该规则忽略 => 和块之间的空格。arrow-spacing 规则处理这些空格。 1804 | - 该规则忽略关键字和块之间的空格。keyword-spacing 规则处理这些空格。 1805 | 1806 | 1807 | **Options** 1808 | 1809 | 该规则有一个参数。如果为 "always",块语句必须总是至少有一个前置空格。如果为"never",所有的块永远不会有前置空格。如果函数块和关键字块要求不同的空格类型,可以单独传递一个可选配置的对象作为该规则的参数来配置这种情况。(比如:{ "functions": "never", "keywords": "always", classes: "always" } ) 1810 | 1811 | 默认为 "always"。 1812 | 1813 | **“always”** 1814 | 1815 | 选项 "always" 的 **错误** 代码示例: 1816 | ``` 1817 | /*eslint space-before-blocks: "error"*/ 1818 | 1819 | if (a){ 1820 | b(); 1821 | } 1822 | 1823 | function a(){} 1824 | 1825 | for (;;){ 1826 | b(); 1827 | } 1828 | 1829 | try {} catch(a){} 1830 | 1831 | class Foo{ 1832 | constructor(){} 1833 | } 1834 | ``` 1835 | 选项 "always" 的 **正确** 代码示例: 1836 | ``` 1837 | /*eslint space-before-blocks: "error"*/ 1838 | 1839 | if (a) { 1840 | b(); 1841 | } 1842 | 1843 | if (a) { 1844 | b(); 1845 | } else{ /*no error. this is checked by `keyword-spacing` rule.*/ 1846 | c(); 1847 | } 1848 | 1849 | 1850 | function a() {} 1851 | 1852 | for (;;) { 1853 | b(); 1854 | } 1855 | 1856 | try {} catch(a) {} 1857 | ``` 1858 | **“never”** 1859 | 1860 | 选项 "never" 的 **错误** 代码示例: 1861 | ``` 1862 | /*eslint space-before-blocks: ["error", "never"]*/ 1863 | 1864 | if (a) { 1865 | b(); 1866 | } 1867 | 1868 | function a() {} 1869 | 1870 | for (;;) { 1871 | b(); 1872 | } 1873 | 1874 | try {} catch(a) {} 1875 | ``` 1876 | 选项 "never" 的 **正确** 代码示例: 1877 | ``` 1878 | /*eslint space-before-blocks: ["error", "never"]*/ 1879 | 1880 | if (a){ 1881 | b(); 1882 | } 1883 | 1884 | function a(){} 1885 | 1886 | for (;;){ 1887 | b(); 1888 | } 1889 | 1890 | try{} catch(a){} 1891 | 1892 | class Foo{ 1893 | constructor(){} 1894 | } 1895 | ``` 1896 | 选项 { "functions": "never", "keywords": "always", "classes": "never" } 的 **错误** 代码示例: 1897 | ``` 1898 | /*eslint space-before-blocks: ["error", { "functions": "never", "keywords": "always", "classes": "never" }]*/ 1899 | /*eslint-env es6*/ 1900 | 1901 | function a() {} 1902 | 1903 | try {} catch(a){} 1904 | 1905 | class Foo{ 1906 | constructor() {} 1907 | } 1908 | ``` 1909 | 选项 { "functions": "never", "keywords": "always", "classes": "never" } 的 **正确** 代码示例: 1910 | ``` 1911 | /*eslint space-before-blocks: ["error", { "functions": "never", "keywords": "always", "classes": "never" }]*/ 1912 | /*eslint-env es6*/ 1913 | 1914 | for (;;) { 1915 | // ... 1916 | } 1917 | 1918 | describe(function(){ 1919 | // ... 1920 | }); 1921 | 1922 | class Foo { 1923 | constructor(){} 1924 | } 1925 | ``` 1926 | 选项 { "functions": "always", "keywords": "never", "classes": "never" } 的 **错误** 代码示例: 1927 | ``` 1928 | /*eslint space-before-blocks: ["error", { "functions": "always", "keywords": "never", "classes": "never" }]*/ 1929 | /*eslint-env es6*/ 1930 | 1931 | function a(){} 1932 | 1933 | try {} catch(a) {} 1934 | 1935 | class Foo { 1936 | constructor(){} 1937 | } 1938 | ``` 1939 | 选项 { "functions": "always", "keywords": "never", "classes": "never" } 的 **正确** 代码示例: 1940 | ``` 1941 | /*eslint space-before-blocks: ["error", { "functions": "always", "keywords": "never", "classes": "never" }]*/ 1942 | /*eslint-env es6*/ 1943 | 1944 | if (a){ 1945 | b(); 1946 | } 1947 | 1948 | var a = function() {} 1949 | 1950 | class Foo{ 1951 | constructor() {} 1952 | } 1953 | ``` 1954 | 选项 { "functions": "never", "keywords": "never", "classes": "always" } 的 **错误** 代码示例: 1955 | ``` 1956 | /*eslint space-before-blocks: ["error", { "functions": "never", "keywords": "never", "classes": "always" }]*/ 1957 | /*eslint-env es6*/ 1958 | 1959 | class Foo{ 1960 | constructor(){} 1961 | } 1962 | ``` 1963 | 选项呢 { "functions": "never", "keywords": "never", "classes": "always" } 的 **正确** 代码示例: 1964 | ``` 1965 | /*eslint space-before-blocks: ["error", { "functions": "never", "keywords": "never", "classes": "always" }]*/ 1966 | /*eslint-env es6*/ 1967 | 1968 | class Foo { 1969 | constructor(){} 1970 | } 1971 | ``` 1972 | 1973 | ### keyword-spacing 1974 | 1975 | > 强制在关键字前后使用一致的空格 1976 | 1977 | **Rule Details** 1978 | 1979 | 该规则强制关键字和类似关键字的符号周围空格的一致性:as、async、await、break、case、catch、class、const、continue、debugger、default、delete、do、else、export、extends、finally、for、from、function、get、if、import、in、instanceof、let、new、of、return、set、static、super、switch、this、throw、try、typeof、var、void、while、with 和 yield。该规则不会与其它空格规则发生冲突:它并不应用于别的规则会报告问题的空格。 1980 | 1981 | Options 1982 | 该规则有一个对象选项: 1983 | 1984 | - "before": true (默认) 要求在关键字之前至少有一个空格 1985 | - "before": false 禁止在关键字之前有空格 1986 | - "after": true (默认) 要求在关键字之后至少有一个空格 1987 | - "after": false 禁止在关键字之后有空格 1988 | - "overrides" 允许覆盖指定的关键字的空格风格 1989 | 1990 | 1991 | **before** 1992 | 1993 | 默认选项 { "before": true } 的 **错误** 代码示例: 1994 | ``` 1995 | /*eslint keyword-spacing: ["error", { "before": true }]*/ 1996 | 1997 | if (foo) { 1998 | //... 1999 | }else if (bar) { 2000 | //... 2001 | }else { 2002 | //... 2003 | } 2004 | ``` 2005 | 默认选项 { "before": true } 的 **正确** 代码示例: 2006 | ``` 2007 | /*eslint keyword-spacing: ["error", { "before": true }]*/ 2008 | /*eslint-env es6*/ 2009 | 2010 | if (foo) { 2011 | //... 2012 | } else if (bar) { 2013 | //... 2014 | } else { 2015 | //... 2016 | } 2017 | 2018 | // Avoid conflict with `array-bracket-spacing` 2019 | let a = [this]; 2020 | let b = [function() {}]; 2021 | 2022 | // Avoid conflict with `arrow-spacing` 2023 | let a = ()=> this.foo; 2024 | 2025 | // Avoid conflict with `block-spacing` 2026 | {function foo() {}} 2027 | 2028 | // Avoid conflict with `comma-spacing` 2029 | let a = [100,this.foo, this.bar]; 2030 | 2031 | // Avoid conflict with `computed-property-spacing` 2032 | obj[this.foo] = 0; 2033 | 2034 | // Avoid conflict with `generator-star-spacing` 2035 | function *foo() {} 2036 | 2037 | // Avoid conflict with `key-spacing` 2038 | let obj = { 2039 | foo:function() {} 2040 | }; 2041 | 2042 | // Avoid conflict with `object-curly-spacing` 2043 | let obj = {foo: this}; 2044 | 2045 | // Avoid conflict with `semi-spacing` 2046 | let a = this;function foo() {} 2047 | 2048 | // Avoid conflict with `space-in-parens` 2049 | (function () {})(); 2050 | 2051 | // Avoid conflict with `space-infix-ops` 2052 | if ("foo"in {foo: 0}) {} 2053 | if (10+this.foo<= this.bar) {} 2054 | 2055 | // Avoid conflict with `x-curly-spacing` 2056 | let a = 2057 | ``` 2058 | 选项 { "before": false } 的 **错误** 代码示例: 2059 | ``` 2060 | /*eslint keyword-spacing: ["error", { "before": false }]*/ 2061 | 2062 | if (foo) { 2063 | //... 2064 | } else if (bar) { 2065 | //... 2066 | } else { 2067 | //... 2068 | } 2069 | ``` 2070 | 选项 { "before": false } 的 **正确** 代码示例: 2071 | ``` 2072 | /*eslint keyword-spacing: ["error", { "before": false }]*/ 2073 | 2074 | if (foo) { 2075 | //... 2076 | }else if (bar) { 2077 | //... 2078 | }else { 2079 | //... 2080 | } 2081 | ``` 2082 | **after** 2083 | 2084 | 默认选项 { "after": true } 的 **错误** 代码示例: 2085 | ``` 2086 | /*eslint keyword-spacing: ["error", { "after": true }]*/ 2087 | 2088 | if(foo) { 2089 | //... 2090 | } else if(bar) { 2091 | //... 2092 | } else{ 2093 | //... 2094 | } 2095 | ``` 2096 | 默认选项 { "after": true } 的 **正确** 代码示例: 2097 | ``` 2098 | /*eslint keyword-spacing: ["error", { "after": true }]*/ 2099 | 2100 | if (foo) { 2101 | //... 2102 | } else if (bar) { 2103 | //... 2104 | } else { 2105 | //... 2106 | } 2107 | 2108 | // Avoid conflict with `array-bracket-spacing` 2109 | let a = [this]; 2110 | 2111 | // Avoid conflict with `arrow-spacing` 2112 | let a = ()=> this.foo; 2113 | 2114 | // Avoid conflict with `comma-spacing` 2115 | let a = [100, this.foo, this.bar]; 2116 | 2117 | // Avoid conflict with `computed-property-spacing` 2118 | obj[this.foo] = 0; 2119 | 2120 | // Avoid conflict with `generator-star-spacing` 2121 | function* foo() {} 2122 | 2123 | // Avoid conflict with `key-spacing` 2124 | let obj = { 2125 | foo:function() {} 2126 | }; 2127 | 2128 | // Avoid conflict with `func-call-spacing` 2129 | class A { 2130 | constructor() { 2131 | super(); 2132 | } 2133 | } 2134 | 2135 | // Avoid conflict with `object-curly-spacing` 2136 | let obj = {foo: this}; 2137 | 2138 | // Avoid conflict with `semi-spacing` 2139 | let a = this;function foo() {} 2140 | 2141 | // Avoid conflict with `space-before-function-paren` 2142 | function() {} 2143 | 2144 | // Avoid conflict with `space-infix-ops` 2145 | if ("foo"in{foo: 0}) {} 2146 | if (10+this.foo<= this.bar) {} 2147 | 2148 | // Avoid conflict with `space-unary-ops` 2149 | function* foo(a) { 2150 | return yield+a; 2151 | } 2152 | 2153 | // Avoid conflict with `yield-star-spacing` 2154 | function* foo(a) { 2155 | return yield* a; 2156 | } 2157 | 2158 | // Avoid conflict with `x-curly-spacing` 2159 | let a = 2160 | ``` 2161 | 选项 { "after": false } 的 **错误** 代码示例: 2162 | ``` 2163 | /*eslint keyword-spacing: ["error", { "after": false }]*/ 2164 | 2165 | if (foo) { 2166 | //... 2167 | } else if (bar) { 2168 | //... 2169 | } else { 2170 | //... 2171 | } 2172 | ``` 2173 | 选项 { "after": false } 的 **正确** 代码示例: 2174 | ``` 2175 | /*eslint keyword-spacing: ["error", { "after": false }]*/ 2176 | 2177 | if(foo) { 2178 | //... 2179 | } else if(bar) { 2180 | //... 2181 | } else{ 2182 | //... 2183 | } 2184 | ``` 2185 | **overrides** 2186 | 2187 | 选项 { "overrides": { "if": { "after": false }, "for": { "after": false }, "while": { "after": false } } } 的 **正确** 代码示例: 2188 | ``` 2189 | /*eslint keyword-spacing: ["error", { "overrides": { 2190 | "if": { "after": false }, 2191 | "for": { "after": false }, 2192 | "while": { "after": false } 2193 | } }]*/ 2194 | 2195 | if(foo) { 2196 | //... 2197 | } else if(bar) { 2198 | //... 2199 | } else { 2200 | //... 2201 | } 2202 | 2203 | for(;;); 2204 | 2205 | while(true) { 2206 | //... 2207 | } 2208 | ``` 2209 | 2210 | ### key-spacing 2211 | 2212 | > 强制在对象字面量的属性中键和值之间使用一致的间距 2213 | 2214 | **Rule Details** 2215 | 2216 | 该规则强制在对象字面量的键和值之间使用一致的空格。如果某一行很长的话,在允许空白出现的情况下,可以增加一空行,这种情况是该规则可以接受的。 2217 | 2218 | **Options** 2219 | 2220 | 该规则有一个对象选项: 2221 | 2222 | - "beforeColon": false (默认) | true 2223 | - false: 禁止在对象字面量的键和冒号之间存在空格 2224 | - true: 要求在对象字面量的键和冒号之间存在至少有一个空格 2225 | - "afterColon": true (默认) | false 2226 | - true: 要求在对象字面量的冒号和值之间存在至少有一个空格 2227 | - false: 禁止在对象字面量的冒号和值之间存在空格 2228 | - "mode": "strict" (默认) | "minimum" 2229 | - "strict": 强制在冒号前后只有一个空格 2230 | - "minimum": 要求在冒号前后最少有一个空格 2231 | - "align": "value" | "colon" 2232 | - "value": 要求对象字面量中的值水平对齐 2233 | - "colon" 要求对象字面量中的冒号和值都水平对齐 2234 | - "align" 允许细粒度的控制对象字面量值的间距直到对齐 2235 | - "singleLine" 为单行对象字面量指定一个空格风格 2236 | - "multiLine" 为多行对象字面量指定一个空格风格 2237 | 2238 | 2239 | 请注意,你可以使用顶级选项或分组选项 (singleLine 和 multiLine),但不能同时使用两者。 2240 | 2241 | **beforeColon** 2242 | 2243 | 默认选项 { "beforeColon": false } 的 **错误** 代码示例: 2244 | ``` 2245 | /*eslint key-spacing: ["error", { "beforeColon": false }]*/ 2246 | 2247 | var obj = { "foo" : 42 }; 2248 | ``` 2249 | 默认选项 { "beforeColon": false } 的 **正确** 代码示例: 2250 | ``` 2251 | /*eslint key-spacing: ["error", { "beforeColon": false }]*/ 2252 | 2253 | var obj = { "foo": 42 }; 2254 | ``` 2255 | 选项 { "beforeColon": true } 的 **错误** 代码示例: 2256 | ``` 2257 | /*eslint key-spacing: ["error", { "beforeColon": true }]*/ 2258 | 2259 | var obj = { "foo": 42 }; 2260 | ``` 2261 | 选项 { "beforeColon": true } 的 **正确** 代码示例: 2262 | ``` 2263 | /*eslint key-spacing: ["error", { "beforeColon": true }]*/ 2264 | 2265 | var obj = { "foo" : 42 }; 2266 | ``` 2267 | **afterColon** 2268 | 2269 | 默认选项 { "afterColon": true } 的 **错误** 代码示例: 2270 | ``` 2271 | /*eslint key-spacing: ["error", { "afterColon": true }]*/ 2272 | 2273 | var obj = { "foo":42 }; 2274 | ``` 2275 | 默认选项 { "afterColon": true } 的 **正确** 代码示例: 2276 | ``` 2277 | /*eslint key-spacing: ["error", { "afterColon": true }]*/ 2278 | 2279 | var obj = { "foo": 42 }; 2280 | ``` 2281 | 选项 { "afterColon": false } 的 **错误** 代码示例: 2282 | ``` 2283 | /*eslint key-spacing: ["error", { "afterColon": false }]*/ 2284 | 2285 | var obj = { "foo": 42 }; 2286 | ``` 2287 | 选项 { "afterColon": false } 的 **正确** 代码示例: 2288 | ``` 2289 | /*eslint key-spacing: ["error", { "afterColon": false }]*/ 2290 | 2291 | var obj = { "foo":42 }; 2292 | ``` 2293 | **mode** 2294 | 2295 | 默认选项 { "mode": "strict" } 的 **错误** 代码示例: 2296 | ``` 2297 | /*eslint key-spacing: ["error", { "mode": "strict" }]*/ 2298 | 2299 | call({ 2300 | foobar: 42, 2301 | bat: 2 * 2 2302 | }); 2303 | ``` 2304 | 2305 | 默认选项 { "mode": "strict" } 的 **正确** 代码示例: 2306 | ``` 2307 | /*eslint key-spacing: ["error", { "mode": "strict" }]*/ 2308 | 2309 | call({ 2310 | foobar: 42, 2311 | bat: 2 * 2 2312 | }); 2313 | ``` 2314 | 选项 { "mode": "minimum" } 的 **正确** 代码示例: 2315 | ``` 2316 | /*eslint key-spacing: ["error", { "mode": "minimum" }]*/ 2317 | 2318 | call({ 2319 | foobar: 42, 2320 | bat: 2 * 2 2321 | }); 2322 | ``` 2323 | **align** 2324 | 2325 | 选项 { "align": "value" } 的 **错误** 代码示例: 2326 | ``` 2327 | /*eslint key-spacing: ["error", { "align": "value" }]*/ 2328 | 2329 | var obj = { 2330 | a: value, 2331 | bcde: 42, 2332 | fg : foo() 2333 | }; 2334 | ``` 2335 | 选项 { "align": "value" } 的 **正确** 代码示例: 2336 | ``` 2337 | /*eslint key-spacing: ["error", { "align": "value" }]*/ 2338 | 2339 | var obj = { 2340 | a: value, 2341 | bcde: 42, 2342 | 2343 | fg: foo(), 2344 | h: function() { 2345 | return this.a; 2346 | }, 2347 | ijkl: 'Non-consecutive lines form a new group' 2348 | }; 2349 | 2350 | var obj = { a: "foo", longPropertyName: "bar" }; 2351 | ``` 2352 | 选项 { "align": "colon" } 的 **错误** 代码示例: 2353 | ``` 2354 | /*eslint key-spacing: ["error", { "align": "colon" }]*/ 2355 | 2356 | call({ 2357 | foobar: 42, 2358 | bat: 2 * 2 2359 | }); 2360 | ``` 2361 | 选项 { "align": "colon" } 的 **正确** 代码示例: 2362 | ``` 2363 | /*eslint key-spacing: ["error", { "align": "colon" }]*/ 2364 | 2365 | call({ 2366 | foobar: 42, 2367 | bat : 2 * 2 2368 | }); 2369 | ``` 2370 | **align** 2371 | 2372 | align 选项可以通过 beforeColon、afterColon、mode 和 on 进行额外的配置。 2373 | 2374 | 如果 align 被定义为一个对象,但是没有提供所有的参数,那么,未定义的参数将默认为: 2375 | ``` 2376 | // Defaults 2377 | align: { 2378 | "beforeColon": false, 2379 | "afterColon": true, 2380 | "on": "colon", 2381 | "mode": "strict" 2382 | } 2383 | ``` 2384 | 选项 { "align": { } } 的 **正确** 代码示例: 2385 | ``` 2386 | /*eslint key-spacing: ["error", { 2387 | "align": { 2388 | "beforeColon": true, 2389 | "afterColon": true, 2390 | "on": "colon" 2391 | } 2392 | }]*/ 2393 | 2394 | var obj = { 2395 | "one" : 1, 2396 | "seven" : 7 2397 | } 2398 | /*eslint key-spacing: ["error", { 2399 | "align": { 2400 | "beforeColon": false, 2401 | "afterColon": false, 2402 | "on": "value" 2403 | } 2404 | }]*/ 2405 | 2406 | var obj = { 2407 | "one": 1, 2408 | "seven":7 2409 | } 2410 | ``` 2411 | **align and multiLine** 2412 | 2413 | multiLine 和 align 选项可以有所区别,这将允许对你的文件进行更细粒度的控制 key-spacing。如果 align 被配置为一个对象,align 将不会 从 multiLine 继承。 2414 | 2415 | multiLine 可以在任何时候被用在跨行的对象字面量上。而当一个对象有多个属性时,使用 align 配置。 2416 | ``` 2417 | var myObj = { 2418 | key1: 1, // uses multiLine 2419 | 2420 | key2: 2, // uses align (when defined) 2421 | key3: 3, // uses align (when defined) 2422 | 2423 | key4: 4 // uses multiLine 2424 | } 2425 | ``` 2426 | 2427 | 选项 { "align": { }, "multiLine": { } } 的 **错误** 代码示例: 2428 | ``` 2429 | /*eslint key-spacing: ["error", { 2430 | "multiLine": { 2431 | "beforeColon": false, 2432 | "afterColon":true 2433 | }, 2434 | "align": { 2435 | "beforeColon": true, 2436 | "afterColon": true, 2437 | "on": "colon" 2438 | } 2439 | }]*/ 2440 | 2441 | var obj = { 2442 | "myObjectFunction": function() { 2443 | // Do something 2444 | }, 2445 | "one" : 1, 2446 | "seven" : 7 2447 | } 2448 | ``` 2449 | 选项 { "align": { }, "multiLine": { } } 的 **正确** 代码示例: 2450 | ``` 2451 | /*eslint key-spacing: ["error", { 2452 | "multiLine": { 2453 | "beforeColon": false, 2454 | "afterColon": true 2455 | 2456 | }, 2457 | "align": { 2458 | "beforeColon": true, 2459 | "afterColon": true, 2460 | "on": "colon" 2461 | } 2462 | }]*/ 2463 | 2464 | var obj = { 2465 | "myObjectFunction": function() { 2466 | // Do something 2467 | // 2468 | }, // These are two separate groups, so no alignment between `myObjectFuction` and `one` 2469 | "one" : 1, 2470 | "seven" : 7 // `one` and `seven` are in their own group, and therefore aligned 2471 | } 2472 | ``` 2473 | **singleLine and multiLine** 2474 | 2475 | 选项 { "singleLine": { }, "multiLine": { } } 的 **正确** 代码示例: 2476 | ``` 2477 | /*eslint "key-spacing": [2, { 2478 | "singleLine": { 2479 | "beforeColon": false, 2480 | "afterColon": true 2481 | }, 2482 | "multiLine": { 2483 | "beforeColon": true, 2484 | "afterColon": true, 2485 | "align": "colon" 2486 | } 2487 | }]*/ 2488 | var obj = { one: 1, "two": 2, three: 3 }; 2489 | var obj2 = { 2490 | "two" : 2, 2491 | three : 3 2492 | }; 2493 | ``` 2494 | 2495 | ### space-in-parens 2496 | 2497 | > 强制在圆括号内使用一致的空格 2498 | 2499 | **Rule Details** 2500 | 2501 | 该规则将通过禁止或要求 ( 右边或 ) 左边有一个或多个空格来强制圆括号内空格的一致性。在任一情况下,仍将允许 ()。 2502 | 2503 | **Options** 2504 | 2505 | 该规则有两个选项: 2506 | 2507 | - "never" (默认) 强制圆括号内没有空格 2508 | - "always" 强制圆括号内有一个空格 2509 | 2510 | 根据您的编码约定,您可以在您的配置中选择使用任一选项: 2511 | ``` 2512 | "space-in-parens": ["error", "always"] 2513 | ``` 2514 | **“never”** 2515 | 2516 | 选项 "never" 的 **错误** 代码示例: 2517 | ``` 2518 | /*eslint space-in-parens: ["error", "never"]*/ 2519 | 2520 | foo( 'bar'); 2521 | foo('bar' ); 2522 | foo( 'bar' ); 2523 | 2524 | var foo = ( 1 + 2 ) * 3; 2525 | ( function () { return 'bar'; }() ); 2526 | ``` 2527 | 选项 "never" 的 **正确** 代码示例: 2528 | ``` 2529 | /*eslint space-in-parens: ["error", "never"]*/ 2530 | 2531 | foo(); 2532 | 2533 | foo('bar'); 2534 | 2535 | var foo = (1 + 2) * 3; 2536 | (function () { return 'bar'; }()); 2537 | ``` 2538 | **“always”** 2539 | 2540 | 选项 "always" 的 **错误** 代码示例: 2541 | ``` 2542 | /*eslint space-in-parens: ["error", "always"]*/ 2543 | 2544 | foo( 'bar'); 2545 | foo('bar' ); 2546 | foo('bar'); 2547 | 2548 | var foo = (1 + 2) * 3; 2549 | (function () { return 'bar'; }()); 2550 | ``` 2551 | 选项 "always" 的 **正确** 代码示例: 2552 | ``` 2553 | /*eslint space-in-parens: ["error", "always"]*/ 2554 | 2555 | foo(); 2556 | 2557 | foo( 'bar' ); 2558 | 2559 | var foo = ( 1 + 2 ) * 3; 2560 | ( function () { return 'bar'; }() ); 2561 | ``` 2562 | **Exceptions** 2563 | 2564 | 一个对象文本可以作为规则数组的第三个元素来制定例外情况,使用 "exceptions" 做主键,对应的值是一个数组。这些例外作用在第一个选项的基础上。如果 "always" 设置为强制使用空格,那么任何例外情况将 不允许使用空格。同样的,如果 "never"设置为禁止使用空格那么,任何例外情况将强制使用空格。 2565 | 2566 | 以下例外情况是有效的:["{}", "[]", "()", "empty"]. 2567 | 2568 | 选项 "never", { "exceptions": ["{}"] } 的 **错误** 代码示例: 2569 | ``` 2570 | /*eslint space-in-parens: ["error", "never", { "exceptions": ["{}"] }]*/ 2571 | 2572 | foo({bar: 'baz'}); 2573 | foo(1, {bar: 'baz'}); 2574 | ``` 2575 | 选项 "never", { "exceptions": ["{}"] } 的 **正确** 代码示例: 2576 | ``` 2577 | /*eslint space-in-parens: ["error", "never", { "exceptions": ["{}"] }]*/ 2578 | 2579 | foo( {bar: 'baz'} ); 2580 | foo(1, {bar: 'baz'} ); 2581 | ``` 2582 | 选项 "always", { "exceptions": ["{}"] } 的 **错误** 代码示例: 2583 | ``` 2584 | /*eslint space-in-parens: ["error", "always", { "exceptions": ["{}"] }]*/ 2585 | 2586 | foo( {bar: 'baz'} ); 2587 | foo( 1, {bar: 'baz'} ); 2588 | ``` 2589 | 选项 "always", { "exceptions": ["{}"] } 的 **正确** 代码示例: 2590 | ``` 2591 | /*eslint space-in-parens: ["error", "always", { "exceptions": ["{}"] }]*/ 2592 | 2593 | foo({bar: 'baz'}); 2594 | foo( 1, {bar: 'baz'}); 2595 | ``` 2596 | 选项 "never", { "exceptions": ["[]"] } 的 **错误** 代码示例: 2597 | ``` 2598 | /*eslint space-in-parens: ["error", "never", { "exceptions": ["[]"] }]*/ 2599 | 2600 | foo([bar, baz]); 2601 | foo([bar, baz], 1); 2602 | ``` 2603 | 选项 "never", { "exceptions": ["[]"] } 的 **正确** 代码示例: 2604 | ``` 2605 | /*eslint space-in-parens: ["error", "never", { "exceptions": ["[]"] }]*/ 2606 | 2607 | foo( [bar, baz] ); 2608 | foo( [bar, baz], 1); 2609 | ``` 2610 | 选项 "always", { "exceptions": ["[]"] } 的 **错误** 代码示例: 2611 | ``` 2612 | /*eslint space-in-parens: ["error", "always", { "exceptions": ["[]"] }]*/ 2613 | 2614 | foo( [bar, baz] ); 2615 | foo( [bar, baz], 1 ); 2616 | ``` 2617 | 选项 "always", { "exceptions": ["[]"] } 的 **正确** 代码示例: 2618 | ``` 2619 | /*eslint space-in-parens: ["error", "always", { "exceptions": ["[]"] }]*/ 2620 | 2621 | foo([bar, baz]); 2622 | foo([bar, baz], 1 ); 2623 | ``` 2624 | 选项 "never", { "exceptions": ["()"] }] 的 **错误** 代码示例: 2625 | ``` 2626 | /*eslint space-in-parens: ["error", "never", { "exceptions": ["()"] }]*/ 2627 | 2628 | foo((1 + 2)); 2629 | foo((1 + 2), 1); 2630 | ``` 2631 | 选项 "never", { "exceptions": ["()"] }] 的 **正确** 代码示例: 2632 | ``` 2633 | /*eslint space-in-parens: ["error", "never", { "exceptions": ["()"] }]*/ 2634 | 2635 | foo( (1 + 2) ); 2636 | foo( (1 + 2), 1); 2637 | ``` 2638 | 选项 "always", { "exceptions": ["()"] }] 的 **错误** 代码示例: 2639 | ``` 2640 | /*eslint space-in-parens: ["error", "always", { "exceptions": ["()"] }]*/ 2641 | 2642 | foo( ( 1 + 2 ) ); 2643 | foo( ( 1 + 2 ), 1 ); 2644 | ``` 2645 | 选项 "always", { "exceptions": ["()"] }] 的 **正确** 代码示例: 2646 | ``` 2647 | /*eslint space-in-parens: ["error", "always", { "exceptions": ["()"] }]*/ 2648 | 2649 | foo(( 1 + 2 )); 2650 | foo(( 1 + 2 ), 1 ); 2651 | ``` 2652 | "empty" 例外关注空括号,与其他例外作用一样,与第一个选项相反。 2653 | 2654 | 选项 "never", { "exceptions": ["empty"] }] 的 **错误** 代码示例: 2655 | ``` 2656 | /*eslint space-in-parens: ["error", "never", { "exceptions": ["empty"] }]*/ 2657 | 2658 | foo(); 2659 | ``` 2660 | 选项 "never", { "exceptions": ["empty"] }] 的 **正确** 代码示例: 2661 | ``` 2662 | /*eslint space-in-parens: ["error", "never", { "exceptions": ["empty"] }]*/ 2663 | 2664 | foo( ); 2665 | ``` 2666 | 选项 "always", { "exceptions": ["empty"] }] 的 **错误** 代码示例: 2667 | 2668 | /*eslint space-in-parens: ["error", "always", { "exceptions": ["empty"] }]*/ 2669 | 2670 | foo( ); 2671 | ``` 2672 | 选项 "always", { "exceptions": ["empty"] }] 的 **正确** 代码示例: 2673 | 2674 | /*eslint space-in-parens: ["error", "always", { "exceptions": ["empty"] }]*/ 2675 | 2676 | foo(); 2677 | ``` 2678 | 你可以在 "exceptions" 数组中包含多个项。 2679 | 2680 | 选项 "always", { "exceptions": ["{}", "[]"] }] 的 **错误** 代码示例: 2681 | ``` 2682 | /*eslint space-in-parens: ["error", "always", { "exceptions": ["{}", "[]"] }]*/ 2683 | 2684 | bar( {bar:'baz'} ); 2685 | baz( 1, [1,2] ); 2686 | foo( {bar: 'baz'}, [1, 2] ); 2687 | ``` 2688 | 选项 "always", { "exceptions": ["{}", "[]"] }] 的 **正确** 代码示例: 2689 | ``` 2690 | /*eslint space-in-parens: ["error", "always", { "exceptions": ["{}", "[]"] }]*/ 2691 | 2692 | bar({bar:'baz'}); 2693 | baz( 1, [1,2]); 2694 | foo({bar: 'baz'}, [1, 2]); 2695 | ``` 2696 | ### arrow-parens 2697 | 2698 | > 要求箭头函数的参数使用圆括号 2699 | 2700 | **Rule Details** 2701 | 2702 | 该规则强制箭头函数的参数使用圆括号括起来,不论参数数量如何。例如: 2703 | ``` 2704 | /*eslint-env es6*/ 2705 | 2706 | // Bad 2707 | a => {} 2708 | 2709 | // Good 2710 | (a) => {} 2711 | ``` 2712 | 这种风格将帮助你找到被错误地包含到条件语句中的箭头函数(=>),其本意是想使用比较语句的,比如>= 2713 | ``` 2714 | /*eslint-env es6*/ 2715 | 2716 | // Bad 2717 | if (a => 2) { 2718 | } 2719 | 2720 | // Good 2721 | if (a >= 2) { 2722 | } 2723 | ``` 2724 | 该规则可以配置在不需要使用圆括号时,阻止圆括号的使用。 2725 | ``` 2726 | /*eslint-env es6*/ 2727 | 2728 | // Bad 2729 | (a) => {} 2730 | 2731 | // Good 2732 | a => {} 2733 | ``` 2734 | **Options** 2735 | 2736 | 该规则有一个字符串选项和一个对象选项。 2737 | 2738 | 字符串选项: 2739 | 2740 | - "always" (默认) 要求在所有情况下使用圆括号将参数括起来。 2741 | - "as-needed" 当只有一个参数时允许省略圆括号。 2742 | 2743 | 2744 | "as-needed" 选项的对象属性: 2745 | 2746 | - "requireForBlockBody": true 修改 as-needed 规则以便如果函数体在一个指令块中(被花括号括起来)要求使用圆括号把参数括起来。 2747 | 2748 | **always** 2749 | 2750 | 默认选项 "always" 的 **错误** 代码示例: 2751 | ``` 2752 | /*eslint arrow-parens: ["error", "always"]*/ 2753 | /*eslint-env es6*/ 2754 | 2755 | a => {}; 2756 | a => a; 2757 | a => {'\n'}; 2758 | a.then(foo => {}); 2759 | a.then(foo => a); 2760 | a(foo => { if (true) {} }); 2761 | ``` 2762 | 默认选项 "always" 的 **正确** 代码示例: 2763 | ``` 2764 | /*eslint arrow-parens: ["error", "always"]*/ 2765 | /*eslint-env es6*/ 2766 | 2767 | () => {}; 2768 | (a) => {}; 2769 | (a) => a; 2770 | (a) => {'\n'} 2771 | a.then((foo) => {}); 2772 | a.then((foo) => { if (true) {} }); 2773 | ``` 2774 | **If Statements** 2775 | 2776 | 该选项的一个好处是,它阻止了在条件语句中不正确地使用箭头函数。 2777 | ``` 2778 | /*eslint-env es6*/ 2779 | 2780 | var a = 1; 2781 | var b = 2; 2782 | // ... 2783 | if (a => b) { 2784 | console.log('bigger'); 2785 | } else { 2786 | console.log('smaller'); 2787 | } 2788 | // outputs 'bigger', not smaller as expected 2789 | ``` 2790 | if语句的内容是个箭头函数,不是比较语句。 2791 | 2792 | 如果需要使用箭头函数,它需要被圆括号括起来以消除歧义。 2793 | ``` 2794 | /*eslint-env es6*/ 2795 | 2796 | var a = 1; 2797 | var b = 0; 2798 | // ... 2799 | if ((a) => b) { 2800 | console.log('truthy value returned'); 2801 | } else { 2802 | console.log('falsey value returned'); 2803 | } 2804 | // outputs 'truthy value returned' 2805 | ``` 2806 | 下面是另一个示例: 2807 | ``` 2808 | /*eslint-env es6*/ 2809 | 2810 | var a = 1, b = 2, c = 3, d = 4; 2811 | var f = a => b ? c: d; 2812 | // f = ? 2813 | ``` 2814 | f 是个箭头函数,a 是其参数,返回的结果是 b ? c: d。 2815 | 2816 | 应该被重写为: 2817 | ``` 2818 | /*eslint-env es6*/ 2819 | 2820 | var a = 1, b = 2, c = 3, d = 4; 2821 | var f = (a) => b ? c: d; 2822 | ``` 2823 | **as-needed** 2824 | 2825 | 选项 "as-needed" 的 **错误** 代码示例: 2826 | ``` 2827 | /*eslint arrow-parens: ["error", "as-needed"]*/ 2828 | /*eslint-env es6*/ 2829 | 2830 | (a) => {}; 2831 | (a) => a; 2832 | (a) => {'\n'}; 2833 | a.then((foo) => {}); 2834 | a.then((foo) => a); 2835 | a((foo) => { if (true) {} }); 2836 | ``` 2837 | 选项 "as-needed" 的 **正确** 代码示例: 2838 | ``` 2839 | /*eslint arrow-parens: ["error", "as-needed"]*/ 2840 | /*eslint-env es6*/ 2841 | 2842 | () => {}; 2843 | a => {}; 2844 | a => a; 2845 | a => {'\n'}; 2846 | a.then(foo => {}); 2847 | a.then(foo => { if (true) {} }); 2848 | (a, b, c) => a; 2849 | (a = 10) => a; 2850 | ([a, b]) => a; 2851 | ({a, b}) => a; 2852 | ``` 2853 | **requireForBlockBody** 2854 | 2855 | 选项 { "requireForBlockBody": true } 的 **错误** 代码示例: 2856 | ``` 2857 | /*eslint arrow-parens: [2, "as-needed", { "requireForBlockBody": true }]*/ 2858 | /*eslint-env es6*/ 2859 | 2860 | (a) => a; 2861 | a => {}; 2862 | a => {'\n'}; 2863 | a.map((x) => x * x); 2864 | a.map(x => { 2865 | return x * x; 2866 | }); 2867 | a.then(foo => {}); 2868 | ``` 2869 | 选项 { "requireForBlockBody": true } 的 **正确** 代码示例: 2870 | ``` 2871 | /*eslint arrow-parens: [2, "as-needed", { "requireForBlockBody": true }]*/ 2872 | /*eslint-env es6*/ 2873 | 2874 | (a) => {}; 2875 | (a) => {'\n'}; 2876 | a => ({}); 2877 | () => {}; 2878 | a => a; 2879 | a.then((foo) => {}); 2880 | a.then((foo) => { if (true) {} }); 2881 | a((foo) => { if (true) {} }); 2882 | (a, b, c) => a; 2883 | (a = 10) => a; 2884 | ([a, b]) => a; 2885 | ({a, b}) => a; 2886 | ``` 2887 | -------------------------------------------------------------------------------- /packages/antd-table/README.md: -------------------------------------------------------------------------------- 1 | 2 | 这个星期都很忙,从早忙到晚,往往回到家已经快11点了。。。 3 | 在负责的一个vue项目中,遇到antd-table的小坑,笔记。 4 | 需求:页面里有个table,点击编辑可以编辑该table,保存数据并展示到页面上来 5 | 6 | 7 | 8 | 第一种方法就是把编辑态的table做成子组件(且叫editeTable),通过v-show判断是否进入编辑态来显示隐藏。先仿造原本父组件(且叫fatherTable),做了一些基本的table样式,子组件editeTable里的tr每格皆为antd-Form表单输入框,接收fatherTable的data数据,用Form的API——validateFields校验并获取输入域的值,进行编辑,用户编辑完后,点保存,然后editeTable里的数据通过$emit函数showPage()传递给fatherTable,覆盖掉fatherTable原本的data数据,这样即可实现。以下为部分代码(不全): 9 | 10 | ```JS 11 | // 父组件中引用 12 | 17 | 18 | 19 | // 子组件js 20 | export default { 21 | props: { 22 | editeData: Object, 23 | editeType: Boolean 24 | }, 25 | mounted() { 26 | this.initDate(); 27 | }, 28 | watch: { 29 | editeType: function() { 30 | // console.log(this.editeType); 31 | if(this.editeType){ 32 | setTimeout(()=>{ 33 | this.initDate(); 34 | },200) 35 | // this.initDate(); 36 | // console.log(111,this.editeData) 37 | } 38 | else { 39 | this.form.setFieldsValue(this.entityinfo); 40 | } 41 | }, 42 | methods: { 43 | handleSearch(e) { 44 | e.preventDefault(); 45 | this.form.validateFields((error, values) => { 46 | // console.log('error', error); 47 | // console.log('Received values of form: ', values); 48 | // console.log(values); 49 | this.$emit('showPage', values) 50 | }); 51 | this.from.validateFields(); 52 | } 53 | } 54 | ``` 55 | 56 | 另一种方法是用antd-table自带的编辑edite功能,这个功能可以实现对每一行的数据进行定点编辑,但是遇到一个坑,如果我编辑态也是做成一个子组件的话,就需要先在子组件通过props取到父组件传来的值data,但我们都知道子组件是没有权利更改父组件传过来的值,这时候我们需要定义一个新的变量newdata,通过深拷贝data给newdata赋值,但细看antd文档就知道,antd-table里的数据需要每一条数据都有一个属于自己的key值,然后我们的data并没有key值,此时就需要遍历newdata,给每个对象就push一个key值。然后在newdata上进行操作。 57 | 58 | ```js 59 | this.newData = [...this.data] || []; 60 | this.newData.forEach((item,index) => { 61 | item.key = index; 62 | } 63 | ``` 64 | 而且要注意一点就是,antd-table的dataIndex和scopedSlots必须为同名,否则不生效,这是第二个坑,所以newdata在初始化数据要注意。之后编辑获取到新的newdata,便可以通过$emit给父组件传值,得到编辑后的效果。 65 | 66 | 以下为antd-table的部分实例代码: 67 | ```js 68 | const columns = [{ 69 | title: 'name', 70 | dataIndex: 'name', 71 | width: '25%', 72 | scopedSlots: { customRender: 'name' }, 73 | }, { 74 | title: 'operation', 75 | dataIndex: 'operation', 76 | scopedSlots: { customRender: 'operation' }, 77 | }] 78 | 79 | const data = [] 80 | for (let i = 0; i < 100; i++) { 81 | data.push({ 82 | key: i.toString(), 83 | name: `Edrward ${i}`, 84 | age: 32, 85 | address: `London Park no. ${i}`, 86 | }) 87 | } 88 | ``` -------------------------------------------------------------------------------- /packages/background/readme.md: -------------------------------------------------------------------------------- 1 | ### 修改vscode背景图 2 | 3 | 1. 打开vscode,在Extensions中搜索并download “background”插件。 4 | 2. 打开setting,找到“在setting.json 中编辑”。 5 | 3. 在用户设置中输入以下代码,按下ctrl + s,重启vscode。 6 | 7 | ```JS 8 | //background 的相关配置 9 | "update.enableWindowsBackgroundUpdates": true, 10 | "background.customImages": [ 11 | "file:///C:/Users/MyUserName/Documents/girl7.png",//图片地址 12 | "file:///C:/Users/MyUserName/Documents/girl6.png"//图片地址 13 | ], 14 | "background.style": { 15 | "content":"''", 16 | "pointer-events":"none", 17 | "position":"absolute",//图片位置 18 | "width":"100%", 19 | "height":"100%", 20 | "z-index":"99999", 21 | "background.repeat":"no-repeat",h 22 | "background-size":"30%,30%",//图片大小 23 | "opacity":0.3 //透明度 24 | }, 25 | { 26 | "content":"''", 27 | "pointer-events":"none", 28 | "position":"absolute",//图片位置 29 | "width":"100%", 30 | "height":"100%", 31 | "z-index":"99999", 32 | "background.repeat":"no-repeat", 33 | "background-size":"30%,30%",//图片大小 34 | "opacity":0.3 //透明度 35 | }, 36 | "background.useFront": true, 37 | "background.useDefault": false 38 | ``` 39 | ![](https://act.weixin.qq.com/static/images/201906/2b2d67f80d4e10240954f2a7b84cdf50.png) 40 | 41 | 我在这里放入了两张图片,通常我们开发需要分屏操作,按下ctrl+\时一屏就会显示一张图片 42 | 43 | **注**:vscode更新后,以管理员身份重启,否则无效 -------------------------------------------------------------------------------- /packages/basic_theory/images/React.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mtonhuang/blog/f5c42844a71529ec8752f79ef1963ce7db205886/packages/basic_theory/images/React.png -------------------------------------------------------------------------------- /packages/basic_theory/readme.md: -------------------------------------------------------------------------------- 1 | ## React基础理论 2 | 3 | 整理了React基础理论,做成了思维导图。 4 | 5 | 如果想要更深入的理解React,还需要系统性的学习。 6 | 7 | 有需要请download高清图,喜欢的请给个star ^_^ 8 | 9 | ![](https://github.com/mtonhuang/bolg/blob/master/React/basic_theory/images/React.png) 10 | -------------------------------------------------------------------------------- /packages/collect/2019.02.28/readme.md: -------------------------------------------------------------------------------- 1 |   原来架构设计比较多关注的是横向的分层,即数据层,逻辑层和UI层。而组件化架构必须同时关注纵向的隔离和解耦。在分层和分模块后,每一个业务组件由三层各自存在的部署包组成,包本身是一个包含了技术组件和服务组件的一个结合体。由数据层,逻辑层,界面层三层的三个业务包可以构成一个完整的具备独立功能的业务组件。 2 | 3 |   我理解的组件化开发是将复杂并混乱的页面逻辑,分割成一个个独立的业务单元。就像下图的房子,把门,屋顶,窗户以及墙体分开,最后拼凑在一起,组成一个房子。 4 | 5 | ![](https://github.com/mtonhuang/bolg/blob/master/images/home.png) 6 | 7 |   本周整理收集了一下GitHub上的几个比较热门的项目,用于组件化开发、提升开发效率。 8 | 9 | 一、ice - 模板库 10 | 丰富模板一键创建,提供多种垂直领域模板,快速创建项目,支持风格切换,满足个性化需求; 11 | 特点: 模板自定义创建, 区块可视化组装, 布局自定义生成, 物料自定义接入, 项目仪表盘插件化。已接入三大框架:React,Vue,Angular。 12 | 13 | github:https://github.com/alibaba/ice 14 | 15 | 效果图如图: 16 | 17 | ![](https://github.com/mtonhuang/bolg/blob/master/images/ice.png) 18 | 19 | 开源协议:MIT 20 | 21 | 二、jqPaginator - 基于jquery的分页组件 22 | 简洁、高度自定义的jQuery分页组件,适用于多种应用场景。 23 | 24 | github:https://github.com/keenwon/jqPaginator 25 | 26 | 效果如图: 27 | 28 | ![](https://github.com/mtonhuang/bolg/blob/master/images/source_2%20(5).png) 29 | 30 | 开源协议:MIT 31 | 32 | 三、react-spring - 动画组件库 33 | Helping react-motion and animated to become best friends. 34 | 35 | 更友好的动画库,效果酷炫,拥有总多贡献者。 36 | 37 | github:https://github.com/drcmda/react-spring 38 | 39 | 演示地址: http://react-spring.surge.sh/ 40 | 41 | 效果如图: 42 | 43 | ![](https://github.com/mtonhuang/bolg/blob/master/images/source_2%20(1).png) 44 | 45 | 开源协议:ISC 46 | 47 | 四、iview-weapp - 小程序UI组件库 48 | 组件库还是挺丰富的,基本可以满足需求。 49 | 50 | github:https://github.com/TalkingData/iview-weapp 51 | 52 | ![](https://github.com/mtonhuang/bolg/blob/master/images/source_2%20(2).png) 53 | 54 | 开源协议:MIT 55 | 56 | 五、react-window - 表格和列表的组件 57 | 看了一下源码,还是比较方便的,能直接引入,快速搭建页面 58 | 59 | github:https://github.com/bvaughn/react-window 60 | 61 | 演示地址:  https://react-window.now.sh/ 62 | 63 | 效果如图: 64 | 65 | ![](https://github.com/mtonhuang/bolg/blob/master/images/source_2%20(4).png) 66 | 67 | 示例代码: 68 | 69 | ```js 70 | import { FixedSizeList as List } from 'react-window'; 71 | 77 | {({ index, style }) => ( 78 |
79 | Row {index} 80 |
81 | )} 82 | 83 |
84 | ``` 85 | 开源协议:MIT 86 | -------------------------------------------------------------------------------- /packages/collect/2019.03.06/readme.md: -------------------------------------------------------------------------------- 1 | 2 | 一、wx-charts - 小程序图标组件 3 | 4 | 微信小程序图表工具,charts for WeChat small app,基于canvas绘制,体积小巧 5 | 6 | 支持图标类型: 7 | 8 | - 饼图 pie 9 | - 圆环图 ring 10 | - 线图 line 11 | - 柱状图 column 12 | - 区域图 area 13 | - 雷达图 radar 14 | - github:https://github.com/xiaolin3303/wx-charts 15 | 16 | 效果图如图: 17 | 18 | 19 | ![](https://github.com/mtonhuang/bolg/blob/master/images/source(1).png) 20 | 21 | 22 | 开源协议:MIT 23 | 24 | 二、v-charts - 基于vue2.0的图表组件 25 |   在使用 echarts 生成图表时,经常需要做繁琐的数据类型转化、修改复杂的配置项,v-charts 的出现正是为了解决这个痛点。基于 Vue2.0 和 echarts 封装的 v-charts 图表组件,只需要统一提供一种对前后端都友好的数据格式设置简单的配置项,便可轻松生成常见的图表。 26 | 27 | github:https://github.com/ElemeFE/v-charts 28 | 29 | 文档:https://v-charts.js.org/#/ 30 | 31 | 兼容性:支持所有现代浏览器及 IE10+ ,包括 pc 端和移动端。 32 | 33 | 效果图如图: 34 | 35 | ![](https://github.com/mtonhuang/bolg/blob/master/images/source(2).gif) 36 | 37 | 示例代码: 38 | 39 | ```js 40 | 43 | 55 | 56 | ``` 57 | 开源协议:MIT 58 | 59 | 三、vue-amap - 基于vue2.x和高德地图的组件 60 | github:https://github.com/ElemeFE/vue-amap 61 | 62 | 文档:https://elemefe.github.io/vue-amap 63 | 64 | 兼容性:支持所有现代浏览器及 IE10+ ,包括 pc 端和移动端。 65 | 66 | 效果图如图: 67 | 68 | ![](https://github.com/mtonhuang/bolg/blob/master/images/source(3).png) 69 | 70 | 示例代码: 71 | 72 | ```js 73 | // 引入vue-amap 74 | import VueAMap from 'vue-amap'; 75 | Vue.use(VueAMap); 76 | 77 | // 初始化vue-amap 78 | VueAMap.initAMapApiLoader({ 79 | // 高德的key 80 | key: 'YOUR_KEY', 81 | // 插件集合 82 | plugin: [ 83 | 'AMap.Autocomplete', 'AMap.PlaceSearch', 'AMap.Scale', 'AMap.OverView', 84 | 'AMap.ToolBar', 'AMap.MapType', 'AMap.PolyEditor', 'AMap.CircleEditor' 85 | ], 86 | // 高德 sdk 版本,默认为 1.4.4 87 | v: '1.4.4' 88 | }); 89 | 90 | 91 | ``` 92 | 93 | 开源协议:MIT 94 | 95 | 四、dayjs - 轻量的处理时间和日期的js组件库 96 | 97 | - 和 Moment.js 相同的 API 和用法 98 | - 不可变数据 (Immutable) 99 | - 支持链式操作 (Chainable) 100 | - 国际化 I18n 101 | - 仅 2kb 大小的微型库 102 | - 全浏览器兼容 103 | github:https://github.com/iamkun/dayjs 104 | 105 | 示例代码: 106 | 107 | ```js 108 | import 'dayjs/locale/es' // 按需加载 109 | 110 | dayjs.locale('es') // 全局使用西班牙语 111 | 112 | dayjs('2018-05-05').locale('zh-cn').format() // 在这个实例上使用简体中文 113 | import advancedFormat from 'dayjs/plugin/advancedFormat' // 按需加载插件 114 | 115 | dayjs.extend(advancedFormat) // 使用插件 116 | 117 | dayjs().format('Q Do k kk X x') // 使用扩展后的API 118 | 119 | ``` 120 |  开源协议:MIT 121 | 122 | 五、react-move - 动画组件库 123 | 124 | ReactiveMove具有美观,可数据驱动的Rection动画(Fackbook出品) 125 | 126 | github:https://github.com/react-tools/react-move 127 | 128 | 效果图如图: 129 | 130 | ![](https://github.com/mtonhuang/bolg/blob/master/images/source(5).gif) 131 | 132 | ![](https://github.com/mtonhuang/bolg/blob/master/images/source(6).gif) 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 开源协议:MIT 165 | 166 | 感谢浏览! -------------------------------------------------------------------------------- /packages/collect/good_net/readme.md: -------------------------------------------------------------------------------- 1 | ### 分享一些有用的前端网站(珍藏版) 2 | 3 | #### 工具类 4 | 5 | - [最全的各式在线工具](http://tool.oschina.net/) 6 | 7 | - [全面理解Git](https://juejin.im/post/582bd0b4da2f600063d4f89e) 8 | 9 | - [解决冲突](https://www.liaoxuefeng.com/wiki/896043488029600/900004111093344) 10 | 11 | - [webpack4.0用之初体验](https://www.cnblogs.com/cangqinglang/p/8964460.html) 12 | 13 | - [VSCode 常用快捷键](https://blog.csdn.net/p358278505/article/details/74221214) 14 | 15 | - [VSCode 插件配置](https://juejin.im/post/5a08d1d6f265da430f31950e) 16 | 17 | - [字体生成器](https://www.fontke.com/tool/fontface/) 18 | 19 | - [FontSpark(在线预览字体)](https://fontspark.app/) 20 | 21 | - [loading gif图](https://loading.io/#) 22 | 23 | - [图片压缩TinyPNG](https://tinypng.com/) 24 | 25 | - [gif压缩](https://www.yasuotu.com/) 26 | 27 | - [hexo设置](https://blog.csdn.net/ganzhilin520/article/details/79047249) 28 | 29 | - [Hexo 博客从搭建部署到SEO优化等详细教程](https://www.jianshu.com/p/efaf72aab32e?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation) 30 | 31 | - [leanCloud数据管理](https://avoscloud.com/dashboard/login.html#/signin) 32 | 33 | - [Web端上传数据——JavaScript客户端签名直传](https://help.aliyun.com/document_detail/31925.html?spm=a2c4g.11186623.6.633.32Z8FV) 34 | 35 | #### 前端知识类 36 | 37 | - [常见HTTP状态码](https://blog.csdn.net/q1056843325/article/details/53147180) 38 | 39 | - [Node入门](https://www.nodebeginner.org/index-zh-cn.html) 40 | 41 | - [Node专业中文社区](https://cnodejs.org/) 42 | 43 | - [如何防止XSS攻击?](https://tech.meituan.com/2018/09/27/fe-security.html) 44 | 45 | - [如何防止CSRF攻击?](如何防止CSRF攻击?) 46 | 47 | - [前端实现文件的断点续传](https://www.cnblogs.com/imwtr/p/5957391.html) 48 | 49 | - [了解真实的『REM』手机屏幕适配](https://juejin.im/entry/5833f572128fe1006ccda98b) 50 | 51 | - [服务器返回的14种常见HTTP状态码](https://blog.csdn.net/q1056843325/article/details/53147180) 52 | #### 面试类 53 | 54 | - [几道高级前端面试题解析](https://www.cnblogs.com/cangqinglang/p/8964448.html) 55 | 56 | - [各大公司技术分享论坛](https://www.devfeed.cn/new) 57 | 58 | - [BAT大厂面试题](https://www.jianshu.com/p/c70989bd5f29) 59 | 60 | - [剑指offer](https://www.nowcoder.com/ta/coding-interviews) 61 | 62 | - [梦魇小栈的blog](https://blog.ihoey.com/posts/Interview/2018-02-28-alibaba-interview.html) 63 | 64 | 65 | #### 编码规则类 66 | 67 | - [如何看待 CSS 中 BEM 的命名方式](https://www.zhihu.com/question/21935157) 68 | 69 | - [JavaScript Standard Style](https://standardjs.com/) 70 | 71 | - [Airbnb JavaScript 编码风格指南](https://segmentfault.com/a/1190000013040555) 72 | 73 | 74 | #### 音乐类 75 | 76 | - [一个好听的白噪音网站](https://noises.online/) 77 | 78 | - [木偶人 —— 薛之谦](https://y.qq.com/portal/player.html) 79 | -------------------------------------------------------------------------------- /packages/filter&&map&&reduce/readme.md: -------------------------------------------------------------------------------- 1 | ### 实现一个map,filter函数 2 | 3 | 1. map 作用是生成一个新数组,遍历原数组,将每个元素拿出来做一些变换然后放入到新的数组中。 4 | 5 | ```js 6 | [1, 2, 3].map(val=> val + 1) // -> [2, 3, 4] 7 | ``` 8 | 9 | 另外 map 的回调函数接受三个参数,分别是当前索引元素,索引,原数组。 10 | 11 | ```js 12 | array.map(function(currentValue, index, arr), thisIndex) 13 | ``` 14 | function(currentValue, index, arr)必须为一个函数,数组中的每个元素都会执行这个函数。其中函数参数: 15 | 16 | - currentValue:必须。当前元素的的值。 17 | - index:可选。当前元素的索引。 18 | - arr:可选。当前元素属于的数组对象。 19 | 20 | 2. filter 的作用也是生成一个新数组,在遍历数组的时候将返回值为 true 的元素放入新数组,我们可以利用这个函数删除一些不需要的元素。 21 | 22 | ```JS 23 | let array = [1, 2, 3] 24 | let newArray = array.filter(val => val !== 2) 25 | console.log(newArray) // [1, 3] 26 | ``` 27 | 28 | 和 map 一样,filter 的回调函数也接受三个参数,用处也相同。 29 | 30 | 3.forEach 方法用于调用数组的每个元素,并将元素传递给回调函数。 31 | 32 | 语法: 33 | 34 | ```JS 35 | array.forEach(function(currentValue, index, arr), thisValue) 36 | ``` 37 | 38 | - currentValue:必塡,当前元素。 39 | - index:可选,当前元素的索引。 40 | - arr:可选,当前元素所属的数组对象。 41 | - thisValue:可选,传递给函数的值一般用this值,如果这个参数为空,"undefined"会传递给"this"值。(这个参数一般很少塡) 42 | 43 | ```JS 44 | [1, 2, 3].forEach(item => console.log(item + 1)) //2,3,4 45 | ``` 46 | 47 | 最后我们来讲解 reduce 这块的内容,同时也是最难理解的一块内容。reduce 可以将数组中的元素通过回调函数最终转换为一个值。 48 | 49 | 如果我们想实现一个功能将函数里的元素全部相加得到一个值,可能会这样写代码。 50 | 51 | ```JS 52 | const arr = [1, 2, 3] 53 | let total = 0 54 | for (let i = 0; i < arr.length; i++) { 55 | total += arr[i] 56 | } 57 | console.log(total) //6 58 | ``` 59 | 60 | 但是如果我们使用 reduce 的话就可以将遍历部分的代码优化为一行代码。 61 | 62 | ```JS 63 | const arr = [1, 2, 3] 64 | const sum = arr.reduce((acc, current) => acc + current, 0) 65 | console.log(sum) 66 | ``` 67 | 对于 reduce 来说,它接受两个参数,分别是回调函数和初始值,接下来我们来分解上述代码中 reduce 的过程 68 | 69 | - 首先初始值为 0,该值会在执行第一次回调函数时作为第一个参数传入 70 | - 回调函数接受四个参数,分别为累计值、当前元素、当前索引、原数组,后三者想必大家都可以明白作用,这里着重分析第一个参数 71 | - 在一次执行回调函数时,当前值和初始值相加得出结果 1,该结果会在第二次执行回调函数时当做第一个参数传入 72 | - 所以在第二次执行回调函数时,相加的值就分别是 1 和 2,以此类推,循环结束后得到结果 6 73 | 74 | 想必通过以上的解析大家应该明白 reduce 是如何通过回调函数将所有元素最终转换为一个值的,当然 reduce 还可以实现很多功能,接下来我们就通过 reduce 来实现 map 函数 75 | 76 | (当然我们可以通过for循环来实现filter和map函数,这里就不再赘述,下面我们用reduce实现。) 77 | 78 | ```js 79 | const mapArray = [1, 2, 3].map(val => val * 2) 80 | const reduceArray = arr.reduce((total, curr) => { 81 | total.push(curr * 2) 82 | return total 83 | }, []) 84 | console.log(mapArray, reduceArray) // [2, 4, 6] 85 | ``` 86 | 87 | 当然filter函数也按道理可得: 88 | 89 | ```JS 90 | const arr = [1, 2, 3] 91 | const filterArray = arr.filter(value => value !== 2) 92 | const reduceArray = arr.reduce((total, curr) => { 93 | if(curr !== 2) { 94 | total.push(curr) 95 | } 96 | return total 97 | }, []) 98 | console.log(filterArray , reduceArray) // [1, 3] -------------------------------------------------------------------------------- /packages/h5/h5_adaptation/readme.md: -------------------------------------------------------------------------------- 1 | >H5页面开发适配方案,平时的一些小总结,希望能帮助到大家。 2 | 3 | ## 样式重置 4 | 5 | ```css 6 | body,p,ul,ol,li,dl,dt,dd,h1,h2,h3,h4,h5,h6,form,fieldset,legend,input,select,textarea,button,th,td{margin:0;padding:0;} 7 | h1,h2,h3,h4,h5,h6{font-size:100%;} 8 | ul,dl,ol{list-style:none;} 9 | img,fieldset,input[type="submit"]{border:0 none;} 10 | img{display:inline-block;overflow:hidden;vertical-align:top;} 11 | em{font-style:normal;} 12 | strong{font-weight:normal;} 13 | table{border-collapse:collapse;border-spacing:0;} 14 | button,input[type="button"]{cursor:pointer;border:0 none;} 15 | textarea{word-wrap:break-word;resize:none;} 16 | menu{margin:0;padding:0;} 17 | body{-webkit-user-select:none;-webkit-text-size-adjust:100%!important;font-family:Helvetica;} 18 | input[type="number"]{-webkit-user-select:text;} 19 | a,button,input,img{-webkit-touch-callout:none;} 20 | input,select,textarea{outline:none;} 21 | a,button,input{-webkit-tap-highlight-color:rgba(0,0,0,0);} 22 | html,body{height:100%;} 23 | a{text-decoration:none;} 24 | ``` 25 | 26 | 27 | ## viewport模板 28 | 29 | 30 | ```css 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 标题 40 | 41 | 42 | 43 | 44 | 内容 45 | 46 | 47 | 48 | ``` 49 | 50 | ## 特殊机型适配 51 | 52 | iPhoneX,作为唯一有刘海手机,对页面适配带来了问题,可以用如下代码适配iPhoneX。 53 | 54 | ```css 55 | /* iPhoneX适配 */ 56 | @media only screen and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) { 57 | .class{} 58 | } 59 | ``` 60 | 61 | iPhone4,作为窄屏手机,分辨率为960x640,web窗口的高度仅有832px,容易引起适配的问题,如页面的主体按钮被隐藏在屏幕外,通常需要对它做特殊适配 62 | 63 | ```css 64 | /* 适配iPhone4 */ 65 | @media (device-height:480px) and (-webkit-min-device-pixel-ratio:2){ 66 | .class{} 67 | } 68 | ``` 69 | -------------------------------------------------------------------------------- /packages/h5/h5_drap/index.js: -------------------------------------------------------------------------------- 1 | document.body.onload = function(){ 2 | //Apply some basic styles 3 | var css = ".draggable{cursor: move;display: inline-block;} .text{display: inline-block; cursor: move;} .text:focus{cursor: auto;} .text-wrapper{width: 100%;position: relative;} .wrap{position: absolute;margin: auto;top: 0;bottom: 0;left: 0;right: 0;}';"; 4 | var style = document.createElement('style'); 5 | if (style.styleSheet) { 6 | style.styleSheet.cssText = css; 7 | } else { 8 | style.appendChild(document.createTextNode(css)); 9 | } 10 | document.getElementsByTagName('head')[0].appendChild(style); 11 | 12 | // Select all elements with the 'draggable' class and stores them in the 'elements' variable 13 | var elements = document.querySelectorAll(".draggable"); 14 | 15 | // Variable to store z index of last moved element 16 | z = 1; 17 | 18 | // Stores the last edited element 19 | var tgt; 20 | 21 | var clickTimer = null; 22 | 23 | // Adds event listeners to every element that has the draggable class 24 | for(var i = 0; i < elements.length; i++){ 25 | elements[i].addEventListener('mousedown', drag); 26 | elements[i].addEventListener('touchstart', handleTouch); 27 | b = elements[i].getBoundingClientRect(); 28 | // Calculate the initial offset of the element from the top left of the page and stores it as a property of the element 29 | elements[i].initialOffsetX = b.left + window.scrollX; 30 | elements[i].initialOffsetY = b.top + window.scrollY; 31 | elements[i].x = b.left; 32 | elements[i].y = b.top; 33 | elements[i].style.cursor = "move"; 34 | document.addEventListener('mouseup', end); 35 | document.addEventListener('touchend', end); 36 | }; 37 | 38 | function handleTouch(evt){ 39 | evt.preventDefault(); 40 | drag(evt); 41 | if (clickTimer == null) { 42 | clickTimer = setTimeout(function () { 43 | clickTimer = null; 44 | }, 500) 45 | } else { 46 | clearTimeout(clickTimer); 47 | clickTimer = null; 48 | editText(evt); 49 | } 50 | } 51 | 52 | // Main logic, called when the mouse is clicked 53 | function drag(event) { 54 | // Prevent default behavior and increase z index to bring the new element to the front 55 | event.preventDefault(); 56 | moving = true; 57 | z = z+1; 58 | 59 | // Identify which element was clicked and store in the 'tgt' element, then get position properties of it 60 | tgt = event.target; 61 | b = tgt.getBoundingClientRect(); 62 | var x = b.left + window.scrollX; 63 | var y = b.top + window.scrollY; 64 | offsetX = event.pageX || event.changedTouches[0].pageX; 65 | offsetY = event.pageY || event.changedTouches[0].pageY; 66 | 67 | document.addEventListener('mousemove',function(e) { 68 | // If the page has been clicked and an element is being dragged 69 | if(moving === true){ 70 | // Calculate the new position of the element, relative to the top left of the page 71 | var dx = e.pageX - offsetX + x - tgt.initialOffsetX; 72 | var dy = e.pageY - offsetY + y - tgt.initialOffsetY; 73 | // Apply the styles to the element 74 | var position = 'transform: translate('+dx+'px, '+dy+'px);z-index:'+z+';'; 75 | tgt.setAttribute('style', position); 76 | }; 77 | }); 78 | document.addEventListener('touchmove',function(e) { 79 | var touches = e.changedTouches; 80 | // If the page has been clicked and an element is being dragged 81 | if(moving === true){ 82 | for(let i = 0; i < touches.length; i++){ 83 | // Calculate the new position of the element, relative to the top left of the page 84 | var dx = touches[i].pageX - offsetX + x - tgt.initialOffsetX; 85 | var dy = touches[i].pageY - offsetY + y - tgt.initialOffsetY; 86 | // Apply the styles to the element 87 | var position = 'transform: translate('+dx+'px, '+dy+'px);z-index:'+z+';'; 88 | tgt.setAttribute('style', position); 89 | } 90 | }; 91 | }); 92 | 93 | }; 94 | 95 | function end(evt) { 96 | // When the mouse is lifted up, set moving to false 97 | moving = false; 98 | }; 99 | 100 | function outerHeight(el) { 101 | var height = el.offsetHeight; 102 | var style = getComputedStyle(el); 103 | 104 | height += parseInt(style.marginTop) + parseInt(style.marginBottom); 105 | return height; 106 | } 107 | } -------------------------------------------------------------------------------- /packages/h5/h5_drap/mobile_drap.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |

Hello, World!

17 |
18 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /packages/h5/h5_drap/mobile_jq.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 25 | 26 | 27 | 67 | 68 | 69 | 70 | 71 | 72 |
73 | H5 拖拽 74 |
75 | 76 | -------------------------------------------------------------------------------- /packages/h5/h5_drap/readme.md: -------------------------------------------------------------------------------- 1 | ## h5移动端拖拽 2 | 3 | 今天有一个需求是需要用到原生JS来对H5移动端进行拖拽,要求不用到插件以及JQ等库。参考了github以及google的一些代码,进行了增删查改。具体代码请看文件 [index.js](https://github.com/mtonhuang/bolg/tree/master/h5/h5_drap/index.js)。 4 | 5 | 另外h5_drapp文件夹里附带了JQ版本实现的效果,可以看看。 6 | 7 | 代码参考链接:[Draggin](https://github.com/chrisnunes57/Draggin.js) 8 | 9 | 10 | -------------------------------------------------------------------------------- /packages/h5/h5_problem/readme.md: -------------------------------------------------------------------------------- 1 | > 平时在开发h5项目中,遇到一些h5的小坑,在此分享(2.17 update again)。 2 | 3 | ### 1.微信端禁止页面分享 4 | ```js 5 | //隐藏微信分享菜单,当点击右上角时不会出现分享的选项 6 | document.addEventListener('WeixinJSBridgeReady', function onBridgeReady() { 7 | WeixinJSBridge.call('hideOptionMenu'); 8 | }); 9 | ``` 10 | 11 | ### 2.禁止页面上下拉动 12 | 13 | ```js 14 | //禁止页面上拉下拉 15 | document.body.addEventListener('touchmove', function (e) { 16 | e.preventDefault(); //阻止默认的处理方式 17 | }, {passive: false}); //passive 参数不能省略,用来兼容ios和android 18 | ``` 19 | 20 | 21 | 22 | ### 3.禁止页面上下拉,但不影响页面内部scroll 23 | 2.20号 在某个微信群里关注到第2点的代码会影响页面内部的scroll,用之前的项目测试了一下,确实如此。 24 | 25 | 但如果去掉第2点的代码,虽然内部的scroll可以正常使用了,但橡皮筋的效果出现了。 26 | 27 | 这怎么能忍呢?于是遍寻良药: 28 | 29 | ```js 30 | 31 | var overscroll = function(el) { 32 | //el需要滑动的元素 33 | el.addEventListener("touchstart", function() { 34 | var top = el.scrollTop, 35 | totalScroll = el.scrollHeight, 36 | currentScroll = top + el.offsetHeight; 37 | //被滑动到最上方和最下方的时候 38 | if (top === 0) { 39 | el.scrollTop = 1; //0~1之间的小数会被当成0 40 | } else if (currentScroll === totalScroll) { 41 | el.scrollTop = top - 1; 42 | } 43 | }); 44 | el.addEventListener("touchmove", function(evt) { 45 | if (el.offsetHeight < el.scrollHeight) evt._isScroller = true; 46 | }); 47 | }; 48 | overscroll(document.querySelector(".aaaa")); //允许滚动的区域 49 | document.body.addEventListener("touchmove",function(evt) { 50 | if (!evt._isScroller) { 51 | evt.preventDefault(); //阻止默认事件(上下滑动) 52 | } 53 | }, 54 | { passive: false } //这行依旧不可以省略,用于兼容ios 55 | ); 56 | ``` 57 | 58 | ### 4.禁止微信浏览器图片长按出现菜单(适用于微信6.0以上版本) 59 | 网上挺多代码无效,下面亲测有效(兼容ios与android) 60 | 61 | ```css 62 | img{ 63 | pointer-events:none; 64 | -webkit-pointer-events:none; 65 | -ms-pointer-events:none; 66 | -moz-pointer-events:none; 67 | } 68 | ``` 69 | 70 | ### 5.禁止微信浏览器长按“显示在浏览器打开”(适用于微信6.0以上版本) 71 | 72 | ```js 73 | document.oncontextmenu=function(e){ 74 | //或者return false; 75 | e.preventDefault(); 76 | }; 77 | ``` 78 | 79 | (注:如果是微信6.0以下的版本,则第3 , 4点一句 -webkit-touch-callout: none 即可解决的出现菜单和“显示在浏览器打开“的问题,当然最好都加上就完美了o(* ̄︶ ̄*)o) 80 | 81 | ### 6.禁止复制文本 82 | 83 | ```css 84 | -webkit-user-select: none; 85 | user-select: none; 86 | -webkit-touch-callout: none; 87 | ``` 88 | 89 | ### 7.禁止浏览器调整字体大小 90 | ios解决方案: 91 | 92 | ```css 93 | body { 94 | -webkit-text-size-adjust: 100% !important; 95 | text-size-adjust: 100% !important; 96 | -moz-text-size-adjust: 100% !important; 97 | } 98 | ``` 99 | android解决方案(用自执行函数强制禁止用户修改字体大小): 100 | 101 | ```js 102 | (function () { 103 | if (typeof WeixinJSBridge == "object" && typeof WeixinJSBridge.invoke == "function") { 104 | handleFontSize(); 105 | } else { 106 | if (document.addEventListener) { 107 | document.addEventListener("WeixinJSBridgeReady", handleFontSize, false); 108 | } else if (document.attachEvent) { 109 | document.attachEvent("WeixinJSBridgeReady", handleFontSize); 110 | document.attachEvent("onWeixinJSBridgeReady", handleFontSize); 111 | } 112 | } 113 | 114 | function handleFontSize() { 115 | // 设置字体为默认大小并且重写事件 116 | WeixinJSBridge.invoke('setFontSizeCallback', {'fontSize': 0}); 117 | WeixinJSBridge.on('menu:setfont', function () { 118 | WeixinJSBridge.invoke('setFontSizeCallback', {'fontSize': 0}); 119 | }); 120 | } 121 | })(); 122 | ``` 123 | 124 | ### 8.移动端伪类:active无效的解决方法 125 | 做项目做到一半,测试按钮点击态的时候,在PC和安卓机测试上都没有问题,但到ios移动端就出现无效的情况,google了一下。 126 | 127 | 在mozilla社区找到了答案: 128 | 129 | > [1] By default, Safari Mobile does not use the :active state unless there is a touchstart event handler on the relevant element or on the . 130 | 131 | 需要在按钮元素或者body/html上绑定一个touchstart事件才能激活:active状态。 132 | 133 | ```js 134 | document.body.addEventListener('touchstart', function (){}); //...空函数即可 135 | ``` 136 | -------------------------------------------------------------------------------- /packages/leetcode/readme.md: -------------------------------------------------------------------------------- 1 | #### leetcode刷题心得分享 2 | > 博主在刷leetcode时认为还不错的题目,大部分有发布个人题解(貌似反响还可以~),在此记录心得并且分享给大家(以下排序不分先后,并在代码里附带了本人leetcode链接,欢迎大家踩踩)[以下题目都来自leetcode,本人题解] 3 | 4 | ##### 369. 两个数组的交集 5 | 6 | 给定两个数组,编写一个函数来计算它们的交集。 7 | 8 | 示例 1: 9 | 10 | 输入:nums1 = [1,2,2,1], nums2 = [2,2] 11 | 输出:[2] 12 | 示例 2: 13 | 14 | 输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4] 15 | 输出:[9,4] 16 | 17 | 18 | ~ 解题思路: 19 | 20 | - 妙用includes和set方法 21 | 22 | ```JS 23 | /** 24 | * @param {number[]} nums1 25 | * @param {number[]} nums2 26 | * @return {number[]} 27 | */ 28 | var intersection = function(nums1, nums2) { 29 | let arr = []; 30 | for(let i = 0; i < nums1.length; i++) { 31 | if (nums2.includes(nums1[i])) { 32 | arr.push(nums1[i]); 33 | } 34 | } 35 | return Array.from(new Set(arr)) 36 | }; 37 | 作者:mtonhuang 38 | 链接:https://leetcode-cn.com/problems/intersection-of-two-arrays/solution/includessettou-lan-jie-fa-by-mtonhuang/ 39 | 来源:力扣(LeetCode) 40 | 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 41 | ``` 42 | --- 43 | 44 | ##### 1464. 数组中两元素的最大乘积 45 | 46 | 给你一个整数数组 nums,请你选择数组的两个不同下标 i 和 j,使 (nums[i]-1)*(nums[j]-1) 取得最大值。 47 | 48 | 请你计算并返回该式的最大值。 49 | 50 | 示例: 51 | 输入:nums = [3,4,5,2] 52 | 输出:12 53 | 解释:如果选择下标 i=1 和 j=2(下标从 0 开始),则可以获得最大值,(nums[1]-1)*(nums[2]-1) = (4-1)*(5-1) = 3*4 = 12 54 | 55 | ~ 解题思路: 56 | - 求出最大值a 57 | - 删除a 58 | - 再求出最大值b 59 | - 进而求出答案 60 | 61 | ```JS 62 | /** 63 | * @param {number[]} nums 64 | * @return {number} 65 | */ 66 | var maxProduct = function (nums) { 67 | let a = Math.max(...nums); 68 | nums.splice(nums.indexOf(a), 1, ''); 69 | let b = Math.max(...nums); 70 | return (a - 1) * (b - 1) 71 | }; 72 | 作者:mtonhuang 73 | 链接:https://leetcode-cn.com/problems/maximum-product-of-two-elements-in-an-array/solution/miao-yong-mathmaxspliceindexof-by-mtonhuang/ 74 | 来源:力扣(LeetCode) 75 | 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 76 | ``` 77 | --- 78 | ##### 面试题 08.05. 递归乘法 79 | 递归乘法。 写一个递归函数,不使用 * 运算符, 实现两个正整数的相乘。可以使用加号、减号、位移,但要吝啬一些。 80 | 81 | 示例1: 82 | 83 | 输入:A = 1, B = 10 84 | 输出:10 85 | 示例2: 86 | 87 | 输入:A = 3, B = 4 88 | 输出:12 89 | 90 | ~ 解题思路: 91 | - 不用递归的方法 92 | 93 | ```JS 94 | /** 95 | * @param {number} A 96 | * @param {number} B 97 | * @return {number} 98 | */ 99 | var multiply = function (A, B) { 100 | let res = 0; 101 | for(let i = 0; i < B; i++) { 102 | res+= A 103 | } 104 | return res; 105 | }; 106 | 107 | 作者:mtonhuang 108 | 链接:https://leetcode-cn.com/problems/recursive-mulitply-lcci/solution/mnben-zhi-jiu-shi-mnci-m-by-mtonhuang/ 109 | 来源:力扣(LeetCode) 110 | 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 111 | ``` 112 | --- -------------------------------------------------------------------------------- /packages/live-miniprogram/live-miniprogram.md: -------------------------------------------------------------------------------- 1 | 小程序直播必要步骤:(原文有图,但鉴于隐私安全,皆del掉) 2 | 3 | 4 | 1、登陆开平后台,点击直播 5 | 6 | 7 | 8 | 2、创建直播间 9 | 10 | 11 | 12 | 3、填写对应的主播信息,开播时间等 13 | 14 | 15 | 16 | 4、上传分享卡片封面图与直播间背景图(商品货架可不选),点击创建 17 | 18 | 19 | 20 | 5、开播码与分享码 21 | 5.1、开播码即主播本人扫码,如图 22 | 23 | 24 | 25 | 5.2、分享码即用户进入直播间的方式之一,点击分享有一个二维码,如图 26 | 27 | 28 | 29 | 6、直播过程效果 30 | 31 | -------------------------------------------------------------------------------- /packages/node/node.md: -------------------------------------------------------------------------------- 1 | #### node版本切换 2 | 3 | 下载nvm window || mac 版本,到node官网download对应版本的node,如 node-v10.16.2 或者 node-v12.0.8 4 | 解压,将文件夹放到C:\Users\xxx\AppData\Roaming\nvm 中 5 | ```JS 6 | // 查看node版本 7 | nvm list 8 | // 切换版本 9 | nvm use xxx 10 | ``` 11 | -------------------------------------------------------------------------------- /packages/promise-mini/dologin.md: -------------------------------------------------------------------------------- 1 | 2 | > 解决繁琐的小程序登录态管理的组件。 3 | 4 | [TOC] 5 | 6 | ### 一、背景 7 | 8 | 在微信***小程序中,用户可以通过多种方式登录账号,进入对应的业务页面。但是,如果每次登录都需要清除登录态,再根据获得的code重新登录的话,这样代码较冗余,请求较多,性能较差。因此,我们需要写一个dologin组件。 9 | 10 | ### 二、业务要求 11 | 12 | ***小程序登录账号,一共有几大业务来源,分别是: 13 | 1. 公众号模板消息; 14 | 2. 外部小程序带登录态跳转; 15 | 3. 注册后登录; 16 | 4. 切换账号。 17 | 18 | 其中需要带入参数做跳转登录的业务入口有外部小程序带登录态跳转、注册后登录、公众号模板消息。 19 | 20 | dologin组件根据业务来源以及带入的参数,进行重置登录账号或者登录账号。 21 | 22 | ### 三、技术难点 23 | 24 | 1. 业务来源的多样性 25 | 业务来源比较多,未来还可能增加,保证dologin组件应对不同来源的兼容与包容性,方便后期各个来源状态管理、维护等。 26 | 27 | 2. 重置登录的设计 28 | 巧妙运用setStorage缓存,请求初始化getStorage获取登录态,对比新旧登录态,如果发现不同,则重置登录,如果相同,则运用当前登录态登录。如果getStorage无值,则直接登录。 29 | 30 | ### 四、前端设计 31 | 32 | dologin组件的本质是一个登录的过程,具体实现原理如下: 33 | 34 | 1. 不同业务来源带入参数(目标页url,***参数,xxx参数); 35 | 2. dologin组件初始化获取入参; 36 | 3. 全局获取登录态; 37 | 4. 登录; 38 | 5. 到达目标页面url(默认首页)。 39 | 40 | 其中第3步全局获取登录态后,根据是否有本地缓存登录态又分为重置登录和直接登录。如果没有本地缓存,则直接登录;反之,校验登录态是否一致,如果一致则直接登录,如果不一致,则重置登录。 41 | 42 | 43 | ![dologin实现原理图](https://wx.gtimg.com/resource/feuploader/202103/9893d8d604aa67511a9838905335e9de_989x713.png) 44 | 45 | ### 五、源码地址 46 | 47 | dologin(暂不开源),以上实现原理供参考。 48 | ### Contributing 49 | 50 | mtonhuang -------------------------------------------------------------------------------- /packages/promise-mini/map.md: -------------------------------------------------------------------------------- 1 | ### 一、封装地图授权函数 2 | 3 | ```js 4 | 5 | // 1、点击事件后调起授权(app.ts,全局调用) 6 | async getAuthAdress(longitude: number, latitude: number, name: string, address: string) { 7 | let getLongitude = longitude, 8 | getLatitude = latitude, 9 | getName = name, 10 | getAddress = address; 11 | try { 12 | let resSetting = await wx.getSetting(); 13 | console.log(resSetting) 14 | if (resSetting.errMsg === 'getSetting:ok' && 15 | typeof resSetting.authSetting['scope.userLocation'] !== 'undefined' && 16 | resSetting.authSetting['scope.userLocation'] === false) { 17 | //TODO: 没有授权 18 | console.log('拒绝了授权') 19 | wx.showModal({ 20 | title: '提示', 21 | content: '需要获取您的地理位置,请确认授权,否则地图功能将无法正常使用', 22 | confirmText: '立即授权', 23 | success: async function (data) { 24 | if (data.confirm) { 25 | console.log('resModal.confirm') 26 | await wx.openSetting({ 27 | 28 | }) 29 | } else if (data.cancel) { 30 | await wx.openLocation({ 31 | latitude: Number(getLatitude), 32 | longitude: Number(getLongitude), 33 | scale: 14, 34 | name: getName, 35 | address: getAddress 36 | }) 37 | } 38 | } 39 | }) 40 | } else { 41 | //TODO: 授权 42 | await wx.getLocation({ type: 'gcj02' }); 43 | await wx.openLocation({ 44 | latitude: Number(getLatitude), 45 | longitude: Number(getLongitude), 46 | scale: 14, 47 | name: getName, 48 | address: getAddress 49 | }) 50 | } 51 | } 52 | catch { 53 | //TODO: 报错 54 | } 55 | }, 56 | 57 | // 2、初始化页面调起地图授权函数(业务侧自我调用) 58 | async getLocation() { 59 | const that = this; 60 | try { 61 | let res = await wx.getSetting(); 62 | if (res.authSetting['scope.userLocation'] !== true) { 63 | //TODO: 如果没有授权,则不需要操作 64 | that.getTest(); 65 | } else { 66 | //TODO: 如果授权,则获取经纬度 67 | let res = await wx.getLocation({ type: 'gcj02' }); 68 | let latitude = res.latitude; 69 | let longitude = res.longitude; 70 | if (latitude && longitude) { 71 | that.setData({ 72 | user_latitude: `${latitude}`, 73 | user_longitude: `${longitude}` 74 | }) 75 | } 76 | that.getTest(); 77 | } 78 | } 79 | catch { 80 | that.getTest(); 81 | //TODO: 报错 82 | } 83 | } 84 | 85 | ``` 86 | 87 | ### 二、在业务页面调用 88 | 89 | ```js 90 | const app = getApp(); 91 | // index.js 92 | let longitude = Number(e.currentTarget.dataset.longitude) || 0; 93 | let Latitude = Number(e.currentTarget.dataset.latitude) || 0; 94 | let Name = e.currentTarget.dataset.name || ''; 95 | let Address = e.currentTarget.dataset.address || ''; 96 | app.longitude(longitude, Latitude, Name, Address) 97 | 98 | ``` 99 | 100 | 101 | **Contributing** 102 | 103 | mtonhuang 104 | -------------------------------------------------------------------------------- /packages/promise-mini/pullload.md: -------------------------------------------------------------------------------- 1 | ### 一、在 components 中创建 pullLoad 2 | 3 | ``` 4 | // pullLoad.wxml 5 | 12 | ``` 13 | 14 | ``` 15 | // pullLoad.less 16 | .pull_load { 17 | font-size: 0; 18 | text-align: center; 19 | padding: 20rpx 0; 20 | margin-top: 30rpx; 21 | } 22 | .pull_dot { 23 | width: 12rpx; 24 | height: 12rpx; 25 | background: #acafb3; 26 | border-radius: 50%; 27 | display: inline-block; 28 | margin: 0 8rpx; 29 | -webkit-animation: pull_loading 0.6s infinite linear both; 30 | animation: pull_loading 0.6s infinite linear both; 31 | -webkit-animation-delay: -0.4s; 32 | animation-delay: -0.4s; 33 | } 34 | .pull_dot:nth-child(2) { 35 | -webkit-animation-delay: -0.2s; 36 | animation-delay: -0.2s; 37 | } 38 | .pull_dot:nth-child(3) { 39 | -webkit-animation-delay: 0s; 40 | animation-delay: 0s; 41 | } 42 | @-webkit-keyframes pull_loading { 43 | 0%,33.3% { 44 | opacity: 1; 45 | } 46 | 66.7%,100%{ 47 | opacity: .2; 48 | } 49 | } 50 | @keyframes pull_loading { 51 | 0%,33.3% { 52 | opacity: 1; 53 | } 54 | 66.7%,100%{ 55 | opacity: .2; 56 | } 57 | } 58 | ``` 59 | 60 | ### 二、在业务页面引入 61 | 62 | ``` 63 | // index.wxml 64 | 65 | 66 | 67 | 68 | 69 | 70 | {{item.text}} 71 | 72 | 73 | 74 | 75 | 76 | 77 | 暂无通知 78 | 79 | 80 | 81 |