JavaScript 中哪个对象没有 `hasOwnProperty`?

Which object does not have `hasOwnProperty` in JavaScript?

对于某些值,调用 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

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

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:

When the hasOwnProperty method is called with argument V, the following steps are taken:

  1. Let P be ? ToPropertyKey(V).
  2. Let O be ? ToObject(this value).
  3. Return ? HasOwnProperty(O, P).

NOTE

The ordering of steps 1 and 2 is chosen to ensure that any exception that would have been thrown by step 1 in previous editions of this specification will continue to be thrown even if the this value is undefined or null.

我认为您可以在任何不是 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

你是对的。它存在于除了未定义和 NULL

之外的所有事物上

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() 和 in 运算符。如果您只想检测自己的属性,则应使用 hasOwnProperty() 属性 方法。如果你想测试 属性 是否存在,而不关心它是一个自己的 属性 还是一个对象 属性,那么 in 运算符就是要使用的。

reference for more information click here

TLDR;

Object.prototype.hasOwnProperty可以直接在

上调用
  • Object.prototype,

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

  • BigInt、Boolean、Number、String 和 Symbol 原始值。在原始值上调用它通常是多余的,但是

      (primitiveValue).hasOwnProperty(propertyName)
    

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


数据类型

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

BigInt (introduced in ECMAScript 2020), Boolean, Null, Undefined, Number, String, Symbol (new in ECMAScript 2015)
and Object.

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

数字、布尔值和字符串

Number、Boolean 和 String 类型的值在与 [=180= 一起使用时分别自动转换为全局构造函数 NumberBooleanString 的“包装”对象实例] 值查找语法。

因此

(1).hasOwnProperty("MAX_SAFE_INTEGER")

returns false 因为 属性 继承自 Number.prototype。类似地,hasOwnProperty 调用布尔值 return false,因为布尔包装对象本身没有任何固有的属性。但是

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

returnstrue 因为“长度”是 String 包装器对象自己的 属性。

未定义且为空

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

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

符号和 BigInt

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

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

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

  • Symbol 充当工厂函数并且 return 是一个新的符号值。

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

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

对象

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

之前的继承链

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

Object.create( null);

扩展这样的对象也会创建不继承自 Object.prototype 的对象,因此不能使用 hasOwnProperty.

请注意,将instanceof Object应用于原型链不包含Object.prototype returns 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 returns 一个布尔值,反映第一个参数是否为 Object 数据类型 并且 有自己的同名 属性作为第二个参数。对于所有原始值,它 return 都是假的。