JavaScript高级编程第四章(变量,作用域,内存问题)的学习摘录 纯手打

简介: 第四章变量,作用域和内存问题JavaScript不允许直接访问内存的位置,也就是说不能直接操作对象的内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象。
第四章
变量,作用域和内存问题
JavaScript不允许直接访问内存的位置,也就是说不能直接操作对象的内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象。为此,引用类型的值时按引用访问的。
动态的属性:
只有给引用类型的变量添加,修改,删除属性;如:
var person=new Object();
person.name="sdf";
alert(person.name);   //"sdf"
创建了一个对象保存在了变量person中然后为其添加了name属性
但是如果给基本类型的值添加属性就会失败  举例:
var name=""sdf";
name.age=23;
alert(name.age);  //undefined

复制变量值:
基本变量值是重新创建了一个新的变量
引用变量值是  相当于指针,两个指向同一个对象

传递参数:
是值传递  相当于将外部的值复制给函数内部
如果是基本变量值  则内部修改不影响外部值 ,因为是复制过来的值
如果是引用变量值  则相当于将指针值复制给函数内部 ,函数内部如果对指针指向的内容进行操作,就会影响外部指针指向的内容  但是 如果内部的指针先给内存赋值操作,外部指针也可以访问被修改的内容,如果内部指针指向新的对象再进行操作 ,则不影响外部。


检测类型:
var s="sdf";
var b=true;
var i=22;
var u;
var n=null;
var o=new Object();
alert(typeof s);  //string
alert(typeof b);  //boolean
alert(typeof i);  //number
alert(typeof u);  //undefined
alert(typeof n);  //object
alert(typeof o);  //object
使用typeof检测函数时,该操作符会返回“function” 
对正则表达式应用typeof 会返回“function”。在IE和Firefox中  会返回“object”;
检测基本数据类型时typeof是个好的助手,但是检测引用类型时用处不大。如果想要知道一个什么类型的对象。用instanceof操作符。举例:
alert(person instanceof Object);  始终返回true  
alert(person instanceof Array);   变量person是Array?
alert(person instanceof RegExp);
如果使用instanceof操作符检测基本类型的值,则操作符始终返回false,因为基本类型不是对象。


执行环境及作用域:
每个函数都有自己的执行环境 当一个代码在一个环境执行的时,会创建变量对象的一个作用域链:用途是保证对执行环境有权访问的所有变量和函数的有序访问。全局执行环境的变量对象始终都是作用于的最后一个对象。
例子:
  <script type="text/javascript">

        var color = "blue";

        function changeColor(){
            if (color === "blue"){
                color = "red";
            } else {
                color = "blue";
            }
        }

        changeColor();

        alert("Color is now " + color);

    </script>
作用域的前端,始终时当前执行的代码所在环境的变量对象,然后一层层往外扩展,逐级向后回溯。    函数changeColor()的作用域链包涵两个对象:他自己的变量对象和全局环境的变量对象。可以在函数内部访问color,就是因为在这个作用域中找到了它。


    举例:
        <script type="text/javascript">

        var color = "blue";

        function changeColor(){
            var anotherColor = "red";

            function swapColors(){
                var tempColor = anotherColor;
                anotherColor = color;
                color = tempColor;

                color, anotherColor, and tempColor 都可以访问
            }

            //color and anotherColor 可以访问, but not tempColor        
            swapColors();
        }

        changeColor();

        //只能访问 color 
        alert("Color is now " + color);

    </script>
以上代码共涉及了三个执行环境:全局环境,changeColor()的局部环境 和swapColors()的局部环境
意思就是说  内环境可以通过作用域链访问所有的外部环境,但是外部环境不能访问内部环境中的任何变量和函数。每个函数都是向上搜索作用域,以查询变量和函数名。

延长作用域链
try-catch语句的catch
with语句
两个语句都会在作用域链的前端添加一个变量对象。 对with来说,会将指定的对象添加到作用域链中。对于catch来说,会创建一个新的变量对象,其中包涵了被抛出的错误对象的声明

举例:
 <script type="text/javascript">

        function buildUrl() {
            var qs = "?debug=true";

            with(location){
                var url = href + qs;        
            }

            return url;
        }

        var result = buildUrl();
        alert(result);

    </script>
    with语句内 可以访问location中的属性和方法,   而且定义了一个url的变量,因而url就成了函数执行环境的一部分,所以可以作为i函数的值被返回。
重要:没有块级作用域:
在其他类c语言中  for循环和if判断句内的局部变量在代码结束后被销毁 但是在javascript中  不会 即使是在代码结束后,也依旧会存在与外部的执行环境    和普通的函数不同 ,因为在函数里面变量是局部的   得和for和if区分开例子:
 <script type="text/javascript">
    if(true){
        var color="blue";
    }
     alert(color)    //"blue"
    </script>
 声明变量:
 使用var声明变量会被自动添加到最接近的环境中。在函数内部最接近的环境就是函数的局部环境。在witch语句中,最接近的环境是函数环境。如果初始化变量时没有使用var声明,该变量会自动被添加到全局环境中:
  <script type="text/javascript">     
       function add(num1, num2) {
            sum = num1 + num2;
            return sum;
        }      
        var result = add(10, 20);  //30
        alert(sum);                //30

    </script>
    sum 没有用var定义 所以它是全局变量  后面的代码依旧可以访问它。
    重要提醒:建议在初始化变量前,一定要先声明,这样可以避免错误。

    查询标识符:
    举例:
        <script type="text/javascript">
        var color = "blue";  
        function getColor(){
            return color;
        } 
        alert(getColor());  //"blue"     
    </script>
    为了确定变量color的值,它向上搜索,首先搜索getColor()的变量对象,查找是否有color的标识符。在没有找到的情况下,搜索继续道下一个变量对象(全局环境的变量对象)然后寻找color的标识符。是沿着作用域链向上搜索的,一直追溯到全局环境的变量对象中。  在搜索的过程中 如果局部环境中存在同名的标识符,就不会使用父环境中的标识符
    访问局部变量要比访问全局变量更快,因为不用向上搜索作用域链。
    举例:
        <script type="text/javascript">
        var color = "blue"; 
        function getColor(){
            var color = "red";
            return color;
        }   
        alert(getColor());  //"red"

    </script>


    垃圾收集;
    1.有自动垃圾收集机制,找到那些不再继续使用的便利啊个,然后释放其占有的内存,为此垃圾收集器会按照固定的时间间隔周期性得执行这个操作。
    最常用的垃圾收集方式是标记清除
    2.引用计数:COM是基于引用计数的。如果有循环引用就无法销毁  因为引用次数不可能为0
    引用循环是对象A包含了一个指向对象B的指针,对象B包涵了一个指向A的指针
    解决方案是将两个指针指向null来断开原生JavaScript对象与DOM元素之间的连接。
    性能问题  :
    在有的浏览器中可以触发垃圾收集过程,但不建议这么做。
    在IE中调用window.CollectGarbage()方法会立即执行垃圾回收。
    在Opera7中及更高版本,调用window.pera.collect()也会启动垃圾收集例程。
    管理内存 :
    分配给Web浏览器的可用内存数量通常比分配给桌面应用程序的少,这样的目的是出于安全方面的考虑,防止运行JavaScript的网页耗尽全部系统内存而导致系统崩溃。 内存限制问题还影响变量的分配内存,调用栈以及在一个线程中能够同时执行的语句数量。一旦数据不再使用,最好将其设置为null来释放其引用,这一做法适合大多数的全局变量和全局对象的属性。局部变量会在他们离开执行环境时自动解除引用。不过解除一个值的引用不是意味着自动回收改制所占用的内存。接触引用的真正目的时让值脱离执行环境,以便垃圾收集器下次运行时将其回收。


    基本类型和引用类型总结:
    1.基本类型在内存中占固定大小的空间,因此被保存在栈内存中
    2.从一个变量向另一个变量复制基本类型的值,会创建这个值的一个副本。
    3.引用类型的值时对象,保存在堆内存
    4.包含引用类型值的变量实际上包含的并不是对象本身,而是一个指向该对象的指针
    5.从一个变量向另一个变量复制引用类型的值,复制的其实时指针,因此两个变量最终都指向同一个对象。
    确定一个值是哪中基本类型可以使用typeof操作符,而确定一个值是哪种引用类型可以使用instanceof操作符

    所有变量都存在与一个执行环境,这个执行环境决定了变量的生命周期,以及哪一部分代码可以访问其中的变量 以下是关于执行环境的总结:
    1.执行环境有全局执行环境和函数执行环境之分
    2.每次进入一个新的执行环境,都会创建一个用于搜索变量和函数的作用域链
    3.函数的局部变量不仅有权访问函数作用域中的函数,而且有权访问其父环境,乃至全局环境
    4.全局环境只能访问在全局环境中定义的变量和函数,而不能访问局部环境中的任何数据
    5.变量的执行环境有助于确定应该何时释放内存

    垃圾回收总结:
    1.离开作用域的值江北自动标记为可以回收,因此将在垃圾收集期间被删除
    2.“标记删除”是目前主流的垃圾收集算法,这种算法的思想是给当前不使用的变量的值加上标记,然后再回收其内存
    3.另一种垃圾收集算法:“引用计数” 跟踪记录所有值被引用的次数   目前不再使用,但是在IE中访问非原生JavaScript(如DOM元素)时,这种算法任然可能会导致问题
    4.当代码中存在循环引用现象时,“引用计数”算法就会导致问题
    5.接触变量的引用不仅有助于消除循环引用现象,而且对垃圾收集也有好处。应该及时接触不再使用的全局对象,全局对象属性,以及循环引用变量的引用
