js中作用域的思考

2018-03-01 07:46:59来源:cnblogs.com作者:李老头人点击

分享

和传统的C,C++等语言不同,javascript中的作用域不是以花括号包围的块级作用域(block scope),不妨看看以下代码:

if(true){  var val = "test-val";  }console.log(val);

 在js中运行以上代码,控制台打印输出:“test-val”;而在C语言中,会报错,这是为什么呢?

  这是因为:JavaScript 的作用域完全是由函数来决定的。


函数作用域

在一个函数中定义的变量只对这一个函数有效,我们称之为函数作用域。当在函数内使用一个变量时,js首先会搜索函数作用域,又称为局部作用域。如果未找到,则搜索上层作用域,直至全局作用域。

举个栗子:

var name="global";var fn1 = function (){  console.log(name);  }var fn2 = function () {  var name="area";  console.log(name);};fn1(); //globalfn2(); // area

  就像你看到的,js的变量搜索是由内而外,函数作用域优先级最高!所以在执行fn2()时会优先取局部变量的值area。那么接下来的一短代码,可能会让你迷茫:

var name ="global";var fn = function () {  console.log(name);  var name = "area";}fn();// undefined

  不要迷茫!这是因为在执行fn()时,在console.log函数访问到变量name时,会优先从函数作用域内进行搜索,而这时恰巧能搜索到变量name,则会屏蔽掉上级的变量name。又加上在执行console.log(name)时,name变量还未被定义,或者我们称之为位初始化,就会输出undefined。

也有一部分人把上述现象称之为:变量提升。所谓变量提升,指的是在刚进入函数时,函数内部的所有变量都被定义了,但直到遇见var的时候,该变量才被初始化。在初始化之前的所有的引用,都会得到undefined。

函数作用域的嵌套

(function () {  var scope ="top";  (function(){    var scope = "middle";    (function () {      console.log(scope);//middle    })()  })()})()

  为什么会输出middle呢?这是因为在访问最内层的变量scope时,会优先搜索函数作用域,结果没搜到,则由内而外搜到其父级作用域middle。

有一点需要注意:函数作用域的嵌套关系由定义时决定,而不是由引用时决定。举个栗子:

var name ="top";var fn1 = function (){  console.log(name);}
fn1();//topvar fn2 = function () { var name="middle"; fn1();}fn2();//top

  为什么会得到top而不是middle呢?这是因为通过fn2调用fn1()时,访问的变量name不是fn2中的变量,而是其父级作用域的变量。 

全局作用域

在js中有一种特殊对象,在node中对应global对象,在浏览器中对应window对象。我们称之为全局对象,又称为全局作用域。它可以在js的整个作用域范围内被使用而不受限制。

满足以下几点可以称为全局对象:

» 在最外层定义的变量

» 全局对象的属性

» 变量的隐式声明,即不通过var声明的变量。

由于全局变量会造成变量污染,高度耦合性等缺点,所以应避免使用全局变量。

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台