JavaScript中确定某个对象是否为普通对象的方法

jbose2ul  于 2023-06-04  发布在  Java
关注(0)|答案(4)|浏览(265)

我最近偶然发现了这个函数,它可以确定某个对象是否是JavaScript的普通对象:

function isPlainObject (value){
  if (typeof value !== 'object' || value === null) return false;

  let proto = value;
  while (Object.getPrototypeOf(proto) !== null) {
    proto = Object.getPrototypeOf(proto);
  }

  return Object.getPrototypeOf(value) === proto;
};

来源:https://github.com/redux-utilities/redux-actions/blob/master/src/utils/isPlainObject.js
我想知道:
1.如果下面的方法将做完全相同的东西?
1.如果是这样的话,是否可以认为是更有效呢?

function isPlainObj(value){
  if (typeof value !== 'object' || value === null) return false;
  let obj = {};
  return Object.getPrototypeOf(value) === Object.getPrototypeOf(obj)
}
x9ybnkn6

x9ybnkn61#

检查一个值是否是普通对象:

/*
 isPlainObject({}) // true
 isPlainObject() // false
 isPlainObject(null) // false
 isPlainObject(true) // false
 isPlainObject('1') // false
 isPlainObject([]) // false
 isPlainObject(new Function()) // false
 isPlainObject(new Date()) // false
 */
const isPlainObject = value => value?.constructor === Object;

排除空值、标量、数组、函数和除Object以外的任何扩展类型。

63lcw9qa

63lcw9qa2#

1.前者遍历整个原型链,但仅当该链由1个原型组成时才返回true(因此,您的第一个示例有点无意义)
1.是也不是。是的,它更有效,不需要循环所有东西只是为了检查原型是Object.prototype。不,它执行不必要的操作。
我会这么做

const isPlainObj = value => !!value &&
                            Object.getPrototypeOf(value) === Object.prototype;

如果您只想知道value原型是Object.prototype,则无需太过复杂。👋

**P.S.**有一件事 * 你的初始示例做了其他示例,包括我的,没有:它与外来对象一起工作,外来对象是来自不同领域的对象(即,iframes)。我不认为这个用例在2021年存在,但如果你的应用/网站在不同的窗口/框架之间传递对象 *,那么 * 第一个函数也会为这些对象返回true,而我的建议,或者你的建议,不会。然而,没有必要循环整个链,你可以简单地这样做:

function isPlainObj(value) {
          // it's truthy
  return  !!value &&
          // it has a prototype that's also truthy
          !!(value = Object.getPrototypeOf(value)) &&
          // which has `null` as parent prototype
          !Object.getPrototypeOf(value);
}

这会抓取proto一次或最多两次,确保其链以null结束,这通常是常见的文字情况。
然而,我认为这些天外来物体是不存在的,所以我坚持我的建议版本。

v1uwarro

v1uwarro3#

无论是OP问题中提供的方法,还是@Javier Rey的答案,在某些情况下,这两种方法都不能很好地工作。Atomics、具有Symbol.iteratorSymbol.toStringTag静态数据属性的对象和JSON namespace object
以下测试用例将失败:

const iterable1 = {};

iterable1[Symbol.iterator] = function* () {
  yield 1;
  yield 2;
  yield 3;
};

isPlainObject(iterable1) // true, should be false
isPlainObject(JSON) // true, should be false

所以我们需要对这些物体进行额外的检查。

export default function isPlainObject(value) {
    if (typeof value !== 'object' || value === null) {
        return false;
    }

    const prototype = Object.getPrototypeOf(value);
    return (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(Symbol.toStringTag in value) && !(Symbol.iterator in value);
}
3qpi33ja

3qpi33ja4#

ToolJS在它的“Obj”模块下有一个方法,用于检查对象是否实际上是普通对象文字。
参考:ToolJS Object Module
NPM上或通过其CDN获取代码,并按如下所示使用

// export the methods in the "Obj" module
var $ = ToolJS.export("Obj");

var myObj = {name: "John Doe"};
var myArr = [1,2,3]; // note that arrays are of type object but are obviously not plain objects
var myEl = document.getElementById("elem"); // elements are also objects

$.isObj(myObj); // => true
$.isObj(myArr); // => false
$.isObj(myEl); // => false

您可以查看它的完整文档here
在后台,该方法检查项目类型不是null或undefined而是一个对象,然后检查其构造函数以查看其是否是一个对象,之后它确保它不是数组,最后将其转换为字符串以查看其是否是普通对象。

相关问题