-
-
Save rkatic/158651 to your computer and use it in GitHub Desktop.
isObjectLiteral STRICT
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv="content-type" content="text/html;charset=utf-8"/> | |
<!-- Online here: http://ejohn.org/files/bugs/isObjectLiteral/ --> | |
<title>isObjectLiteral</title> | |
<style> | |
li { background: green; } li.FAIL { background: red; } | |
iframe { display: none; } | |
</style> | |
</head> | |
<body> | |
<ul id="results"></ul> | |
<script> | |
if ( !Object.getPrototypeOf && ({}).__proto__ === Object.prototype ) { | |
Object.getPrototypeOf = function(obj) { | |
return obj.__proto__; | |
}; | |
} | |
var isObjectLiteral = ( Object.getPrototypeOf ) ? | |
function(obj) { | |
if ( typeof obj !== "object" ) { | |
return false; | |
} | |
var proto = Object.getPrototypeOf(obj); | |
return !(proto && Object.getPrototypeOf(proto)); | |
} : | |
(function(){ | |
var OP = Object.prototype; | |
function getProto(obj) { | |
var c = obj.constructor; | |
if ( OP.hasOwnProperty.call(obj, "constructor") ) { | |
var t = c; | |
if ( !(delete obj.constructor) ) { | |
return null; | |
} | |
c = obj.constructor; | |
obj.constructor = t; | |
} | |
return c ? c.prototype : null; | |
} | |
return function(obj) { | |
if ( OP.toString.call(obj) !== "[object Object]" ) { | |
return false; | |
} | |
var proto = getProto(obj), | |
hasProp = OP.hasOwnProperty; | |
if ( !proto ) { | |
return true; | |
} | |
if ( !hasProp.call(proto, "hasOwnProperty") || getProto(proto) ) { | |
return false | |
} | |
for ( var i in obj ) { | |
if ( !hasProp.call(obj, i) && !(i in proto) ) { | |
return false; | |
} | |
} | |
return true; | |
}; | |
})(); | |
// Function serialization is not permitted | |
// Does not work across all browsers | |
Function.prototype.toString = function(){}; | |
// The use case that we want to match | |
log("{}", {}, true); | |
log("{constructor: 1}", {constructor: 1}, true); | |
// Instantiated objects shouldn't be matched | |
log("new Date", new Date, false); | |
var fn = function(){}; | |
log("new fn (with no prototype changes)", new fn, false); | |
// Makes the function a little more realistic | |
// (and harder to detect, incidentally) | |
fn.prototype = {someMethod: function(){}}; | |
// Functions shouldn't be matched | |
log("fn", fn, false); | |
// Again, instantiated objects shouldn't be matched | |
log("new fn", new fn, false); | |
/* Note: | |
* The restriction against instantiated functions is | |
* due to the fact that this method will be used for | |
* deep-cloning an object. Instantiated objects will | |
* just have their reference copied over, whereas | |
* plain objects will need to be completely cloned. | |
*/ | |
var iframe = document.createElement("iframe"); | |
document.body.appendChild(iframe); | |
var doc = iframe.contentDocument || iframe.contentWindow.document; | |
doc.open(); | |
doc.write("<body onload='window.top.iframeDone(Object, Date);'>"); | |
doc.close(); | |
function iframeDone(otherObject, otherDate){ | |
// Objects from other windows should be matched | |
log("new otherObject", new otherObject, true); | |
log("new otherDate", new otherDate, false); | |
} | |
function log(msg, a, b) { | |
var pass = isObjectLiteral(a) === b ? "PASS" : "FAIL"; | |
document.getElementById("results").innerHTML += | |
"<li class='" + pass + "'>" + msg + "</li>"; | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment