企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
JS变量可能包含两种不同数据类型的值;基本类型值和引用类型值。基本类型指的是简单的数据段,而引用类型值那些由多个值构成的对象; 在将一个值赋给变量时,解析器必须确定这个值是基本类型值还是引用类型值。JS有5种基本数据类型:Undefined, Null,Boolean,Number和String。这5种基本数据类型是按值访问的。因为可以操作保存在变量中的实际的值。 引用类型的值保存在内存中的对象。与其他语言不同,JavaScript不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象,为此,引用类型的值是按引用访问的。引用是js面向对象的基本概念之一。它是一个指向对象实际位置的指针。实际的对象肯定不会是引用。比如字符串永远是字符串,不过多个变量能够指向同一个对象。 对象可以中有多个原型属性(property) 动态的属性 定义基本类型值和引用类型值的方式是类似的:创建一个变量并为该变量赋值。但是,当这个值保存到变量中以后,对不同类型值可以执行的操作则很相同。对于引用类型的值,我们可以为其添加属性和方法每页可以移除改变和删除其属性和方法。 ~~~ var person=new Object(); person.name="张三"; alert(person.name); var name="李四"; name.age="13"; alert(name.age); ~~~ 以上代码创建了一个对象将其保存在了变量person中。然后,我们为该对象添加了一个名字为name的属性,并为这个属性赋了值,当我打印这个属性的时候,是可以得到结果的。这说明如果对象不被销毁或者这个属性不被删除,则这个属性将一直存在。但是我们不能给基本数据类型添加属性。 复制变量值: 除了保持的方式不同之外,在从一个变量向另一个变量复制基本类型和引用类型的值时,也存在不同。如果从一个变量向另一个变量复制基本类型的值,会在变量对象上创建一个新值,然后把该值复制到位新变量分配的位置上; ~~~ var num1=5; var num2=num1; num1=3; alert(num2); ~~~ 在此num1种保存的值是5.当使用num1的值来初始化num2时,num2中也保存了值5。但num2中的5与num1中的5是完全独立的。该值只是num1中5的一个副本。此后,这两个变量可以参与任何操作互不影响。我觉得这一点和其他高级语言很相似例如java。 当从一个变量向另一个变量复制引用类型的值时,同样也会将存储在变量对象中的值复制一份到为新变量分配的空间中。不同的是们这个值的副本实际上是一个指针,而这个指针指向存储在堆中的一个对象,复制操作结束后,两个变量实际上将引用同一个对象。因此,改变其中一个变量,就会影响到另一个变量。这个跟引用类型的存储位置有关。 ~~~ var obj1=new Object(); var obj2=obj1; obj1.name="张三"; alert(obj2.name); ~~~ 打印出来的是张三,这是因为obj1和obj2是两个引用,这两个引用指向的值都是Object();我们操作值的时候是通过引用的,当我们的对象发生改变的,其引用的值也发生了改变; 传递参数: JS中所有函数的参数都是按值传递的。Java里面的参数有人认为是按值传递的,有人认为是按参数传递的,不过我写过一遍博客,里面专门讨论过这个,Java其实是按值传递的。也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。基本类型值的传递如同基本类型变量的复制一样,而引用变量传递也和复制一样。 在向参数传递基本类型的值时,被传递的值会被复制给一个局部变量(即命名参数,用JS的概念来说,就是arguments数组中的一个元素)。在向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化会反映在函数的外部。 ~~~ function add(num){ num+=10; return num; } var count=20; var resule=add(count); alert(resule); alert(count); ~~~ 参数count和参数num互不影响,只是num复制了count的值而已; ~~~ function setName(obj){ obj.name="张三"; } var person=new Object(); setName(person);alert(person.name); ~~~ 以上代码创建了一个对象,并将其值保存在person引用中,然后调用setName函数,把值传递给obj,obj这个时候引用的对象和person引用的对象是同一个对象,所以里面修改了属性值,外面会有显示。有很多程序员错误的认为,在局部作用域中修改的对象会在全局作用域中反映出来,就说明是按引用传递的,这个说法不现实; ~~~ function setName(obj){ obj.name="张三"; obj=new Object(); obj.name="李四"; } var person=new Object(); setName(person);alert(person.name); ~~~ 如果是按引用传递的话,我们为这个引用重新创建了一个对象,并赋值,但是最后的结果还是张三,证明了是按值传递的;