# defaults
# Description
分配来源对象的可枚举属性到目标对象所有解析为 undefined 的属性上。 来源对象从左到右应用。 一旦设置了相同属性的值,后续的将被忽略掉。
# Params
(object, ...sources)
# Return
object
# Depend
import eq from './eq.js'
# Code
/** Used for built-in method references. */
const objectProto = Object.prototype
/** Used to check objects for own properties. */
const hasOwnProperty = objectProto.hasOwnProperty
function defaults(object, ...sources) {
object = Object(object)
sources.forEach((source) => {
if (source != null) {
source = Object(source)
for (const key in source) {
const value = object[key]
if (value === undefined ||
(eq(value, objectProto[key]) && !hasOwnProperty.call(object, key))) {
object[key] = source[key]
}
}
}
})
return object
}
# Analyze
sourcesforEach遍历,拿到每个source- 如果
source不为undefined或者 不为null - 则遍历
source, 判断object上对应的key是否为undefined,如果为undefined,则将source[key]设置给object[key] - 如果
object[key]不为undefined,则判断是不是Object原型上的值,如果是其原型上的值,默认也会认为object本身是没有该属性的,也是可以设置的 - 但是只判断
prototype是不够的,defaults规则有一条说后续的值不能覆盖已有的值,所以要判断当前的key不在object上!hasOwnProperty.call(object, key) - 满足3 或者 4,5 会将 source[key] 设置给 object[key]
- 使用
Object构造函数是为了 避免基本类型出错
# Remark
- Object.prototype.hasOwnProperty() MDN (opens new window) 方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)
- Object () 构造函数 (opens new window)
# Example
defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }) // => { 'a': 1, 'b': 2 }