基本类型的值有:未定义、空、布尔、数字和字符串。这些类型在内存中占据固定大小的空间,它们的值存储在堆栈空间中,我们通过值来访问堆栈空间。
(1)值类型:数值、布尔值、空值、未定义。(2)引用类型:对象、数组、函数。
如果分配引用类型的值,则必须在堆内存中为该值分配空间。由于这些值的大小不是固定的(对象有许多属性和方法),它们不能保存在堆栈内存中。但是内存地址大小是固定的,所以内存地址可以保存在堆栈内存中。
脚本类型=' text/JavaScript " var box=new Object();//创建一个引用类型var box=' lee//基本类型值是string box.age=23//在基本类型值中添加属性很奇怪,因为只有对象才能添加属性。alert(box . age);//不是引用类型,不能输出;/script简而言之,堆内存存储引用值,堆栈内存存储固定类型值。
脚本类型=' text/JavaScript ' var man=new Object();//man指向堆栈内存man.name='Jack '的空间地址;var man2=man//man2得到了man的指向地址告警(man 2 . name);//两者都弹出杰克提醒(man . name);/script复制变量值
请看下面的例子:
脚本类型=' text/JavaScript ' var man=new Object();//man指向堆栈内存man.name='Jack '的空间地址;var man2=man//man2得到了man2.name='ming '的指向地址;//因为它们都指向同一个对象和名称,不管是谁修改的,大家都修改了alert(man 2 . name);//两者都弹出明警戒(man . name);/script从上面可以得出,基本类型和引用类型在变量复制方面也是不同的。基本类型复制值本身,而引用类型复制地址。
传递参数
在ECMAScript中,所有函数的参数都是通过值传递的。
脚本类型=' text/JavaScript '函数框(num){//按值传递num=10返回数字;} var num=10var结果=box(num);警报(结果);//如果是引用传递,函数中的num会变成类似的全局变量,alert(num)会被外面的数字代替;//也就是说,最终的输出应该是20(这里,输出10)。/Script JavaScript不是通过引用传递的。如果有引用传递,函数中的变量将是全局变量,可以从外部访问。但这显然是不可能的。
执行环境和范围
执行环境是javascript中最重要的概念之一,它定义了变量或函数可以访问其他数据。
全局执行环境是最外层的执行环境。在web浏览器中,全局执行环境是窗口对象。因此,全局变量的所有函数都被创建为窗口的属性和方法。
脚本类型=' text/JavaScript ' var name=' Jack ';//定义全局变量functionsetname(){ return ' trig kit 4 ';} alert(window . name);//全局变量,最外层,属于窗口属性alert(window . setname());//全局函数,最外层,属于window方法/脚本。当执行环境中的代码被执行时,环境会被破坏,保存在其中的变量和函数也会被破坏。如果是全局环境,则在所有程序执行完毕或网页完成之前不会被破坏。
移除var的局部变量
脚本类型=' text/JavaScript ' var name=' Jack ';函数SetName(){ name=' trig kit 4 ';//去掉var成为全局变量} setName();警报(名称);//弹出trigkit4/script,也是通过参数传递的局部变量。
脚本类型=' text/JavaScript ' var name=' Jack ';函数setName(name){ //通过传递参数也是一个局部变量alert(name);} setname('trigkit4');//弹出trigkit4告警(名称);//弹出的Jack/script函数体也包含函数,只有这个函数才能访问内层的函数
脚本类型=' text/JavaScript ' var name=' Jack ';函数setName(){ function setyear(){//setyear()方法的作用域在setName()中返回21;} } alert(setYear());//无法访问,错误/脚本可以通过以下方法访问:
脚本类型=' text/JavaScript ' var name=' Jack ';函数setName(){ function setyear(){//setyear()方法的作用域在setName()中返回21;}返回setYear();} alert(setName());//弹出21/脚本另一个范围示例:
脚本类型=' text/JavaScript ' var name=' Jack ';函数setName(){ function setyear(){//setyear()方法在setName()中的作用域为var b=' hi//变量b的作用域是setYear()中的return 21}警报(b);//不可访问}/脚本当代码在环境中执行时,会形成一种叫做范围链的东西。其目的是确保在执行环境中有序地访问具有访问权限的变量和函数(指根据规则级别的访问)。范围链的前端是执行环境的变量对象。
行动范围
当变量未在函数中声明或声明时,它是不带var的全局变量,并且具有全局范围。窗口对象的所有属性都有一个全局范围。它可以在代码中的任何地方被访问。在函数内部声明并由var修改的变量是局部变量,只能在函数体中使用。虽然没有使用var,但是函数的参数仍然是局部变量。
没有块级范围
没有块级范围
//if语句:脚本类型=' text/JavaScript ' if(true){//if语句的大括号没有作用域函数。var box=' trigkit4}警报(框);//当trigkit4/scriptfor循环语句弹出时也是如此。
变量查询
在变量的查询中,访问局部变量比全局变量更快,所以不需要向上搜索范围链。以下示例:
脚本类型=' text/JavaScript ' var name=' Jack ';函数SetName(){ var name=' trig kit 4 ';返回名称;//从下往上搜索变量} alert(setName());/script内存问题
Javascript有自动垃圾收集机制,一旦数据不再使用,就可以设置为“null”来释放引用
循环引用
一个简单的例子:一个DOM对象被一个Javascript对象引用,同时,它引用相同或其他的Javascript对象。这个DOM对象可能会导致内存泄漏。当脚本停止时,垃圾收集器不会回收这个DOM对象的引用。要打破循环引用,需要将引用DOM元素的对象或DOM对象的引用赋为null。
关闭
当闭包之外的变量被引入到闭包中时,当闭包结束时,对象不能被垃圾收集。
var a=function(){ var large str=new Array(1000000)。联接(' x ');return函数(){ return largeStr}}();DOM泄漏
当移除原始组件时,如果不移除子节点引用,则无法回收它。
var select=document . queryselector;var TreeRef=select(' # tree ');//在COM树中,leafRef是treef的子节点。var LeaveRef=select(' # leaf ');var body=select(' body ');body . remove child(TreeRef);//#tree无法返回,因为treeRef仍然存在。//Resolution : ref=null;//树还不能被回收,因为叶结果leafRef仍在leafRef=null中;//#tree现在可以发布了。计时器计时器(计时器)泄漏
计时器也是发生内存泄漏的常见场所:
for(var I=0;我90000;I){ var buggyObject={ callagin: function(){ var ref=this;var val=setTimeout(function(){ ref . callague();}, 90000);} } buggyobject . callague();//虽然你想回收,但是计时器还在buggyObject=null}调试内存
Chrome自带的内存调试工具可以轻松检查内存使用情况和内存泄漏情况:点击时间轴-内存中的记录: