引言

JavaScript的变量本质是松散类型的,也就是说其变量就是用于保存特定值的一个名字,变量的值和数据类型可以在脚本执行的生命周期中发生变化。这是一个很有趣很强大的特性,但是也是一个极容易出错误的地方。

两大类型

基本类型:指的是简单的数据段,有五种基本类型:Undefined,Null,Boolean,Number,String。这几种基本类型是按值访问的,操作变量时操作的是保存在变量中实际的值。

引用类型:指哪些可能由多个值构成的对象(Object)。引用类型的值是保存在内存中的对象。需要注意的是,JavaScript不允许直接访问内存中的位置,所以操作对象时,实际是操作对象的引用(这种说法是不严谨的,因为当复制保存对象的变量时,操作的是对象的引用;但是在为对象添加属性时,操作的是对象实际本身)。

变量的复制

基本类型变量的复制

当复制基本类型的变量时,实际是在变量对象上创建一个新值,然后把这个创建的新值分配给为新变量复制的位置上。所以原始变量和被赋值的变量在内存中是独立的,这两个变量可以参与任意操作而不会相互影响

var a = 'test';
var b = a;
a = 'change';
console.log(b);
//输出:test

 

引用类型变量的复制

当复制引用变量的值时,也是讲存储在变量对象中的值复制一份放在新变分配的空间中。但是这里需要理解的是,这个值的副本实际是一个指针,而这个指针指向存储在堆内存中的一个对象。上面已经说过了:对于引用类型的变量,JavaScript不允许直接操作对象,而是操作对象的引用,所以在引用变量中存储的是一个指向实际存储空间的指针。复制结束后两个变量实际引用的一个对象,所以改变其中一个变量,另一个将会受到影响。

var a = new Object();
var b = a;
a.title = 'test';
console.log(b.title);
//输出:test

保存在变量对象中的变量和保存在堆中的对象之间的关系(不要在意图片丑~)

参数传递

在ECMAScript中所有函数的参数都是按值传递的。什么意思呢?就是把函数体外面的值复制给函数内部的参数(如同把值从一个变量复制到另一个变量一样)。这样子就很好理解了。和理解了上面变量的复制,也就很好理解js中参数的传递特性了。

在向参数传递基本类型值时,被传递的值会被赋值给一个局部变量,即函数体的命名参数(在ECMAScript中就是arguments对象中的一个元素)。在向参数传递引用类型的值时,会把这个值在内存中的地址赋值给参数。

function setName(n) {
n = 'test';
return n;
}
var a = 'haha';
var b = setName(a);
console.log(a);
console.log(b);
//输出:
//haha
//test

如果使用引用类型作为参数:

function setName(obj) {
obj.name = 'shanlei';
}
var a = new Object();
setName(a);
console.log(a.name);
//输出:shanlei

在这个函数中obj和a引用的是同一个对象,挡在setName中添加name属性后,函数外部也会有所反应。在这里有人可能会错误的认为在局部作用域中修改的对象会在全局作用域中反映出来,就是说明这个参数是按引用传递的。这个思想是错误的。可以看下面这个例子:

function setName(obj) {
obj.name = 'shanlei';
obj = new Object();
obj.name = 'Grep';
}
var a = new Object();
setName(a);
console.log(a.name);
//输出:shanlei

在这段中,我们将obj重新定义了一个对象,并且给这个新对象定义一个不同值的name属性。如果参数是按引用传递的,那么a应该会自动被修改为指向其name属性设置为'Grep'的新对象。因为如果参数是以引用传递的,那么obj和a应该是统一引用,这个引用指向堆中实际存储对象的空间。当生成一个新的对象设置新的name属性并将这个新对象给obj时,实际上就是改变了这个引用在堆中的指向,所以外部的a也就会自动改变。而输出的依旧是'shanlei',这说明在函数内部修改了参数的值,但原始的引用依旧没有改变。因为obj和a在内存中是两个独立的变量对象,这两个变量对象指向堆中同一空间,当生成新对象并传递给obj时,obj的指向发生改变,但是a的指向依旧是堆中原始的空间,所以输出的依旧是‘shanlei’。当在函数内部重写obj时,这个变量引用就是一个局部对象,且这个局部对象在函数执行完毕以后会立即销毁。

以上~~

