zoukankan      html  css  js  c++  java
  • 浅谈javascript中变量作用域和内存(1)

    先理解两个概念:基本类型和引用类型的值

    1、基本类型和引用类型的值

    (1)定义:

    基本类型:指简单的数据段,比如按值访问的js五种基本数据类型undefined、null、boolean、number、srtring

    引用类型的值:指保存在内存中的对象,注意一点,js不允许直接操作对象的空间

    (2)相似和区别:

         相同:定义两种类型的方式都类似:创建一个变量并赋值

         不同点1:对于引用数据的值,我们可以添加属性进去,但是基本类型不行,强行添加会报undefined

      下面给个例子:

      var person = new Object()
      person.name = "saebr";
      console.log(person.name)//saber

      而基本类型添加属性会报undefined:

      var name = "saber";
      name.sex = "女";
      console.log(name.sex)//undefined

        不同点2:变量的复制也不相同:

      var num = 777;
      var num1 = num;
      console.log(num1)//777

      基本类型的复制,简单来说就是用num的值来初始化num1,num1中也保存了值777,但是num和num1保存的777是两个完全独立的。

      var obj = new Object();
      var obj1 = obj;
      obj.name = "saber";
      console.log(obj1.name)//saber

      而引用类型的复制,最简单的话来说就是obj保存了一个对象的新实例,复制的过程就是让obj1的指针也指向这个对象,因此改变其中一个变量就会影响到另外一个变量。

        不同点3:参数传递的不同

      传递基本类型的值时,被传递的值会被复制给一个局部变量,而传递引用类型的值时,会把值得内存的地址复制给局部变量,这么说可能不好理解,撸两个例子看看:

      首先是基本类型的传递参数:

      function add(num) {
          num += 1;
          return num;
      }
      var saber = 7;
      var archer = add(saber);
      console.log(saber)//7
      console.log(archer)//8

      使用数值等基本类型来传参,函数内部的不会影响外部saber的变量,因为num和saber互相不认识,他们仅仅有相同的值,也就是如同上面所说的是完全独立的。

      其次是引用类型的传递参数:

      var person  = new Object();
      function setName(obj){
          obj.name = "saber"
      };
      setName(person);
      console.log(person.name)//saber

      看上去好像引用类型的传递参数是按引用传递,第一次看上去好像是这么回事,在局部作用域里面修改对象,会在全局作用域里展现出来,所以误认为是按引用传递。

      实际上js都是按值来传递参数的,上面的基本类型就不说了,简单明了,下面写个例子证明一下,引用类型是按值传递的:

      var person  = new Object();
      function setName(obj){
          obj.name = "saber"
          obj = new Object();
          obj.name = "archer"
      };
      setName(person);
      console.log(person.name)//saber

    也就是说如果是按引用传递的话,person会被修改为指向name属性值为archer的新对象,但是结果是saber,这已经说明了一切。事实上,当函数执行完毕,这个archer的局部对象会被立即销毁。

    (3)检测引用类型

    检测基本数据类型使用typeof,那么如何检测引用类型呢?

    所有引用类型的值都是Object的实例,escript提供了instanceof来检测引用类型和Object构造函数,如果是的话,返回true;

     

    2、作用域

     首先,要了解一个概念,全局执行环境被认为是windows对象,然后,每个函数都有自己的执行环境,当执行流进入一个函数时,这个函数的环境就会被推入一个环境栈中,当执行完,就会退出这个环境栈,然后返回之前的执行环境

    作用域链

    所以,当代码在一个环境中执行时,就会创建一个对象的作用域链。简单说一下作用域链,作用域链的下一个变量对象来自于外部环境,再下一个变量对象又来自更外一层的环境,这样一层一层直到最外层的全局执行环境windows。

    还是撸一串代码看看,光说根本一连懵逼呀:

    var SName = "saber";
    function changeSavant(){
        var AName = "archer";
        // console.log(SName)//saber
        // console.log(AName)//archer这里可以访问两个,访问不了beateSavant里面的LName
        beateSavant();
        function beateSavant(){
            var LName = AName;
            AName = SName;
            SName = LName;
            console.log(SName)//archer
            console.log(AName)//saber
            console.log(LName)//archer这里三个都可以访问到
        }
    }
    // console.log(SName)//saber这个地方只能访问到SName
    // console.log(AName)//AName is not defined
    changeSavant();

    简单来说,可以看到,函数内部的可以访问到外部的,但是外部的无法访问到内部的变量,那么这是如何访问到的呢,所以这就是作用域链的作用,首先函数的局部环境会先在自己的环境中搜索变量和函数名,搜索不到就再搜索上一层的作用域链。

    这下是不是简单明了了很多~

    延长作用域链

    js有两种方式来延长作用域链:

    (1)try catch中的catch

    function add() {
        try{}
        catch{}//延长的作用域链
    }

    (2)with

    作者:SaberInoryKiss

    出处:SaberInoryKiss的博客--https://www.cnblogs.com/SaberInoryKiss

    您的支持是对博主最大的鼓励,感谢您的认真阅读。

    本文版权归作者所有,欢迎转载,但请保留该声明。

  • 相关阅读:
    AS3.0纯代码编写的两款loading效果
    AS3.0 Vector的运用
    java 垃圾回收总结(1)
    as3垃圾回收机制
    AS3.0 效率优化
    数组去重的方法
    javascript 的垃圾回收机制讲一下
    浅拷贝和深拷贝
    判断 js 类型的方式
    前端安全问题?
  • 原文地址:https://www.cnblogs.com/SaberInoryKiss/p/11770974.html
Copyright © 2011-2022 走看看