目录
相关文章
|
存储 缓存 Java
【高薪程序员必看】万字长文拆解Java并发编程!(5):深入理解JMM:Java内存模型的三大特性与volatile底层原理
JMM,Java Memory Model,Java内存模型,定义了主内存,工作内存,确保Java在不同平台上的正确运行主内存Main Memory:所有线程共享的内存区域,所有的变量都存储在主存中工作内存Working Memory:每个线程拥有自己的工作内存,用于保存变量的副本.线程执行过程中先将主内存中的变量读到工作内存中,对变量进行操作之后再将变量写入主内存,jvm概念说明主内存所有线程共享的内存区域,存储原始变量(堆内存中的对象实例和静态变量)工作内存。
417 0
|
JavaScript 前端开发
js的作用域作用域链
【10月更文挑战第29天】理解JavaScript的作用域和作用域链对于正确理解变量的访问和生命周期、避免变量命名冲突以及编写高质量的JavaScript代码都具有重要意义。在实际开发中,需要合理地利用作用域和作用域链来组织代码结构,提高代码的可读性和可维护性。
|
JavaScript 前端开发 开发者
JavaScript基础——JavaScript变量名称命名规范
JavaScript变量命名规范是编写高质量代码的重要部分。通过遵循基本规则、使用常见命名约定并应用最佳实践,可以提高代码的可读性和可维护性。希望本文能帮助开发者在日常编程中更好地理解和应用JavaScript变量命名规范,从而编写出更清晰、更可靠的代码。
1035 11
|
JavaScript 数据可视化 前端开发
three.js简单实现一个3D三角函数学习理解
1.Three.js简介 Three.js是一个基于JavaScript编写的开源3D图形库,利用WebGL技术在网页上渲染3D图形。它提供了许多高级功能,如几何体、纹理、光照、阴影等,以便开发者能够快速地创建复杂且逼真的3D场景。同时,Three.js还具有很好的跨平台和跨浏览器兼容性,让用户无需安装任何插件就可以在现代浏览器上观看3D内容。
497 0
|
JavaScript 前端开发 容器
盘点JavaScript中所有声明变量的方式及特性
本文详细介绍了JavaScript中变量定义的多种方式,包括传统的`var`、`let`和`const`,以及通过`this`、`window`、`top`等对象定义变量的方法。每种方式都有其独特的语法和特性,并附有代码示例说明。推荐使用`let`和`const`以避免作用域和提升问题,谨慎使用`window`和`top`定义全局变量,不建议使用隐式全局变量。掌握这些定义方式有助于编写更健壮的JS代码。
505 11
|
前端开发 JavaScript
如何在 JavaScript 中访问和修改 CSS 变量?
【10月更文挑战第28天】通过以上方法,可以在JavaScript中灵活地访问和修改CSS变量,从而实现根据用户交互、页面状态等动态地改变页面样式,为网页添加更多的交互性和动态效果。在实际应用中,可以根据具体的需求和场景选择合适的方法来操作CSS变量。
778 12
|
JavaScript 前端开发
javascript的作用域
【10月更文挑战第19天javascript的作用域
|
前端开发 JavaScript 数据处理
CSS 变量的作用域和 JavaScript 变量的作用域有什么不同?
【10月更文挑战第28天】CSS变量和JavaScript变量虽然都有各自的作用域概念,但由于它们所属的语言和应用场景不同,其作用域的定义、范围、覆盖规则以及与其他语言特性的交互方式等方面都存在明显的差异。理解这些差异有助于更好地在Web开发中分别运用它们来实现预期的页面效果和功能逻辑。
332 11
|
Web App开发 JavaScript 前端开发
如何学习JavaScript?
如何学习JavaScript?
474 5
|
JavaScript 前端开发 索引
JavaScript学习第二章--字符串
本文介绍了JavaScript中的字符串处理,包括普通字符串和模板字符串的使用方法及常见字符串操作方法如`charAt`、`concat`、`endsWith`等,适合前端学习者参考。作者是一位热爱前端技术的大一学生,专注于分享实用的编程技巧。
269 2