热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JS基本类型与引用类型值

本文讲述了在JavaScript中,基本类型与引用类型值的概念及区别。

引入概念:基本类型和引用类型

1、可以感受到,JS 的变量及其松散,那么,正是 JS 变量松散 的本质,决定了:JS 变量名只是 一个在特定的时间用于保存特定值的一个名字 而已,也就是说,变量的值及其数据类型可以在脚本的生命周期内改变 ,尽管这个功能看起来有趣、强大,但是 JS 变量实际上是比较复杂。

2、ECMAScirpt 变量有两种不同的数据类型:基本类型 和 引用类型,另外还有其他的叫法,比如:原始类型和对象类型、拥有方法的类型和不能拥有方法的类型 等/0

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

基本类型 指的是简单的数据段,而 引用类型 指的是可能由多个值构成的对象

基本类型:undefined、null、string、number、boolean、symbo(ES6)

引用类型:Object、Array、RegExp、Date、Function

两种类型的区别

存储:

基本类型的值是存放在 栈区 的,即内存中的栈内存

假如有以下变量:

var name = 'jozo';
var city = 'guangzhou';
var age = 22;

那么他们的存储结构如下:(栈区包括了变量的标识符和值)

引用类型的值是同时保存在 栈内存和堆内存 的

假如有以下对象:

var person1 = {name:'jozo'};
var person2 = {name:'xiaom'};
var person3 = {name:'xiaoq'};

那么他们的存储结构如下:

访问:

基本类型的值是 按值访问 的,因为可以操作保存在变量中的实际的值。

引用类型的值是 按引用访问 的,因为引用类型的值是保存在内存中的对象,而与其他语言不同的是,Javascript 不允许直接访问内存中的位置,即不可以直接操作对象的内存空间,那么,在操作对象时,实际上是在操作对象的引用而不是实际的对象。

动态的属性:

对于引用类型的值,很明显,我们可以为其 添加、改变、删除 属性和方法:

var person = new Object();
person.name = "Ozzie";
console.log(person.name);    //"Ozzie"

上述过程中,我们创建了一个对象并为其添加了一个属性,如果对象不被销毁或者这个属性不被删除,那么这个属性将一直存在

但是,我们不可以给基本类型的值添加方法和属性

var name = "Ozzie";
name.age = 19;
consoe.log(name.age);    //undefined

尽管这样操作不会报错,但是仍然会被默默地挂掉

比较:

基本类型的比较是 值的比较 :

例如:

var a = 1;

var b = true;

console.log(a == b); //true

引用类型的比较是 引用的比较 :

例如:

var person1 = {};
var person2 = {};
console.log(person1 == person2);    //false

上文提到过,引用类型时按引用访问的,换句话说就是比较两个对象的堆内存中的地址是否相同,很明显,并不是同一个内存位置:

复制变量值:

将一个基本类型的值复制给另一个变量,那么,会在新变量上创建一个新值,然后再把该值复制到为新变量分配的位置上:

例如:

var a = 10;
var b = a;
a++;
console.log(a);    // 11
console.log(b);    // 10

a 与 b 是完全独立的,该值只是 a 中的值的一个副本。

基本类型在赋值操作后,两个变量是相互不受影响的:

那么,复制引用类型的值时,同样也会将一份存储在对象中的值复制到新变量的空间中,不同的是,这个值的副本实际上是一个 指针,指向的是存储在堆中的对象。也就是说,复制结束后,这两个变量将引用同一个对象。

例如:

var a = {}; // a保存了一个空对象的实例
var b = a;  // a和b都指向了这个空对象
a.name = 'jozo';
console.log(a.name); // 'jozo'
console.log(b.name); // 'jozo'

改变其中一个变量就会影响到另一个变量

传递参数:

请记住,尽管在访问变量时有着按值访问和按引用访问这两种方式,但 ECMAScript 中所有的函数的参数都是按值传递的,即参数只能按值传递,也就是说,把函数外部的值复制给函数内部的参数,就类似于变量之间的值复制一样

基本类型的值的传递如同基本类型的变量的复制,被传递的值会被赋值给一个局部变量(即命名参数,用 ECMAScript 中的概念说,就是 arguments 对象中的一个元素),此处不再赘述…

但是向参数传递引用类型的值时,复制给局部变量的是 内存中的地址,因此这个局部变量的变化会被反映在函数的外部。

例如:

function setName(obj){
      obj.name = "Ozzie";
}
var person = new Object();
setName(person);
console.log(person.name);    //"Ozzie"

我们可以看到,在函数内部,obj 和 person 引用的是同一个对象,换句话说,即使这个变量是按值传递的,obj 也会按引用来访问同一个对象,因为 person 指向的对象在堆内存中只有一个,而且是全局对象。

