So I have a simple isPlainObject
method that I use to test for JavaScript object literals:
var isPlainObject = function (obj) {
return typeof obj === "object" && {}.toString.call(obj) === "[object Object]";
};
Now I have a plain object:
var obj = {'one': 1, 'two': 2, 'three': 3};
When I run it through the isPlainObject(obj)
function it works as expected and returns true
. My question arrives from adding a property to the object's prototype:
obj.constructor.prototype.four = 4;
Now when I run isPlainObject(obj)
on obj
it returns false
. typeof obj
returns object
in both instances. The toString
returns [object Number]
in the second instance after I've added a property to the prototype.
What exactly has happened to change obj
? What's going on?
EDIT: This only happens when tested within the confines of a QUnit function call.
test("each", function() {
_.each([1, 2, 3], function(i,v) {
equal(v, i + 1, 'each iterator provided index and value from array');
});
var obj = {'one': 1, 'two': 2, 'three': 3};
console.log(_.isPlainObject(obj)); // => true
obj.constructor.prototype.four = 4;
console.log(_.isPlainObject(obj)); // => false
});
EDIT:
This is the console.log I get when logging the arguments
array-like object within isPlainObject
.
Looking at the log would seem to indicate the array now has two arguments. But the length still reads 1
.
true
for me...? – Fongtypeof obj
and{}.toString.call(obj)
return for you? – Cumquattypeof obj
now? What does{}.toString.call(obj)
return now?) – PavlaObject.prototype
! (whichobj.constructor.prototype
is). Not sure how that affects your function, though. – UndirectedisPlainObject
calls returntrue
. jsfiddle.net/mXHKE – Melgartypeof obj
returns"object
" in both instances. ThetoString
returns[object Number]
in the second instance after I've added a property to the prototype. – RasiaObject.prototype
is causing errors. – Melgartrue
andtrue
). Is my fiddle setting_.isPLainObject
the same way your code does? You never specify exactly how you do that in your code. – NicotianaisPlainObject
method differs in that in my library it calls a method that builds an arguments object. See: boilerjs.com/boiler.js ... search forisPlainObject =
. – Rasia_.__args()
function, which is incorrectly reporting the arguments after the prototype manipulation. (In my fiddle, you'll see that the first time you get{ obj: {'one':1...} }
and the second time you get{obj: 4}
.) – Nicotianaargs()
method to detect an argument of a different type once this modification has been made. Any clue as to what gives? – Rasialength
property of the arguments object being1
when you iterate over it (the arguments array-like object) in in the second instance after the prototype has been modified, two iterations are encountered. One over the object. And one over the added property. ... WTF? I thoughtfor in
loops weren't supposed to iterate over object literals' prototypes? – RasiaObject
now has a bonus enumerable value, which cause and extra loop to happen onfor (var d in types)
when looping over the properties of thetypes
argument to__args
. It happens again onfor (var a in args)
and anywhere you usefor..in
. – Nicotianaobject.hasOwnProperty(prop)
(e.g.types.hasOwnProperty(d)
) for each loop or, better still, never modify Object.prototype!(!!) (Seriously! This is why you don't!) Voting to close as too localized, although it may be a duplicate of another "modifiedObject.prototype
, nowfor..in
doesn't work" question. – Nicotiana