0

We have the function

function Buffer(initValue) {
    this.append(initValue);
}
Buffer.prototype = {
    items: [],
    append: function(str) {
        this.items[this.items.length] = str instanceof Buffer ?       str.toString() : str;
    return this;
},
    toString: function() {
        return this.items.join("");
    }
};
console.log(new Buffer("one").append(new Buffer("two")).toString());

but suddenly it logs "onetwoonetwo" - beyond all expectations... Why?

Justinas
  • 41,402
  • 5
  • 66
  • 96
designeng
  • 39
  • 4
  • 4
    Your `Buffer.prototype.items` is shared across all instances of `Buffer`. – Alexey Ten Feb 26 '15 at 09:11
  • the Buffer.prototype.append method is called 3 times: new Buffer("one"), new Buffer("two") and .append(newBuffer("two")). Third time, new Buffer("two") already contains items "one" and "two" so toString will return "onetwo". Prepending "one" and "two" from first 2 calls you will get "onetwoonetwo" – Valentin S. Feb 26 '15 at 09:12
  • prototype members are shared as explained by others. What that means and how to use it is explained here: http://stackoverflow.com/a/16063711/1641941 hope it helps because it is kind of complicated but once you understand it should be easy. – HMR Feb 26 '15 at 10:39

3 Answers3

1

Several answers explain why this happens in your specific instance.

I suspect that what you really want is to let items be local to each instance of Buffer instead of shared via the prototype. This is simply done by declaring items = []; in the constructor:

function Buffer(initValue) {
    this.items = []; // This line replaces `items: [],` in the original code.
    this.append(initValue);
}
Buffer.prototype = {
    append: function(str) {
        this.items[this.items.length] = str instanceof Buffer ? str.toString() : str;
        return this;
    },
    toString: function() {
        return this.items.join("");
    }
};
jensgram
  • 31,109
  • 6
  • 81
  • 98
0

This is because you applied append multiple time.

Since you are using prototype, your item array is shared by your two instance of Buffer.

You should have this: http://jsbin.com/luhoki/3/watch?html,css,js,output

function Buffer(initValue) {
    this.append(initValue);
}
Buffer.prototype = {
    items: [],
    append: function(str) {
        this.items[this.items.length] = str instanceof Buffer ?       str.toString() : str;
    return this;
},
    toString: function() {
        return this.items.join("");
    }
};
a = new Buffer("one")
a.append("two")
console.log(a.toString());
// result: "onetwo"
Yves Lange
  • 3,914
  • 3
  • 21
  • 33
0

Here is why you get such a behavior.

When following line is encountered

console.log(new Buffer("one").append(new Buffer("two")).toString());

let's breakdown it in smaller for our convenience.

  1. browser evaluates new Buffer("one").

  2. then browser evaluates new Buffer("two")

  3. finally above two results are evalueated like result1.append(result2).

So when first gets evaluated Item array will have one. Then after second will be evaluated then item array will have two element "one" & "two" since it is shared array.

Consider first result as result1 and second result as result2. Now when third step is executed it will join result1's item array which is having two elements and result2's item array which is same as result1's so you get four element in log as onetwoonetwo.

Jenish Rabadiya
  • 6,708
  • 6
  • 33
  • 62