zoukankan      html  css  js  c++  java
  • JavaScript学习系列2一JavaScript中的变量作用域

    在写这篇文章之前,再次提醒一下

    JavaScript 是大小写敏感的语言

    // 'test', 'Test', 'TeSt' , 'TEST' 是4个不同的变量名

    JavaScript中的变量,最重要的就是它的作用域, JS中变量的作用域其实就是函数作用域

    比如我们的浏览器,在JavaScript中,它就是一个被实例化的window对象, 如果我们在window下面定义一个name字段, 那么name字段就具有window这个函数的作用域, 也就是说在整个window下面是可以访问这个name字段来获取它的值的

    那现在我们在window下面定义一个函数Function MyFunc, 然后在这个函数里面定义了一个变量myName, 那么这个新定义的变量myName,它的作用域就是在函数MyFunc里面,也就是说只能在MyFunc函数中才可以访问myName变量

    上面是在Chrome=》F12的Console中的一个例子. 刚写的时候一直报错,后来发现是我把function写成了Function,第一个字母大写了,就报错

    现在我们换一种方式来写,看看会出现什么情况

    这里,我们做了一下更改,在函数MyFunc中,在定义name变量之前,就使用console.log(name)语句来输出name, 如果没有在Chrome的console中执行的话,我可能会误以为它应该输出windowName. 因为这个时候,在函数MyFunc中还没定义name, 而全局变量(window对象下的变量)中已经定义了一个name="windowName", 所以我觉得它应该获取全局变量的值。但实际呢,我们可以看到,在实际中它输出的是undefined, 这是怎么个情况呢?

    原来JavaScript的解析器在执行函数MyFunc的时候,第一件事情就是寻找这个函数中的所有局部变量,然后再执行后续语句, 所以它会先找到在函数MyFunc中定义了局部变量name, 但既然找到定义了局部变量name,为什么没有取到它的值funcName呢。 而是输出undefined呢。 这是因为解析器虽然先会寻找函数中的所有局部变量,但是在执行语句时,还是一条一条来执行的,所以解析器先找到函数MyFunc中已经定义了局部变量name,然后执行时,一条一条语句来执行

    执行第一条语句 console.log(name);  => 此时,发现MyFunc函数中已经定义了局部变量name,但是此时还没有给它赋值,所以得到的就是undefined.  

    这一点也可以如下解释 JavaScript在解析代码的时候,都会搜索一下var声明的变量,然后将其声明提前。 javascript这个特性被非正式地称为 声明提升(hoisting)

    所以,如下语句

    alert(name);  // 这里弹出undefined
    var name = "Luke";

    它实际的解析过程如下:

    var name;
    alert(name);  // 这里弹出undefined
    name = "Luke";

     那么,我们在换一种写法,来看看

    在这里,我们首先定义了一个全局变量name="windowName", 然后在函数中,有一行语句

    name="funcName"

    注意,这里不是var name = "funcName", 也就是说它并不是在函数MyFunc中定义一个新的变量var name, 而是重新给全局变量name赋值,把它的值由windowName改为了funcName

    所以JavaScript解析器在执行MyFunc函数这段代码时,先会去找这个函数内部的局部变量,发现没有。所以执行console.log(name);语句时,获取的就只能是全局变量name的值,这里就是windowName

    接下来name="funcName", 将这个全局变量name的值由windowName改为了(重新赋值)funcName, 所以在MyFunc()之后执行console.log(name),输出的是全局变量name中的新值 funcName

    我们再来看两个相似的例子

    var testList = [11,12,13];
    function myShow(){
    
     if(typeof testList === 'undefined')
     {
          testList = [];
     }
    
    alert(testList.length);
    
    };
    
    myShow();//结果 3

    这里结果将输出3,因为在这个例子中,在函数myShow中没有定义testList(var testList), 所以JavaScript编译器找的就是全局变量testList,显然,它的length就是3

    再看下面

    var testList = [11,12,13];
    function myShow(){
    
     if(typeof testList === 'undefined')
     {
         var testList = [];
     }
    
    alert(testList.length);
    
    };
    
    myShow(); //结果 0

    注意到在函数myShow中,var testList是在myShow函数内部的if语句块中定义的。 这里要注意一下

    JavaScript中没有块级作用域(由{}限定的作用域), 函数中声明的变量,无论在函数内部的哪一个地方声明,在这整个的函数中都是有定义的,都是一样的效果。

    所以,这里,实际的执行过程是这样的:

    var testList = [11,12,13];
    function myShow()
    {
       var testList;
     
    if(typeof testList === 'undefined')
     {
         testList = [];
     }
    
    alert(testList.length);
    
    };
    
    myShow(); //结果 0

    所以在执行函数myShow时,发现定义了和全局变量testList同名的局部变量,此时还没给它赋值,所以确实是undefined, 所以执行if条件中的语句, testList = [], 它的length就是0

    接下来,我们来看看函数定义式函数表达式之间的区别

    函数定义式  function show(){} 采用这种函数定义式的声明方法,函数的定义会提前

    函数表达式 var show = function(){}  函数的表达式,和普通的JavaScript变量的处理是一样的,也就是说函数声明会提前,但函数定义的位置不变

    我们来看下面两个例子

    alert(typeof myFunc);  //输出结果: function
    function myFunc(){}

    JavaScript在解析代码时, 像function myFunc()这种函数定义,和var声明定义变量一样,都会被提到前面。不同点在于:

    var声明定义变量时,只会把var声明提到最前面,而定义还会停留在原处

    而函数定义function myFunc(),函数声明和定义是一起的,都会同时被提到前面。所以上面的语句和下面执行是一样的

    function myFunc(){}
    alert(typeof myFunc);  //输出结果: function

    那我们再来看函数表达式的例子

    alert(typeof myFunc); //输出: undefined
    var myFunc = function(){};

    这个执行起来就是下面这样的

    var myFunc;
    alert(typeof myFunc); //输出: undefined
    myFunc = function(){};

     我们再来看两个更容易出错更让人抓狂的例子

    var myData = {name:'testName'};
    function myData()
    {
       alert('testName function');
    }
    myData();   //输出 TypeError: object is not a function

    这个例子非常抓狂吧,这里很容易以为是输出"testName function". 这个确实是很难辨别的一个例子

    我们前面说过,var声明定义的变量会把声明提前,通过function myFunc(){}这种函数定义的函数会把函数的声明和定义同时提前. 这里就是这种情况,两个都会提前,那到底谁更前呢? 注意

    var声明定义变量和函数定义同名时,函数的声明定义会在更前面,所以上面的JavaScript执行时会变成如下:

    function myData()
    {
       alert('testName function');
    }
    var myData;
    myData = {name:'testName'};
    
    myData();   //输出 TypeError: object is not a function

    可以看出,myData此时不再是函数,所以你不能采用这种方法myData(), 所以报错

    那我们再看下面这个例子

    var myData = {name:'testName'};
    var myData = function()
    {
       alert('testName function');
    }
    myData();   //输出结果: testName function

    在这里函数是通过函数表达式(而不是函数定义式)的var形式来声明定义的,而前面的变量var myData = {name:'testName'}也是var形式,两个优先级是一样的,所以就按代码顺序来,实际执行过程如下

    var myData;
    myData = {name:'testName'};
    myData = function()
    {
       alert('testName function');
    }
    myData();   //输出结果: testName function

    上面的例子就是这样,JavaScript的变量是一个非常绕的事情, 我们再来看一个例子

    alert(name);  //报错: 对象未定义, 使用一个压根就不存在的变量,所以出错
    
    age = 24; //这里有错吗,这里不会报错,为什么呢?  
                   //  JavaScript中给一个未定义的变量赋值,就会自动创建一个全局变量, 这就
                       相当于 var age = 24

     

  • 相关阅读:
    手把手教你使用markdown
    spring WebSocket详解
    springmvc请求参数异常处理
    蓝桥杯java 算法提高 摆花
    蓝桥杯java 算法提高 扶老奶奶过街
    蓝桥杯java 算法训练 未名湖边的烦恼
    蓝桥杯java 算法训练 Torry的困惑(基本型)
    java算法 硬币
    java算法 牌型种数
    java算法 方格填数
  • 原文地址:https://www.cnblogs.com/wphl-27/p/9327062.html
Copyright © 2011-2022 走看看