探析 JavaScript 中令人困惑的变量赋值

转载 2010年03月30日 11:05:00

 

Javascript是一门弱类型的语言,声明变量不需要声明其类型,var x 就可以等于任何类型的值。
比如:

var str = "string....";
var arr = ["this","is","array"];
var obj = {name:"caizhongqi",age:26,sex:"male"};

这些都是正确的,这似乎非常简单方便,但是这种方便也会带来一些令人难于捉摸的意外,看看下面的例子(例1):

<script> var x = "this is string";
 var y = x;
 x="ni hao";
 alert(y)
</script>


你可能一下子知道alert出来的就是“this is string”,没错,但对于用Java语言的程序员来说,var y=x 应该是把x在存储器中的地址(指针)赋给y变量才对,因此他们觉得应该alert出“ni hao”才会更符合Java语言的习惯,但JavaScript语言不是这样,字符串的赋值是直接量操作,直接把数据copy给y的存储空间。

再看看下面的例子(例2):

<script>
var x = ["hello"]  // 这是一个数组,只有一个元素,并且该元素为字符串类型
var y = x;
x[0] = "world";
alert(y[0]);
</script>


如果你还以为alert出来的是“hello”,那就错了。当 var y = x 时,x不是已经把它的数组给了y吗?但事实上却不是这样, 当 var y = x 时,x传的是它在存储器中的地址(指针)!x[0]="world" 修改了在原存储位置上的数据,因此alert(y[0])就是拿x的新值出来alert。混乱了吧?怎么一会儿是直接量一会儿是引用量呢?
不急,下面的例子将更加混乱(例3):

<script>
var x = ["hello"]  // 这是一个数组,只有一个元素,并且该元素为字符串类型
var y = x;
x = ["ni","hao"];  // x 将变成一个新的数组了。
alert(y[0]);
</script>


你的眼睛告诉你,alert出来的是“hello”!这让人捉摸不透古灵精怪的JavaScript!

周星驰的《国产零零漆》中有类似的一幕:
当星爷刚从深圳到香港执行任务时,袁咏仪从他的行李中发现一个吹头发的风筒,星爷说这其实是个须刨,把皮鞋拿出来一看却是一个风筒,一个貌似大哥大电话的玩意其实又是一个须刨。须刨与风筒把袁咏仪与观众都搞混乱了,哈哈哈哈,这是我很喜欢的一部片,第一次看时肚子都笑痛了。

回过头来再看看刚才的变量赋值,直接量与引用量的使用,就好像须刨与风筒换来换去,把我们都搞晕了。
其实问题出在对x的第二次赋值 x = ["ni","hao"] 上,我们看看变量在存储器上变化以及JavaScript在对待字符串类型与对象类型的不同:

我们观察下面两种情况:
var x = "this is string...";
var y = ["this","is","string"];

x与y不同之处在于类型,javascript的解析器把字符串直接赋值(其实就是copy)给x(直接量),却把数组的指针赋给y(引用量),这一切都是瞬间全自动的!结合下面的图,可能会更好地理解:



图中p1、p2...就是变量的指针,上面的 var y 中的y存的就是Object类型变量的指针p1(假设),而x存放的就是字符串本身。再分析一下例3,执行 var x = ["hello"] 时,解析器就在内存上开辟一块存储空间放这个数组,而 x 就拿到了这个空间的地址(指针),再执行 x = ["ni","hao"] 时,解析器又新开辟一块存储空间放这个新数组,而x就是这个新存储空间的指针,这也就是说,JavaScript 里变量的重定义(或重新赋值)将会新开辟一块存储空间,而没有销毁原来的空间;回过头来再看例2,x[0] = "world",这句没有给x新定义值,没有新开辟存储空间,只是修改了它存储空间里面的数据,因此例2最后alert出来的就是“world”;例1是字符串赋值,全过程是直接量操作。

从上面的分析可以看出,JavaScript 的变量可以存储直接量也可以存储指针,这是没办法被人工干扰的,因此,在日常的编码中,就需要注意这些问题,比如大字符串连接,循环里面赋值等细节就能直接影响到程序的执行效率。

