We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
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
本文为读 lodash 源码的第一百一十六篇,后续文章会更新到这个仓库中,欢迎 star:pocket-lodash
gitbook也会同步仓库的更新,gitbook地址:pocket-lodash
import baseAssignValue from './baseAssignValue.js' import eq from '../eq.js'
《lodash源码分析之baseAssignValue》 《lodash源码分析之NaN不是NaN》
assignValue 的作用是将 value 设置到 object 指定的 key 上。
assignValue
value
object
key
源码如下:
const hasOwnProperty = Object.prototype.hasOwnProperty function assignValue(object, key, value) { const objValue = object[key] if (!(hasOwnProperty.call(object, key) && eq(objValue, value))) { if (value !== 0 || (1 / value) === (1 / objValue)) { baseAssignValue(object, key, value) } } else if (value === undefined && !(key in object)) { baseAssignValue(object, key, value) } }
要将 value 设置到指定的 key 上很简单,只要检测一下 object 上是否有这个 key ,如果这个 key 不存在,或者原来的值 objValue 和 value 不相等时,就可以将 value 设置到 obj 上了。
objValue
obj
const hasOwnProperty = Object.prototype.hasOwnProperty function assignValue(object, key, value) { const objValue = object[key] if (!(hasOwnProperty.call(object, key) && eq(objValue, value))) { baseAssignValue(object, key, value) } else if (value === undefined && !(key in object)) { baseAssignValue(object, key, value) } }
0
但是 eq 是不区分正负 0 的,也即eq(0, -0) 为 true,而 assignValue 是要区分正负零的。
eq
eq(0, -0)
true
如果原来的值为 0 ,传入的值为 -0 ,assignValue 会将 0 更新成 -0 。
-0
可以看到,lodash 现有的代码是将处理正负零的逻辑放在第一个分支内。
lodash
但是假设原来的值 objValue 和 传入的值刚好是一对正负零,则 eq 得到的结果为 true,此时要进入第一个分支的判断,hasOwnProperty 要为 false,也即 objValue 是从原型链上取得的,此时应该直接调用 baseAssinValue 更新值即可。
hasOwnProperty
false
baseAssinValue
所以在这个分支内的判断我觉得是毫无必要的。
如果 hasOwnProperty 为 true ,eq 也为 true,则会跳过第一个分支的逻辑,此时,应该判断一下传入的 value 是否等于 0(可以为正0,也可以为负0 ,如果为 0 ,再判断 objValue 和 value 是否同为正 0 或者同为负 0 ,如果不相同,那要也调用 baseAssignValue 来更新值。
baseAssignValue
源码修改如下:
function assignValue(object, key, value) { const objValue = object[key] if ( !(hasOwnProperty.call(object, key) && eq(objValue, value)) || (value === 0 && (1 / value !== 1 / objValue)) || (value === undefined && !(key in object)) ) { baseAssignValue(object, key, value) } }
至于第三个分支,我觉得是永远不会为 true 的,其实可以去掉的。
因为第进入第三个分支,必须要 hasOwnProperty 为 true ,eq 也为 true 。
当 hasOwnProperty 为 true 时,key in object 也必定为 true ,也即 !(key in object) 必定为 false,那么 value === undefined && !(key in object) 必定为 false ,所以这个分支是永远都不会进入的。
key in object
!(key in object)
value === undefined && !(key in object)
以上是我个人的一点见解,也给 lodash 提了个 pr,如果有理解得不正确的地方,还请指正。
署名-非商业性使用-禁止演绎 4.0 国际 (CC BY-NC-ND 4.0)
最后,所有文章都会同步发送到微信公众号上,欢迎关注,欢迎提意见:
作者:对角另一面
The text was updated successfully, but these errors were encountered:
截至目前源码: function assignValue(object, key, value) { var objValue = object[key]; if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || (value === undefined && !(key in object))) { baseAssignValue(object, key, value); } } 第一、 和作者说的一样,第一个判断已经cover了+/- 0的情况。 第二、 in和hasOwnProperty的行为不一样,in会拿到原型链上的值,也就是说这里的意思是如果object本身没有key但是原型链上key有值,就不要使用undefined将原型链上的值覆盖掉,只有在value不为undefined的时候才去赋值。
Sorry, something went wrong.
第二点,要 !(hasOwnProperty.call(object, key) && eq(objValue, value)) 为 false,则 hasOwnProperty.call(object, key) 必定为 true,即 object 上必定有 key 这个属性,那 key in object 必定为 true 了
!(hasOwnProperty.call(object, key) && eq(objValue, value))
hasOwnProperty.call(object, key)
No branches or pull requests
本文为读 lodash 源码的第一百一十六篇,后续文章会更新到这个仓库中,欢迎 star:pocket-lodash
gitbook也会同步仓库的更新,gitbook地址:pocket-lodash
依赖
《lodash源码分析之baseAssignValue》
《lodash源码分析之NaN不是NaN》
源码分析
assignValue
的作用是将value
设置到object
指定的key
上。源码如下:
要将
value
设置到指定的key
上很简单,只要检测一下object
上是否有这个key
,如果这个key
不存在,或者原来的值objValue
和value
不相等时,就可以将value
设置到obj
上了。处理正负
0
问题但是
eq
是不区分正负0
的,也即eq(0, -0)
为true
,而assignValue
是要区分正负零的。如果原来的值为
0
,传入的值为-0
,assignValue
会将0
更新成-0
。可以看到,
lodash
现有的代码是将处理正负零的逻辑放在第一个分支内。但是假设原来的值
objValue
和 传入的值刚好是一对正负零,则eq
得到的结果为true
,此时要进入第一个分支的判断,hasOwnProperty
要为false
,也即objValue
是从原型链上取得的,此时应该直接调用baseAssinValue
更新值即可。所以在这个分支内的判断我觉得是毫无必要的。
如果
hasOwnProperty
为true
,eq
也为true
,则会跳过第一个分支的逻辑,此时,应该判断一下传入的value
是否等于0
(可以为正0
,也可以为负0
,如果为0
,再判断objValue
和value
是否同为正0
或者同为负0
,如果不相同,那要也调用baseAssignValue
来更新值。源码修改如下:
至于第三个分支,我觉得是永远不会为
true
的,其实可以去掉的。因为第进入第三个分支,必须要
hasOwnProperty
为true
,eq
也为true
。当
hasOwnProperty
为true
时,key in object
也必定为true
,也即!(key in object)
必定为false
,那么value === undefined && !(key in object)
必定为false
,所以这个分支是永远都不会进入的。以上是我个人的一点见解,也给
lodash
提了个 pr,如果有理解得不正确的地方,还请指正。License
署名-非商业性使用-禁止演绎 4.0 国际 (CC BY-NC-ND 4.0)
最后,所有文章都会同步发送到微信公众号上,欢迎关注,欢迎提意见:
作者:对角另一面
The text was updated successfully, but these errors were encountered: