携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第29天,点击查看活动详情
前言
lodash里的toPairsIn方法可以创建一个object对象自身和继承的可枚举属性的键值对数组。这个数组可以通过_.fromPairs撤回。如果object 是 map 或 set,将返回其条目。
使用如下:
function Foo() {
this.a = 1;
this.b = 2;
}
Foo.prototype.c = 3;
_.toPairsIn(new Foo);
// => [['a', 1], ['b', 2], ['c', 3]]
在上篇文章《 lodash里的toLength和toPairs 》中我们了解到toPairs的实现,在实现上其借助了createToPairs工厂函数。
toPairsIn在实现上也将借助该方法,并且将借助另一个封装方法,keysIn方法。
keysIn
keysIn方法是lodash对外导出的方法,该方法创建一个 object 自身 和 继承的可枚举属性名为数组。
使用如下:
function Foo() {
this.a = 1;
this.b = 2;
}
Foo.prototype.c = 3;
_.keysIn(new Foo);
// => ['a', 'b', 'c'] (iteration order is not guaranteed)
keysIn方法实现上,通过isArray方法判断参数是否是数组,是的话调用arrayLikeKeys方法,否则调用baseKeysIn方法。
源码如下:
import arrayLikeKeys from './_arrayLikeKeys.js';
import baseKeysIn from './_baseKeysIn.js';
import isArrayLike from './isArrayLike.js';
function keysIn(object) {
return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
}
arrayLikeKeys
arrayLikeKeys方法是一个内部方法,该方法返回属性名称的数组。其中,该方法接收两个参数,第一个参数是源数据,第二个参数表示是否继承指定返回继承的属性名称。
实现的处理逻辑如下:
- 先对参数进行初始化判断,如果是数组类型、Argument类型、Buffer类型、typeArray类型,会调用baseTimes方法,否则赋值为空数组,然后将结果赋值给result变量。
- 其次进行for in遍历,不满足条件的话在遍历中不处理,如果满足的话,会讲遍历中的keypush到初始化的结果上。
- 返回result结果。
import baseTmes from './_baseTimes.js';
import isArguments from './isArguments.js';s
import isArray from './isArray.js';
import isBuffer from './isBuffer.js';
import isIndex from './_isIndex.js';
import isTypedArray from './isTypedArray.js';
var objectProto = Object.prototype;
var hasOwnProperty = objectProto.hasOwnProperty;
function arrayLikeKeys(value, inherited) {
var isArr = isArray(value),
isArg = !isArr && isArguments(value),
isBuff = !isArr && !isArg && isBuffer(value),
isType = !isArr && !isArg && !isBuff && isTypedArray(value),
skipIndexes = isArr || isArg || isBuff || isType,
result = skipIndexes ? baseTimes(value.length, String) : [],
length = result.length;
for (var key in value) {
if ((inherited || hasOwnProperty.call(value, key)) &&
!(skipIndexes && (
// Safari 9有可枚举的参数。严格模式下的“长度”。
key == 'length' ||
// Node 0.10在缓冲区上具有可枚举的非索引属性
(isBuff && (key == 'offset' || key == 'parent')) ||
// PhantomJS 2在类型化数组上具有可枚举的非索引属性
(isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
// 跳过索引属性
isIndex(key, length)
))) {
result.push(key);
}
}
return result;
}
baseTimes
baseTimes 是一个内部方法,该方法可以返回一个数组。baseTimes方法的第一个参数是迭代的次数,第二个参数是每次迭代时调用的方法。
function baseTimes(n, iteratee) {
var index = -1,
result = Array(n);
while (++index < n) {
result[index] = iteratee(index);
}
return result;
}
baseKeysIn
baseKeysIn方法是keysIn 的基本实现,它不会将稀疏数组视为密集数组,实现上借助isObject 判断对象类型,借助isPrototype 方法判断是否是原型对象,该方法返回属性名称的数组。
实现的处理逻辑如下:
- 如果不是参数不是对象,直接返回nativeKeysIn的调用结果。
- 通过for in循环遍历参数,在每一次循环中判断,只有参数不是某一个原型对象时才输出该参数对象的每一个键,其他情况则输出空数组。
import isObject from './isObject.js';
import isPrototype from './_isPrototype.js';
import nativeKeysIn from './_nativeKeysIn.js';
var objectProto = Object.prototype;
var hasOwnProperty = objectProto.hasOwnProperty;
function baseKeysIn(object) {
if (!isObject(object)) {
return nativeKeysIn(object);
}
var isProto = isPrototype(object),
result = [];
for (var key in object) {
if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
result.push(key);
}
}
return result;
}
isPrototype
isPrototype方法是lodash里的一个内部方法,该方法主要检查参数是否可能是原型对象。
var objectProto = Object.prototype;
function isPrototype(value) {
var Ctor = value && value.constructor,
proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
return value === proto;
}
nativeKeysIn
nativeKeysIn是lodash里的一个内部方法,该方法类似于Object.keys可获得一组包含对象的键的数组。
function nativeKeysIn(object) {
var result = [];
if (object != null) {
for (var key in Object(object)) {
result.push(key);
}
}
return result;
}
toPairsIn
toPairsIn方法实现上主要借助copyObject工厂函数和keysIn方法。 源码如下:
import createToPairs from './_createToPairs.js';
import keysIn from './keysIn.js';
var toPairsIn = createToPairs(keysIn);
小结
本篇章我们认识了keysIn方法和toPairsIn方法的实现,其中toPairsIn方法的实现依赖keysIn方法和createToPairs工厂函数。
在实现keysIn过程中我们也认识了baseTimes和baseKeysIn等内部方法的实现,了解源码的过程中关注其内部封装及依赖的方法实现。