Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >lodash源码分析之获取数据类型

lodash源码分析之获取数据类型

作者头像
对角另一面
发布于 2018-04-19 10:54:48
发布于 2018-04-19 10:54:48
91800
代码可运行
举报
文章被收录于专栏:对角另一面对角另一面
运行总次数:0
代码可运行

所有的悲伤,总会留下一丝欢乐的线索,所有的遗憾,总会留下一处完美的角落,我在冰峰的深海,寻找希望的缺口,却在惊醒时,瞥见绝美的阳光! ——几米

本文为读 lodash 源码的第十八篇,后续文章会更新到这个仓库中,欢迎 star:pocket-lodash

gitbook也会同步仓库的更新,gitbook地址:pocket-lodash

作用与用法

我们都知道,可以借用 Object 原型上的 toString 方法来获取数据的类型。 baseGetTag 利用的也是这一特性,其返回的结果如 [object String] 这样的形式,调用方式如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
baseGetTag('string') // [object String] 

为什么可以用Object.prototype.toString

先看 es5 规范对 Object.prototyep.toString 的运行步骤规定:

当调用 toString 方法,采用如下步骤:

  1. 如果 this 的值是 undefined, 返回 "[object Undefined]".
  2. 如果 this 的值是 null, 返回 "[object Null]".
  3. 令 O 为以 this 作为参数调用 ToObject 的结果 .
  4. 令 class 为 O 的 [[Class]] 内部属性的值 .
  5. 返回三个字符串 "[object ", class, and "]" 连起来的字符串 .

在第三步的时候,会调用 ToObject 来转换成对象,而转换成对象后,会有个 [[Class]] 的内部属性,而这个内部属性的值正是 toString 的关键部分。

接下来再看规范对 [[Class]] 的规定:

本规范的每种内置对象都定义了 [[Class]] 内部属性的值。宿主对象的 [[Class]] 内部属性的值可以是除了 "Arguments", "Array", "Boolean", "Date", "Error", "Function", "JSON", "Math", "Number", "Object", "RegExp", "String" 的任何字符串。[[Class]] 内部属性的值用于内部区分对象的种类。注,本规范中除了通过 Object.prototype.toString ( 见 15.2.4.2) 没有提供任何手段使程序访问此值。

由规范可见,要获取这个 [[Class]] 内部属性的值的唯一手段是通过 Object.prototype.toString

源码分析

源码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const objectProto = Object.prototype
const hasOwnProperty = objectProto.hasOwnProperty
const toString = objectProto.toString
const symToStringTag = typeof Symbol != 'undefined' ? Symbol.toStringTag : undefined

function baseGetTag(value) {
  if (value == null) {
    return value === undefined ? '[object Undefined]' : '[object Null]'
  }
  if (!(symToStringTag && symToStringTag in Object(value))) {
    return toString.call(value)
  }
  const isOwn = hasOwnProperty.call(value, symToStringTag)
  const tag = value[symToStringTag]
  let unmasked = false
  try {
    value[symToStringTag] = undefined
    unmasked = true
  } catch (e) {}

  const result = toString.call(value)
  if (unmasked) {
    if (isOwn) {
      value[symToStringTag] = tag
    } else {
      delete value[symToStringTag]
    }
  }
  return result
}

export default baseGetTag

Symbol.toStringTag

ES6 中,规范对 Object.prototype.toString 的步骤进行了重新定义,不再使用 [[Class]] 的内部属性进行获取,具体的规范如下:

在ES6,调用 Object.prototype.toString 时,会进行如下步骤:

  1. 如果 thisundefined ,返回 '[object Undefined]' ;
  2. 如果 thisnull , 返回 '[object Null]'
  3. O 为以 this 作为参数调用 ToObject 的结果;
  4. isArrayIsArray(O)
  5. ReturnIfAbrupt(isArray) (如果 isArray 不是一个正常值,比如抛出一个错误,中断执行);
  6. 如果 isArraytrue , 令 builtinTag'Array' ;
  7. else ,如果 O is an exotic String object , 令 builtinTag'String'
  8. else ,如果 O 含有 [[ParameterMap]] internal slot, , 令 builtinTag'Arguments'
  9. else ,如果 O 含有 [[Call]] internal method , 令 builtinTagFunction
  10. else ,如果 O 含有 [[ErrorData]] internal slot , 令 builtinTagError
  11. else ,如果 O 含有 [[BooleanData]] internal slot , 令 builtinTagBoolean
  12. else ,如果 O 含有 [[NumberData]] internal slot , 令 builtinTagNumber
  13. else ,如果 O 含有 [[DateValue]] internal slot , 令 builtinTagDate
  14. else ,如果 O 含有 [[RegExpMatcher]] internal slot , 令 builtinTagRegExp
  15. else , 令 builtinTagObject
  16. tagGet(O, @@toStringTag) 的返回值( Get(O, @@toStringTag) 方法,既是在 O 是一个对象,并且具有 @@toStringTag 属性时,返回 O[Symbol.toStringTag] );
  17. ReturnIfAbrupt(tag) ,如果 tag 是正常值,继续执行下一步;
  18. 如果 Type(tag) 不是一个字符串,let tag be builtinTag
  19. 返回由三个字符串 "[object", tag, and "]" 拼接而成的一个字符串。

