1

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

让我们检查以下代码:

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

是否有任何其他变量,而不是null并且undefined在调用时会引发错误.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

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

4

5 回答 5

2

使用 hasOwnProperty 作为属性名称

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

还要注意最新的草稿

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

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

笔记

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

于 2018-08-24T04:39:52.637 回答
2

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 中的新功能)
和 Object。

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

数字、布尔值和字符串

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

因此

(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

符号和 BigInt

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

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

  • 无论是函数Symbol还是BigInt全局函数都不允许对new它们使用之前的调用。

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

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

  • boolean与旧的,number和数据类型的对象包装器string不同,尝试在or数据类型上设置属性永远不会悄悄地成功。symbolbigint

目的

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

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

Object.create( null);

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

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

包装对象和严格模式。

在 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如果第一个参数是 Object 数据类型并且具有与第二个参数同名的属性,则返回一个布尔值。它为所有原始值返回 false。

于 2018-08-24T07:19:00.823 回答
0

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

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

于 2018-08-24T04:40:43.633 回答
0

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

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')

于 2018-08-24T04:45:36.427 回答
0

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

更多信息参考点击这里

于 2018-08-24T04:55:07.347 回答