js 变量、作用域

一、基本类型与引用类型

  • 1.1 基本类型:保存在栈内存中的简单数据段,值保存在内存中的一个位置

  • 1.2 引用类型:保存在堆内存中的对象,变量保存的仅仅是一个指针,这个指针指向内存中的另一个位置,该位置保存对象

    • 1.2.1 5种基本数据类型:Undefined、Null、Boolean、Number、String在内存中分别占有固定大小的空间,保存在栈内存中

    • 1.2.2 按值访问:对于保存基本数据类型的变量,我们操作的是它们实际保存的值

    • 1.2.3 引用类型的值由于大小不固定,因此保存在堆内存中,但存放引用类型值的堆内存的内存地址大小是固定的,因此我们将这个地址保存在栈内存中,当操作引用类型的值时,先到栈内存        读取该引用类型值的堆内存地址,然后在找到保存在堆内存中的引用类型的值

    • 1.2.4 按引用访问:因为我们操作的不是实际的值,而是被这个值所引用的对象

    • 1.2.5 保存在栈内存中的每个值分别占据固定大小的空间,因此可以按照顺序来访问
      在这里插入图片描述

  • 1.3 动态属性:只能给引用类型值动态的添加属性
  • 1.4 复制变量值:针对基本数据类型值的复制,会在栈中创建一个新值,然后把该值复制到为新变量分配的位置上

针对引用类型值时,复制的只是一个指针,复制操作结束后,两个变量实际上将引用同一个对象

var num1=5;
var num2=num1;
num1=6;
alert(num2);//5
/**/
var obj1=new Object();
var obj2=obj1;
obj1.name="Jim";
alert(obj2.name);//"Jim"

在这里插入图片描述

  • 1.5 传递参数:所有的参数传递全部是按值传递,虽然访问变量的时候有按值和按引用两种方式,但是参数传递只能按值传递。在向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量,这个变量的变化不会反映在函数外面
function setName(obj){
    obj.name="Jim";
    obj=new Object();
    obj.name="Greg";
}
var p=new Object();
setName(p);
alert(p.name);//"Jim"
//如果是按引用传递的话,那么p就会被自动修改为指向其name属性为”Greg“的新对象,但是由下图分析可知,参数传递是按值传递

在这里插入图片描述

  • 1.6 检测类型:typeof操作符是确定一个变量是字符串、数值、布尔、还是undefined,以及object的最佳工具,但是对于一个对象或者null,却只能返回"object",因此在检测引用类型值的时候,引入了instanceof操作符
function Name(){
}
var p=new Name();
alert(p instanceof Name);//true

二、执行环境和作用域

  • 2.1 执行环境定义了变量和函数有权访问的其他数据,每个执行环境都有一个变量对象,环境中的所有变量和函数都保存在这个对象中,我们编写的代码无法访问这个对象
  • 2.2 全局执行环境:最外围的一个执行环境,在web浏览器中,全局执行环境是window对象,因此全局变量和函数都作为window对象的属性和方法创建的
  • 2.3 当某个执行环境的所有代码执行完毕后,该环境会被销毁,保存在其中的变量和函数也会被销毁
  • 2.4 全局执行环境的销毁是在关闭网页或者浏览器时
  • 2.5 每个函数都有自己的执行环境,当执行到某个函数时,会把控制权交给该函数,直到该函数执行完毕后,再把控制权交给之前的环境
  • 2.6 当代码在一个环境(例如一个函数)中执行时,会创建变量对象的作用域链
  • 2.7 作用域链的作用是保证对执行环境中的变量和函数的有序访问
  • 2.8 作用域链的前端始终是当前代码的执行环境的变量对象
  • 2.9 如果执行环境是函数,那么变量对象是活动对象,初始只包含一个变量arguments对象,外层是包含该环境的环境,外层的外层是包含该环境的环境的环境,一直延伸到全局执行环境
  • 2.10 全局执行环境始终是作用域链的最后一个对象
  • 2.11 在搜索某个标识符(如变量名,函数名等)时,会沿着作用域链一级一级的搜索,直到找到,搜索停止,这也就达到了2.7中提到的作用域链的作用(保证对执行环境中的变量和函数的有序访问)
var color="blue";
function change(){
    var another="red";
    function swap(){
        var temp=another;
        another=color;
        color=temp;
    }//这里swap函数只是定义,并没有执行
    swap();//这里才是swap函数的执行
}//这里change函数只是定义,并没有执行
change();//这里才是change函数的执行

在这里插入图片描述

  • 2.12 内部环境可以通过作用域链一级一级访问都所有外部的变量以及函数,包括最外层的全局执行环境,但是外部环境却不能访问内部环境的变量和函数,作用域链只能从下向上搜索,不能从下向上搜索
  • 2.13 例如swap函数可以访问全局变量color,但是全局变量window却不能访问到another或者temp
  • 2.14 延长作用域链的方式:第一try-catch语句中的catch块,第二with语句,这两个语句都会在作用域链的前端添加一个变量对象,对于with语句来说,其变量对象中包含着为指定对象的所有属性和方法所作的变量声明。对于catch语句来时,其变量对象中包含的是被抛出的错误对象的声明,这些变量对象是只读的
  • 2.15 浏览器的兼容性问题1注意IE与标准在try-catch语句延长作用域链的不同之处:即使在catch块的外部也可以访问到错误对象
  • 2.16 js没有块级作用域的概念,所谓块级作用域就是由花括号封闭的代码块都有自己的作用域,但是js中使用var声明的变量,会被自动添加到距离最近的可用的执行环境中,未使用var声明被初始化的变量,会被自动添加到全局环境,其作用范围跟花括号没有关系
  • 2.17 查询标识符时也会根据作用域链,从下向上一级一级进行搜索,搜索到后,就停止,因此,如果局部环境存在同名的标识符,就不会使用父环境中的标识符
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值