规范对类型的判断进行了细化,前15步可以看成跟 es5 的作用一样,获取到数据的类型 builtinTag ,但是第16步调用了 @@toStringTag 的方法,如果再看规范的描述,可以知道这个其实是对象中的 Symbol.toStringTag 属性,如果这个属性返回的是一个字符串,则采用这个返回值 tag 作为数据的类型,否则才采用 builtinTag

处理null和undefined

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (value == null) {
  return value === undefined ? '[object Undefined]' : '[object Null]'
}

这里是处理浏览器兼容性,在 es5 之前,并没有对 nullundefined 进行处理,所以返回的都是 [object Object]

处理不含Symbol.toStringTag的情况

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (!(symToStringTag && symToStringTag in Object(value))) {
   return toString.call(value)
}

如果浏览器不支持 Symbol 或者 value 并不存在 Symbol.toStringTag 的方法,则可以直接调用 toString ,将结果返回了。

处理Symbol.toStringTag 的情况

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const isOwn = hasOwnProperty.call(value, symToStringTag)
const tag = value[symToStringTag]
let unmasked = false
try {
  value[symToStringTag] = undefined
  unmasked = true
} catch (e) {}

const result = toString.call(value)
if (unmasked) {
  if (isOwn) {
    value[symToStringTag] = tag
  } else {
    delete value[symToStringTag]
 }
}

为了避免 Symbol.toStringTag 的影响,先将 valueSymbol.toStringTag 设置为 undefined ,这样可以屏蔽掉原型链上的 Symbol.toStringTag 属性,然后再使用 toString 方法获取到 value 的属性描述。

在获取到属性描述后,如果 Symbol.toStringTag 为自身的属性(不为原型链上的属性),则将原来保存下来的 tag 重新赋值,否则将 Symbol.toStringTag 属性移除。

参考

es5规范中文版

Standard ECMA-262

MDN:Symbol.toStringTag

ECMAScript 6 入门

谈谈 Object.prototype.toString 。

License

署名-非商业性使用-禁止演绎 4.0 国际 (CC BY-NC-ND 4.0)

最后,所有文章都会同步发送到微信公众号上,欢迎关注,欢迎提意见:

