走进Javascript变量的世界

本文详细解析JavaScript中的基本类型值与引用类型值的区别,包括属性动态赋值、变量赋值、参数传递及类型检测等方面。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先了解两个概念来引入本帖的重点讨论话题。

  • 基本类型值
    由五种基本数据类型(Number、Boolean、String、Null、Undefined)创建的值;
    按值访问。可以操作保存在变量中实际的值。

    如:

// 10是Number类型,属于基本类型值,将这个值赋值给变量a,直接操作a等于直接操作10这个值
var a = 10;
alert(a + 10);   // 返回结果 20
  • 引用类型值
    由复杂数据类型(Object)创建的值;
    按引用访问。引用类型的值是保存在内存中的对象,操作对象变量实际上是操作对象的引用而不是对象本身。

下图可以帮助理解:

   这里的Object类型指的是Object对象的引用,简单的说就是通过这个引用我可以在堆内存中找到Object这个对象。

复杂类型值操作的是对象的引用,而不是对象本身

本帖讨论主题:

基本类型值和引用类型值的区别?



区别一:属性的动态赋值

   基本类型值和引用类型值的定义方法类似:创建一个变量并为该变量赋值。但是当这个值保存到变量中以后,对不同类型的值可以执行的操作则大相径庭。
  • 对于引用类型值,可以为其添加属性和方法,也可以改变和删除其属性和方法。

    如:

// 创建引用类型值并赋值给变量student,实际上赋值的是对象的引用
var student = new Object();    
student.name = '小明';   
alert(student.name);    // 返回结果 "小明"
  • 对于基本类型值,添加属性和方法会丢失属性

如:

// 创建基本类型值'小明'并赋值给变量name
var name = '小明';
name.age = 12;
alert(name.age);    // 返回结果 undefined

区别二:赋值变量值
这个区别直接看例子讲解:

  • 对于基本类型值。赋值给新变量后两个值是独立的,只是值的赋值。
var num1 = 12;
// 把变量num1的值赋值给变量num2,二者只是值的赋复制,之后操作num2不会影响num1
var num2 = num1;
num2 = num2 + 8;
alert(num2);    // 返回结果 20
alert(num1);    // 返回结果 12

这里写图片描述

  • 对于引用类型值。赋值给新变量的是对象的引用,此时两个变量指向同一个对象。操作其中任何一个变量,也会影响另一个变量。
var obj1 = new Object();
// 复制obj1的值给obj2,实际上复制的是对象的引用,二者仍然指向同一个对象,操作任何一个变量会影响另一个
var obj2 = obj1;
obj2.name = 'bob';
alert(obj1.name);    // 'bob'
alert(obj2.name);    // 'bob'

这里写图片描述

区别三:参数的传递

    这里说的参数的传递是说方法里的参数,可以把参数变量当做是方法内部的一个局部变量看待。

这里写图片描述

  • 对于基本类型的值作为参数传递,同变量的值传递一样,只是值的传递,相互独立。
// 定义方法,参数为基本类型值【参数变量为num】
function add (num) {
    num = num + 10;
    return num;
}
var num1 = 12;
/*
 * 这里调用了add方法,将【全局变量num1】作为参数传递到了方法内部,可以看成是:将【全局变量num1】的值复制给了【参数变量为num】,只是值的复制,二者相互独立
 */
alert(add(num1));    // 返回结果 20
alert(num1);    // 返回结果 10 ,
  • 对于引用类型值的参数传递,引用类型的传递
// 定义方法setName,参数为引用类型值
function setName (obj) {
    obj.name = 'bob';
}
var obj1 = new Object();
// 这里调用setName方法,将变量obj1的对象引用传递给了方法。所以obj1和方法内的obj都指向了同一个对象,在方法内添加对象的属性,在外部的也同样改变
setName(obj1);
alert(obj1.name);    // 返回结果 'bob'

区别四:检测类型

首先对于所有的变量都可以使用 typeof 操作符得到数据类型。
检测基本类型值的类型时使用 typeof 操作符。
检测引用类型值的类型时使用 instanceof 操作符。

如:

 var   aa = 12;
 var   bb = 'I am bob';
 var   cc = true;
 var   dd;
 var   ee = null; 
 var   ff  = /^\w*$/;
 var   gg =  {key1: 'value1', key2: 'value2'}; 
 var   hh = function () {
            alert(111);
         }  

 alert(typeof aa);     // number
 alert(typeof bb);     // string
 alert(typeof cc);     // boolean
 alert(typeof dd);     // undefined
 alert(typeof ee);     // object
 alert(typeof ff);     // object
 alert(typeof gg);     // object
 alert(typeof hh);     // function
    这样写的话有个缺陷,就是对于基本数据类型可以直接得到我们想要的,但是对于复杂数据类型得到的结果都是Object,这不是我们想要的。我们想要知道的是这个变量到底是复杂数据类型中的哪一种,是数组还是正则表达式还是其它...

instanceof 操作符介绍

instanceof操作符可以帮助我们确定复杂数据类型的具体类型。

如:

var color = ['red', 'yellow'];    // 数组
var reg = /^\w*$/;    // 正则表达式
var obj = {};
alert(color instanceof Array);     // true,是数组
alert(color instanceof Object);    // true,因为数组是Object的子集
alert(reg instanceof RegExp);      // true,是正则表达式
alert(reg instanceof Object);      // true,因为正则表达式是Object的子集
alert(obj instanceof Object);      // true,{} 和 new Object() 都能创建对象
    var obj = { }; 等效于  var obj = new Object();二者都是创建对象,只是前者写法上更加简单。
    复杂数据类型的子集有Array、Date、RegExp、Function等,具体用法见下篇帖子。


补充知识:

1.变量的生命周期。即一个变量什么时候会被创建出来,什么时候又会被销毁。知道了这个机制我们才能明确在一个具体步骤使用有意义的变量(即未被销毁的变量),减少错误的发生。

2.全局变量和局部变量的区别:使用 var  关键字定义的变量都是局部变量,其它为全局变量,全局变量容易变量名冲突造成错误,因此在定义变量时都使用 var 定义是个减少错误的好习惯。

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值