前言
underscore.js源码分析第四篇,前三篇地址分别是,如果你对这个系列感兴趣,欢迎点击watch,随时关注动态。
逗我呢?哥!你要说什么bug,什么bug,什么bug,我最讨厌bug。去他妹的bug。
客观别急,今天真的是要说一个bug,也许你早已知晓,也许你时常躺枪于他手,悄悄地,我们慢慢开始。
for in 遍历对象属性时存在bug
for in 遍历对象属性时存在bug
for in 遍历对象属性时存在bug
使用for in
去遍历一个对象俺们再熟悉不过了,经常干这种事,那他到底可以遍历一个对象哪些类型的属性呢? 长得帅的
还是看起来美美的
,瞎说,它能够遍历的是对象身上那些可枚举标志([[Enumerable]])为true
的属性。
- 对于通过直接的赋值和属性初始化的属性,该标识值默认为即为
true
- 对于通过 Object.defineProperty 等定义的属性,该标识值默认为 false
举个例子哪些属性可以被枚举
|
|
- 可以看到我们手动地用defineProperty,给某个对象设置属性时,enumerable为false此时该属性是不可枚举的
- Person继承自Object构造函数,但是
for in
并没有枚举出Object原型上的一些方法 - 手动地覆盖对象原型上面的方法
toString
也是可枚举的
如何判断一个对象的属性是可枚举的
方式其实很简单,使用原生js提供的
Object.propertyIsEnumerable
来判断
|
|
为什么obj判断toString为不可枚举属性,而obj2就是可枚举的了呢?原因很简单,obj2将toString
重写了,而一个对象自身直接赋值的属性是可被枚举的
说了这么多,接下来我们来看一下下划线中涉及到遍历的部分对象方法,come on!!!
_.has(object, key)
判断对象obejct是否包含key属性
平时你可能经常这样去判断一个对象是否包含某个属性
|
|
但是这样做有缺陷,比如某个属性其对应的值为0,null,false,’’空字符串呢?这样明明obj有以下对应的属性,却因为属性值为假而通过不了验证
|
|
所以我们可以采用下划线中的这种方式
源码
_.keys(object)
获取object对象所有的属性名称。
使用示例
|
|
源码
|
|
collectNonEnumProps函数分析
该函数为下划线中的内部函数一枚,专门处理ie9以下的枚举bug问题,
for in
到底有啥bug,终于可以说出来了。
简单地说就是如果对象将其原型上的类似toString
的方法覆盖了的话,那么我们认为toString
就是可枚举的了,但是在ie9以下的浏览器中还是认为是不可以枚举的,又是万恶的ie
源码
|
|
代码看起来并不复杂,但是有一个小疑问,对于constructor属性为什么要单独处理呢?各个看官,如果知晓,请教我啊
_.allKeys(object)
获取object中所有的属性,包括原型上的。
举个简单的例子说明
|
|
接下来看下源码是怎么干的
源码
|
|
可以看到和_.keys的唯一的不同就在于遍历obj的时候有没有用hasOwnProperty
去判断
_.values()
返回object对象所有的属性值。
使用案例
|
|
源码
|
|
_.invert(object)
返回一个object副本,使其键(keys)和值(values)对换。
使用案例
|
|
注意哟,如果对象中有些属性值是相等的,那么翻转过来的对象其key取最后一个
源码
|
|
_.functions(object)
返回一个对象里所有的方法名, 而且是已经排序的(注意这里包括原型上的属性)
源码
|
|
结尾
夜深人静,悄悄地说一个bug这个鬼故事讲完了,各位good night。