说点别的

这是《关于 JavaScript 你必须要知道的 33 个概念 》系列的第三篇文章,今天稍微给大家介绍下这个系列。

如今前端的发展日新月异,很多人(包括我)都是追逐着一些流行的框架学习,但往往是浮于表面,知其然而不知其所以然。当我认真的想要搞懂 react、redux 实现原理时,才发现,JavaScript 的基础知识是如此重要。

一直以来,自己对于 JavaScript 的理解都散乱无章,这就造成很多知识当时看过后感觉明白了,过一段时间用到的时候却仍旧一脸懵逼。因此,我决定整理这样一个系列,加深自己对 JavaScript 的理解,形成知识体系,以达到融会贯通。

这个计划会写 33 篇文章,会包括 JavaScript 中的基础概念如「数据类型」、「表达式和语句」、「作用域」等,以及如「闭包」、「this」、「promise」等有些理解难度的知识点。

首先声明我不是什么大佬,对于很多知识也是一边钻研一边写,所以如果有不同的看法,恳请大家指正,我会及时更新文章的不足之处!

接下来,我们言归正传。

定义和分类

在上一篇文章(数据类型)中我们知道 JavaScript 的数据类型分为基本数据类型和对象数据类型。它们的区别之一就是在计算机中的存储方式不同:基本类型数据是将变量名及值存储在变量对象中,而引用类型的数据是将变量名和地址存储在变量对象中,真正的值是存储在堆内存中。

再次将那张图放过来:

其中,基本类型(number,string,boolean,undefined,null),便称为值类型,而对象类型(object,function,array及封装对象)便称为引用类型。

值类型与引用类型的区别

1. 可变性与不可变性

值类型的数据是不可变的。 这里说的不可改变,是指值本身,一旦创建,便不可更改。什么意思?举个例子:

let a = 34;
a = 43;

我们先声明一个变量 a 并赋值为 34,此时,在变量对象中 34 就已经存放在固定位置,后边将 a 的值改为 43,看起来好像是将 34 改变成了 43, 其实不然,我们只是又在变量对象中存入了 43,原来的 34,仍旧原封未动的存在那里,等待着被内存回收。如下图所示:

引用类型值是可以改变的。 引用类型的值是将变量名称和引用地址存储在变量对象中,而值是在堆内存中,我们可以随时更改它本身的值。

let b = {m: 1,n: 'emmm'
}
b.m = 4;
b;   // {m: 4,n: 'emmm'}

在上例中,我们声明 b 是一个引用类型值,接着,我们对 b 进行了更改,我们可以看到,更改是有效的。

2. 值的复制

值类型的复制是值本身的复制,引用类型的复制是值得引用的复制。 不同的复制方式会在复制后有不同的表现。

// 值类型的复制
var a = 45;
var b = a;
console.log(b); // 45
b = "someword";
console.log(b) // "someword"
console.log(a); // 45
// 引用类型的复制
var someone= {age: 14,weight: 134,sex: 'man'
};
var anthor = someone;
console.log(anthor); // {age: 14, weight: 134, sex: "man"}
anthor.age = 16;
console.log(anthor); // {age: 16, weight: 134, sex: "man"}
console.log(someone); // {age: 16, weight: 134, sex: "man"}

从上面的代码中可以看到,变量 b 复制变量 a 的之后进行了更改,b 的值改变了,而 a 的值没变;变量 anthor 复制的是 someone 的引用,anthor 更改了引用指向的那个对象的值,someone 的值自然也跟着改变了。

具体过程如图所示:

应用

它们的概念理解起来很简单,但很多时候应用到实际场景中,我们就可能想不到这一层,会造成很多意外的问题,接下来我们看一下。

1. =====

在进行 ===== 判断时,前者会对等号两边的值进行强制类型转换,这对判断值类型的相等有所区别。但是对于引用类型,它们都只会判断引用地址是否相同,而不管对象里的属性值是否相同。

比如:

// 值类型相等
let a = 45;
let b  = 45;
console.log(a == b); //  true
b = '45';
console.log(a == b); // true
console.log(a === b); // false
// 引用类型相等
let men_1 = {age: 23,sex: 'man',
};
let men_2 = {age: 23,sex: 'man',
};let men_3 = men_1;
console.log(men_1 == men_2); //  false
console.log(men_1 === men_2); //  false
console.log(men_1 == men_3); // true
console.log(men_1 === men_3); // true

从上面我们可以看到:45 === 4545 != '45',但 men_1 虽然和 men_2 的值相同,但他们并不相等,无论是 == 还是 ===

那该如何按照我们的想法比较呢?

可以把它们转化为字符串进行比较,当然,这样也不能保证完全正确(比如对象中含有正则表达式),更严格的方法以后再讨论。

function compare(a, b) {return JSON.stringify(a) == JSON.stringify(b);
}

2. 函数传参

函数传参时,是将传入的参数拷贝到函数的参数参数变量上,因此,拷贝带来的问题在函数传参时仍旧存在。

function foo(a,b) {var d = a;d = 'string';var e = b;e.name = 'xiaohong';
}
var exmp_1 = 3;
var exmp_2 = {name: 'xiaohua'
};
foo(exmp_1,exmp_2);
console.log(exmp_1); // 3
console.log(exmp_2); // {name: "xiaohong"}

如上所示,值类型传入后再函数内的修改不会污染外部的变量,而引用类型的变量由于复制的是引用,在函数内部的改动会影响到外部的变量。

