javascript——基本类型和引用类型

来源:互联网 发布:文字图片制作软件 编辑:程序博客网 时间:2024/06/05 19:21
基本类型和引用类型的值:
基本类型的值:
基本类型的值指的是简单的数据段,在将一个值赋给变量时,解析器必须确定这个值是基本类型的值还是引用类型的值,javascript中有5中常见的基本数据类型:Undefined、Null、Boolean、Number、和String,这5中基本数据类型是按值访问的,因为可以操作保存在变量中实际的值。
引用类型:
引用类型的值是指哪些可能由多个值构成的对象,引用类型的值是保存在内存中的对象,与其他语言不同,javascript不允许直接访问内存中的位置,换言之就是javascript不允许我们直接操作对象的内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象,因此,引用类型的值是按引用访问的。
动态的属性:
定义基本类型值和引用类型值的方式是类似的:创建一个变量并为该变量赋值,但是,当这个值保存到变量中以后,对不同类型值可以执行的操作则大相径庭,对于引用类型的值,我们可以为其添加属性和方法,也可以改变和删除其属性和方法。
实例代码如下:
var person = new Object();person.name = "zhang";alert(person.name);//zhang
上面的实例中就是一个简单的引用类型,对于引用类型的值我们可以为其添加属性和方法,上例中我们创建了一个对象并保存在了变量person中,然后为这个变量添加了一个属性name,因为这种是引用类型所以可以为其添加属性,但是如果是基本类型的值呢!?我们是不是也能添加属性或方法呢!?来看看下面这个实例:
var work = "IT";work.time = "3";alert(work.time);
我们运行上面的代码来看看结果是什么如下图:
我们可以看见控制台上并没有报错,但是弹出的确实undefined。所以可以总结出我们在给基本类型值添加属性或方法是虽然在浏览器的控制台上并不会报错但是代码运行时发现该属性不见了。这就说明了基本类型值是不能够添加属性或方法的,但是引用类型值可以动态添加属性或方法,以方便我们后期的调用。
复制变量值:
复制基本类型值:
我们在上面提到过基本类型值的存储方式是有区别的,另外就是在复制变量的值也存在一定的区别,如果我们从一个变量向另一个变量复制基本类型的值,会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上。
实例代码部分如下:
var name1 = "zhang";var name2 = name1;alert(name1);//zhangalert(name2);//zhang
由上面代码可见我们将name1的值赋给了name2此时虽然name1与name2的值是一样的,但是他们却是彼此独立的,后面调用的时候也是相互之间不影响的,也就是相当于将name1的值重新复制了一份,然后将这个重新复制一份的值给了name2。
上面我们讲的只是复制基本类型值,那么该如何复制引用类型值呢!?
复制引用类型值:
当从一个变量向另一个变量复制引用类型的值时,同样也会将存储在变量对象的值复制一份到为新变量分配的空间中。
实例代码如下:
var myfile1 = new Object();var myfile2 = myfile1;myfile1.name = "zhang";alert(myfile2.name);//zhang
在上面例子中我们新创建了一个实例对象,然而这个实例对象是存储在什么地方呢!?其实它在被创建出来后就会被存储在内存中,然后我们可以不断向这个实例对象中添加属性及方法,在这里我们仅仅只添加了name属性,我们将新创建的对象保存在myfile1中并且将myfile1复制给了myfile2,注意我们复制给myfile2的不是任何属性或方法,我们复制给myfile2的是保存在myfile1中新创建的实例对象,这也就意味着myfile1与myfile2同时都会指向同一个对象中,所以无论我们现在向这个新的实例对象中添加什么属性或方法,myfile1跟myfile2都是可以共享的。
传递参数:
有一点我们必须要很清楚,在javascript中所有函数的参数都是按值传递的。也就是说,我们可以把函数外部的值复制给函数内部的参数,这个过程就像我们将一个变量的值复制给另一个变量一样,但是我们有时会感到迷惑,那就是如果是基本类型值的话会很容易理解,但是如果是引用类型的值那么我们又该怎么办呢!?其实很简单,就像是引用类型变量的复制一样的。我们将新的实例对象保存的所在变量复制给参数,无论我们将新创建的实例对象复制给谁,前提有点一就是我们上面提到过的他们指向的对象都是同一个,这是无法改变的,换言之,不管我们是向这个被复制的对象添加任何属性及方法,在外部的本体上都会有所体现。
我们先做一个按基本类型值传递的例子:
function myfile(num){num+=10;return num;};var myNum = 10;var result = myfile(myNum);alert(myNum);//10alert(result);//20
由上面代码可以看出如果我们直接alert(myNum);弹出的值就是10,因为在则行这句代码的时候跟随着作用域链向上找的化变量myNum的值就是10,而我们如果将变量myNum当参数传递给函数是,现在就是相当于将myNum复制给了num所以这就是按值传递的结果弹出的是20。
那么我们来看看如果是按对象传值呢!?
(代码段一:)
function myfile(obj){obj.name = "zhang";};var myself = new Object();myfile(myself);alert(myself.name);//zhang
如上代码,弹出的结果为“zhang”这个是怎么运行的呢!?是的,我们在外部中并没有为myself添加新的属性,但是当我们将保存的有新实例对象的变量当作参数传递给myfile函数的时候,这时的代码可以如同下面:
(代码段二:)
var myself = new Object();var obj = myself;obj.name = "zhang";alert(myself.name);//zhang
上面两段代码其实是等效的,运行原理也是一样的,只不过在在代码段一种是将obj变成了参数,但是在函数的内部它依然还是一个局部变量,所以无论它的形式怎么变其结果还是两个变量都指向了同一个内存对象中的,不管我们给两个变量的哪一个添加了属性或方法,另一个变量都会得到继承。那么这里有一个小问题就是在局部作用域中修改的对象会在全局作用域中反映出来,究竟是属于按值传递呢!?还是按引用传递呢!?
我们来看看下面的代码就明白了:
function myfile(obj){obj.name = "zhang";//基本类型var obj = new Object();//引用类型obj.name = "hu";};var myself = new Object();myfile(myself);alert(myself.name);//zhang
从上面的代码中我们可以看出在局部作用域中修改的对象会在全局作用域中反映出来并不是按引用传递的如果是按引用传递的话那么弹出的值将会是“hu”。
如有理解不当之处,欢迎各位老铁留言指正。谢谢!!!!
原创粉丝点击