0

I've found that sometimes I'll have a var with a bunch of methods and properties that I can't seem to locate somehow, event with Object.keys and Object.getOwnPropertyNames on both the var and the prototype.

Here's an example: I'm playing with RethinkDB and I want to override the run function. However, I don't know where it lives -- what object prototype I need to change, etc. In fact, I can't find any way of finding it with the functions I specified above:

> r.db('test').tableCreate('authors').run
[Function]
> r.db('test').tableCreate('authors')
{ [Function]
  args: 
   [ { [Function] args: [Object], optargs: {} },
     { [Function] data: 'authors' } ],
  optargs: {} }
> r.db('test').tableCreate('authors').prototype
{}
> r.db('test').tableCreate('authors').run
[Function]
> Object.keys(r.db('test').tableCreate('authors'))
[ 'args', 'optargs' ]
> typeof r.db('test').tableCreate('authors')
'function'
> Object.getOwnPropertyNames( r.db('test').tableCreate('authors') )
[ 'length',
  'name',
  'arguments',
  'caller',
  'prototype',
  'args',
  'optargs' ]
> Object.getOwnPropertyNames( r.db('test').tableCreate('authors').prototype )
[ 'constructor' ]

The run function never shows up... Any ideas?

EDIT:

I did some snooping in the source code. this is the method I want to wrap.

Then, you can following the inheritance chain from TermBase to Eq (RDBVal, RDBOp, Eq).

r.eq().run returns a function -- the function I want to wrap.

@T.J. Crowder's answer: findProps('run', r.eq()) prints out a bunch of stuff including:

I20150625-10:33:31.047(-7)? Props for run[[Proto]][[Proto]][[Proto]][[Proto]]
I20150625-10:33:31.047(-7)? 0: constructor
I20150625-10:33:31.047(-7)? 1: showRunWarning
I20150625-10:33:31.047(-7)? 2: run

So thats it!

8
  • 1
    You don't need to know who first defined it to override it, that's the beauty of inheritance. If you provide one, as the last one, it wins. Commented Jun 25, 2015 at 17:04
  • Agreed! I'd like to something like SomeObj.prototype.run = //.... And I have no idea what SomeObj is. Its returned by tableCreate though... Commented Jun 25, 2015 at 17:16
  • 1
    You really shouldn't modify someone else's prototype. It's generally safer to wrap the object with your own that provides the helpers, rather than touching an external object. Commented Jun 25, 2015 at 17:18
  • but then I have to have a method for all this chaining... right? As in, one method in my object for every method in the wrapped object... Commented Jun 25, 2015 at 17:20
  • run sounds like it should be the final link in a chain, though, so you might just be able to define a helper like function runWithLogs(obj) { log('pre'); var r = obj.run(); log('post', r); return r; } Commented Jun 25, 2015 at 17:23

1 Answer 1

2

Object.keys gives you that object's enumerable property names. Many properties are not enumerable.

As ssube said, you don't have to know at what level a property is defined to override it. But if you want to know, you can in ES5 and later, via Object.getOwnPropertyNames, which includes non-enumerable properties of an object, and Object.getPrototypeOf, which lets you traverse up the object's prototype chain.

Example:

function findProps(objname, obj) {
  var p;
  
  snippet.log("Props for " + objname);
  Object.getOwnPropertyNames(obj).forEach(function(name, index) {
    snippet.log(index + ": " + name);
  });
  p = Object.getPrototypeOf(obj);
  if (p != null) {
    findProps(objname + "[[Proto]]", p);
  }
}

var a = {};
Object.defineProperty(a, "foo", {      // A non-enumerable property
  value: "bar"
});

var b = Object.create(a);              // b's prototype is a
b.answer= 42;                          // An enumerable property
Object.defineProperty(a, "question", { // A non-enumerable property
  value: "Life, the Universe, and Everything"
});


var c = Object.create(b);              // c's prototype is b
c.last = "property";

findProps("c", c);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

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

2 Comments

Object.getPrototypeOf does yeild some new results, but I still havent found the run function!
@Chet: "I dont actually know the object name" Objects don't have names. Variables have names, and variables can refer to objects. Crucially, multiple variables can refer to the same object. "I still havent found the run function" If you're not finding run using findProps above, then the object you're using it on (or the root of the prototype chain for that object) is a host-provide object. They're allowed to break the JavaScript rules. Depending on how it's breaking them, you may not be able to wrap run on the object (you can pass the object into a function, though).

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.