• javascript 作用域的一些小知识


    首先,奉献两个题目

    1.

     1 var foo = 1;
     2 function bar() {
     3     if (!foo) {
     4         var foo = 10;
     5     }
     6     console.log(foo); //返回10
     7 }
     8 bar();
     9 /****** 我是分割线******/
    10 var foo = 1;
    11 function bar() {
    12     if (!foo) {
    13         foo = 10;
    14     }
    15     console.log(foo); //返回1
    16 }
    17 bar();
    18 
    19 //why ?

    Ctr +A 可以看答案哦~

    why?先来看看一下ECMA上的描述

    /*
     * If the variable statement occurs inside a FunctionDeclaration, 
     * the variables are defined with function-local scope in that function.
     * Otherwise, they are defined with global scope (that is, they are created as members of the global object.
     * 如果变量声明实在函数内部,那么变量定义的是函数的局部范围,否则它将作为一个全局变量
     * 
     * Variables are created when the execution scope is entered. 
     * A Block does not define a new execution scope. Only Program and FunctionDeclaration produce a new scope. 
     * Variables are initialised to undefined when created. 
     * A variable with an Initialiser is assigned the value of its AssignmentExpression when the VariableStatement 
      is executed, * not when the variable is created. * * 变量的创建发生在程序执行到那一步 * 一个语句块并不定义一个新的执行作用域,只有程序和函数声明产生作用域 * 变量初始化的时候被初始化为undefined * 当执行变量声明的时候 ,变量才会由表达式赋值,而并非在变量产生的时候就有 *
    */

    看明白了没?

      总结:1.javascript 语言没有JAVA C++ 等块级作用域,if 判断,switch等不会使里面的声明的变量困在其中,而是作为块区域外的变量存在,只有函数声明产生新的作用域。

         2.变量的定义|初始化发生在进入程序但是还没执行前,变量初始化为undefined,当程序往下执行时,变量会被表达式赋值,这个时候变量采有值。

    看代码,由此我们将上面的代码改成如下!

     1 var foo = 1;
     2 function bar() {
     3     var foo;    //undefined,先声明
     4     console.log(foo)
     5     if (!foo) {
     6         foo = 10;   //10
     7     }
     8     console.log(foo); //返回10
     9 }
    10 bar();
    11 //第二个
    12 
    13 var foo = 1;
    14 function bar() {
    15     console.log('foo',foo); //1 因为函数体内没有foo,这个时候通过作用域链获取window的foo 变量
    16     if (!foo) {
    17         foo = 10;
    18     }
    19     console.log(foo); //返回1
    20 }
    21 bar(); 

    如何创建一个不影响其它程序的作用域呢,放在闭包内

     1 var foo = 1;
     2 function bar() {
     3     console.log("a",foo)
     4     if (foo) {
     5         (function(){
     6             var foo = 10;   //10
     7             console.log('foo',foo)
     8         })()
     9     }
    10     console.log(foo); //返回1
    11 }
    12 bar();

    在javascript中,一个名称进入作用域有四种基本方法( 作用域的提升)

     * Language-defined: All scopes are, by default, given the names this and arguments.
     * 语言本身所定义的
     * Formal parameters: Functions can have named formal parameters, 
     * which are scoped to the body of that function.
     * 函数参数
     * Function declarations: These are of the form function foo() {}.
     * 函数声明
     * Variable declarations: These take the form var foo;.
     * 变量声明
    function test() {
        foo(); // TypeError "foo is not a function"
        bar(); // "this will run!"
        var foo = function () { // function expression assigned to local variable 'foo'
            alert("this won't run!");
        }
        function bar() { // function declaration, given the name 'bar'
            alert("this will run!");
        }
    }
    test();

      如上代码,foo 是没有被定义的,在表达式var foo = function(){} 之前,foo被“提升”到了前面,但是它的主体部份(赋值表达式)要等到执行到它才赋值,因此相当于被赋值为undefined,当执行到这个表达式时 ,它才被赋值为function,因此foo()执行错误。而function bar 是声明,它整体都被“提升”到了最前面,因此可以执行。

    总结就是在函数首部定义所有需要的变量,这样就不会产生作用域混淆的问题,最好每个变量前都加var吧!

    源地址请看这里

  • 相关阅读:
    java ArrayList存储基本类型
    java ArrayList的几种方法使用
    java ArrayList的基本使用
    java 猜数字
    java Random随机生成一个数
    java Scanner输入数字、字符串
    java 构造方法
    java this的应用
    java pravite关键字的使用
    云计算服务
  • 原文地址:https://www.cnblogs.com/simplevoid/p/2923585.html
Copyright © 2020-2023  润新知