-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
underscore源码剖析之keys #1
Comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
underscore源码分析之_.keys
这篇文章主要分析underscore中_.keys以及相关方法的源码,着重分析_.keys内部的collectNonEnumProps方法。
在看源码前,我们先了解keys的用法。keys和原生的Object.keys的用法一样,都是返回一个以对象本身属性名(不包括原型上的)为集合的数组,如果是重写了原型上面的属性,也会返回。
我们再来看一下keys的源码:
_.has
keys方法大致这这么多,这里我先讲has方法。has方法是用来判断对象自身是否具有某个属性,这里可以看一下has的源码:
这里使用了Object原型上的hasOwnProperty方法,也许你会好奇,为什么不直接用hasOwnProperty来判断?因为hasOwnProperty方法可能会被重写覆盖掉,所以用hasOwnProperty在一开始就保存了一份Object.prototype.hasOwnProperty的引用,这样就不会出现被覆盖的情况了。
collectNonEnumProps
看完了has方法,我们来重点讲collectNonEnumProps这个方法。这里我们不得不先说一下for in循环。
我们都知道,for in循环只遍历可枚举属性。像使用像Object内置构造函数所创建的对象都会继承来自Object.prototype的不可枚举属性。
我们前面说过keys返回对象的属性名集合,但是不包括原型上的,除非你在对象自身上写了一个和原型上名字一模一样的属性。但是在ie9以下浏览器中会出现一个bug,那就是Object原型上的包括**['valueOf', 'isPrototypeOf','toString','propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString']**在内的6个方法,即使在对象上写了一模一样的方法,也不会被for in遍历到。
我们先搬出源码,简单的注释一下:
可能上面注释不是很详细,我在这里逐条解释一下。
首先是hasEnumBug这个属性,我们知道propertyIsEnumerable是判断对象上的某个属性是否可被枚举的,当然这个在ie9以下的浏览器中也会出现for in上面的那个bug,所以这里可以用一个重写过toString方法的对象来判断toString方法是否可枚举,如果返回了false,那么就说明浏览器中存在这个bug。
这里可能大家会有两个疑问,一个是为什么constructor要单独用_.has处理?直接放到while里面和大家一起处理不行吗?
我自己的理解是,可能是为了防止出现下面这种情况。
如果没有重写,obj.proto.constructor原本就是指向Object构造函数的,现在重写后其实根本没有改变,那么obj[prop] !== proto[prop]这个返回的肯定是true,但是constructor却是实实在在在obj上被重写过了,所以这里对constructor用_.has来处理。
另一个疑问则是prop in obj && obj[prop] !== proto[prop]中为什么还有prop in obj这一句?难道这个不是一定会返回true吗?当前的prop不是一定会存在于原型上?
同样是我自己的理解,我觉得可能会出现一种情况,那就是如果obj的原型被修改了,那么原型上就不会有toString等方法了,比如:
写到这里,其实我也有一个疑问,那就是为什么不全部都用_.has来判断,反而将toString等六个属性用prop in obj && obj[prop] !== proto[prop]来判断?prop in obj && obj[prop] !== proto[prop]判断一定可靠吗?
看下面这个例子:
这种场景类似上面的constructor,因为obj[prop] !== proto[prop]必定会返回false,所以其他几种方法也有我刚说的constructor类似的情况,所以到这里我对自己前面讲的constructor单独处理的原因产生质疑,既然大家都会遇到这种问题,为什么不都直接用_.has来处理呢?
按照我自己的理解,这里我重写一下collectNonEnumProps方法,如下:
以上都是个人理解,如果理解有偏差,望指出。
The text was updated successfully, but these errors were encountered: