JS变量值类型

按照ECMA-262的定义,JS的变量与其他语言的变量有很大的区别。JS变量的松散类型的本质,决定了它只是在特定时间保存特定值的一个名字而已。由于不存在定义某个变量必须要保存何种数据类型值的规则,变量的值及其数据类型可在脚本的生命周期内改变。

ECMAScript变量可能包含两种不同数据类型的值:基本类型和引用类型值

  • 基本类型值:简单的数据段
  • 引用类型值:可能由多个值构成的对象

将一个值赋给变量时,JS解析器必须确定这个值是基本类型还是引用类型。

  • 基本类型
    UndefinedNullBooleanNumberString,这5种基本数据类型是按值访问的,因为可操作保存在变量中的实际的值。
  • 引用类型
    引用类型的值是保存在内存中的对象。与其他语言不同,JS不允许直接访问内存的位置,也就是说不能直接操作对象的内存空间。在操作对象时,实际上是在操作对象的引用而非实际的对象。为此,引用类型的值是按引用访问的。

动态的属性

定义基本类型值和引用类型值的方式是类似的:创建一个变量并为该变量赋值。但是,当值保存到变量后,对不同类型值可以执行的操作则大相径庭。

  • 对于基本类型的值:不能为基本类型的值添加属性,尽管这样做不会导致任何错误。
var person = 'alice';
person.age = 27;
console.log(person.age);// undefined
  • 对于引用类型的值:如果对象不被销毁或属性不被删除,则属性将一直存在。
var person = new Object();
person.name = 'alice';
console.log(person.name);// alice

复制变量值

基本类型值和引用类型值除了保存方式不同之外,在从一个变量向另一个变量复制时也存在不同。

  • 复制基本类型的值:在变量对象上创建新值,然后将该值复制到为新变量分配的位置上。
var num1 = 5; // num1中保存的值是5

// num2中的5和num1中的5是完全独立的,num2中的5只是num1中5的一个副本。
var num2 = num1;// 使用num1的值来初始化num2时,num2中也保存了值5。

# 两个变量可参与任何操作而互不影响
4933701-1dd86dccc0e31d43.png
复制基本类型的值
  • 复制引用类型的值
    将存储在变量中的引用类型的值复制一份放置到新变量分配的空间中,不过这个值的副本实际上是一个指针,指针指向存储在中的一个对象。复制操作结束后,两个变量实际上引用同一个对象。因此,改变其中给一个变量,就会影响到另一个变量。
var obj1 = new Object(); // 变量obj1 保存了对象的新实例
var obj2 = obj1;//将实例复制到新变量后,两对象都指向同一个对象。
obj1.name = 'alice';
console.log(obj2.name);// alice
4933701-39bbd74ded1bc614.png
复制引用类型的值

传递参数

ECMAScript中所有函数的参数都是按值传递的

访问变量有按值和按引用两种方式,一般而言参数只能按值传递。而ECMAScript中所有函数的参数都是按值传递的,也就是说,把函数外部的值复制给函数内部的参数,和把值从一个变量赋值到另一个变量一样

  • 基本类型值的传递
    在向参数传递基本类型的值时,被传递的值会被复制给一个局部变量(即命名参数,或ECMAScript的概念来说,就是arguments对象中的一个元素)
// 函数拥有一个参数,而参数实际上是函数的局部变量。
function add(num){
  return num+1;
}

var num = 1;
var result = add(num); // 调用函数时,变量作为参数被传递给函数。变量值被赋值给参数以便在函数中使用。
console.log(num, result);// 1 2
  • 引用类型值的传递
    在向参数传递引用类型的值时,会把值在内存中的地址复制给一个局部变量,因此这个局部变量的变化会反映在函数外部。
function setName(obj){
  // 函数内部obj和person引用的是同一个对象
  obj.name = 'alice';
}

var person = new Object(); // 创建一个对象并将其保存在变量中
setName(person);// 对象被传递到setName()函数之后就被赋值给了obj,obj也会按引用来访问同一个对象。
console.log(person.name);// alice
  • 错误地认知:在局部作用域中修改的对象会在全局作用域中反映出来,就说明参数是按引用传递的。
  • 正确地认知:对象是按值传递的
function setName(obj){
  obj.name = 'alice';
  // 在函数内部重写obj时,这个变量引用的就是一个局部对象了
  // 这个局部对象会在函数执行完毕后立即被销毁。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
  obj = new Object();                                                                                                                                                                                                                                                   
  // 在函数内部修改了参数值,但原始的引用仍然保持未变。
  obj.name = 'ben';
}

var person = new Object();
setName(person);
console.log(person.name);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值