簡體   English   中英

JavaScript 中哪個對象沒有 `hasOwnProperty`?

[英]Which object does not have `hasOwnProperty` in JavaScript?

對於某些值,調用hasOwnProperty會引發錯誤。

讓我們檢查以下代碼:

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

在使用.hasOwnProperty調用時,是否還有其他變量而不是nullundefined會引發錯誤?

設置對象屬性的相同問題:

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'

========

最后,我發現在 JavaScript 中檢查一個值是否是一個對象

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

該解決方案完全滿足我的需求。

使用 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 值為 undefined 或 null,本規范先前版本中第 1 步會拋出的任何異常仍將繼續拋出。

TLDR;

Object.prototype.hasOwnProperty可以直接調用

  • Object.prototype

  • 在繼承鏈中具有Object.prototype並且不在繼承鏈或對象上重新定義hasOwnProperty的對象子集,以及

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

     (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因為“長度”是 String 包裝器對象自己的屬性。

未定義和空

數據類型 Undefined ( undefined ) 或 Null ( null ) 的原始值不會轉換為包裝器對象,並在嘗試將其作為方法調用hasOwnProperty時生成語法錯誤:

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

符號和 BigInt

Symbol 和 BigInt 數據類型值有單獨的處理——它們都是在 ECMAScript 中的新數據類型沒有對象包裝器的決定之后引入的。

實際上,這意味着 JavaScript 引擎在內部實現了將Symbol.prototypeBigInt.prototype方法分別應用於symbolbigint數據類型的語法,但只允許對原型方法和屬性進行讀取訪問 - 任何嘗試在symbol上設置屬性或bigint數據類型生成錯誤。

  • SymbolBigInt全局函數都不允許在調用它們之前使用new

  • Symbol充當工廠函數並返回一個新的符號值。

  • BigInt是一個類型轉換函數,用於將字符串和數字轉換為bigint數據類型。

  • booleannumberstring數據類型的舊對象包裝器不同,嘗試在symbolbigint數據類型上設置屬性永遠不會悄然成功。

目的

對象(數據類型為 Object)通常從Object.prototype繼承hasOwnProperty 如果hasOwnProperty在繼承鏈后面的某個地方重新定義(不是一個好主意),或者如果在到達Object.prototype之前在其繼承鏈中使用null創建對象,則此繼承可能會失敗。

在繼承鏈的開頭創建一個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。

我認為你可以在任何不是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

你是對的。 它存在於所有事物上,但未定義和為空

 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 運算符。

有關更多信息的參考,請單擊此處

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM