微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

#我的21天#《你不知道的javascript》- D3

函数作用域

函数作用域的含义指的是,属于这个函数的全部变量都可以在整个函数的范围内使用及复用(事实上在嵌套的作用域中也可以使用)。

隐藏内部实现

可以通过函数声明的方式对一些代码片段进行包装,这样可以将这段代码声明的变量或函数隐藏在当前的函数作用域下面。
不过,为什么要提出“隐藏”变量和函数
有很多原因促成了这种基于作用域的隐藏方法,他们大都是从最小特权原则中引申出来的,也叫最小授权或最小暴露原则。这个原则是指在软件设计中,应该最小限度地暴露必要内容,而将其他内容都“隐藏”起来,比如某个模块或对象的API设计。
下面举个栗子:

向上面这样,在doSomething内部可以访问到全局函数doSomethingElse全局变量b,但是我们只在doSomething调用了这2个全局函数Ϙ量。对于其他任何函数作用域来说,提供对这2个全局函数Ϙ量的访问都是没有必要也是有“危险”的,因为这2个全局函数Ϙ量可能会面临被无意或有意的篡改。更为合理的设计将会将这些私有的具体内容隐藏在doSomething内部。现在我们来看下更好的设计:

现在bdoSomethingElse都无法从外部被访问,但是代码要实现的功能效果没有受到影响,设计上将具体内容私有化了,设计良好的软件都会依次进行实现。

函数作用域

通过函数来对变量和内部函数进行隐藏封装,可能会导致我们新建的这个函数对全局或外部作用域的污染。所以我们接下来可以通过立即执行匿名函数表达式来完成封装。
通常来讲,我们可以通过(function ( ) {…}) ()来创建一个匿名函数表达式,并且执行它。注意,在javascript中,我们是无法定义匿名函数申明的,所以不可以通过funciton() {..}的方式来申明函数(引擎会报错),必须要通过在完成嵌套(function( ) {..})的形式来创建一个匿名函数表达式。
当然,有利也有弊,匿名函数表达书的缺点同样不容我们忽视:

  • 匿名函数砸栈追踪中不会显示出有意义的函数名,使得调试很困难。

  • 函数需要引用自身的时候只能用已经过时的arguments.callee引用。还有就是在事件监听中,某些情况下需要通过传入函数名来显示的解除事件绑定。

  • 匿名函数省略的函数名使得这个函数理解性下降,我们不能通过查看函数名了解这个函数的具体作用而是的得查看这个函数的具体代码

解决上面的第三点现在看起来十分简单,我们只需要在执行函数表达式的时候指定函数名称就行了:

立即执行函数表达式

无论是通过(function(){…})( ) 还是(function(){}( ))的形式调用函数表达式都可以,具体的使用要看个人的喜好。
IIFE还有一种比较普遍的用法是将他们当作函数调用并且传递参数进去。例如:

这样做的好处是可以减少作用域的查找,提升代码的质量。
另外一种应用场景时解决undefined标识符的认值被错误覆盖而导致的异常。将一个参数命名为undefined,但是在对应的位置不传入任何的值,这样就可以保证在代码块中undefined标识符的值真的是undefined

代码挖了一个大坑 千万不要这么做!!!
(function IIFE(undefined) {
     var a;
     if(a === undefined) {
         console.log(“undefined is true here!");
     }
})( )

最后不得不提一下IIFE在UMD中的使用场景:

这样可以显示的倒置代码的运行顺序。

块级作用域

通常在javascript中没有类似c语言中的块级作用域,这也使得我们要更加小心翼翼地注意类似for循环中的代码可能对本层作用域产生的污染。

  • ES3开始 try/catch结构中的catch分句中具有块级作用域

  • 在ES6中引入了let/const关键字,用来在任意代码块中声明变量

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