ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
#### 函数作用域 由于bar中的i没有用到var来声明,导致i的声明自动跑到了foo的作用域中,与for循环中的i相互覆盖。导致执行foo函数的时候i一直被赋予3,无限循环下去 ``` function foo(){ function bar(a) { i = 3; console.log(a + i); } for(var i = 0; i< 10; i++){ bar(i * 2); } } ``` 区分函数表达式和函数声明:function关键字是否是声明语句中的第一个词(不仅仅是一行,而是整个声明中的位置),是-->函数声明,否-->函数表达式。立即执行函数前面有(,所以也是函数表达式。函数声明和函数表达式之间最重要的区别就是它们的名称标识符将会绑定在何处。 ``` var f1 = function(){...} function f2(){...} //二者均被绑定在所在的作用域中,可以直接通过f1()、f2()来调用 (function(){...})() //被绑定在了自身里,只能在...中访问它 ``` 函数表达式可以是匿名的,而函数声明不可以匿名 ``` setTimeout(function() { console.log(1); }, 1000) //function关键字并不位于整个声明语句的第一个词,所以该function是表达式,是匿名表达式,除了function内部外,任何地方都不能使用它 ``` 始终给函数一个名字是最佳实践,这有利于调试和维护 ``` setTimeout(function timeoutHandler() { console.log(1); }, 1000) ``` ``` (function(){})() (function(){}()) //二者在功能上是一致的 ``` #### 块作用域 ``` for(var i = 0; i < 10; i++){ console.log(i); } ``` i会被绑在外部作用域中,这也是为什么 ``` for(var i = 0; i < 10; i++){ element[i].onClick = function(){ console.log(i) } } ``` 最后的结果都是11的原因,因为click事件是异步函数,当你点击元素的时候for早就已经结束了,此时的i是11。 try/catch的catch会创建块级作用域,内部的变量只能在catch中使用。 块级作用域有利于垃圾回收: 点击事件并不需要data数据,按理说process执行完后data就会被回收,但由于click函数形成了覆盖整个作用域的闭包,导致该作用域内的一切资源都可能无法回收。 ``` function process(data){...} var data = {...} process(data); element.onClick = function(){...} ``` 使用块级作用域就可以解决该问题,告诉引擎该变量没必要再保存了 ``` function process(data){...} { let data = {...} process(data); } element.onClick = function(){...} ```