资讯专栏INFORMATION COLUMN

关於Javascript基本类型和引用类型小知识

iKcamp / 2351人阅读

摘要:变量有两种不同的数据类型基本类型,引用类型。知识一基本类型值就是简单的数据段引用类型值保存的是对象的引用,不是实际的对象。

ECMAScirpt 变量有两种不同的数据类型:基本类型引用类型

基本的数据类型有:undefinedbooleannumberstringnull. 基本类型的访问是按值访问的,就是说你可以操作保存在变量中的实际的值。JavaScript中除了上面的基本类型之外就是引用类型了。

区别如下:
基本类型:

佔用空间固定,保存在栈中

保存与复製的是本身

使用typeof检测数据类型

值类型

引用类型:

佔用空间不固定,保存在堆中

保存与复製的是指向对象的一个指针

使用instanceof检测数据类型

使用new()方法构造出来的对象是引用类型(相关内容可参考关於Javascript中的new运算符,构造函数与原型链一些理解)

基本类型是不会改变,衹能重新赋值,而引用类型值是可以改变的

var a = "123456789",
      b = a;
 
a = "321";
console.log(a) // 321
console.log(b) // 123456789

上面因為是把值保存在了变量了 而不是保存的是引用地址,所以他们两个是相对独立的整体,互不影响。但是如果换成引用类型的话

var a = {
    n: "123456789"
},
b = a;

a.n ="321";
console.log(a) // { n: "321" }
console.log(b) // { n: "321" }

原因在於在javascript语言中创建的对象值中其保存的是对象的引用(也就是一个地址.引用类型值保存在内存中,而JS是不能直接访问内存的,所以对於引用类型,操作的不是实际的对象而是对象的引用。)

这里有个小提示説一下,假如两个相同的基本类型或引用类型(内容一样)相比,看看结果是怎样的?

var base1 = "123",
    base2 = "123",
    obj1 = { a: "123" },
    obj2 = { a: "123" };

console.log(base1 === base2) // true
console.log(obj1 === obj2) // false

如果你还错了那就证明你没理解透上面的东西了,因为前面是值之间直接比较,后面是指向地址的比较,即使两个引用类型看起来一样,衹要不是同一个声明变量,它们就一定不同。

知识一:基本类型值就是简单的数据段;引用类型值保存的是对象的引用,不是实际的对象。

但是在函数中的对象传值又是不是同一回事呢?看看下面代码

function setName(obj) {
    obj.name = "1";
    obj = {};
    obj.name = "2";
}

var obj = {};
setName(obj);

console.log("最终结果obj:", obj) // 最终结果obj: { name: "1" }

没错,结果出乎意料的是1.而不是大多数人刚开始认为的2.
接下来我们在一步步分析出在函数过程中对象发生了什么样的变化?稍微修改下对象名便於区分。

function setName(innerObj) {
    console.log("初始的innerObj:", innerObj); // 初始的innerObj: {}

    innerObj.name = "1";
    console.log("第一次设置属性值的innerObj:", innerObj); // 第一次设置属性值的innerObj: { name: "1" }

    //保存下原对象
    var _innerObj = innerObj;

    innerObj = {};
    console.log("重新赋值的innerObj:", innerObj); // 重新赋值的innerObj: {}

    innerObj.name = "2";
    console.log("第二次设置属性值的innerObj:", innerObj); // 第二次设置属性值的innerObj: { name: "2" }

    console.log("两者之间是不是同一个对象?:", _innerObj == innerObj) // 两者之间是不是同一个对象?: false
    console.log("innerObj:", innerObj) // innerObj: { name: "2" }
    console.log("_innerObj: ", _innerObj) // _innerObj:  { name: "1" }
}

var outerObj = {};
setName(outerObj);
console.log("最终结果outerObj:", outerObj) // 最终结果outerObj: { name: "1" }

过程中可以看出在函数中间 innerObj = {} 之后;对象的指向就已经变了,也就是说这里相当於重新建立一个新的指向,后续的操作都是基於新指向之上进行的。
此时,outerObj === _innerObj !== innerObj, 所以最终输出的是1而不是2.

如果还有些混乱的同学,看看如果不通过函数直接修改会是什么结果?

var obj = {"a":1}
obj = {};
obj = {"a":2};
console.log(obj) // { a: 2 }

这次确确实实的是输出2了。

知识二:JS中所有函数传参都是按值传递的。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/106154.html

相关文章

  • 关於Javascript中的new运算符,构造函数与原型链一些理解

    摘要:前言文章主要基于高级程序设计总结的基本重写了全文补充知识点新增实例优化排版新增检测方法技巧用法构造函数创建一个用护定义的对象类型的实例或具有构造函数的内置对象类型之一命令执行构造函数返回一个实例对象构造函数一个指定对象实例的类型的函数传惨一 前言 文章主要基于>总结的!!!PS: 2018/05/09 基本重写了全文,补充知识点,新增实例,优化排版PS: 2018/05/11 新增检测...

    cikenerd 评论0 收藏0
  • Javascript难点知识运用---递归,闭包,柯里化等

    摘要:作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的前端,始终都是当前执行的代码所在环境的变量对象。对语句来说,会将指定的对象添加到作用域链中。 前言 ps: 2018/05/13 经指正之后发现惰性加载函数细节有问题,已改正在这里也补充一下,这些都是根据自己理解写的例子,不一定说的都对,有些只能查看不能运行的要谨慎,因为我可能只是将方法思路写出来,没有实际跑...

    hqman 评论0 收藏0
  • 关于前端上传文件全面基础扫盲贴(四) ----- FileReader

    摘要:没有浏览器测试,所以不知道是不是有效,其实里面看起来比我写的那个复杂,实际上多了个检验格式上兼容写法所以不要怕,如果我错了记得提醒下我啊。目前为止其实已经该说的都差不多覆盖到了吧,动手能力强的话已经可以根据教程写一个实例出来的了。 系列文章 关于前端上传文件全面基础扫盲贴(零)关于前端上传文件全面基础扫盲贴(一) ----- XMLHttpRequest关于前端上传文件全面基础扫盲贴(...

    Tony 评论0 收藏0
  • 三、值类型引用类型

    摘要:它们的区别之一就是在计算机中的存储方式不同基本类型数据是将变量名及值存储在变量对象中,而引用类型的数据是将变量名和地址存储在变量对象中,真正的值是存储在堆内存中。 showImg(https://segmentfault.com/img/remote/1460000017151449); 说点别的 这是《关于 JavaScript 你必须要知道的 33 个概念 》系列的第三篇文章,今天...

    tinysun1234 评论0 收藏0
  • JavaScript知识架构学习路径(一)- 变量篇

    摘要:在此,我们首先根据变量的作用域,将变量划分为三级,具体是全局变量局部变量和参数变量。 【摘要】本文是专为JavaScript入门者而总结的,总体上将JavaScript的基础部分分成了九大块,分别是变量、运算符、数组、流程控制结构、字符串函数、函数基础、DOM操作基础、文档对象模型DOM和正则表达式。 【关键字】变量、运算符、数组、流程控制结构、函数、DOM、正则表达式。 本篇文章的主...

    toddmark 评论0 收藏0

发表评论

0条评论

iKcamp

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<