引言

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大规模数据处理技巧之一:数据常用操作

    面对读取上G的数据,python不能像做简单代码验证那样随意,必须考虑到相应的代码的实现形式将对效率的影响.如下所示,对pandas对象的行计数实现方式不同,运行的效率差别非常大.虽然时间看起来都微不 ...

  2. Visual Studio 2010 常用快捷方式

    调试快捷键 F6:           生成解决方案 Ctrl+F6:   生成当前项目 F7:           查看代码 Shift+F7:  查看窗体设计器 F5:           启动调 ...

  3. 有关jQuery valid 验证多个同name属性的input的问题

    今天遇到需要动态添加多个同name属性的input框,用jQuery valid进行验证时,没有指定不同的id,验证只会在第一个显示提示信息,因为jQuery valid显示的提示信息是根据每个inp ...

  4. asdfadsf

    bool is_r_value(int &&) { return true; } bool is_r_value(const int &) { return false; } ...

  5. Java 设计模式系列(十四)命令模式(Command)

    Java 设计模式系列(十四)命令模式(Command) 命令模式把一个请求或者操作封装到一个对象中.命令模式允许系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复 ...

  6. Hadoop学习【一】单机版搭建

    首先要说一下,Hadoop 2.x版本以后的改动,在这里帖一篇文章,觉得写的不错. http://www.ibm.com/developerworks/cn/opensource/os-cn-hado ...

  7. 使用word 2010 发布csdn博客

    目前大部分的博客作者在用Word写博客这件事情上都会遇到以下3个痛点: 1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.使用Word写 ...

  8. 从Objective-C到Swift 单例模式

    在Objective-C中经常会用到单例模式.最常见的就是: [UIApplication sharedApplication].delegate 这里的sharedApplication就是一个返回 ...

  9. C的打印输出格式

    #include<stdio.h> int main() { float test1=12.3224356546565461-0.1; int test2=13; char test3[] ...

  10. ffmpeg学习(三)——ffmpeg+SDL2 实现简单播放器

    本篇实现基于ffmpeg动态库用测试程序播放本地文件和RTSP视频流. 参考文章:http://blog.csdn.net/leixiaohua1020/article/details/8652605 ...