JAVAScript的变量、作用域和内存问题

前言:

按照ECMA-262的定义,JavaScript的变量与其他语言的变量有很大的区别。JavaScript变量松散类型的本质,决定了它只是在特定时间用于保存特定值的一个名字而已。由于不存在定义某个变量必须保存何种数据类型值得规则,变量的值以及数据类型可以在脚本的生命周期内发生改变。尽管从某种角度看,这可能是一个既有趣又强大,同时又容易出现问题的特性,但JavaScript变量实际的复杂程度还远不止如此。

目录大纲

一.基本类型和引用类型的值

1.赋值变量的值

2.传参

3.检测类型

1.操作符typeof
2.操作符instanceof

二.执行环境以及作用

1.arguments介绍

2.延长作用域链

1.with语句
2.try-catch语句

3.js没有块级作用域

三.垃圾收集机制

1.标记清除

2.引用计数

一.基本类型和引用类型的值

变量包括两种不同的数据类型的值
1.基本类型指的是简单的数据段,包括Undefined、Null、Boolean、Number和String。
2.引用类型指的是保存在内存中,由多个值组成的对象。
创建对象举例

var person = new Object();
person.name = "Nicholos";

注意
1.Object的‘O’一定大写。
2.直接增加属性并且赋值。
3.只能给引用类型才能添加属性,是动态地添加属性。

1.赋值变量的值

基本类型的赋值方法与C语言相同,会增加一个新的空间用于存放副本,变量保存在栈内存中。

var num1= 5;
var num2=num1;
1.png

引用类型的值则不同,引用类型的值是保存在堆内存对象中,JS不允许直接访问内存中的位置,所以引用类型的值是按照引用类型访问的。当一个变量复制到另一个变量中,副本其实是一个指针,两个对象指的是同一个对象。


2.png

2.传参

传参就是把变量的值复制给函数内部的变量,是复制值的过程,永远满足值传递的关系。
引用类型也是复制一个新的指针,实际上指的还是同一个对象。

function setName(obj){
obj.name ="Ac";
obj = new Object();
obj.name = "Bc";
}
var person =new Object();
setName(person);
//person.name ="Ac";

一开始函数内的obj是和person指向同一个对象的,但是obj新声明了一个对象,引用类型的值不再是指向原来的对象的值,而且函数运行完后被销毁。

3.检测类型

1.操作符typeof
var s="Nicholas";
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); //undefine
alert(typeof n); //object
alert(typeof o); //object

null和object都是返回object

2.操作符instanceof
alert(person instanceof Object);// person 是Object吗?
alert(colors instanceof Array );// colors 是Array吗?
alert(pattern instanceof RegExp);// pattern 是RegExp吗?

是的话,就返回一个true,不是的话就返回一个false。

二.执行环境以及作用

执行环境(简称 环境)定义了变量和函数有权访问的其他的数据。每一个环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。
全局环境是一个最外围的执行环境,web中一般认为全局环境是window对象,全局环境会一直运行到应用退出它所定义的函数和变量才会被销毁。
每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中,函数执行完后,栈将环境弹出,把控制权返回给之前的执行环境。
当函数在一个环境中执行的时候,会创建一个作用域链,是为了保证对执行环境有权访问的所有变量和函数有序的访问,作用域链的前端,始终都是当前执行代码所在环境中变量对象。如果环境是函数,将其活动对象作为变量对象。活动对象最开始只包含一个变量-----arguments(arguments在全局环境中不存在)对象,作用域链的下一个变量对象来自包括外部的环境,一直延续到全局执行环境。

1.arguments介绍

arguments是JS中每个函数(除全局环境外)都有的类数组对象,用于储存函数传入的参数。

  • arguments.length 记录参数个数。
  • arguments.callee 储存调用这个函数的代码。
  • arguments可以实现函数的重载。
function add() {
    var len = arguments.length,
        sum = 0;
    for(;len--;){
        sum += arguments[len];
    }
    return sum;
}

console.log( add(1,2,3) );   //6
console.log( add(1,3) );     //4
console.log( add(1,2,3,5,6,2,7) );   //26

标识符解析是沿着作用域链一级一级的搜索标识符的过程,从作用域链的前端开始,逐级地向后回溯,直到找到标识符为止。
搜索标识符举例:

      var scope = "global";   //全局
      function fn1(){
         return scope; 
      }
      fn2();
作用域链

函数嵌套的作用域链举例:

  <script>
      function outer(){
         var scope = "outer";
         function inner(){
            return scope;
         }
         return inner;
      }
      var fn = outer();
      fn();
   </script>
作用域链

说明:当调用outer函数,inner函数的作用域链已经初始化了(即复制父函数的作用域链,再在前端插入自己的活动对象)

2.延长作用域链

1.with语句:

作用:接收一个对象,将指定对象添加到作用域链中。
with语句使用方法:

with(people) 
{ 
       var str = "姓名: " + name + "<br>"; 
       str += "年龄:" + age + "<br>"; 
       str += "性别:" + gender; 
       document.write(str); 
} 

优点是不用多次写对象的名字,在代码块里直接使用对象的值,但是注意with语句内不能改变对象的属性,改变对象的属性还是要引用对象来改变。

2.try-catch语句:

作用:catch语句产生一个新对象添加到作用域链的前端,主要用来检测代码中的错误。
try-catch的用法:

try{
    //可能会导致出错的代码
}catch(error){
  alert("catch an error");
}

当try运行的代码运行出现错误的时候,就会立即退出代码进程,执行catch语块,catch接收到一个包含错误对象的信息,对象下的message是包含错误信息,对象的名字要自己起。

3.JS没有块级作用域

花括号的边界表示一个块,但是在JS中,花括号封闭的的代码中声明的变量会添加到当前的执行环境。

if(true){
   var color="blue";
}
alert(color); //blue

用关键字let让生命的变量只在块作用域内有效。

for(let i=0;i<5;i++){
  //操作
}
alert(i); //ReferenceError: i is not defined

三.垃圾收集机制

JS中会自动找出不再使用的变量,释放其占用的内存,按照固定是时间间隔,周期性地重复操作。

1.标记清除

当变量进入环境的时候就标记“进入环境”,当环境离开环境的时候就标记为“离开环境”。

2.引用计数

引用计数是根据每个变量使用的次数。
1.声明一个变量并且将引用类型的值赋值给该变量,这个的引用次数加一。
2.同一个值赋值给另一个变量,该值的引用次数加一。
3.包含这个值的引用变量又取得了另外一个值,该值的引用次数减一。
4.该值的引用次数变成0时,等待垃圾收集器运行时释放该值所占的内存。

但是此机制有弊端:

function problem(){
     var  a =new Object();
     var  b =new Object();
     
     a.some = b;
     b.some = a;
}

例子中的两个对象通过各自的属性相互引用,两个对象的引用次数都是2,不会是0。

参考文献:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容