main.js (3036B)
1 /** 2 * @license Apache-2.0 3 * 4 * Copyright (c) 2018 The Stdlib Authors. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 'use strict'; 20 21 // MODULES // 22 23 var isObject = require( './../../is-object' ); 24 var isFunction = require( './../../is-function' ); 25 var getPrototypeOf = require( '@stdlib/utils/get-prototype-of' ); 26 var hasOwnProp = require( './../../has-own-property' ); 27 var nativeClass = require( '@stdlib/utils/native-class' ); 28 29 30 // VARIABLES // 31 32 var objectPrototype = Object.prototype; 33 34 35 // FUNCTIONS // 36 37 /** 38 * Tests that an object only has own properties. 39 * 40 * @private 41 * @param {Object} obj - value to test 42 * @returns {boolean} boolean indicating if an object only has own properties 43 */ 44 function ownProps( obj ) { 45 var key; 46 47 // NOTE: possibility of perf boost if key enumeration order is known (see http://stackoverflow.com/questions/18531624/isplainobject-thing). 48 for ( key in obj ) { 49 if ( !hasOwnProp( obj, key ) ) { 50 return false; 51 } 52 } 53 return true; 54 } 55 56 57 // MAIN // 58 59 /** 60 * Tests if a value is a plain object. 61 * 62 * @param {*} value - value to test 63 * @returns {boolean} boolean indicating whether value is a plain object 64 * 65 * @example 66 * var bool = isPlainObject( {} ); 67 * // returns true 68 * 69 * @example 70 * var bool = isPlainObject( null ); 71 * // returns false 72 */ 73 function isPlainObject( value ) { 74 var proto; 75 76 // Screen for obvious non-objects... 77 if ( !isObject( value ) ) { 78 return false; 79 } 80 // Objects with no prototype (e.g., `Object.create( null )`) are plain... 81 proto = getPrototypeOf( value ); 82 if ( !proto ) { 83 return true; 84 } 85 // Objects having a prototype are plain if and only if they are constructed with a global `Object` function and the prototype points to the prototype of a plain object... 86 return ( 87 // Cannot have own `constructor` property: 88 !hasOwnProp( value, 'constructor' ) && 89 90 // Prototype `constructor` property must be a function (see also https://bugs.jquery.com/ticket/9897 and http://stackoverflow.com/questions/18531624/isplainobject-thing): 91 hasOwnProp( proto, 'constructor' ) && 92 isFunction( proto.constructor ) && 93 nativeClass( proto.constructor ) === '[object Function]' && 94 95 // Test for object-specific method: 96 hasOwnProp( proto, 'isPrototypeOf' ) && 97 isFunction( proto.isPrototypeOf ) && 98 99 ( 100 // Test if the prototype matches the global `Object` prototype (same realm): 101 proto === objectPrototype || 102 103 // Test that all properties are own properties (cross-realm; *most* likely a plain object): 104 ownProps( value ) 105 ) 106 ); 107 } 108 109 110 // EXPORTS // 111 112 module.exports = isPlainObject;