JavaScript变量那些事的更多相关文章

  1. javascript变量的作用域

    javascript变量的作用域 基本类型和引用类型 基本类型值指的是简单的数据段,而引用类型值指的是那个可能由多个值组成的对象  讲一个值赋值给变量时,javascript解析器首先要确定是基本类型 ...

  2. JavaScript 变量声明提前

    <JavaScript权威指南>中指出:JavaScript变量在声明之前已经可用,JavaScript的这个特性被非正式的称为声明提前(hoisting),即JavaScript函数中声 ...

  3. JavaScript 变量

    一,JavaScript 变量(存储信息的容器) 与代数一样,JavaScript 变量可用于存放值(比如 x=2)和表达式(比如 z=x+y). 变量可以使用短名称(比如 x 和 y),也可以使用描 ...

  4. javascript变量声明 及作用域

    javascript变量声明提升(hoisting) http://openwares.net/js/javascript_declaration_hoisting.html 可能要FQ一下 java ...

  5. JavaScript 变量作用域

    一. 变量声明 变量用var关键字来声明,如下所示: 变量在未声明的情况下被初始化,会被添加到全局环境. JavaScript执行代码时,会创建一个上下文执行环境,全局环境是最外围的环境.每个函数在被 ...

  6. 【转】javascript变量声明 及作用域

    javascript变量声明提升(hoisting) javascript的变量声明具有hoisting机制,JavaScript引擎在执行的时候,会把所有变量的声明都提升到当前作用域的最前面. 先看 ...

  7. JavaScript变量和数据类型

    变量 变量就是一个元素,类似于数学中的概念,用来指定表示一个对象.在JavaScript中,用来指定变量的关键字为var.当声明新变量时,可以使用关键词 "new" 来声明其类型 ...

  8. 回归基础: JavaScript 变量提升

    from me: javascript的变量声明具有hoisting机制,它是JavaScript一个基础的知识点,也是一个比较容易犯错的点,平时在开发中,大大小小的项目都会遇到. 它是JavaScr ...

  9. JavaScript - 变量,作用域,内存

    JavaScript 变量可以用来保存两种类型的值:基本类型值和应用类型值.基本类型的值源自以下5种基本数据类型:Undefined.Null.Bollean.Number和String. 所有变量都 ...

随机推荐

  1. python操作vmware

    import pysphere from pysphere import VIServer host_ip = "200.200.173.45" username = " ...

  2. lib

    E:\\Qt\\Qt5.12.2\\5.12.2\\msvc2017_64\\lib\\ ------------------------------------------------------- ...

  3. git 查询某人的提交记录

    git log --author=liubo --name-only

  4. 8.3 mysql 表操作

    库操作 一 系统数据库 information_schema: 虚拟库,不占用磁盘空间,存储的是数据库启动后的一些参数,如用户表信息.列信息.权限信息.字符信息等    performance_sch ...

  5. html 中的<script>标签

    https://www.w3.org/TR/html51/semantics-scripting.html#the-script-element 一. <script type='text/ja ...

  6. (广搜)Catch That Cow -- poj -- 3278

    链接: http://poj.org/problem?id=3278 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 6211 ...

  7. 解决阿里云OSS跨域问题

    解决阿里云OSS跨域问题 现象 本人项目中对阿里云图片请求进行了两次,第一次通过img标签进行,第二次通过异步加载获取.第一次请求到图片,浏览器会进行缓存,随后再进行异步请求,保存跨域失效. 错误信息 ...

  8. Vivado安装教程

    Vivado的各个版本的安流程其实都差不多,本教程用Vivado2016.4为例进行安装,同样适用于之前和之后的各个版本. 下载好安装包后打开,双击xsetup.exe运行安装程序 弹出的窗口,提示现 ...

  9. VS2017安装时自动退出

    电脑重装系统后 win10,安装VS2017,一直不成功:保持一定时间后就自动退出,而没有跳到具体安装选择项界面.重复了好几次,并且电脑也重启还是这样. 最后在系统盘下面找到文件夹:C:\Progra ...

  10. vmware之VMware Remote Console (VMRC) SDK(三)

    前两节我们介绍了vmrc sdk的基本用法.在前面的demo中,有一个关键的问题是,我们现在所作的工作都是基于局域网的,作为应用层面上,主机不会直接暴露给用户,而是通过一系列的web service服 ...