zoukankan      html  css  js  c++  java
  • js 变量、作用域和内存问题

    基本类型和引用类型

    • 5种基本类型:undefined、null、boolean、number、string

    • 引用类型:由多个值构成的对象

    属性

    引用类型可以动态添加属性,而基本类型不可以

    var p = new Obj();
    p.name = "huyuping";
    console.log(p.name)//huyuping
    
    var a;
    a.name = "huyuping";
    console.log(a,name)//出错
    

    复制变量值

    • 基本类型

    会在变量的对象上创建了一个新值,然后把复制到新变量分配的位置上。

    下面的我形象化的帮助大家理解

    这就相当于a和b都有一个房子,a把值复制给b后,b的房子了也有了这个值。

    • 引用类型

    当从一个变量向另一个变量复制引用类型的值时,同时也会将存储在变量类型中的复制一份放到为新变量分配的内存空间中。

    这可以这样理解:a,b都有自己的地方,a的值时放在另一个屋子里的,a复制给b,那a和b都要在哪个房子里去拿值,这个房子就是给a分配的内存,b的内存也指向哪个位置。

    传递参数

    • 基本类型
      在向参数传递基本类型的值时,被传递的值会被复制给一个局部变量(即命名参数)。
    unction addTen(num) {
        num+=10;
        return num;
    }
    var count = 20;
    var result = addTen(count);
    console.log(count);//20
    console.log(result);//30
    

    这里函数有个局部变量num,在使用之后就被回收了,然后函数返回一个值。

    我们看下面一种情况

    function addTen(num) {
        num+=10;
        return num;
    }
    var count = 20;
    addTen(count);
    console.log(count);//20
    console.log(addTen(count));//30
    

    这次,我们没有定义result变量,而是直接输出addTen(count),输出的值还是30,这更说明了num时局部变量,不会影响count的值。

    • 引用类型
      在向参数传递引用类型的值时,会把这个值在内存中的地址复制给局部变量,因此这个局部变量的变化会反映在函数外部。
    function setName(obj) {
        obj.name = "huyuping";
    }
    var person = new Object();
    setName(person);
    console.log(person.name);//huyuping
    

    在这个函数内部,obj和person引用的时同一个对象,所以为obj添加name属性的时候,在外面也有反应。

    作用域

    1. script:全局变量、全局函数
    2. 函数:自上而下、由里到外

    e.g.1

    alert(a);//undefined
    var a = 1;
    function fn1 () {
        alert(a);//undefined
        
        var a = 3;
    }
        fn1();
        alert(a);//1
    

    分析:

    1.预解析:

    1)a= undefined
     
    2)fn1 = function fn1 () {alert(a);var a = 3; }(函数里的a是新定义的,所以预解析的时候会先是var a = undefined)
    

    2.表达式:

    1)a=1;
    2)调用函数
             1.预解析 a= undefined
             2.表达式 a=3
    

    e.g.2

            alert(a);//undefined
            var a = 1;
            function fn1 () {
            	alert(a);//1
            	a = 3;
            }
            fn1();
            alert(a);//2
    

    分析:

    1.预解析:

    1)a= undefined
    2)fn1 = function fn1 () {alert(a);var a = 3; }
    

    2.逐行解读代码:

    1)a=1;
    2)调用函数
            1.预解析 (没有预解析,此时返回父级作用域(从子级作用域返回到父级作用域的过程叫作用域链)) 找到a=1,改为a=2
    

    e.g.3

     alert(a);//undefined
            var a = 1;
            function fn1 (a) {
            	alert(a);//undefined
            	a = 3;
            }
            fn1();
            alert(a);//1
    

    分析:

    1.预解析:

    1)a= undefined
    2)fn1 = function fn1 (a) {alert(a);var a = 3; }
    

    2.逐行解读代码:

    1)a=1;
    2)调用函数
          1.预解析  
          function fn1 (a) a相当与var a
                                  a=undefined
         2.逐行解读代码
          a=3
    

    e.g.4

    
    
    
            var a = 1;
            function fn1 (a) {
            	alert(a);//1
            	a = 3;
            }
            fn1(a);
            alert(a);//1
    

    分析:

    1.预解析:

    1)a= undefined
    2)fn1 = function fn1 (a) {alert(a);var a = 3; }
    

    2.逐行解读代码:

    1)a=1;
    2)调用函数
        1.预解析  function fn1 (a) a相当与var a
                                  因为fn1(a),相当于对a传了参数,所以function fn1 (a)相当于function fn1 (var a = 1)
        2.逐行解读代码
                                   a=3     
    

    if、for 是通透的不是作用域
    注意:火狐解析不到if语句里面包着的函数体,所以尽量不要向if、for里面定义变量或函数

  • 相关阅读:
    用函数装饰一首诗
    [转]最常用的15大Eclipse开发快捷键技巧
    [转]python 模块 chardet下载及介绍
    python手动设置递归调用深度
    view-xpath
    开源项目的贡献流程
    MIT许可证
    scrapy分布式的几个重点问题
    【bzoj1026】[SCOI2009]windy数 数位dp
    【bzoj5064】B-number 数位dp
  • 原文地址:https://www.cnblogs.com/huyuzhu/p/6601552.html
Copyright © 2011-2022 走看看