From bf7f350c2cbafe40f9bbbaf52163d2587d32dca0 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Sat, 25 Nov 2023 10:15:58 +0100 Subject: [PATCH] doc: add a section regarding `instanceof` in `primordials.md` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/50874 Reviewed-By: Matteo Collina Reviewed-By: Chengzhong Wu Reviewed-By: Michaƫl Zasso --- doc/contributing/primordials.md | 46 +++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/doc/contributing/primordials.md b/doc/contributing/primordials.md index b763c88880f94c..4ca383c41cbd25 100644 --- a/doc/contributing/primordials.md +++ b/doc/contributing/primordials.md @@ -775,3 +775,49 @@ const proxyWithNullPrototypeObject = new Proxy(objectToProxy, { }); console.log(proxyWithNullPrototypeObject.someProperty); // genuine value ``` + +### Checking if an object is an instance of a class + +#### Using `instanceof` looks up the `@@hasInstance` property of the class + +```js +// User-land +Object.defineProperty(Array, Symbol.hasInstance, { + __proto__: null, + value: () => true, +}); +Object.defineProperty(Date, Symbol.hasInstance, { + __proto__: null, + value: () => false, +}); + +// Core +const { + FunctionPrototypeSymbolHasInstance, +} = primordials; + +console.log(new Date() instanceof Array); // true +console.log(new Date() instanceof Date); // false + +console.log(FunctionPrototypeSymbolHasInstance(Array, new Date())); // false +console.log(FunctionPrototypeSymbolHasInstance(Date, new Date())); // true +``` + +Even without user mutations, the result of `instanceof` can be deceiving when +dealing with values from different realms: + +```js +const vm = require('node:vm'); + +console.log(vm.runInNewContext('[]') instanceof Array); // false +console.log(vm.runInNewContext('[]') instanceof vm.runInNewContext('Array')); // false +console.log([] instanceof vm.runInNewContext('Array')); // false + +console.log(Array.isArray(vm.runInNewContext('[]'))); // true +console.log(vm.runInNewContext('Array').isArray(vm.runInNewContext('[]'))); // true +console.log(vm.runInNewContext('Array').isArray([])); // true +``` + +In general, using `instanceof` (or `FunctionPrototypeSymbolHasInstance`) checks +is not recommended, consider checking for the presence of properties or methods +for more reliable results.