[英]How to reliably detect exotic objects in JavaScript?
“異國”是指(出於該問題的目的)無法使用Object.create
創建的任何內容。 這包括ES2016規范定義為外來的所有內容 (任何“不具有一個或多個基本內部方法默認行為的對象”),以及由ObjectCreate規范方法使用非空的internalSlotsList創建的所有內容 ,以及任何種類的宿主對象。
“可靠”是指不受使用對象的屬性添加/刪除,使用Object.create
或Object.setPrototypeOf
為對象提供意外原型,修改對象的@@ toStringTag或構造函數的@@ hasInstance的欺騙。 這對於需要正確處理任意用戶數據的庫函數很重要。
(特別是,這意味着instanceof
和Object.prototype.isPrototypeOf()
。例如: var a = Object.create(Array.prototype)
產生看起來和聞起來像數組a instanceof Array === true
, a.push
和a.pop
可以按預期工作,但是缺少魔術行為.length
,很容易顯示它不是實際的外來數組: Array.isArray(a) === false
。)
“類型”,我大致是指ECMAScript 5.1語言規范所指的[[Class]],即,將Array實例以其特殊的[[DefineOwnProperty]]行為與普通對象分開的特性。
有些情況很簡單:
Array.isArray(a)
可靠地檢測到數組外來對象。 typeof f === 'function'
可靠地檢測typeof f === 'function'
。
Set.prototype.has.apply(s, undefined)
並查看其是否引發TypeError來檢測集合。 尤其是:
我注意到Object.toString.apply(o)
曾經在此目的上工作得很好:盡管在許多瀏覽器中,它取決於宿主對象的類型,但對於ES 5.1規范中定義的所有類型,它都可以依靠可靠地告訴您該對象是普通的[object Object]
還是奇異的[object <Type>]
。 但是,在ES6和更高版本中,修改@@toStringTag
將破壞此測試。
在任何符合JS的實現中都可以使用的檢測方法是理想的,但是特定於Node.js的方法仍然有用。
但是,有什么方法可以檢測一個函數是綁定函數,本機函數還是閉包?
否。它們都是簡單明了的功能。
通過謹慎地應用其原型對象中的方法,可以可靠地檢測到其他一些奇特對象,例如
可以通過調用Set.prototype.has.apply(s,undefined)並查看其是否引發TypeError來檢測集合。
您可以使用instanceof
運算符測試對象是否是特定函數構造函數的實例(或其原型鏈中的某個對象)。
var mySet = new Set();
console.log(mySet instanceof Set);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.