Skip to content

Instantly share code, notes, and snippets.

@sttk
Created March 11, 2021 13:01
Show Gist options
  • Save sttk/2b95754c418dafa608dbb44272204596 to your computer and use it in GitHub Desktop.
Save sttk/2b95754c418dafa608dbb44272204596 to your computer and use it in GitHub Desktop.
Checks for plain objects

(Node.js v0.11〜)

               typeof=o       protoToStr     proto=ObjProto proto=null     ctor=Obj       ctor=null      protoCtor=Obj  protoCtor=null 
-- strict plain object --
(1)            true           true           true           false          true           false          true           false          
(2)            true           true           true           false          true           false          true           false          
(3)            true           true           true           false          true           false          true           false          
-- wider plain object --
(4)            true           true           false          true           false          false          false          false          
(5)            true           true           false          false          true           false          true           false          
-- non plain object --
(6)            true           false          false          false          false          false          false          false          
(7)            false          false          false          false          false          false          false          false          
(8)            false          false          false          false          false          false          false          false          
(9)            false          false          false          false          false          false          false          false          
(10)           false          false          false          false          false          false          false          false          
(11)           true           false          false          false          false          false          false          false          
(12)           true           false          false          false          false          false          false          false          
(13)           true           false          false          false          false          false          false          false          
(14)           true           false          false          false          false          false          false          false          
(15)           true           false          false          false          false          false          false          false          
(16)           true           false          false          false          false          false          false          false          
(17)           false          false          false          false          false          false          false          false          
(18)           false          false          false          false          false          false          false          false          
(19)           false          false          false          false          false          false          false          false          
(20)           true           true           false          false          false          false          false          false          
(21)           true           true           false          false          false          false          false          false          
-- by JSON.parse --
(22)           true           true           true           false          true           false          true           false          
(23)           true           true           true           false          true           false          true           false          
(24)           true           true           true           false          true           false          true           false          
(25)           true           true           true           false          true           false          true           false          
(26)           true           true           true           false          true           false          true           false          
(27)           true           true           true           false          true           false          true           false          
(28)           true           true           true           false          true           false          true           false          
(29)           true           true           true           false          true           false          false          false          
(30)           true           true           true           false          false          false          true           false          
(31)           true           true           true           false          false          false          true           false          
(32)           true           true           true           false          false          false          true           false          
(33)           true           true           true           false          false          false          true           false          
(34)           true           true           true           false          false          false          true           false          
-- fiddle .__proto__ and .constructor
(35)           true           true           true           false          false          true           true           true           
(36)           true           true           false          true           false          false          false          false          
(37)           true           true           true           false          false          true           false          true      

(Node.js 〜v0.10)

               typeof=o       protoToStr     proto=ObjProto proto=null     ctor=Obj       ctor=null      protoCtor=Obj  protoCtor=null 
-- strict plain object --
(1)            true           true           true           false          true           false          true           false          
(2)            true           true           true           false          true           false          true           false          
(3)            true           true           true           false          true           false          true           false          
-- wider plain object --
(4)            true           true           false          true           false          false          false          false          
(5)            true           true           false          false          true           false          true           false          
-- non plain object --
(6)            true           false          false          false          false          false          false          false          
(7)            false          false          *Error*        *Error*        false          false          false          false          
(8)            false          false          *Error*        *Error*        false          false          false          false          
(9)            false          false          *Error*        *Error*        false          false          false          false          
(10)           false          false          *Error*        *Error*        false          false          false          false          
(11)           true           false          false          false          false          false          false          false          
(12)           true           false          false          false          false          false          false          false          
(13)           true           false          false          false          false          false          false          false          
(14)           true           false          false          false          false          false          false          false          
(15)           true           false          false          false          false          false          false          false          
(16)           true           false          false          false          false          false          false          false          
(18)           false          false          false          false          false          false          false          false          
(19)           false          false          false          false          false          false          false          false          
(20)           true           true           false          false          false          false          false          false          
(21)           true           true           false          false          false          false          false          false          
-- by JSON.parse --
(22)           true           true           true           false          true           false          true           false          
(23)           true           true           true           false          true           false          true           false          
(24)           true           true           true           false          true           false          true           false          
(25)           true           true           false          false          true           false          true           false          
(26)           true           true           false          false          true           false          true           false          
(27)           true           true           false          false          true           false          true           false          
(28)           true           true           false          false          true           false          true           false          
(29)           true           true           false          true           false          false          false          false          
(30)           true           true           true           false          false          false          true           false          
(31)           true           true           true           false          false          false          true           false          
(32)           true           true           true           false          false          false          true           false          
(33)           true           true           true           false          false          false          true           false          
(34)           true           true           true           false          false          false          true           false          
-- fiddle .__proto__ and .constructor
(35)           true           true           true           false          false          true           true           true           
(36)           true           true           false          true           false          false          false          false          
(37)           true           true           true           false          false          true           false          true       
'use strict';

