【问题标题】:Which object does not have `hasOwnProperty` in JavaScript?JavaScript 中哪个对象没有“hasOwnProperty”?
【发布时间】:2019-01-30 12:35:24
【问题描述】:

对于某些值,调用 hasOwnProperty 会引发错误。

让我们检查以下代码:

null.hasOwnProperty('bar') // Error
undefined.hasOwnProperty('bar') // Error
(0).hasOwnProperty('bar') // Returns false

除了nullundefined 之外,是否还有其他变量在使用.hasOwnProperty 调用时会引发错误?

设置对象属性的相同问题:

null.bar // Error
undefined.bar // Error
(0).bar === undefined // Returns true

=========

在我的 Node.js 环境中引发错误的另一种情况:

在浏览器中

'use strict';
(0).bar = 0; // Nothing happens

在 Node.js v.10.3.0 中:

(0).bar = 0; // Nothing
'use' strict';
(0).bar === undefined; // Returns true
true.bar === undefined; // Returns true
''.bar = '';// STILL NOTHING HAPPENS
(0).bar = 0; //TypeError: Cannot create property 'bar' on number '0'
(true).bar = true; // TypeError: Cannot create property 'bar' on boolean 'true'

========

最终,我找到了Check if a value is an object in JavaScript

if (obj instanceof Object) obj.hasOwnProperty(...) // Or set a property on it

这个解决方案完全满足我的需求。

【问题讨论】:

  • nullundefined 不是变量,它们是类型。从概念上讲,不存在的东西 (null) 或未定义的东西 (undefined) 不可能有任何属性。
  • null 派生的任何对象都没有hasOwnProperty 方法,但是您可以创建该方法。
  • hasOwnProperty 需要一个对象(或从对象继承的东西)。要查看什么是 not 对象,请参见此处:quora.com/Is-everything-an-object-in-Javascript
  • 不确定(0).bar = 0 与您最初的问题有什么关系……?无论如何,请参阅stackoverflow.com/questions/49682661/…
  • @Ry- 我在对象上递归设置属性。我只想涵盖所有可能发生的情况。例如,recursivelySet(obj, path, value)。如果有人通过recursivelySet(1, 'foo.bar', 0),我希望该功能检测到这种情况并且什么都不做。或者更明显的情况,recursivelySet({foo: 1}, 'foo.bar', 0)

标签: javascript node.js ecmascript-6 strict hasownproperty


【解决方案1】:

TLDR;

Object.prototype.hasOwnProperty可以直接调用

  • Object.prototype,

  • 在其继承链中具有Object.prototype 且未在继承链或对象上重新定义hasOwnProperty 的对象子集,并且

  • BigInt、布尔值、数字、字符串和符号原始值。然而,在原始值上调用它通常是多余的,因为

      (primitiveValue).hasOwnProperty(propertyName)
    

    总是返回false - 原始值没有自己的属性。


数据类型

JavaScript 目前支持ECMAScript 2020 规范中的八种不同数据类型:

BigInt(ECMAScript 2020 中引入)、Boolean、Null、Undefined、Number、String、Symbol(ECMAScript 2015 中的新功能)
和对象。

其中前七个是原始值而不是对象值 - 包括数据类型为 Null 的 null。 (是的,typeof null 返回“object”而不是“null”,但这是早期 JavaScript 引擎设计的产物,无法修复,因为它会破坏网络。)

数字、布尔值和字符串

与属性值查找语法一起使用时,Number、Boolean 和 String 类型的值会自动转换为全局构造函数 NumberBooleanString 的“包装”对象实例。

因此

(1).hasOwnProperty("MAX_SAFE_INTEGER")

返回 false,因为该属性继承自 Number.prototype。同样,hasOwnProperty 对布尔值的调用返回 false,因为布尔包装对象本身没有任何固有的属性。但是

("hello folks").hasOwnProperty("length");

返回true,因为“长度”是字符串包装对象的自有属性。

未定义和空

Undefined (undefined) 或 Null (null) 数据类型的原始值不会转换为包装对象,并且在尝试将 hasOwnProperty 作为方法调用它们时会产生语法错误:

    (undefined).hasOwnProperty("example")  // TypeError
    (null).hasOwnProperty("example")       // TypeError

