VitaLemon__的专栏

代码即文字

js变量作用域的一些例子

本来想要在“作用域”这个专题上自己总结出一些东西的,结果想了好久都没有形成一个固定的思路,也不想贸然拷贝网上的说法。所以,还是先记录几个容易犯错的小例子,以后再来形成总结吧。


1、“变量声明提升”

例子1:

var x = 'global';

function f1() {
    console.log(x);
}

function f2() {
    console.log(x);

    /*
        这里x的声明让f2的函数作用域中拥有了x这个变量,所以以后访问x的时候,不会再沿着作用域链上搜索
        而上面那一句把x打印出来的时候,x只是声明了但没有初始化
        所以输出undefined
    */
    var x = 'local';
}

f1();   // global
f2();   // undefined

例子2(摘自360校招笔试题):

var a, b;

(function () {
    console.log(a);// undefined
    console.log(b);// undefined

    var a = b = 0;// (1)

    console.log(a);// 0
    console.log(b);// 0
})();

console.log('window', a);// window undefined
console.log('window', b);// window 0

解释:这里最关键的是理解清楚语句(1)处的执行情况,这个语句做的工作实际上是:

b = 0;         // (2)
var a = b;     // (3)

   语句(2)执行之后,在匿名函数的scope中并没有找到b的声明,故这里修改的是全局scope中的b,也就是让window.b赋值为0了。所以,在语句(1)之前,window.b的值是undefined,在(1)之后,window.b就是0了,就算出了匿名函数,window.b也是0。
   语句(3)声明了a,那么匿名函数中所有出现的a都是本scope中的a,而不是window.a。所以,在a声明了却还没初始化的时候,a的值为undefined,初始化之后就是0了。而出了匿名函数之后,打印的是window.a的值,自然是undefined了。


2、js的函数作用域是静态作用域

var x = 'global';

function f1() {
    console.log(x);
    // 此函数被调用的时候,x在这里没有声明,所以会沿着作用域链开始寻找
    // 然而,Js的作用域是“静态”作用域,也就是说在声明函数的时候就可以确定而不必等到运行时
    // 所以,这里的作用域链为:f1-->window,所以输出window.x的值“global”
}

function f2() {
    var x = 'f2';

    // f2在函数内部调用f1
    f1();
}

f1();   // global
f2();   // global(并非f2)

如果把作用域的嵌套结构改成下面的样子,结果就会不一样:

var x = 'global';

function f1() {
    console.log(x);
}

function f2() {
    var x = 'f2'; // (1)

    // 将函数f1声明在f2内部,这样,作用域链就变成:
    // f1 --> f2 --> window
    // 所以输出的是f2的x即'f2'
    function f1() {
        console.log(x);
    }

    f1();
}

f1();   // global
f2();   // f2

举一反三,如果把上面(1)这一句放在f1被调用的后面,自然就输出“undefined”了:

var x = 'global';

function f1() {
    console.log(x);
}

function f2() {
    //var x = 'f2'; // (1)

    // 将函数f1声明在f2内部,这样,作用域链就变成:
    // f1 --> f2 --> window
    // 所以输出的是f2的x即'f2'
    function f1() {
        console.log(x);
    }

    f1();

    var x = 'f2'; // (1)
}

f1();   // global
f2();   // undefined

3、不加var修饰的变量,并不一定是window下的变量

例如下面这个小程序,很容易以为输出的是“global”,然而并不是:

function f1() {

    function f2() {
        x = 'global';   // (2)

        // 解释:
        // 这里x没有var关键字修饰,但也不一定就是指window.x
        // 根据作用域链:f2 --> f1 --> window
        // 首先,在f2中,并没有x的声明,所以去f1找
        // 然后,在f1中,语句(1)声明了有x,所以在这一层停止搜索x了
        // 也就是说,语句(2)修改的是f1函数作用域中的x
        // 所以最终,输出window.x的值是undefined
    }

    f2();

    var x = 10; // (1)
}

f1();
console.log(window.x);  // 结果:undefined
阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/VitaLemon__/article/details/52438164
文章标签: javascript
个人分类: JavaScript语言
上一篇AngularJS自定义指令directive:scope属性
下一篇html引入外部文件的路径问题
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