看看两个例子:

var _tmpStr="";
var str = "this is big string...";
for (i=0; i<100; i++){
    _tmpStr += a;
}
a = _tmpStr;


因为是字符串操作,使用直接量,每次循环都要操作大字符串,非常笨重,效率低下。如果改用引用量操作,即通过数组:

var str = "this is big string...";
var _tmpArray = [];
for (i=0; i<100; i++){
    _tmpArray[i]=str;
}
str = _tmpArray.join("");


做个测试,假如有个100k的字符串,用直接量连接操作,我的机器上需要约2600毫秒,如果用数组连接,则需要150毫秒,效率相差十几倍。

 

分析 JavaScript 中令人困惑的变量赋值

Javascript是一门弱类型的语言,声明变量不需要声明其类型,var x 就可以等于任何类型的值。  比如:  var str = "string....";  var arr = ["this...
  • u010373419
  • u010373419
  • 2013年07月18日 18:57
  • 1794

javascript进阶之基础篇一: 变量与赋值

JavaScript 变量: 变量是存储信息的容器。JavaScript 变量可用于存放值(比如 x=2)和表达式(比如 z=x+y)。 1、JavaScript变量的命名规则: .变量必须以字母开头...
  • DemonCode
  • DemonCode
  • 2016年08月03日 18:20
  • 475

javascript中给变量赋值,是引用还是复制?

要搞清这个问题,首先要搞清楚在javascript中的值有哪些类型,总结如下: javascript中的值类型分为两大类:基本类型和引用类型,所谓的引用类型就是对象,每种类型下面又分为5中类型: ...
  • u014114702
  • u014114702
  • 2015年05月14日 10:35
  • 2160

JavaScript中关于变量初始化和变量未定义

简单理解  变量未定义,就是根本没有var(声明)这个变量.                 而变量未初始化,其实也就是变量根本没赋值.               例如: ...
  • foreverlikui
  • foreverlikui
  • 2017年08月03日 18:18
  • 275

探析 JavaScript 中令人困惑的变量赋值(转自快乐笛子的博客)

Javascript是一门弱类型的语言,声明变量不需要声明其类型,var x 就可以等于任何类型的值。比如:var str = "string....";var arr = ["this","is",...
  • luohuayh
  • luohuayh
  • 2010年04月26日 11:49
  • 142

JavaScript eval定义动态变量名及赋值教程

/*简单代码,看懂eval动态变量定义的创建和使用*/ eval("var input_id1;"); input_id1 = 100; ...
  • qq285679784
  • qq285679784
  • 2017年04月25日 08:41
  • 1364

javascript中函数声明、变量声明以及变量赋值之间的关系与影响

javascript中函数声明、变量声明以及变量赋值之间的关系与影响函数声明、变量声明以及变量赋值之间有以下几点共识: 1、所有的全局变量都是window的属性 2、函数声明被提升...
  • javaloveiphone
  • javaloveiphone
  • 2015年12月09日 13:28
  • 831

如何把session中的值赋给javaScript变量

如下:     var bm='';     var curreceUserN
  • lyr1985
  • lyr1985
  • 2010年07月19日 17:24
  • 2319

JavaScript 对变量进行赋值的条件运算符

条件运算符JavaScript 还包含了基于某些条件对变量进行赋值的条件运算符。语法variablename=(condition)?value1:value2 例子greeting=(visitor...
  • forest_fire
  • forest_fire
  • 2016年03月21日 10:56
  • 731

javascript大括号赋值给变量

var xxx ={} 这个是js中定义对象的一种写法 相当于 var xxx = new Object(); 这种写法叫定义直接量 var xxx =();//声明xxx为空函数 ---- 这个写...
  • weiyong1999
  • weiyong1999
  • 2012年08月28日 11:15
  • 2055
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:探析 JavaScript 中令人困惑的变量赋值
举报原因:
原因补充:

(最多只允许输入30个字)