1

I am declaring a function that, when given a string as an argument, returns an object where keys are the words in the string. Values are the # of occurrences of that word in the string.

When I run the below code, I get {}.

function countWords(string) {
  var result = {};
  var words = string.split(' ');
  for (var i = 0; i < words.length; i++) {
    var currentElement = words[i];
    var prop = result[currentElement];
    if(prop) {
        prop += 1;
    } else {
        prop = 1;
    }
  }
  return result;
}

console.log(countWords('hello hello')); // => {'hello': 2}

However, replacing prop = 1 with result[CurrentElement] = 1 returns the expected answer.

Why is it wrong to use prop = 1 in this context?

Qwertiy
  • 19,681
  • 15
  • 61
  • 128
Reign
  • 65
  • 1
  • 6
  • 2
    `prop` is just a variable. If you assign it to some property, then write `prop = 1`, you just redefine `prop` to be `1`. You don’t actually touch the property itself. – Sebastian Simon Apr 17 '17 at 15:16
  • Possible duplicate of [Are variables/objects passed by value and why can't I change object's property with variable in javascript?](http://stackoverflow.com/questions/36865168/are-variables-objects-passed-by-value-and-why-cant-i-change-objects-property-w) – Sebastian Simon Apr 17 '17 at 15:23

5 Answers5

3

var prop = result[currentElement]; This makes a copy of the value in result[currentElement] into prop, then you add one but never put it back into the array. The assignment is by value, not by reference.

Doqnach
  • 372
  • 1
  • 8
1

You need to use the reference to the object for checking and incrementing.

result[currentElement]
^^                      object
      ^^^^^^^^^^^^^^^^  property of object

If you just get the value of it, you get a primitive value and not the wanted reference to the object.

value = result[currentElement] // undefined in the first call
                               //         1 in the second call

but you do not have a reference to result anymore.

function countWords(string) {
  var result = {};
  var words = string.split(' ');
  for (var i = 0; i < words.length; i++) {
    var currentElement = words[i];
    if (result[currentElement]) {
      result[currentElement] += 1;
    } else {
      result[currentElement] = 1;
    }
  }
  return result;
}

console.log(countWords('hello hello')); // => {'hello': 2}
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

In this line:

var prop = result[currentElement];

you are copying the value of result[currentElement] (apparently a number) and then increment the copy, thus th original value (result[currentElement]) remains the same.

ibrahim mahrir
  • 31,174
  • 5
  • 48
  • 73
0

Because variables are almost never linked by reference with anything else.

There are only 2 cases when it goes in other way:

  1. arguments in nonstrict mode.

    function f(a) {
      console.log(a, arguments[0]);
      a = 10;
      console.log(a, arguments[0]);
    }
    
    function g(a) {
      'use strict';
      console.log(a, arguments[0]);
      a = 10;
      console.log(a, arguments[0]);
    }
    
    f(7);
    g(7);
  2. Left side of assignment including decomposition.

    var a = 8, b = 10;
    console.log(a, b);
    [a, b] = [b, a];
    console.log(a, b);
    
    var x = [0, 1, 2];
    console.log(x.join(" "));
    [x[1], x[0], x[2]] = x;
    console.log(x.join(" "));
Qwertiy
  • 19,681
  • 15
  • 61
  • 128
0

you need to add it in the result like this :

<script>
    function countWords(string) {
  var result = {};
  var words = string.split(' ');
  for (var i = 0; i < words.length; i++) {
    var currentElement = words[i];
    var prop = result[currentElement];
    if(prop) {
        prop += 1;
    } else {
        prop = 1;
    }
    result[currentElement]=prop;
  }
  return result;
}

console.log(countWords('hello hello test khalil'));
</script>