符号和大整数

Symbol 和 BigInt 数据类型值有不同的处理方式——它们都是在 ECMAScript 中的新数据类型没有对象包装器的决定之后引入的。

实际上,这意味着 JavaScript 引擎在内部实现了将 Symbol.prototypeBigInt.prototype 方法分别应用于 symbolbigint 数据类型的语法,但只允许对原型方法和属性进行读取访问 - 任何尝试在 symbolbigint 数据类型上设置属性会产生错误。

  • SymbolBigInt 全局函数都不允许在调用它们之前使用 new

  • Symbol 充当工厂函数并返回新的符号值。

  • BigInt是一个类型转换函数,用于将字符串和数字转换为bigint数据类型。

  • booleannumberstring 数据类型的旧对象包装器不同,尝试在 symbolbigint 数据类型上设置属性永远不会成功。 p>

对象

对象(数据类型为 Object)通常从 Object.prototype 继承 hasOwnProperty。如果 hasOwnProperty 在继承链的稍后位置被重新定义(不是一个好主意),或者如果在到达 Object.prototype 之前在其继承链中使用 null 创建对象,则此继承可能会失败.

在继承链的开头使用null 创建对象的最简单方法是调用

Object.create( null);

扩展此类对象还会创建不继承自 Object.prototype 的对象,因此无法使用 hasOwnProperty

请注意,将instanceof Object 应用于原型链不包含Object.prototype 的对象将返回false。不要使用instanceof 来确定对象数据类型。

包装对象和严格模式。

在 JavaScript 的早期版本中,为从原始值自动创建的包装对象设置属性在语法上是正确的,并且不会产生错误。 然而,一旦包装对象表达式被评估,包装对象就被丢弃了。尝试在以后的代码中查找自定义属性失败,因为查找时使用了一个新的、不同的包装对象,缺少自定义属性。

如果尝试将属性值分配给任何原始值,则严格模式会产生错误。

可能的检查功能

const checkOwnProperty = (obj, propertyName) =>
    (obj && (typeof obj == "object" || typeof obj == "function") &&
    Object.prototype.hasOwnProperty.call( obj, propertyName))
    ? true : false;

// Test:
var o = {name: "foo"};
console.log (  "name " + checkOwnProperty( o, "name"))
console.log (  "foo " +  checkOwnProperty( o, "foo"))
console.log (  "0 " +  checkOwnProperty( 0, "foo"))

CheckOwnProperty 返回一个布尔值,反映第一个参数是否为对象数据类型并且 具有与第二个参数同名的自己的属性。它为所有原始值返回 false。

【讨论】:

  • 请重新检查''.bar = ''; OP中显示的案例>>使用节点v14.0.0。这不会引发错误。
  • 答案中没有提到BigInt类型
  • @transang 我在 2018 年没有注意到:“使用严格”;必须是 JavaScript 源代码中要识别的第一个语句/表达式。将其移至第一行(并更正字符串语法)在测试时尝试将属性添加到节点 10.15.3 和节点 14.2.0 中的字符串时产生错误。
  • 你是对的。我已经测试并成功复制。如果将“use strict”放在开头,它最终会引发错误
【解决方案2】:

Using hasOwnProperty as a property name:

var foo = {
  hasOwnProperty: function() {
    return false;
  },
  bar: 'Here be dragons'
};

foo.hasOwnProperty('bar'); // always returns false

// Use another Object's hasOwnProperty
// and call it with 'this' set to foo
({}).hasOwnProperty.call(foo, 'bar'); // true

// It's also possible to use the hasOwnProperty property
// from the Object prototype for this purpose
Object.prototype.hasOwnProperty.call(foo, 'bar'); // true

还要注意最新的draft

当使用参数 V 调用 hasOwnProperty 方法时,将执行以下步骤:

  1. 让 P 是 ? ToPropertyKey(V)。
  2. 让 O 成为? ToObject(此值)。
  3. 返回 ? HasOwnProperty(O, P)。

注意

选择步骤 1 和 2 的顺序是为了确保即使 this 值未定义或为 null,也会继续抛出本规范先前版本中步骤 1 引发的任何异常。

【讨论】:

    【解决方案3】:

    我认为您可以在任何不是undefinednull 的变量上调用它。

    console.log([1].hasOwnProperty(0)); // true
    console.log([1,2].hasOwnProperty(1)); // true
    console.log([1,2].hasOwnProperty(2)); // false
    
    console.log({ a: 's'}.hasOwnProperty('a')); // true
    console.log({ b: 's'}.hasOwnProperty('a')); // false
    console.log({}.hasOwnProperty('a')); // false
    
    console.log((555).hasOwnProperty('a')); // false
    console.log((false).hasOwnProperty('a')); // false
    console.log((true).hasOwnProperty('a')); // false
    console.log(("skjhkdasj").hasOwnProperty('a')); // false
    console.log((1.045).hasOwnProperty('a')); // false
    // console.log((null).hasOwnProperty('a')); // error
    // console.log((undefined).hasOwnProperty('a')); // error

    【讨论】:

    • 不在Object.create(null) 中,这是一个没有Object 原型的对象。
    • 使用Object.create(null)而不是{}创建对象是很常见的。
    【解决方案4】:

    如果您只想检查属性是否存在,而不一定要检查它们的值,那么您有两个安全的选择:hasOwnProperty() 和 in 运算符。如果您只想检测自己的属性,则应使用 hasOwnProperty() 属性方法。如果您想测试属性是否存在,而不关心它是自己的属性还是对象属性,则可以使用 in 运算符。

    reference for more information click here

    【讨论】:

    • 安全选项:它抛出错误(我的问题),它确实不安全,我认为
    • 关于函数错误 带有 request.query.hasOwnProperty('whatever') 的处理函数将导致“request.query.hasOwnProperty 不是函数”错误。更改为 Object.prototype.hasOwnProperty.call(request.query, 'whatever') 工作 这是预期的。 nodejs 修改了 querystring 模块返回的查询对象,使其使用 null 原型,因此不继承普通 Object 实例的基本属性和方法。
    • 你检查代码了吗? Object.prototype.hasOwnProperty.call(null, 'whatever')Cannot convert undefined or null to object
    • 请给我更多的细节......你也可以参考这个链接[链接]stackoverflow.com/questions/29721205/…
    【解决方案5】:

    你是对的。它存在于一切之上,但未定义且为空

    class Vehicle {
      constructor(name, type) {
        this.name = name;
        this.type = type;
      }
    }
    
    class Car extends Vehicle {
      constructor(color) {
        super()
        this.color = color
      }
    }
    
    console.log(new Car().hasOwnProperty('color'))
    console.log(new Car().hasOwnProperty('name'))
    
    console.log(new Vehicle().hasOwnProperty('color'))
    console.log(new Vehicle().hasOwnProperty('name'))
    
    function foo() {}
    foo.hasOwnProperty('bar')
    true.hasOwnProperty('bar')
    
    const symbol = Symbol();
    Symbol.hasOwnProperty('bar')
    symbol.hasOwnProperty('bar')
    
    Boolean.hasOwnProperty('bar')
    String.hasOwnProperty('bar')
    Array.hasOwnProperty('bar')
    Number.hasOwnProperty('bar')
    Object.hasOwnProperty('bar')
    Car.hasOwnProperty('bar');
    [].hasOwnProperty('bar');
    "".hasOwnProperty('bar');
    (1).hasOwnProperty('bar');
    
    //null.hasOwnProperty('bar')
    //undefined.hasOwnProperty('bar')

    【讨论】:

    • 我认为您的数组和数字问题来自不正确的语法(缺少分号,缺少括号)。试试;[].hasOwnProperty('bar')1..hasOwnProperty('bar')
    • 也许“你不能在课堂上调用它”来自错误地使用Foo而不是Car
    • @Ry 我把课程修好了。
    • @Ry-哇哦!从来没有第二行的阵列这样做。哇!每天学些新东西。谢谢!
    • 您可以拨打一个号码。 1.hasOwnProperty 被解析为数字 1.(尾随小数点),然后只是一个随机的 hasOwnProperty。使用1..hasOwnProperty;(1).hasOwnProperty
    猜你喜欢
    • 2013-05-11
    • 2011-12-30
    • 2023-03-12
    • 1970-01-01
    • 2023-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多