10

Is it possible for any arbitrary object to obtain a reference to an accessor function that would act exactly as [] operator?

Something like the following?:

function get(x) { return this[x] }

So that if I had an object foo instead of doing foo['bar'] I could call foo.get('bar')

10
  • 2
    What problem are you trying to solve here? The question itself, as asked, seems pretty weird. What's wrong with [ ]? Commented Dec 8, 2013 at 17:04
  • Yes it is possible, when written correctly. Commented Dec 8, 2013 at 17:04
  • Here is a working sample: jsfiddle.net/RS6ET Commented Dec 8, 2013 at 17:04
  • 3
    The thing is that if you have a reference to an object, and you have a property name, then the [ ] operator already allows you to access the property value. Yes, you can write a function to use the operator, but how does that make anything less complicated? Commented Dec 8, 2013 at 17:06
  • 1
    @Pointy, having [] as a function would be useful for writing programs in functional paradigm (using it as a higher order function to compose other functions, doing partial function applications and so on). Commented Dec 8, 2013 at 17:11

4 Answers 4

5

You can write a function:

function get( propertyName ) {
  return this[ propertyName ];
}

Then you can bind that function to some particular object:

var myObject = { /* ... */ }; // that looks like a little face, kind-of
var getter = get.bind(myObject);

Now, why is that interesting? The only reason I can think of is that it gives you an object (the bound version of the function) that you can pass to other code, allowing that code to get property values but not update them. I suppose that's kind-of useful, though I can't say I've found myself wanting it.

You can add a "get" function to the Object prototype, but if you do so I'd do it in such a way as to make it non-enumerable. Otherwise, you may have weird behavior of for ... in loops:

Object.defineProperty(Object.prototype, "get", {
  value: function( key ) { return this[key]; }
});

Another interesting thing to contemplate if you're doing functional-style programming is the semantics of your "get" function. The sample I did above makes it possible to create a function to get a particular property of an object too, in addition to being a getter for any property:

var getSomeObjectName = get.bind( someObject, "name" );

Now all that the function "getSomeObjectName" will do is fetch the "name" property value.

It might also be interesting to consider higher-order functions. A really useful notion is that of a "pluck" function, to pull a particular attribute from an object. It's kind-of like "get" but I'd write it differently:

function pluck(propertyName, object) {
  object = object || this;
  return object[propertyName];
}

Now I can make a getter as before, pretty much the same way:

var getter = pluck.bind( someObject );

Alternatively, I can make a "plucker" for a particular property name that will get that property from any object:

var getName = pluck.bind(null, "name");

Now I can call:

getName( someOtherObject )

and that's effectively like calling

pluck( "name", someOtherObject )

because I've "pre-loaded" the first parameter ("name") in the "getName" function. That becomes really useful with things like the .map() facility:

var myArray = [
  { name: "Thomas", type: "tank engine" }
, { name: "Flipper", type: "dolphin" }
, { name: "Rocinante", type: "horse" }
// ...
];

var allNames = myArray.map(pluck.bind(null, "name"));

You can of course write a wrapper function to hide the somewhat ugly call to .bind:

function plucker( name ) {
  return pluck.bind(null, name);
}

allNames = myArray.map( plucker("name") );
Sign up to request clarification or add additional context in comments.

3 Comments

I didn't know about bind. Is it a ECMA 5 standard? Although this solution is not exactly what I was looking for, but since there is no such native function this solution seems to be the best one. I like it better than altering Object prototype as it doesn't pollute the global namespace and I have a control on this accessor function visibility.
@wajda yes, .bind() is a fairly new standard method on the Function prototype. It's available in all new browsers, and there are versions for older browsers available. Altering built-in object prototypes is itself a controversial practice. If you do it, you should make sure that the added function is made non-enumerable. (I'll update my answer.)
Re the reasons, yes, I need to pass []-ish function to another function to read my object properties in a uniform way.
3

Yes, by prototyping

var foo = {bar : 3};

Object.prototype.getz = function(what) {
    return this[what];
}

var value = foo.getz('bar'); // outputs 3

FIDDLE

No idea why you would need it ?

3 Comments

I know how to do it via prototype. I was wondering if there is already such function, so I don't need altering the Object prototype. The biggest problem with this approach is possible interference with other libraries, since changes in Object prototype is visible everywhere.
What a strange comment, if you knew how to do it, why did you ask, and what are the chances another library is using Object.getz, or that it would ever be an issue, I'd say close to nill. And no, there's no such function available natively, that's what dot and bracket notation is for.
@adeneo I don't think it is a strange comment. Altering Object.prototype is widely considered bad practice.
0

You can.

http://jsfiddle.net/sdaDK/

var foo = {
    bar: 'foo2',
    get: function (a) { return this[a]; }
}

alert(foo.get('bar'));

Comments

0

If you need this function only for one object then you can do

var myObject = {
    x: 'anything',
    get: function (x) { return this[x]; }
}
alert(myObject.get('x'));

Or if you need this for all object you need to extend the prototype of Object class

var myObject = {
    x: 'anything'
}
Object.prototype.get = function(x) {
    return this[x];
}
var value = myObject.get('x');

In javascript prototype is the way of extending any property.

Comments

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.