考虑以下:
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()
:
哪个检查value是否是Object的语言类型.(例如数组,函数,对象,正则表达式,新的Number(0)和new String('')
.isPlainObject()
:
其中,如果值是一个普通的对象,即,由所述对象的构造或一个用空的原型创建的对象
我们的好朋友,可靠的朋友typeof x === 'object'
.
我有三个问题:
有没有一个有意识的设计决定制作.isObject
和.isPlainObject
行为不同于本机.js类型检查?
如果我的第一个问题是真的,那么设计决策是什么,以这种方式做到这一点有什么好处?
是否存在任何与lodash(或underscore.js)is*
函数完全相同的函数typeof x === 'object'
?
显然我可以继续使用typeof
,但从语法上讲,在某些地方使用一个或另一个有点奇怪,例如.isObject
在检查时使用会返回误报typeof x === 'object' && typeof x !== 'function'
.我真的没有看到.isObject
在.isFunction
已经存在的情况下为函数返回true的任何好处.
typeof
与某物是否是物体无关.函数,字符串和它们都是{}
不同的typeof
,它们都是对象.函数当然是第一类对象,就像字符串是第一类对象一样,因此isObject
必须为字符串和对象返回true.
为了记录,文档涵盖了这个:
检查value是否是Object的语言类型.(例如数组,函数,对象,正则表达式,新的Number(0)和new String(''))
哇!如果没有方便的isObject
方法,那真的有很多东西需要测试.最公平的回报typeof
是object
,但更高级别的方法,尤其是像lodash这样的图书馆,是程序员可以忘记那些废话.
如果你关心typeof
一个参数,那就用吧typeof
.如果你关心不是函数的对象,你有几个选择:你可以特别使用typeof
和检查字符串,或者你可以使用isObject && !isFunction
.我更喜欢后者.后者确实恰好说出了你想传达的内容,所以编码是正确的.如果你认为当你说"对象"时你隐含的意思不是函数,那么你不认为函数是一等对象,或者你更希望你的代码更接近于它们不是的语言.但是你不能责怪lodash作为一个广泛使用函数是第一类对象的事实的库来创建一种语言,其中函数是第一类对象更具表现力.
我相信这是你的大部分问题.我相信用例isPlainObject
是回答"这只是数据吗?"的问题.或者"是这个代码吗?" 所以创建为伪类(对象)的对象new
不计算在内.
有时代码比言语更响亮.这是来自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文档:
检查value是否是Object 的语言类型.(例如数组,函数,对象,正则表达式,新的Number(0)和new String(''))
检查value是否是普通对象,即Object构造函数创建的对象或[[Prototype]]为null的对象.
什么是对象?也许isObject
在JavaScript中存在一个函数本质上有点令人困惑,所以很多东西就像对象一样.关键思想是JavaScript中的某些值被视为原始值,而其他值则被视为完整的对象.字符串,数字和布尔值在内部级别的处理方式与使用对象文字或构造函数创建的对象的处理方式不同(这最终没有太多实际意义,因为基元会在必要时自动将其自身转换为对象).
事实typeof null === 'object'
可能源于对象是引用类型的事实,并且通常从函数返回null来代替对象.(一个怪癖可能会回到指针的概念和C和C++中的NULLPTR.类型void *
有很多值,但NULLPTR仍然被认为是指针类型的有效值.)