[英]Which object does not have `hasOwnProperty` in JavaScript?
對於某些值,調用hasOwnProperty
會引發錯誤。
讓我們檢查以下代碼:
null.hasOwnProperty('bar') // Error
undefined.hasOwnProperty('bar') // Error
(0).hasOwnProperty('bar') // Returns false
在使用.hasOwnProperty
調用時,是否還有其他變量而不是null
和undefined
會引發錯誤?
設置對象屬性的相同問題:
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
該解決方案完全滿足我的需求。
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 方法時,將采取以下步驟:
- 讓 P ? ToPropertyKey(V)。
- 讓 O 成為? ToObject(這個值)。
- 返回 ? 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 類型的值分別自動轉換為全局構造函數Number
、 Boolean
和String
“包裝器”對象實例。
因此
(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.prototype
和BigInt.prototype
方法分別應用於symbol
和bigint
數據類型的語法,但只允許對原型方法和屬性進行讀取訪問 - 任何嘗試在symbol
上設置屬性或bigint
數據類型生成錯誤。
Symbol
和BigInt
全局函數都不允許在調用它們之前使用new
。
Symbol
充當工廠函數並返回一個新的符號值。
BigInt
是一個類型轉換函數,用於將字符串和數字轉換為bigint
數據類型。
與boolean
、 number
和string
數據類型的舊對象包裝器不同,嘗試在symbol
或bigint
數據類型上設置屬性永遠不會悄然成功。
目的
對象(數據類型為 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。
我認為你可以在任何不是undefined
或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
你是對的。 它存在於所有事物上,但未定義和為空
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.