4

I know this sounds silly, but now my curiosity has me stuck on this idea. Is it possible to declare a collection of key/value pairs, like var collection = {a:"1", b:"2"} and then have a third pair saying c: "3" + b.value?

prasanth
  • 22,145
  • 4
  • 29
  • 53
Andrew
  • 43
  • 3

5 Answers5

6

First way, using a property getter.

Please note c is a property as b and c.

var collection = {
  a: 1,
  b: 2,
  get c() {
    return this.a + this.b;
  }
};

console.log(collection.a); // 1
console.log(collection.b); // 2
console.log(collection.c); // 3

Second way, using concise method in ES6 or a more "classical" function declaration in ES5.

Please note c is now a function.

let collection = {
  a: 1,
  b: 2,
  c() {
    return this.a + this.b;
  }
};

console.log(collection.a); // 1
console.log(collection.b); // 2
console.log(collection.c()); // 3 called as a function

Third way, using a dedicated function for initialization.

This is useful if you have a more complex initialization, maybe on more properties, and could work similarly as a "constructor".

var collection = {
  a: 1,
  b: 2,
  c: 3,
  init: function() {
    this.c = this.a + this.b;
  }
};
collection.init();
console.log(collection.a); // 1
console.log(collection.b); // 2
console.log(collection.c); // 3

Forth way, directly on c property.

var collection = {
  a: 1,
  b: 2,
  c: undefined
};
collection.c = collection.a + collection.b;
console.log(collection.a); // 1
console.log(collection.b); // 2
console.log(collection.c); // 3

Regarding specifically your question, I would solve it using a getter and appending value "3" in front of b (please note result is of type string), example:

var collection = {
  a: 1,
  b: 2,
  get c() {
    return '3' + this.b;
  }
};
console.log(collection.a); //1
console.log(collection.b); //2
console.log(collection.c); //"32"
console.log(typeof collection.c); // string
GibboK
  • 71,848
  • 143
  • 435
  • 658
3

You can't do anything like this:

var collection = {
 a: 1,
 b: 2,
 c: a + b
}

But you can do this:

var collection = {
 a: 1,
 b: 2
}

collection.c = collection.a + collection.b;
Martha
  • 178
  • 1
  • 11
2

Yes, you can store functions in JavaScript objects:

var collection = {a:"1", b:"2"}
var newObj = {c: function(){
      return "3" + collection.b
    }
  }
console.log( newObj.c() );
mb21
  • 34,845
  • 8
  • 116
  • 142
0

c: "3" + b Its not performing the same object .so You need insert the key and value in to the object .declare the c value from outer of the object

var collection = {
  a: "1",
  b: "2",
}
collection['c'] = '3'+collection.b

console.log(collection)
prasanth
  • 22,145
  • 4
  • 29
  • 53
  • it can also work without using bracket notation `collection['c'] = ...` example: `collection.c = '3'+collection.b` – GibboK May 02 '17 at 14:14
  • 1
    yes.i know both are same .Declaration of the method only different – prasanth May 02 '17 at 14:19
  • Yes, I think bracket notation is more appropriate when creating "dynamic" property name on an object. But I think it is good you mentioned as could be instructive for the readers. Thanks :) – GibboK May 02 '17 at 14:22
0

You can't really pass "references" that get evaluated like that. Expressions are evaluated before assignment.

let obj = {
    a: 1,
    b: 2
};

obj.c = 3 + obj.b;

console.log(obj.c);
> 5

obj.b = 10;
console.log(obj.c);
> 5

If you really wanted to do something like that, you can create a new type of object with a form of lazy evaluation.

function Lazy(value) {
  this.value = value;
}

Lazy.prototype.valueOf = function() {
  if (typeof this.value === 'function') {
    return this.value();
  }
  return this.value;
};

Lazy.prototype.toString = function() {
  return this.valueOf() + "";
}

/* Then you can do this.. */
let obj = {
  a: new Lazy(1),
  b: new Lazy(2)
};

/* We have to defer the evaluation of the expression. */
obj.c = new Lazy(() => 3 + obj.b);

console.log(obj.c.toString());

obj.b = 10;
console.log(obj.c.toString());
noahnu
  • 3,479
  • 2
  • 18
  • 40