首页 > PHP,Javascript > javascript中数组与php数组初始化差异

javascript中数组与php数组初始化差异

准确来说,javascript中我们需要称之为数组对象,因为数组就是对象,不信你看:

<script type="text/javascript">
var a=[1,2,3];
//竟然会弹出object
alert(typeof(a));
</script>

之前学习php的时候也接触过php数组,包括索引数组和关联数组。

其中索引数组和js中的数组“表面”上是一样的,取值方式也是类似的。关联数组和js中的普通对象是差不多的。

一直这么认为,然后今天悲剧了,代码如下(千万被运行!):

<script type="text/javascript">
var arr = brr = new Array();
arr[0] = 'a';
arr[1] = 'a';
arr[2] = 'a';
for(var i=1; i<arr.length; i++){
	brr.push(arr[i].replace('a', 'b'));
}
console.log(arr);
console.log(brr);
</script>

我只是想给brr填充一些数据而已,浏览器为何会卡死?难道是arr的长度太大了,可是我明明只给了3个元素。

于是我在循环中打印出arr的元素,结果让我震惊了。

<script type="text/javascript">
var arr = brr = new Array();
arr[0] = 'a';
arr[1] = 'a';
arr[2] = 'a';
for(var i=1; i<arr.length; i++){
	brr.push(arr[i].replace('a', 'b'));
	console.log(arr);
}
console.log(arr);
console.log(brr);
</script>

arr的元素竟然在无限增长,同时我的CPU占用也满了。之后我特意去重新学习了javascript中的数组对象,终于找到了问题的原因:

<script type="text/javascript">
//例子一: 引用
var myArrayRef = new Array(0,1,2); //创建数组对象
var mySeconArrayRef = myArrayRef; // 对象复制.
myArrayRef[0] = 100; // 修改元素值
/**
* 输出 100; 学过其它语言的都应该知道这里应该输出的是0 为什么输出的是100呢?
* 上面程序通过把myArrayRef对象复制给了mySeconArrayRef这时就存在了2个独立的 但最初值是相同的对象
* 因为是独立的为什么修改myArrayRef会对别一个对象有影响呢?大家都知道只有当他们引用的是同一个对象时这时修改一个才会
* 对别一个产生影响.但是在javascript语言中创建的对象myArrayRef值中其时保存的是对象的引用(也就是一个地址).
* 也就是 我用 new Array生成的保存在内存中而new Array把它所在的地方告诉了myArrayRef,myArrayRef又把这地址告诉了mySeconArrayRef
* 他们两个都指向的是new Array生成对象的地址而不是把对象保存在myArrayRef中,所以通过其中的一个去修改值时其时是修改他们同指象的那对象.
*/
alert(mySeconArrayRef[0] );
//例子二: 赋值
var myVa = 'ABC'; //把ABC的值 赋予了myVa
var myVb = myVa; // myVa 赋值给 myVb
myVa = 'DEF'; //修改myVa
/**
* 输出的是:ABC. 因为是把值保存在了变量了 而不是保存的是引用地址,所以他们两个是相对独立的整体.
*/
alert(myVb);
</script>

原来在javascript中的对象赋值都是浅复制,只是传递了内存地址,并未在内存中复制新的拷贝。也就是说我们常常在dom编程中使用以下方式并占用太多的内存,因为他们始终代表同一个对象:

function $(id){
    return document.getElementById(id);
}
var one = document.getElementById(id);
var two = $("test");
//改变其中任何一个都会直接影响另一个

然而,在php中却没有这样的说法,如果按照下面的方式编写代码,并不会使用引用,而是在内存中直接复制一份:

<?php
$arr = $brr = array();
$arr[0] = 'a';
$arr[1] = 'a';
$arr[2] = 'a';
for($i=1; $i<count($arr); $i++){
	array_push($brr, str_replace('a', 'b', $arr[$i]));
}
var_dump($arr);
var_dump($brr);
var_dump($brr == $arr);
var_dump($brr === $arr);

如果你是在javascript中,还是老老实实分开初始化数组和对象吧:

<script type="text/javascript">
var arr = new Array();
var brr = new Array();
arr[0] = 'a';
arr[1] = 'a';
arr[2] = 'a';
for(var i=0; i<arr.length; i++){
	brr.push(arr[i].replace('a', 'b'));
	console.log(arr);
}
console.log(arr);
console.log(brr);
</script>

以上便是javascript数组与php数组的差异了。

=======================================================================

其实一开始初始化数组的时候,$arr和$brr已经位于内存中不同的地方了,所以在php中使用赋值语句的时候需要考虑到内存消耗的问题,如果$abcdefghijklmn即使是一个非常难记却又庞大的数组,你贸然使用$arr = $abcdefghijklmn;进行简写,势必会造成此处内存消耗翻倍。

那么php中的数组和普通常量都是直接拷贝一整份内容,那么php的对象呢?

<?php
class test{
	public $text = 'nothing';
	function say()
	{
		echo $this->text."<br/>";
	}
}
//实例化一个a对象
$a = new test();
$a->text = "I am a's object";
$a->say();
//将$a对象直接赋值给$b
$b = $a;
//即使不设置b,输出I am a's object,说明b和a是指向同一份内存的
$b->say();
//改变b的设置a同样也会受到影响
$b->text = "I am b's object";
$a->say();
//我们看下$a===$b是个什么鬼,果然是true
var_dump($a===$b);


在对象的处理上,php和其他语言一样都认为是引用数据类型,唯有php数组被认为是复合数据类型(非引用),而像java这样的语言中数据也是引用数据类型。

另外,php中可以使用单例模式来保证每一次new出来的类指向同一份内存。

<?php
//单例模式
class Test { 
	private $unique; 
	public $text = 'nothing'; 
	static private $instance;//静态属性保存该类实例 

	private function __construct(){//构造方法私有(防止外界调用) 
		$this->unique=rand(0,20000); 
	} 
	static public function getInstance(){//静态方法提供对外接口(获取实例) 
		if(!self::$instance instanceof self){ 
			self::$instance=new self(); 
		} 
		return self::$instance; 
	} 
	private function __clone(){}		//私有克隆方法,防止外界直接克隆该实例 
}
$test=Test::getInstance(); 
$test2=Test::getInstance(); 
$test->text = 'test';
print_r($test);  
print_r($test2); 

if($test===$test2){ 
	echo 'equal!'; 
}else{ 
	echo 'not equal!'; 
}

这个getInstance有什么好处呢?实际上从new过渡到getInstance应该非常方便,只需要改动少量代码,并且无需浪费多余的内存,目前来看还是很不错的。

永久地址:http://blog.zhengshuiguang.com/php/js-array.html

转载随意~请带上教程地址吧^^

标签:javascript数组 对象 浅复制 引用 单例模式

评论已关闭