很多人会 错误地认为:参数是按引用传递的,因为在局部作用域中修改的参数会在全局作用域中反映出来,OK,那么我们再看一个例子:

function setName(obj){
      obj.name = "Ozzie";
      obj = new Object();
      obj.name = "Nicholas"
}
var person = new Object();
setName(person);
console.log(person.name);    //Ozzie

如果是按引用传递参数的,那么显然 person 对象就会在函数内部自动修改 name 属性为 Nicholas,但结果仍然是 Ozzie,这说明,即使在函数内部修改了参数的值,但原始的引用仍然保持不变,实际上,在函数内部重写 obj 时,这个变量的引用就是一个局部对象了,而这个局部对象在函数执行完毕后立即被销毁。

推荐教程:《PHP教程》

以上就是JS 基本类型与引用类型值的详细内容,更多请关注 第一PHP社区 其它相关文章!


推荐阅读
  • 本文探讨了线性表中元素的删除方法,包括顺序表和链表的不同实现策略,以及这些策略在实际应用中的性能分析。 ... [详细]
  • 本文将详细介绍如何在Adobe Illustrator中实现仅移动一个对象以完成对齐,同时确保另一个对象保持原位不变的方法。通过具体的操作步骤,帮助设计师们更加高效地完成设计任务。 ... [详细]
  • Python网络编程:深入探讨TCP粘包问题及解决方案
    本文详细探讨了TCP协议下的粘包现象及其产生的原因,并提供了通过自定义报头解决粘包问题的具体实现方案。同时,对比了TCP与UDP协议在数据传输上的不同特性。 ... [详细]
  • 实现Win10与Linux服务器的SSH无密码登录
    本文介绍了如何在Windows 10环境下使用Git工具,通过配置SSH密钥对,实现与Linux服务器的无密码登录。主要步骤包括生成本地公钥、上传至服务器以及配置服务器端的信任关系。 ... [详细]
  • PHP中Smarty模板引擎自定义函数详解
    本文详细介绍了如何在PHP的Smarty模板引擎中自定义函数,并通过具体示例演示了这些函数的使用方法和应用场景。适合PHP后端开发者学习。 ... [详细]
  • 本文探讨了在无法使用个人身份信息的情况下,利用他人(如网络上公开的个人信息)注册游戏账号的行为及其潜在的法律和道德问题。 ... [详细]
  • 本文由chszs撰写,详细介绍了Apache Mina框架的核心开发流程及自定义协议处理方法。文章涵盖从创建IoService实例到协议编解码的具体步骤,适合希望深入了解Mina框架应用的开发者。 ... [详细]
  • 本题提供了一个区间数组 intervals,其中每个区间 intervals[i] 包含两个整数 [starti, endi],并且所有 starti 值各不相同。任务是找到每个区间的右侧区间,即存在一个区间 j 满足 startj >= endi 并且 startj 是尽可能小的。返回一个数组,该数组包含每个区间右侧区间的索引;如果没有合适的右侧区间,则返回 -1。 ... [详细]
  • 本文介绍了使用Python和C语言编写程序来计算一个给定数值的平方根的方法。通过迭代算法,我们能够精确地得到所需的结果。 ... [详细]
  • C/C++ 应用程序的安装与卸载解决方案
    本文介绍了如何使用Inno Setup来创建C/C++应用程序的安装程序,包括自动检测并安装所需的运行库,确保应用能够顺利安装和卸载。 ... [详细]
  • 本文提供了一个关于AC自动机(Aho-Corasick Algorithm)的详细解析与实现方法,特别针对P3796题目进行了深入探讨。文章不仅涵盖了AC自动机的基本概念,还重点讲解了如何通过构建失败指针(fail pointer)来提高字符串匹配效率。 ... [详细]
  • 10月19日,限量免费参与IBM云计算大会
    10月19日,限量免费报名参加IBM云计算大会,探索前沿科技,推动商业转型。 ... [详细]
  • 本报告记录了嵌入式软件设计课程中的第二次实验,主要探讨了使用KEIL V5开发环境和ST固件库进行GPIO控制及按键响应编程的方法。通过实际操作,加深了对嵌入式系统硬件接口编程的理解。 ... [详细]
  • 本文分享了作者在使用LaTeX过程中的几点心得,涵盖了从文档编辑、代码高亮、图形绘制到3D模型展示等多个方面的内容。适合希望深入了解LaTeX高级功能的用户。 ... [详细]
  • LeetCode 102 - 二叉树层次遍历详解
    本文详细解析了LeetCode第102题——二叉树的层次遍历问题,提供了C++语言的实现代码,并对算法的核心思想和具体步骤进行了深入讲解。 ... [详细]
author-avatar
小永劲_289
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有