【问题标题】:How to detect if a variable is a pure javascript object如何检测变量是否是纯 javascript 对象
【发布时间】:2019-12-05 05:17:31
【问题描述】:

我有一个函数需要传递一个对象。我使用typeof 运算符在处理前进行检查。但是看看this link,似乎许多javascript实例,例如数组或正则表达式,都被键入为对象。

我需要我的论点是一个纯对象(例如:{key: value, . . .})。

他们有什么方法可以检查一个变量是否是纯对象,而不必为每个 Object 实例运行特定的测试,比如Array.isArray() ?

【问题讨论】:

  • 查看this extensive answer 了解构成普通对象的内容。 “我需要我的论点是一个纯对象” - 为什么?你的函数不需要关心。
  • Boolean(obj) && obj.constructor === Object 对您来说是否足够好,知道即使是任何类的实例的对象也不会被匹配?
  • Object.getPrototypeOf(variable) === Object.prototype怎么样
  • @Bergi 错误!如果您需要区分普通的 javascript 对象和 HTMLElement、SVGElement、Date 对象、Node 对象等,该怎么办……“您的函数不需要关心”是一个非常判断性的陈述,考虑到您的合同可以指定,“如果参数是一个普通对象,做 X,否则做 Y”!
  • @Michael 是的,我认为一个好的 API 契约不应该是那样的,通过对象的简单性来区分事物是一个坏主意。你有实际用例吗?如果你想找到HTMLElement(等等),你可以使用instanceof。 “普通对象”是 else 案例。

标签: javascript object typeof


【解决方案1】:

要达到预期的效果,请使用以下查找构造函数名称的选项来检查变量是否为纯 javascript 对象

根据 MDN,

所有对象(使用创建的对象除外 Object.create(null)) 将具有构造函数属性。创建的对象 没有显式使用构造函数(即对象 和数组文字)将有一个构造函数属性指向 该对象的基本对象构造函数类型。

有关构造函数属性的更多详细信息,请参阅此链接 - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor

var x = {a:1,b:2};
var y = [1,2,3];

console.log(x.constructor.name === "Object")//x.constructor.name is Object
console.log(y.constructor.name === "Object")//y.constructor.name is Array

codepen - https://codepen.io/nagasai/pen/NQbxXa

【讨论】:

    【解决方案2】:

    您可以检查原型:

    function isPureObject(input) {
      return null !== input && 
        typeof input === 'object' &&
        Object.getPrototypeOf(input).isPrototypeOf(Object);
    }
    
    console.log(isPureObject({}));
    console.log(isPureObject(new Object()));
    console.log(isPureObject(undefined));
    console.log(isPureObject(null));
    console.log(isPureObject(1));
    console.log(isPureObject('a'));
    console.log(isPureObject(false));
    console.log(isPureObject([]));
    console.log(isPureObject(new Array()));
    console.log(isPureObject(() => {}));
    console.log(isPureObject(function () {}));

    【讨论】:

    • 我发现这个@falinksy 非常有用,可以帮助递归遍历对象属性
    • 这就是我最终得到的结果:stackoverflow.com/questions/41221672/…
    • function myFunction (){ /* ... */ } 测试它isPureObject(myFunction) 并返回true
    【解决方案3】:

    由于“普通”或“纯”的定义,普通对象的检测有点问题。我使用以下方法来检测普通对象。我从不使用x instanceof NodeList 类型验证,因为它们不适用于跨框架情况。 (每个窗口或框架都有自己的实例)

    我认为这是检测普通物体最简单、最有效的方法。

    function isPlainObject(o) {    
        var c = Object.prototype.toString.call(o) == '[object Object]'
            && o.constructor && o.constructor.name=="Object";
        return c === true;
    }
    
    function myTestFunction(){
    /* ... */
    }
    
    class myTestClass{
    /* ... */
    }
            
    console.log( isPlainObject({"a":1,"b":2}) ); //true
    console.log( isPlainObject({}) ); //true
    console.log( isPlainObject(null) ); //false
    console.log( isPlainObject("my string") ); //false
    console.log( isPlainObject("") ); //false
    console.log( isPlainObject([1,2,3]) ); //false
    console.log( isPlainObject(document.querySelectorAll("*")) ); //false
    console.log( isPlainObject(new RegExp(/[a-z]+/)) ); //false
    console.log( isPlainObject(myTestFunction) ); //false
    console.log( isPlainObject(new myTestFunction()) ); //false
    console.log( isPlainObject(myTestClass) ); //false
    console.log( isPlainObject(new myTestClass()) ); //false

    【讨论】:

    • return c === true ? true : false; 可以简化为 return c === true;
    • @flinsky 在许多浏览器上的一些测试中,我注意到它有时会在测试 null 和 undefined 值时返回 undefined 或 null 而不是 false。所以我添加它以确保它只返回真或假。是的return c === true 是一个更好的方法。我编辑了它。谢谢。
    • 在您的实施环境中也使用此条件typeof o === 'object' 有点多余(只要您依赖.toString 实施)请在tc39.es/ecma262/#sec-object.prototype.tostring 中查看更多信息
    • @fallinsky 是为了让评估更有效率。第一次评估后,非对象值将立即返回 false。以下检查范围更广。
    • 请记住,一般而言,默认情况下不应该争取过早优化。除非您明确地(理想情况下)对或多或少已知或预期的数据集进行实际测量(或至少知道数据的性质或限制) - 您真的不知道什么会真正更有效。例如,考虑对一组 1000000 个数组执行此函数或仅对 null 执行此函数 - 此 typeof o === 'object' 将导致 1000000 次不必要的检查。
    【解决方案4】:

    最短的版本

    const isObj = o => o?.constructor === Object;
    

    在这里找到:https://stackoverflow.com/a/61684890/7138254

    【讨论】:

      猜你喜欢
      • 2016-07-27
      • 1970-01-01
      • 2018-02-19
      • 2013-03-28
      • 2011-10-20
      • 2020-05-27
      • 2011-08-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多