作者:对角另一面

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-04-07 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Tina-SDK开发
Tina-SDKV2.0源码网盘链接:https://pan.baidu.com/s/13uKlqDXImmMl9cgKc41tZg?pwd=qcw7
韦东山
2024/08/24
5020
Tina-SDK开发
Linux GPIO 开发指南
本文档对内核的 GPIO 接口使用进行详细的阐述,让用户明确掌握 GPIO 配置、申请等操作的编程方法。
韦东山
2023/02/24
8.7K0
Linux GPIO 开发指南
Linux U-Boot 开发指南
介绍 U-Boot 的编译打包、基本配置、常用命令的使用、基本调试方法等, 为 U-BOOT 的移植及应用开发提供了基础。
韦东山
2023/02/25
4.8K0
Linux U-Boot 开发指南
全志 Tina Linux LCD显示屏调试指南 支持MIPI DSI RGB LVDS I8080 SPI等接口,开发板支持百问网T113 D1-H哪吒 DongshanPI-D1s V853
素时钟不超过180MHz 都支持。或者两个串行RGB 接口,串行RGB 的最高分辨率最大不超过800*480@60
韦东山
2022/12/28
5.7K0
全志 Tina Linux LCD显示屏调试指南 支持MIPI DSI RGB LVDS I8080 SPI等接口,开发板支持百问网T113 D1-H哪吒 DongshanPI-D1s V853
快速启动开发板
将开发板配套的两根typec线,一根 直接连接至 开发板 OTG烧录接口 另一头连接至电脑的USB接口,开发板默认有系统,接通otg电源线就会通电并直接启动。
韦东山
2024/08/24
2400
快速启动开发板
Uboot查看并修改内核设备树节点
FDT:flattened device tree 的缩写在 U-Boot 控制台停下后,输入fdt,可以查看fdt命令帮助。
韦东山
2024/08/19
4230
全志 Tina Linux 系统资源配置 开发指南 支持百问网T113 D1-H哪吒 DongshanPI-D1s V853-Pro等开发板
Tina Linux SDK的根目录下,执行make menuconfig命令可进入Tina Linux的配置界面。
韦东山
2022/12/28
9.4K0
全志 Tina Linux 系统资源配置 开发指南 支持百问网T113 D1-H哪吒 DongshanPI-D1s V853-Pro等开发板
使用基于全志D1-H的LicheeRV的 86 Panel 与 Tina BSP 实现 RGB 与 SPI 双屏显示
Tina 提供了2种 SPI TFT 显示屏的驱动方式。第一种是官方推荐的 fbdev 方式,使用 Framebuffer implementaion without display hardware of AW 进行 SPI屏幕的驱动。另外一种是使用 fbtft 进行 SPI 屏幕驱动。 fbdev 方式由于 pinctrl 在新内核中调用方式出现修改,所以暂时无法使用。修改难度较大。fbtft 虽然官方wiki表明不建议在 Linux 5.4 中使用,但是其实也是可以使用的,只需要修改一下 GPIO 的注册方式就行。
阿志小管家
2024/02/02
3370
使用基于全志D1-H的LicheeRV的 86 Panel 与 Tina BSP 实现 RGB 与 SPI 双屏显示
基于全志D1-H 芯片与 Tina Linux 框架下的 LCD 屏幕适配
Linux 提供了一套完整的屏幕驱动,支持 RGB,MIPI DSI,eDP,LVDS,E-INK屏幕,也支持低分辨率的 SPI,IIC 屏幕。具体屏幕的驱动情况,需要根据芯片而确定。本文将通过介绍 D1-H Kernel 中的 LCD 驱动,讲解配置屏幕驱动的基本方法。
阿志小管家
2024/02/02
1.8K0
基于全志D1-H 芯片与 Tina Linux 框架下的 LCD 屏幕适配
快速启用开发板
将开发板配套的两根typec线,一根 直接连接至 开发板 OTG烧录接口 另一头连接至电脑的USB接口,开发板默认有系统,接通otg电源线就会通电并直接启动。
韦东山
2024/08/27
1680
快速启用开发板
梦回2004!我用全志V3s做了个成本100元,功能媲美MP4的随身终端
本项目是基于全志V3S的随身终端(类似MP4),命名为V3S-PI,开发板使用四层板制作,全板采用0603电容电阻,相较于0402,制作更为方便,同时成本可压缩至100以内。
阿志小管家
2024/02/02
5320
梦回2004!我用全志V3s做了个成本100元,功能媲美MP4的随身终端
Linux SPI 开发指南
SPI 是一种高速、高效率的串行接口技术。通常由一个主模块和一个或多个从模块组成,主模块选择一个从模块进行同步通信,从而完成数据的交换,被广泛应用于 ADC、LCD 等设备与 MCU 之间。全志的 spi 控制器支持以下功能:
韦东山
2023/02/25
9.5K0
Linux SPI 开发指南
启动开发板
将开发板配套的两根typec线,一根 直接连接至 开发板 OTG烧录接口 另一头连接至电脑的USB接口,开发板默认有系统,接通otg电源线就会通电并直接启动。
韦东山
2024/08/19
2260
启动开发板
Tina R329 swupdate OTA升级步骤
第一步: 编译路径执行make menucinfig和make ota_menucinfig中分别选中: (1)Allwinner > swupdate (2)Allwinner > swupdate > Swupdate Settings > General Configuration > MTD support (3)Allwinner > swupdate > Image Handlers > ubivol
阿志小管家
2024/02/02
4380
TinaSDKV2.0 Kernel基本开发
可以在tina-sdk source后,在tina-sdk任意目录内执行 cconfigs命令直接切换到板级 Linux 设备树 和 配置文件目录。
韦东山
2024/08/19
1880
TinaSDKV2.0 Kernel基本开发
Tina_Linux_Wi-Fi_开发指南
介绍Allwinner 平台上Wi-Fi 驱动移植,介绍Tina Wi-Fi 管理框架,包括Station,Ap 以及Wi-Fi 常见问题。
韦东山
2023/02/25
5.1K0
Tina_Linux_Wi-Fi_开发指南
LCD模组驱动开发
由于使用的是 SPI0,所以 TinyVision 的 LCD 模块并不支持使用MIPI-DBI进行驱动,这里我们使用普通的SPI模拟时序。
韦东山
2024/08/24
2230
LCD模组驱动开发
DshanMCU-R128s2 配置引脚复用
R128 平台使用 sys_config.fex 作为引脚配置文件,他会在打包时打包编译进入系统,在系统运行时会解析并配置,系统解析 sys_config.fex 的驱动配置位于 lichee\rtos-components\aw\sys_config_script 中。
韦东山
2023/12/23
1920
4.100ASK_V853-PRO开发板支持4寸MIPI屏
tina-v853-open/kernel/linux-4.9/drivers/video/fbdev/sunxi/disp2/disp/lcd
韦东山
2023/05/23
7250
4.100ASK_V853-PRO开发板支持4寸MIPI屏
Tina_Linux_音频_开发指南
Allwinner 硬件平台R6, R7s, R11, R16, R18, R30, R58, R328, R332, R333, R311, MR133, T7, R329, MR813, R818, R818B, R528, H133, V853, F133。
韦东山
2023/02/25
7.7K0
Tina_Linux_音频_开发指南
推荐阅读
相关推荐
Tina-SDK开发
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验