大阳城集团娱乐网2138欢迎您!
大阳城集团娱乐网2138 > 计算机前端 > ES5中模仿块级作用域

ES5中模仿块级作用域

时间:2020-01-05

有一定JavaScript开发经验的人应该会熟悉下面这种立即执行函数的写法:

(function(name){ console.log('hello ' + name);// hello Bob})('Bob');

不过即使不熟悉也没关系,这里我会讲解这种写法的含义。

先来看下面这个更容易理解的示例:

var sayHello = function(name){ console.log('hello ' + name);}var name = 'Bob';sayHello(name);// hello Bob

首先使用函数表达式的语法定义函数sayHello,然后声明一个变量name,紧接着调用sayHello,参数为name。

由于变量name没有在其他地方被使用,这里其实也就没有必要声明,可以使用更简便的语法,直接把值传递给函数:

sayHello('Bob');// hello Bob

按照这种逻辑,假如sayHello也是只执行一次,sayHello(name)不是也可以写成下面这种形式吗?

function(name){ console.log('hello ' + name)}('Bob');//Uncaught SyntaxError: Unexpected token (

但是运行发现报错了,这是因为JavaScript将function关键字当作一个函数声明的开始,而函数声明的后面是不能跟圆括号的。不过,函数表达式的后面可以跟圆括号,要将函数声明转换成函数表达式,只要像下面这样给它加上一对圆括号即可:

(function(name){ console.log('hello ' + name);// hello Bob})('Bob');

也就是本文开头的立即执行函数,模仿块级作用域正是通过立即执行函数实现的。

来看下面的示例:

function outputNumbers(count){ for(var i = 0; i  count; ++i){ console.log(i); } console.log(i);// 5}outputNumbers(5);

在Java、C++等语言中,变量i只会在for循环的语句块中有定义,循环一旦结束,变量i就会被销毁。可是在JavaScript中,作用域只分为全局作用域和函数作用域,函数内部声明的变量是绑定在函数作用域对应的变量对象上的,也就是说这里的i是定义在函数的变量对象上的,在函数内部的任何位置都可以访问它,即使for循环结束,i依然存在。

但是如果用立即执行函数包裹for循环,情况就不一样了:

function outputNumbers(count){ (function(){ for(var i = 0; i  count; ++i){ console.log(i); } })(); console.log(i);//Uncaught ReferenceError: i is not defined}outputNumbers(5);

此时i绑定在内部立即执行函数的变量对象上,立即执行函数执行完毕就会销毁,i也会随之销毁。根据闭包机制,内部的立即执行函数也可以访问到count。这样就实现了块级作用域——无论在立即执行函数中声明什么变量都不会影响外部变量的使用。

这种技术也经常在全局作用域中被用在函数外部,从而限制向全局作用域中添加过多的变量和函数,避免冲突,例如:

(function(){ var now = new Date(); if(now.getMonth() == 0  now.getDate() == 1){ console.log('Happy new year!'); }})();

这段代码放在任何全局作用域中都可以在1月1日向用户显示祝贺新年的消息,不必担心全局作用域中是否定义了now变量,从而引起变量的覆盖等问题。

原文来自:

上一篇:没有了 下一篇:没有了