若是想要避免这种情况,则需要在接受参数时进行深拷贝。

function foo(people) {const newPeople = JSON.parse(JSON.stringify(people));newPeople.firstName = 'wang';
}
var Liu = {firstName: 'liu'
}
foo(Liu);
console.log(Liu); // {firstName: "liu"}

一道小题

到此,关于值类型与引用类型的介绍就结束了,留一道题给大家,大家可以借此看一看对本文的理解。

function create(person) {var personA = person;personA.name = 'David';var personB = {name: 'saay',age: 13};return personB;
}
var Jone = {name: 'Join',age: 25
}
var Wang = create(Jone);
console.log(Jone) ;// ??
console.log(Wang); // ??

三、值类型与引用类型相关推荐

  1. 第2篇 C#数据类型-值类型与引用类型

    一 C#内存分配 在应用程序与操作系统之间有一个"中间人"--公共语言运行时(Common Language Runtime,CLR).它为应用程序提供内`存管理,线程管理和远程处 ...

  2. 栈和托管堆/值类型和引用类型/强制类型转换/装箱和拆箱[C#]

    一.栈和托管堆 通用类型系统(CTS)区分两种基本类型:值类型和引用类型.它们之间的根本区别在于它们在内存中的存储方式..NET使用两种不同的物理内存块来存储数据-栈和托管堆.如下图所示:     值 ...

  3. string:值类型?引用类型?[转]

    string是一种很特殊的数据类型,它既是基元类型又是引用类型,在编译以及运行时,.Net都对它做了一些优化工作,正式这些优化工作有时会迷惑编程人员,使string看起来难以琢磨,这篇文章分上下两章, ...

  4. 值类型与引用类型(下)

    本文将介绍以下内容: 类型的基本概念 值类型深入 引用类型深入 值类型与引用类型的比较及应用 [下载]:[类型示例代码] 1. 引言 值类型与引用类型的话题经过了两个回合([第八回:品味类型---值类 ...

  5. 转:图解C#的值类型,引用类型,栈,堆,ref,out

    C# 的类型系统可分为两种类型,一是值类型,一是引用类型,这个每个C#程序员都了解.还有托管堆,栈,ref,out等等概念也是每个C#程序员都会接触到的概念,也是C#程序员面试经常考到的知识,随便搜搜 ...

  6. C# - 值类型、引用类型走出误区,容易错误的说法

    C# - 值类型.引用类型&走出误区,容易错误的说法 1. 值类型与引用类型小总结 1)对于引用类型的表达式(如一个变量),它的值是一个引用,而非对象. 2)引用就像URL,是允许你访问真实信 ...

  7. [你必须知道的.NET]第九回:品味类型---值类型与引用类型(中)-规则无边

    发布日期:2007.5.28 作者:Anytao ©2007 Anytao.com ,原创作品,转贴请注明作者和出处. 接上回[第八回:品味类型---值类型与引用类型(上)-内存有理]的探讨,继续我们 ...

  8. .NET六大剑客:栈、堆、值类型、引用类型、装箱和拆箱

    .NET六大剑客:栈.堆.值类型.引用类型.装箱和拆箱 一."堆","栈"专区 这两个字我相信大家太熟悉了,甚至于米饭是什么?不知道..."堆&quo ...

  9. 值类型与引用类型比较与区别

    在.NET中或许我们不用担心内存管理以及垃圾回收器(Garbage Collection GC)的问题,但是我们还是应该了解这些东东以便在必要的时候优化我们程序的性能.而且,如果对内存管理如何工作有所 ...

最新文章

  1. HTML手风琴原理,使用Html5实现手风琴案例
  2. java面试题标签_java面试笔试题 (WEB)
  3. flink中各种图的原理(还没搞完)
  4. Codeforces Round #618 (Div. 2)-B. Assigning to Classes
  5. 机器学习笔记:Overview
  6. python vimrc的安装,并用pep8检测python代码
  7. webpack:Cannot find module 'extract-text-webpack-plugin'
  8. 热门好用的空号检测API推荐
  9. 推荐几个微信小程序开源项目
  10. Slicer学习笔记(十七)编写一个python扩展模块
  11. ios7下弹出新浪微博界面,一出现就消失的问题
  12. 利用ps制作油画风格的照片
  13. 三步搞定ABAP DOI操作EXCEL
  14. 初几学的计算机二进制,说说二进制与计算机的那些事儿
  15. win10 高DPI 高分屏 解决模糊问题的方法
  16. 电脑蓝屏c语言代码大全,Win10电脑卡机遇到蓝屏代码0xc000014c应该怎么办?
  17. Delphi RAD Studio 10.4.2 Sydney的新增与改进介绍原版全文
  18. 【算法千题案例】每日一练LeetCode打卡——110.种花问题
  19. 王了个王(羊了个羊)H5游戏源码下载
  20. STM32BootLoader引导SecureCRT串口固件升级(YModem协议)

热门文章

  1. boost::container_hash模块实现哈希序列
  2. Boost:boost::bimaps::vector_of的测试程序
  3. Boost:post process后期处理的测试程序
  4. ITK:二维高斯混合模型期望最大化
  5. OpenCV配置选项参考
  6. 嵌入式Linux的Qt
  7. C++求tree树的高度(附完整源码)
  8. C语言递归算法十进制数转换为八进制(附完整源码)
  9. QT的QStorageInfo类的使用
  10. QT的QOpenGLTextureBlitter类的使用