js:变量,作用域以及内存问题
Posted waiting_h
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js:变量,作用域以及内存问题相关的知识,希望对你有一定的参考价值。
最近在重读《javascript高级程序设计》这本书,“温故而知新”,古人诚不欺我,再看的时候发现很多知识是之前不理解便跳过的,也有很多之前只是知道并记住了,并不能形成一套体系,而不断的回顾,不断地总结,我发现有很多零零散散的知识点在不经意间就被串在了一起,恍然大悟的感觉甚是美妙
而我一向喜欢思维导图和记忆的方式去学习总结,在用文字表达和总结方面显得很贫乏,所以打算用这种博客的形式来记录下重读过程中的总结,就当是记个笔记,也顺便练练表达能力
变量:
js中的变量可能包含两种不同数据类型的值:分为基本类型值和引用类型值。两者区分的本质是取决于变量在内存中的存储方式,基本类型值存放在栈内存中,引用类型值保存在堆内存中。
而由于两种类型的保存方式不同,我们在复制变量值的时候就会发现:对基本类型值的复制是值复制,复制后的变量值与变量值只是数据相同而且,在内存中是独立的;对引用类型值的复制是其实也是“值”复制,不过这个值是一个指针,而我们真正会操作的数据是指针指向的一个内存,我们复制的那个指针“值”只是一个指向真正数据内存的地址,也就是我们常说的引用,所以,在引用类型的复制中,最终复制后的变量与复制前的变量指向同一数据,所以对其中任何一个变量进行改变都会影响另外一个
目前简单数据类型有:Undefined,Null,String,Number,Boolean,Symbol(es6新增数据类型)
复杂数据类型:Object
而对简单数据类型,通常用typeof来判断,其返回值有:“undefined”,“string”,“number”,“boolean”,“symbol”,“function”,“object”而typeof null == “object”,是因为历史遗留问题,而本身null也表示“该变量为一个空的指针”,所以,其typeof的结果为“object”也可以理解了
而对复杂数据类型,通常使用instanceof来判断,表示是否是该对象的实例对象,通过原型链(暂不做讨论)来判断
而对一些特殊的数据类型,我们也有对应的方法判断其类型:数据的Array.isArray,非数字的isNaN
执行环境与作用域:
首先,明确几个知识点:1)每个函数都有自己的执行环境 2)执行环境定义了变量或函数有权访问的其他数据 3)每个执行环境都有一个与之关联的变量对象,执行环境中定义的所有变量和函数都保存在这个对象中
对以上三点我所理解的就是:每个函数在内存中都有一个与之关联的对象,该对象中保存了这个函数内部定义的变量,方法等一切信息,是对这个函数的一个描述对象
而当函数执行时,函数的执行环境会被推入到一个环境栈中,此时会形成与其他执行环境的一种“包含”或者“平行”的关系,而这种“包含”的体现就是“作用域链”,更严谨的说法是:当代码再一个环境中执行时,会创建变量对象的一个作用域链。而作用域链的作用就很牛逼了,我们经常说的变量查找从局部作用域到外层再到外层直至全局作用域就是依靠这条作用域链。作用域链只能向上查找。
内存问题:
js的垃圾回收机制使得执行环境会管理代码执行过程中使用的内存,而按照我们对执行环境和作用域的理解,我们知道,代码执行结束后,执行环境被从环境栈中推出,此时执行环境中的局部变量也就没有存在的意义了,所以,此时需要告知该执行环境中的局部变量应该被回收,而具体的回收策略在浏览器中有:
1:标记清除:变量的标记从“进入执行环境”到“离开执行环境”,回收机制只要清除那些标有“离开”的变量即可
2:引用计数:当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数加1,如果同一个值又被赋给另外一个变量,则减1,回收机制负责回收引用次数为0的值。但是这种方法遇到循环引用时,便会陷入僵局,所以,该方法使用场景较少
越写越乱的感觉,表达能力还是太欠缺了,还需要多练习,对知识也要深入理解,加油!!!
以上是关于js:变量,作用域以及内存问题的主要内容,如果未能解决你的问题,请参考以下文章