5

I'm seeing the following behaviour, in the middle of a javascript debug session:

o // function (a1, a2, a3) {  return a1 + a2 + a3; }

typeof(o) //'function'

for (var n in o) { console.log(n); } //<a list of properties>

Object.keys(o) //TypeError: not an object

Object.prototype.toString.call(o); //"[object Function]"

which makes me wonder - can a function, ever not be object?

[running on Chrome 29, on a mac]


Note that this is in the middle of a very complex debug session. I don't exactly know where 'o' is coming from, or how it was created. Also, I've so far been unable to reproduce this issue with a simple test case. A simple setup works as expected:

var t = function() { return true; } //undefined
t.a = "aa" //"aa"
Object.keys(t) //["a"]
19
  • 4
    Please reconstruct where o was coming from - maybe it is a buggy host object. The question is useless however if this is not reproducable. Commented Sep 17, 2013 at 18:45
  • 3
    You were not using a ES5 shim that overwrites Object.keys despite its existence and that does the type check wrong (with typeof)? Commented Sep 17, 2013 at 18:47
  • 2
    "Clearly, sometimes, functions are not objects..." No that's the part that's not clear without a reproduceable test Commented Sep 17, 2013 at 18:48
  • 3
    ahahahaha. It's a custom implementation of "Object.keys"! I'm going to go smack my head into some bricks. Commented Sep 17, 2013 at 19:31
  • 3
    @Bergi deserves credit for anticipating an overwrite of Object.keys a long time ago. Commented Sep 17, 2013 at 19:45

2 Answers 2

4

When you see something like this, you might try:

console.log(Object.keys)

or equivalent.

(if you can find the original implementation of keys for your browser, to compare and make sure it's identical to what you're seeing)

(read the comments on the question for more ideas of things to look at if seeing this kind of problem)


False alarm. Functions are always objects, and the people at Chrome know how to make virtual machines.

I ran

grep -r "Object.defineProperty(" *

grep -r "Object.defineProperties(" *

and found a place where Object.keys is being overwritten, with a buggy function.

The related code was being loaded dynamically, so I didn't get to see it explicitly get loaded in the browser.

Sign up to request clarification or add additional context in comments.

4 Comments

Good job. I suggest you leave this question with all the answers/comments. There is a lot of interesting knowledge here.
Whatever code you have that dynamically loaded a broken overwrite of Object.keys needs to be removed from your code base, followed by an email to the developer suggesting that they apply for a job at their local car wash..
@user2736012 it's on my todo list... One thing at a time :P
...but +1 for drilling down to the issue. In retrospect, a console.log(Object.keys) would have been a good suggestion.
2

The first step performed by the Object.keys algorithm is:

  1. If the Type(O) is not Object, throw a TypeError exception.

Since you're getting such an error, I believe your object must be a host object, as Bergi commented above. Still, it's strange that Object.prototype.toString.call(o) is giving "[object Function]", since host objects are not allowed to use "Function" as their [[Class]] property value.

* For the meaning of Type(x), see the last sentence from Section 8 of the spec.

16 Comments

@user2736012 I'm not saying it can't work on a host object (it does work on document and window in Chrome, for example). And my first version was incorrect, the spec says the type must be Object, or an error will be thrown.
@freakish No, because 15.2.4.2 step 4 uses [[Class]], but section 8.6.2 says: The value of the [[Class]] internal property of a host object may be any String value except one of "Arguments", "Array", "Boolean", "Date", "Error", "Function", "JSON", "Math", "Number", "Object", "RegExp", and "String". Thus, shouldn't [object Function] be not spec-compliant for a host object?
@bfavaretto There's even more: every time they talk about host/native object it is clearly stated so, for example: assume O is a native ECMAScript object. And here they even distinguish the same condition: ecma-international.org/ecma-262/5.1/#sec-15.2.2.1 I'm sorry, but this is an overinterpretation of ECMAScript and I have to give -1.
It doesn't even need to inherit from Object.prototype. This will work: Object.keys(Object.create(null));
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.