变量-内存-作用域(JavaScript)

Posted 减一

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了变量-内存-作用域(JavaScript)相关的知识,希望对你有一定的参考价值。

基本类型和引用类型

ECMAScript变量可能包含两种不同数据类型的值:基本数据类型值和引用类型值。
基本数据类型为:Undefined,Null,Boolean,Number和String五种。
引用类型为:Object,Array,Date,RegExp,Function。

基本变量值复制

var a = 11;
var b = a;
console.log(b);//11
a = 22;
console.log(a);//22
console.log(b);//11 
//b still has not been changed after the a was changed

以上代码说明:值复制(b复制a的值)后的两个变量(a和b)可以参与任何操作而不会相互影响。

对象变量值复制

var obj1 = new Object();
var obj2 = obj1;
obj1.name = ‘MUSTANG‘;
console.log(obj2.name);//MUSTANG
obj1.age = 23;
obj2.age = 24;
console.log(obj1.age);//24

以上代码说明:obj2复制obj1后,两个对象指向的是同一个堆内存(即共享一个堆内存)。
因此任意一个对象(obj1或者obj2)添加/删除属性或者方法都是在堆内存中更改的(如果两个对象拥有同一个属性名或者方法名,则以最后一个为准,即同名时前者被后者覆盖)。

参数的传递

function add(num){
    num += 20;
    return num;
}
var a = 10;
var result = add(a);
console.log(result);//30
console.log(a);//10

以上代码说明:参数是按值传递的,如果num是按引用传递,那么a的值也将为30。因为引用传递是通过堆内存来传递的。

一个有趣的例子

//#1
function setName(obj){
    obj.name = ‘MUSTANG‘;
}
var horse = new Object();
setName(horse);
console.log(horse.name);//MUSTANG
//---------------------------------
//#2
function setName(obj){
    obj.name = ‘MUSTANG‘;
    obj = new Object();
    obj.name = ‘SHELBY‘;
}
var horse = new Object();
setName(horse);
console.log(horse.name);//MUSTANG
//still MUSTANG

以上代码说明:结合#1看#2,首先执行setName()时参数按值传递,但是此时的参数是一个对象,对象则是按引用传递。
因此当执行setName()时,obj对象(即person对象)添加了name属性。
前面讲到,对象添加/删除属性或者方法都是在堆内存中操作的,因此外部person也会添加name属性。
因此执行console.log(horse.name)得到的是’MUSTANG’而不是’SHELBY’
至于为什么obj = new Object(); obj.name = ‘SHELBY‘;不会生效是因为此时的obj是局部变量,而且此时的obj又是另外一个堆内存了,所以并不会影响外部结果。

文章说明:

参考资料文献:《javascript高级程序设计》(第3版) 第四章

水平有限,欢迎指正。








以上是关于变量-内存-作用域(JavaScript)的主要内容,如果未能解决你的问题,请参考以下文章

作用域是什么?

JS---闭包

JavaScript中变量作用域和内存问题

第一百零六节,JavaScript变量作用域及内存

让你拿10万年薪技能:JavaScript 变量作用域及内存详解!

javascript 变量,作用域,内存管理小结