功能
创建一个object
对象自身可枚举属性的键值对数组。如果Object
是map或者set,返回其条目。
function Foo() {
this.a = 1;
this.b = 2;
}
Foo.prototype.c = 3;
_.toPairs(new Foo);
// => [['a', 1], ['b', 2]]
源码实现
var createToPairs = require('./_createToPairs'),
keys = require('./keys');
var toPairs = createToPairs(keys);
从这里来看先理解keys
方法和createToPairs
方法的实现。
keys
就是_.keys
方法,功能是创建一个object自身可枚举属性名的数组 (暂时解释,接下来会写一篇keys的文章)
从toPairs
来看,createToPairs
接收一个函数返回一个方法。
func => object => {}
createToPairs
function createToPairs(keysFunc) {
return function(object) {
var tag = getTag(object);
if (tag == mapTag) {
return mapToArray(object);
}
if (tag == setTag) {
return setToPairs(object);
}
return baseToPairs(object, keysFunc(object));
};
}
module.exports = createToPairs;
keysFunc
是用来获取给定对象object
的keys的方法。对toPairs
和toPairsIn
的区别就是keysFunc
不同。
对于返回的函数
function(object) {
var tag = getTag(object);
if (tag == mapTag) {
return mapToArray(object);
}
if (tag == setTag) {
return setToPairs(object);
}
return baseToPairs(object, keysFunc(object));
};
}
对其来讲,set
和map
类型会分别由mapToArray
和setToPairs
来处理。除了二者的类型都会由baseToPairs
处理。
在这之前,可以先了解下getTag
的实现。
getTag
关于getTag百度出来一个很好的文章
在es5规范中,调用Object.prototype.totring
会采用下面的步骤
- 如果 this 的值是 undefined, 返回 "[object Undefined]".
- 如果 this 的值是 null, 返回 "[object Null]".
- 令 O 为以 this 作为参数调用 ToObject 的结果 .
- 令 class 为 O 的 [[Class]] 内部属性的值 .
- 返回三个字符串 "[object ", class, and "]" 连起来的字符串
对es5来讲,除了undefined
和null
会返回[object Undefined]和[object Null]。
对于其它的类型,都会返回一个[Object [[class]]
]的字符串。[[Class]]
为内部属性的值。
在es6中的,没有了[[class]]这个内部属性,这部分逻辑可以查看深入理解Object.prototype.toString方法来理解。
对稳重的步骤17,需要引用一下令 tag 为 Get(O, @@toStringTag) 的返回值( Get(O, @@toStringTag) 方法,既是在 O 是一个对象,并且具有 @@toStringTag 属性时,返回 O[Symbol.toStringTag] )
let obj = {}
Object.defineProperty(obj, Symbol.toStringTag, {
get: function() {
return "newClass"
}
})
console.log(Object.prototype.toString.call(obj))
// => [object newClass]
在es6规范table1中Symbol.toStringTag被解释为 该属性值是一个字符串,创建对象时它是对其的默认描述。通过Object.prototype.toString
才能访问这个属性
也就是当调用Object.prototype.toString
如果Symbol.toStringTag
存在会返回它的属性值。
通过上边的这些认识,我们再去查看baseGetTag
就容易理解了。
baseTag
function baseGetTag(value) {
if (value == null) {
return value === undefined ? undefinedTag : nullTag;
}
return (symToStringTag && symToStringTag in Object(value))
? getRawTag(value)
: objectToString(value);
}
对于是symToStringTag
会调用getRawTag
方法,其它类型直接调用Object.prototype.toString
返回tag
。
正如在es6
规范所描述。
getRawTag
function getRawTag(value) {
var isOwn = hasOwnProperty.call(value, symToStringTag),
tag = value[symToStringTag];
try {
value[symToStringTag] = undefined;
var unmasked = true;
} catch (e) {}
var result = nativeObjectToString.call(value);
if (unmasked) {
if (isOwn) {
value[symToStringTag] = tag;
} else {
delete value[symToStringTag];
}
}
return result;
}
getRawTag
方法实际做的就是去除掉symToStringTag
对获取tag的影响。先通过value[symToStringTag] = undefined;
移除掉该属性。再通过nativeObjectToString.call(value)
获取其tag
.
if (unmasked) {
if (isOwn) {
value[symToStringTag] = tag;
} else {
delete value[symToStringTag];
}
}
这段代码也很简单,做了一个修正。
总结
toParis依次调用了toParis
,getTag
,baseTag
,getRawTag
.
至于Object.prototype.toString的由来可结合代码再自行体会。
参考