匿名函数模仿块级作用域

问题

【无块级作用域】JavaScript中没有块级作用域的概念。这意味着在块语句中定义的变量,实际上是在包含函数中而非语句中创建的。

function outputNumbers(count){
    for(var i = 0; i < count; i++){
        alert(i);
    }
    console.log(i);
}
outputNumbers(2);//弹出0,1输出2
//变量i是定义在outputNumbers()的活动对象中的,因此从它有定义开始,就可以在函数内部随时访问它。

  函数中的多重声明,对于多次声明同一个变量,JavaScript只会对后续的声明视而不见。

function outputNumbers(count){
    for(var i = 0; i < count; i++){
        alert(i);
    }
    var i;
    console.log(i);
}
outputNumbers(2);//弹出0,1输出2

解决过程

【过渡写法】先创建一个匿名函数,并把匿名函数赋值给变量someFunction,然后通过在函数名称后面添加一对圆括号来调用函数。

var someFunction = function(){
    //这里是块级作用域
};
someFunction();

【错误写法】这种匿名函数直接跟圆括号会报错,因为JavaScript将function关键字当作一个函数声明的开始,而函数声明后面不能跟圆括号

function(){
    //这里是块级作用域
}();//出错

【正确写法】而函数表达式的后面可以跟圆括号,要将函数声明转换成函数表达式,只要给函数整体套上一个圆括号即可。

(function(){
    //这里是块级作用域
})();
//定义并立即调用了一个匿名函数。将函数声明包含在一对圆括号中,表示它实际上是一个函数表达式。而紧随其后的另一对圆括号会立即调用这个函数。

解决办法

【设置块级作用域】在重写后的outputNumbers()函数中,在for循环外部插入了一个私有作用域。在匿名函数中定义的任何变量,都会在执行结束时被销毁。因此,变量i只能在循环中使用。

function outputNumbers(count){
    (function(){
        for(var i = 0; i < count; i++){
            alert(i);
        }
    })()
    console.log(i);
}
outputNumbers(2);//弹出0,1,然后报错,提示i is not defined

应用场景

这种技术经常在全局使用域中被用在函数外部,从而限制向全局作用域中添加过多的变量和函数。通过创建私有作用域,每个开发人员既可以使用自己的变量,又不必担心搞乱全局作用域。

(function(){
    var now = new Date();
    if(now.getMonth() === 0 && now.getDate() === 1){
        alert("happy new year!");
    }
})();
//代码中的变量now是匿名函数中的局部变量,不必在全局作用域中创建它。

好处

这种做法可以减少闭包占用的内存问题,因为没有指向匿名函数的引用,只要匿名函数执行完毕,就可以立即销毁其作用域链了。

时间: 2024-12-26 06:22:31

匿名函数模仿块级作用域的相关文章

函数调用的几种方法 几种主流框架使用匿名函数模仿块级作用域的方式

函数调用的几种方法 js 里函数调用有4种模式:方法调用.正常函数调用.构造器函数调用.apply/call 调用.同时,无论哪种函数调用除了你声明时定义的形参外,还会自动添加2个形参,分别是 this 和 arguments.这里你既然问 this,那么就只谈 this.this 的值,在上面4中调用模式下,分别会绑定不同的值.分别来说一说:方法调用:这个很好理解,函数是一个对象的属性,比如 var a = { v : 0, f : function(xx) { this.v = xx; }

函数表达式-模仿块级作用域

模仿块级作用域 Javascript中没有块级作用域的概念,这意味着在块语句中定义的变量,实际上是在包含函数中而非语句中创建的 1 function outputNumbers(count){ 2 for (var i = 0; i < count; i++){ 3 console.log(i); 4 } 5 console.log(i); 6 } 在for循环中定义的局部变量i可以再for循环外访问,因为变量i是定义在outputNumbers()的活动对象中的,因此从它有定义开始,就可以在函

JS函数表达式 -- 模仿块级作用域

JavaScript没有块级作用域的概念.这意味着在语句中定义的变量,实际上是在包含函数中而非语句中创建的. 1 function outputNumbers(count){ 2 for(var i=0; i<count; i++){ 3 alert("In: " + i); 4 } 5 var i; 6 alert("Out: " + i); 7 } 8 outputNumbers(2); //In: 0 In: 1 Out:2 在这个函数中定义了一个for

javascript模仿块级作用域

作用域有词法作用域和块级作用域之分,javascript属于词法作用域,而在java.C++中却是块级作用域.在javascript中,只有函数能够创建作用域,作用域是以function作为边界的. 先看一段代码: function outPut(){ for(i=0;i<5;i++) { console.log(i);//0,1,2,3,4 第一个i } console.log(i);//5 第二个i }; 解释:在java等语言中,for循环这块代码中的i变量将会被销毁,第二个i打印出来就是

javascript中的闭包、模仿块级作用域和私有变量

闭包是指有权访问另一个函数作用域中的变量的函数.创建闭包的常见方式为:在一个函数内部创建另一个函数. "当某个函数被调用时,会创建一个执行环境(execution context)及相应的作用域链.然后,使用arguments和其他命名参数的值来初始化函数的活动对象(activation object).但在作用域链中,外部函数的活动对象始终处于第二位,外部函数的外部函数的活动对象出于第三位.....直至作用域链终点的全局执行环境." function creawteCompariso

javascirpt怎样模仿块级作用域(js高程笔记)

因为javascript没有块级作用域的概念,所以在块语句中定义的变量,实际上是在包括函数中而非语句中创建的. 如: function outputNumbers(count){ for(var i=0; i< count; i++){ alert(i); } alert(i); } 这个函数中定义了一个for循环,而变量 i 的初始值被设置为0.在Java.C++等语言中,变量i仅仅会在for循环的语句块中有定义,循环一旦结束,变量i就会被销毁.但是Javascript中,变量i是定义在out

javascirpt如何模仿块级作用域(js高程笔记)

由于javascript没有块级作用域的概念,所以在块语句中定义的变量,实际上是在包含函数中而非语句中创建的. 如: function outputNumbers(count){ for(var i=0; i< count; i++){ alert(i); } alert(i); } 这个函数中定义了一个for循环,而变量 i 的初始值被设置为0.在Java.C++等语言中,变量i只会在for循环的语句块中有定义,循环一旦结束,变量i就会被销毁.可是Javascript中,变量i是定义在outp

JS 模仿块级作用域

function outputNumbers(count) { for (var i=0; i<count; i++) { console.log(i); } var i;  // 重新声明变量 console.log(i);  // 计数 } 上述中,重复声明了i变量,但是JS从来不会告诉你是否多次声明了同一变量:遇到这种情况,它只会对后续的声明视而不见 不过,它会执行后续声明中变量的初始化.匿名变量可以用来模仿块级作用域并避免这个问题. (function() { // 这里是块级作用域(私

js私有作用域(function(){})(); 模仿块级作用域

摘自:http://outofmemory.cn/wr/?u=http%3A%2F%2Fwww.phpvar.com%2Farchives%2F3033.html js没有块级作用域,简单的例子: for(var i=0;i<10;i++){ alert(i); } alert(i); for循环后的i,在其它语言像c.Java中,会在for结束后被销毁,但js在后续的操作中仍然能访问到i值,即for循环后的alert(i);会弹出数值i=10; js模仿块级作用域: (function(){