Shared array between class instances in node.js

I have a weird problem in node.js:

person.js

var Person;

Person = (function() {
  Person.prototype.name = "";
  Person.prototype.friends = [];

  function Person(name) {
    if (name) {
      this.name = name;
    }
  }

  Person.prototype.sayHello = function() {
    return console.log("Hello, my name is " + this.name + " and I have " + this.friends.length + " friends");
  };

  Person.prototype.addFriend = function(name) {
    this.friends.push(name);
  };

  return Person;

})();

module.exports = Person; 

factory.js

var Person = require('./Person.js');

module.exports = function(name) {
  return new Person(name);
};

index.js

factory = require('./factory');

tyrion = factory("Tyrion");
tyrion.addFriend("Bronn");
tyrion.sayHello();
daenerys = factory("Daenerys");
daenerys.addFriend("Illyrio");
daenerys.addFriend("Daario");
daenerys.addFriend("Barristan");
daenerys.sayHello();
tyrion.sayHello();

Actual output

Hello, my name is Tyrion and I have 1 friends
Hello, my name is Daenerys and I have 4 friends
Hello, my name is Tyrion and I have 4 friends

Expected Result

Hello, my name is Tyrion and I have 1 friends
Hello, my name is Daenerys and I have 3 friends
Hello, my name is Tyrion and I have 1 friends

Why adding an item to one instance adds it to both? It looks like the array is friend"split" between instances. How to prevent this?

+4
source share
4 answers

Line

Person.prototype.friends = [];

Adds the friends property to the Person prototype, which makes it common to all new objects created using the Person constructor. So, if you want each object to have its own friends, you need to add the friends property to a separate object.

, , - , :

function Person(name) {
    // friends is a property of this, the new instance object.
    this.friends = [];
    if (name) {
        this.name = name;
    }
}

Javascript OO ( , ). - , , . "sayHello" , , Person "Hello". , : " , Person".

, Javascript , . 1, , , , . 2, , . , " " 1, , , , , , .

, . , . , , , .

Javascript , . , , , "", "", Javascript . , , - , . , .

Javascript , " ", , . . tyrion sayHello, :

tyrion.sayHello()

Javascript tyrion , sayHello. , , , , , sayHello. , , , , , tyrion 'this' . javascript, :

function find_property(original_obj, property_name) {

    var found_prop = undefined;
    var current_obj = original_obj;

    // we keep searching until we either have a property or we run out of 
    // places to look.
    while(found_prop == undefined && current_obj != undefined) {
       // does the object we are looking at have it own property with that name?
       if ( obj.hasOwnProperty(property_name) ) {
           // yes, so we can set found_prop
           found_prop = obj[property_name];
       } else {
           // no, we have to look at the next prototype up the chain.
           current_obj = current_obj.__proto__;
       }
    }
    return found_prop;
}

var sayhello = find_property(tyrion, 'sayHello');
if (typeof sayhello == 'function') {
   sayhello.call(tyrion);
}

, . , - , , , , - . , , "" .

, , , "", javascript "", , .

, , . , Douglas Crockford "Javascript: The Good Parts" - .

+1

Person.prototype.name = "";
Person.prototype.friends = [];

:

this.name = name;
this.friends = [];

friends.

+3

, Person, . Node.js.

person.js

function Person(name) {
  this.name = name || "";
  this.friends = [];
}

Person.prototype.sayHello = function sayHello() {
  console.log("Hello, my name is %s and I have %d friends", this.name, this.friends.length);
};

Person.prototype.addFriend = function addFriend(name) {
  this.friends.push(name);
};

// factory
Person.create = function create(name) {
  return new Person(name);
};

module.exports = Person;

. factory person.js Person.create. , . .

index.js

// don't forget your `var` keyword
var factory = require('./person').create;

tyrion = factory("Tyrion");
tyrion.addFriend("Bronn");
tyrion.sayHello();
// Hello, my name is Tyrion and I have 1 friends

daenerys = factory("Daenerys");
daenerys.addFriend("Illyrio");
daenerys.addFriend("Daario");
daenerys.addFriend("Barristan");
daenerys.sayHello();
// Hello, my name is Daenerys and I have 3 friends

tyrion.sayHello();
// Hello, my name is Tyrion and I have 1 friends
+2

, .

  Person.prototype.friends = []; 

, , , Person .

Instead, you want to assign a new array to each person:

function Person(name) {
  if (name) {
    this.name = name;
  }
  this.friends = []; // create a new array in the constructor
}

Generally speaking, the prototype is dedicated to sharing functions and properties in JavaScript.

+1
source

All Articles