object,你的腰间盘为啥这么突出?——数据类型转换中object的不同之处及原因探究

突出.jpg

在我的上一篇文章中JavaScript的家族谱(数据类型)已经介绍了关于object和普通类型在数据类型呈现方式上的不同,object是复杂类型,不同于其他基本类型的不可再分割,object内部可能有函数、数组和其他数据类型混合其中。而本文将从另外一个角度——储存方式来阐述object的特殊之处。(注意本文不谈symbol)

数据类型之间的相互转化

为什么要先谈这个,因为基本类型和复杂类型(object)的存储方式并不一样,在数据转化过程中这个事实最为明显。

其他基本类型转化为String(特别注意object)

方式一 :原始数据.toString()

var a = 1
a.toString()
"1" //数值转化为字符串

var a = true
a.toString()
"true" //布尔值转化为字符串

var a = null
a.toString()
VM426:1 Uncaught TypeError: Cannot read property 'toString' of null
    at <anonymous>:1:3 
//null不能直接转化为字符串,因为null没有toString这个属性

var a = undefined
undefined
a.toString()
VM446:1 Uncaught TypeError: Cannot read property 'toString' of undefined
    at <anonymous>:1:3
(anonymous) @ VM446:1
// 同理undefined也没有

var a = {}
undefined
typeof a
"object"
a.toString()
"[object Object]"
// 突出1:要么就老老实实转化,要么就像null一样说没有不就好了,给个奇怪的返回值

方式二:String(原始数据)

var a = 1
String(a)
"1"
//剩下的就省略了,结果和上面的相同

方式三:原始数据 + "
这种方式并不是调用属性,而是让原始数据匹配字符串,所以null和undefined也是可以转化的

a + ''
"1"

null+''
"null" 

undefined+''
"undefined"

var a = {key:1}
undefined
a+""
"[object Object]" //行,你NB

其他类型转化为布尔值

五个falsy值

这里说一下,所有数据类型转化成布尔值,其中只有5个会被转化为false:

  1. 0
  2. NaN
  3. ''(空字符串)
  4. null
  5. undefined

方法

方法一:Boolean(原始数据)

Boolean(a)
true
Boolean(0)
false
Boolean(NaN)
false
Boolean('')
false
Boolean(null)
false
Boolean(undefined)
false
Boolean({})
true // 突出2:object啥也没有也是true

方法二:!!原始数据(!是取反的意思)

!!1
true
!!null
false
// 其他的就不举例了

其他类型转化成数值(这个不突出,主要是有NaN背锅)

方法

方法一:Number(原始值)

var a = {key :'1'}
typeof a
"object"
Number(a)
NaN
Number('1')
1
Number('1sss')
NaN //这个方法只要字符串中有非数字的就返回NaN
Number(true)
1 //后面从储存的角度来解释
Number(false)
0  //后面从储存的角度来解释
Number(null)
0
Number(undefined)
NaN

方法二:parseInt(原始值,'进制数')--注意是十进制时可以不写,系统默认是存在的
这个方法和上面不同之处在于这个命令只取整,除了数值和能转化的字符串,其他的全是NaN。另外,他能提取字符串前面的数字,具体用法见parseInt

parseInt('1sss')
1 //

方法三:parseFloat('原始值'),具体用法见parseFloat

方法四(简单写法):原始数据 - 0
方法五(更简单写法):+ 原始数据

true -0
1
'a' -0
NaN
+ true
1
+'a' 
NaN

(symbol转化我们就不谈及,至于怎么转化成null或者undefined,请把你的需求写在评论区,让大家一起来深入探讨)

那么其他数据类型转化成对象怎么做?

答案是:obeject(原始值)

var a =1
typeof(a)
"number"
b = Object(a)
typeof b
"object" //给值一个对象包裹器

讨论(开始闲扯)

现在我们来回顾一下上面所有的转化过程,只从数据的展现形式什么也看不出来。这时候我们只能从数据的储存方式来看看。

简单的存储模型

JS有两个储存数据的区域(Stack和Heap),基本数据类型几乎全部存放在Stack里面,如此我们假设一个简单模型 stack里面保存数据都是用哈希表的方式保存(key:value),Heap保存数据的方式是堆(无序存放,只有地址)。--比实际情况简单便于理解

  1. 模型中基本类型数据的储存方式(注意所有的数据都是用二进制表示)
    布尔值(booleantrue保存的时候就是1false就是0
    字符串(String)把引号内部的内容用utf-16保存,单双引号就是单双引号,前后各一个表示开头结尾(真实情况并非如此);
    数值(number)用二进制表示;
    null:null用二进制表示;
    undefined:undefined用二进制表示;
    以上全部保存在Stack里面

  2. 模型中复杂类型数据(object)的储存方式(突出3:存的地方有两个)
    object保存在Stack里面的是object Object(二进制表示) +地址(二进制表示),Heap保存的是这个地址引用的数据,也就是object里面的内容。

  3. String等命令只在Stack里面寻找数据。

推演

  1. 基本类型之间转化在储存的角度上的事件(简单模型中)
    那么所有的基本类型的转化,只需要把他原始的数据修改或者全部删除然后写入,读取的时候把要读取的部分取出来就可以了。

  2. object在上文中的突出点的解读
    突出1:为什么字符串转化是"[object Object]"

var a = {}
undefined
typeof a
"object"
a.toString()
"[object Object]"

看看我们的对象在Stack里面是怎么保存的:object Object(二进制表示) +地址(二进制表示)。字符串没有解读地址而已,而每一个对象都是这个格式保存着。这个模型也就解释了突出2:空的对象转成布尔值也是true,因为里面写着object Object,不是5个Falsy值,返回true。至于地址有没有,对不起,布尔值无法解读。

  1. 综上看,实际上object和其他数据类型转化这涉及到了储存数据方式的变化

拓展--深拷贝和浅拷贝

深拷贝就是我变你也不变,浅拷贝就是我变你也变
用上面这个简单模型可以很好地解决深浅拷贝的问题
例如

var a = {name:'a'}
var b = a
b.name = 'b'
// a = ?

模型分析:

  1. Stack存储着哈希表a:object Object 地址1
  2. Heap里面存储着堆数据:地址1{name:'a'}
  3. b = a 使又增加一个哈希表b:object Object 地址1,这时b变量也是引用地址1
  4. b.name(这是object的命令)调用地址1里面的属性name,让name:'a'变成name:'b',此时Heap里的地址1变成地址1{name:'b'}
  5. 然后问a,a的stack并没有变化a:object Object 地址1,而引用的地址1数据是地址1{name:'b'},所以a = 'b'。这就是浅拷贝,你变我也变。变的原因在于地址里的内容变了。

再举一个深拷贝的例子

var a = 1
var b = a
b = 2
// a = ?

模型分析:

  1. Stack存储着哈希表a:1
  2. b = a使Stack中又多出一个哈希表b:1
  3. b = 2使Stack中b的value由1变成2,哈希表为b:2
  4. 问a是多少,哈希表a:1并没有变化,所以a=1。这就是深拷贝,你变我不变。

由这两个例子可以看出,只涉及Stack的数据变化并不会发生浅拷贝,所以基本类型的拷贝全是深拷贝

文末要谢谢方方老师精彩的知识讲解,这篇文章中大部分知识借鉴方方老师的知识,另外因为内存图是方方老师原创,而且简书不能加动态图,所以这里使用了简单模型代替,如有错误欢迎指正。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,099评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,828评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,540评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,848评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,971评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,132评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,193评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,934评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,376评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,687评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,846评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,537评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,175评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,887评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,134评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,674评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,741评论 2 351

推荐阅读更多精彩内容