请考虑以下事项:
var o1 = {}
var O = function () {
return this
}
var o2 = new O()
var o3 = function() {}
var o4 = [o1, o1]
var output = [
[_.isObject(o1), _.isObject(o2), _.isObject(o3), _.isObject(o4)],
[_.isPlainObject(o1), _.isPlainObject(o2), _.isPlainObject(o3), _.isPlainObject(o4)],
[typeof o1 === 'object', typeof o2 === 'object', typeof o3 === 'object', typeof o4 === 'object'],
[o1 instanceof Array, o2 instanceof Array, o3 instanceof Array, o4 instanceof Array]
]
/* outputs:
[
[true,true,true,true],
[true,false,false,false],
[true,true,false,true],
[false,false,false,true]
]
*/
显然,我们可以看到.isObject()
:
.isPlainObject()
:
我们的好朋友typeof x === 'object'
。
我有三个问题:
.isObject
和.isPlainObject
的行为与本机.js类型检查的行为不同?is*
完全相同的原生lodash(或underscore.js)typeof x === 'object'
函数? 显然我可以继续使用typeof
,但从语法上讲,在某些地方使用其中一个有点奇怪,例如.isObject
的使用在检查{时会返回误报{1}}。当typeof x === 'object' && typeof x !== 'function'
已经存在时,我并没有真正看到.isObject
对函数返回true的任何好处。
答案 0 :(得分:8)
typeof
与某事物是否是一个无关。函数,字符串和{}
具有不同的typeof
,它们都是对象。函数当然是第一类对象,就像字符串是第一类对象一样,因此isObject
必须为字符串和对象返回true。
对于记录,文档涵盖了这个:
检查value是否是Object的语言类型。 (例如数组,函数,对象,正则表达式,新数字(0)和新字符串(''))
哇!如果没有方便的isObject
方法,那么真的需要进行大量测试。最公平的是将typeof
作为object
返回,但更高级别的方法,尤其是像lodash这样的库,是程序员可以忘记那些废话。
如果您关心typeof
参数,请使用typeof
。如果您关心不是函数的对象,您有几个选项:您可以使用typeof
和特别检查字符串,或者您可以使用isObject && !isFunction
。我更喜欢后者。后者确实恰好说出了你想传达的内容,所以编码是正确的。如果你认为当你说"对象"你隐含地不是指函数,那么你不认为函数是一流的对象,或者你希望你的代码更接近于它们不是的语言。但是,你不能责怪lodash是一个广泛使用函数是第一类对象的事实的库,这个函数是一种语言,其中函数是第一类对象更具表现力。
我认为这是你的大部分问题。我相信isPlainObject
的用例是回答问题"这只是数据吗?"或"是这个代码?"所以创建为伪类(new
的东西)的对象不算数。
答案 1 :(得分:7)
有时代码比言语更响亮。这是来自lodash的来源:
function isObject(value) {
var type = typeof value;
return !!value && (type == 'object' || type == 'function');
}
function isPlainObject(value) {
var Ctor;
if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isHostObject(value) && !isArguments(value)) ||
(!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) {
return false;
}
var result;
if (lodash.support.ownLast) {
baseForIn(value, function(subValue, key, object) {
result = hasOwnProperty.call(object, key);
return false;
});
return result !== false;
}
baseForIn(value, function(subValue, key) {
result = key;
});
return result === undefined || hasOwnProperty.call(value, result);
}
根据lodash docs:
检查值是否为Object的language type。 (例如数组,函数,对象,正则表达式,新数字(0)和新字符串(''))
检查value是否是普通对象,即Object构造函数创建的对象或[[Prototype]]为null的对象。
在JavaScript中存在isObject
函数本身就有点令人困惑,所以很多东西都像对象一样。关键思想是JavaScript中的某些值被视为原始值,而其他值则被视为完整的对象。字符串,数字和布尔值在内部级别的处理方式与使用对象文字或构造函数创建的对象的处理方式不同(这并不具有很大的实际意义,因为基元会在必要时自动将其自身转换为对象)。
typeof null === 'object'
可能源于对象是引用类型并且通常从函数返回以代替对象这一事实。void *
(一个怪癖可能会回到指针的概念和C和C ++中的NULLPTR。类型who_first <- function(n) {
players <- seq_len(n)
found_winner <- FALSE
die_poss <- c(rep(c(0, 1), each = 3))
while (!found_winner) {
cat("Rolling for players", paste(players, collapse = ", "), "\n")
results <- replicate(length(players), sum(sample(die_poss, 4, replace=T)))
cat("Players rolled", paste(results, collapse = ", "), "points\n")
if (sum(max(results) == results) == 1) {
found_winner <- TRUE
winner <- players[which.max(results)]
cat("Winner is player", winner, "\n")
} else {
players <- players[max(results) == results]
}
}
invisible(winner)
}
有很多值,但NULLPTR仍然被认为是指针类型的有效值。)
答案 2 :(得分:3)
isObject
和isPlainObject
将是额外的。它们是实用功能。我确信他们知道他们的类型不同,这就是为什么他们可能对某些人有用。他们可能认为原生typeof
的性能,一致性和语法并不能保证.typeOf
能够做同样的事情。.isObject
为函数返回true是因为JS中的函数是对象。当本地typeof
返回函数而不是对象时,它就是一种欺骗。由于typeof []
不返回数组而是返回对象这一事实进一步令人费解,为什么它应该返回函数而不是函数上的对象。 typeof
相同的功能。下划线的_.isObject
与lodash .isObject
相同。您可以使用lodash的.isFunction
和.isObject
来创建自己的typeof函数,该函数返回与typeof
本机相同的内容。