为了账号安全,请及时绑定邮箱和手机立即绑定

如何理解ESLint的no-inner-declarations规则?

如何理解ESLint的no-inner-declarations规则?

蝴蝶不菲 2019-03-08 15:11:13
如下代码:if (true) {    // 在某个条件分支下创建一个函数,并且只在这个分支内使用。    function a() {        // code...    }    a();}// 报错:"Move function declaration to program root. (no-inner-declarations)"要把函数定义在整个文档的最外层才行。我在网上搜索看到的说法是:ES6以前,函数声明只能在程序或另一个函数体的最前面,所以在代码块内部声明函数是错误的做法。另外,由于 javascript 中代码声明会被提升到代码当前作用域的最前面,所以在代码块内声明变量也是不明智的做法是不是在ES6之前,这样声明是语法错误?另外,我会把这个函数保持在它被调用之前,这样就不会发生变量提升了。其实我很郁闷,因为我的代码要根据不同场景执行不同的代码,有些函数只在某一个场景下使用。按照这个标准的话要把大量函数移出来,结果就是声明的这些函数有很多根本没有被调用。这样是不是会多占用资源?
查看完整描述

2 回答

?
Smart猫小萌

TA贡献1911条经验 获得超7个赞

1、题主第一个问题:想这样:


在某个条件分支下创建一个函数,并且只在这个分支内使用。

所以写出下面代码:


if (true) {

    // 在某个条件分支下创建一个函数,并且只在这个分支内使用。

    function a() {

        // code...

    }

    a();

}

但是,题主如果在 if 语句块之外访问函数 a,是可以的,因为


ES6 在非严格模式下块级函数的作用域会被提升到所在函数或全局环境的顶部,而不是代码块的顶部。

所以下面代码不会报错:


if (true) {

    // 在某个条件分支下创建一个函数,并且只在这个分支内使用。

    function a() {

        // code...

    }

    a();

}

a;//返回函数 a 

所以,题主想要的


在某个条件分支下创建一个函数,并且只在这个分支内使用

在非严格模式下,并没有实现,或者说,看起来实现了,但实际上没有,反而造成了全局变量污染且容易引起歧义;


在严格模式下,是实现了的,也就是说,上面的函数 a 只能在 if 语句块内访问,因为


ES6 会将 a() 函数视为块级声明,并允许它在定义所在的代码块内部被访问,且块级函数会被提升到所在代码块的顶部

2、题主的第二个问题:


是不是在ES6之前,这样声明是语法错误?

答:


在 ES3 或更早版本中,在代码块中声明函数(即块级函数)严格来说应当是一个语法错误,但所有的浏览器却都支持该语法。可惜的是,每个支持该语法的浏览器都有轻微的行为差异,所以最佳实践就是不要在代码块中声明函数(更好的选择是使用函数表达式)。

为了控制这种不兼容行为, ES5 的严格模式为代码块内部的函数声明引入了一个错误


3、题主的第三个问题:


另外,我会把这个函数保持在它被调用之前,这样就不会发生变量提升了。

题主请先去了解下函数声明语句的变量提升,题主的这句话代表题主并不理解变量提升;


https://img1.sycdn.imooc.com//5c8f04950001b96e06440063.jpg


4、题主的第四个问题:


其实我很郁闷,因为我的代码要根据不同场景执行不同的代码,有些函数只在某一个场景下使用。按照这个标准的话要把大量函数移出来,结果就是声明的这些函数有很多根本没有被调用。这样是不是会多占用资源?

这个不太清楚,我粗浅的认为不会,因为 js 有垃圾回收机制,如果没有闭包,正常情况下都会被垃圾回收掉的,闭包题主请单独查资料,或者戳这

参考:深入理解ES6-中-非扫描版


查看完整回答
反对 回复 2019-03-18
?
茅侃侃

TA贡献1842条经验 获得超21个赞

重新回答一份

1.ESLint只是一个代码检查工具,它报错不代表代码是错误的
2.ESLint的提示都是有原因的
3.在代码块儿中定义函数自己使用的做法很常见,不喜欢提示可以关掉这个选项
4.如果“提升”整个概念是指编译阶段将所有的声明都挪到执行代码的前面,那我可以接受。为什么会将声明的部分提到最前面,我觉得应该是方便申请内存吧。
5.我也不支持在代码块(尤其是逻辑分支)中定义自己使用的函数。如果你能确定这个方法绝对没有地方再使用,大可这么做,语法也支持,协作起来也只有你自己知道这段代码并维护。
6.方法定义在哪里都一样,代码体积也不会变,也省不了多少内存。在逻辑分支里定义了函数基本上也会马上调用,理论上修改起来并不方便。

写在后面:这个语法是没有错误的,但是是存在的隐患的,所以ESLint告诉你不要这么做。你担心的占用资源问题是多余的,方法执行起来占用的资源才是你应该担心的。另外考虑到复用性和协作,即使是不同分支要执行不同代码,也不要在代码块儿内声明方法。复用性上不便于方法的复用,协作性上不便于别人修改你的代码。如果说需求是根据不同的条件需要不同的方法体,那为什么不把这个条件作为参数传入方法,在方法体中进行逻辑分支。ESLint给出的提示是根据设计模式和代码规范给出的,完全按照提示去做绝对没有坏处,不按照他说的做也不一定会报错。养成良好的代码习惯,学会去构建代码,而不是一味地实现逻辑,这也是ESLint这样的工具存在的目的。


查看完整回答
反对 回复 2019-03-18
  • 2 回答
  • 0 关注
  • 1313 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信