var padRight = require('@fav/text.pad-right');

var funcs = [
  ['typeof=o', function(v) {
    return (typeof v === 'object');
  }],
  ['protoToStr', function(v) {
    return Object.prototype.toString.call(v) === '[object Object]';
  }],
  ['proto=ObjProto', function(v) {
    try {
      return (v != null) && (Object.getPrototypeOf(v) === Object.prototype);
    } catch (e) {
      return '*Error*';
    }
  }],
  ['proto=null', function(v) {
    try {
      return (v != null) && (Object.getPrototypeOf(v) === null);
    } catch (e) {
      return '*Error*';
    }
  }],
  ['ctor=Obj', function(v) {
    return (v != null) && (v.constructor === Object);
  }],
  ['ctor=null', function(v) {
    return (v != null) && (v.constructor === null);
  }],
  ['protoCtor=Obj', function(v) {
    return (v != null) && (v.__proto__ != null) && (v.__proto__.constructor === Object);
  }],
  ['protoCtor=null', function(v) {
    return (v != null) && (v.__proto__ != null) && (v.constructor === null);
  }],
];

var colWidth = 15;

function header() {
  var str = funcs.map(function(fn) {
    return fn[0];
  }).reduce(function(s, r) {
    return s + padRight(r, colWidth);
  }, padRight('', colWidth));
  console.log(str);
}

function test(n, v) {
  var str = funcs.map(function(fn) {
    try {
      return fn[1](v);
    } catch (e) {
      return '*Error*';
    }
  }).reduce(function(s, r) {
    return s + padRight('' + r, colWidth);
  }, padRight('(' + n + ')', colWidth));
  console.log(str);
}

header();
console.log('-- strict plain object --');
test(1, {});
test(2, { foo: 'bar' });
test(3, Object.create(Object.prototype));

console.log('-- wider plain object --');
test(4, Object.create(null));
test(5, Object.create({}));

console.log('-- non plain object --');
test(6, null);
test(7, true);
test(8, 0);
test(9, 123);
test(10, 'abc');
test(11, new Date(0));
test(12, new Number(123));
test(13, new String('abc'));
test(14, []);
test(15, ['foo', 'bar']);
test(16, new Array());
//test(17, Symbol('foo'));
test(18, function() {});
test(19, function Foo() {});
test(20, new function() {});
test(21, new function Bar() {});

console.log('-- by JSON.parse --');
test(22, JSON.parse('{}'));
test(23, JSON.parse('{"foo":"bar"}'));
test(24, JSON.parse('{"hasOwnProperty":"bar"}'));

test(25, JSON.parse('{"__proto__":{}}'));
test(26, JSON.parse('{"__proto__":{"polluted":1}}'));
test(27, JSON.parse('{"__proto__":{"__proto__":{}}}'));
test(28, JSON.parse('{"__proto__":{"__proto__":{"polluted":1}}}'));
test(29, JSON.parse('{"__proto__":null}'));

test(30, JSON.parse('{"constructor":{"prototype":{}}}'));
test(31, JSON.parse('{"constructor":{"prototype":{"polluted":1}}}'));
test(32, JSON.parse('{"constructor":{"prototype":{"__proto__":{}}}}'));
test(33, JSON.parse('{"constructor":{"prototype":{"constructor":{"prototype":{"polluted":1}}}}}'));
test(34, JSON.parse('{"constructor":{"prototype":null}}'));

console.log('-- fiddle .__proto__ and .constructor')
var a = {};
a.constructor = null;
test(35, a);

a = {};
a.__proto__ = null;
test(36, a);

a = {};
a.__proto__.constructor = null;
test(37, a);
@sttk
Copy link
Author

sttk commented Mar 11, 2021

% node
Welcome to Node.js v15.5.0.
Type ".help" for more information.
> function A() {}
undefined
> var a = new A();
undefined
> a
A {}
> a instanceof A
true
> a.constructor = Object
[Function: Object]
> a
{ constructor: [Function: Object] }
> a instanceof A
true
> a.__proto__ = Object.prototype
[Object: null prototype] {}
> a
{ constructor: [Function: Object] }
> a instanceof A
false
> a = new A();
A {}
> a.__proto__ = Object.prototype
[Object: null prototype] {}
> a instanceof A
false
>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment