I am extending cc.Node class in the following way:
var CardNode = cc.Node.extend(new function()
{
// MARK:
this.ctor = function(card)
{
this._super();
_card = card;
_spriteCard = new cc.Sprite(res.Card_png);
_spriteCard.setScale(cc.winSize.width / _spriteCard.width * 0.08);
this.addChild(_spriteCard, 1);
};
this.getCard = function()
{
return _card;
};
// MARK:
var _card;
var _spriteCard;
});
I created two instances of the CardNode class like the following way:
var cardNode1 = new CardNode(309);
cardNode1.setPosition(cc.winSize.width * 0.4, cc.winSize.height * 0.5);
this.addChild(cardNode1, 10);
var cardNode2 = new CardNode(410);
cardNode2.setPosition(cc.winSize.width * 0.6, cc.winSize.height * 0.5);
this.addChild(cardNode2, 10);
When I log the card value of the two CardNodes I get the same value (410):
cc.log("cardNode1: " + cardNode1.getCard()); // prints 410
cc.log("cardNode2: " + cardNode2.getCard()); // prints 410
It looks like the private variable _card is acting like a static variable shared across instances. What is the work around for this problem? I would like to keep the private variable private.
Try changing all instances of _card to this._card.
1 Like
Yes. The way the code is written in @mr746866’s original example should work fine, but scope in JS can be a bit of a pain, making them explicitly a property should fix that issue.
I understand that this would technically make _card not being hidden/private anymore, but that’s a sacrifice at least I’m willing to make in order to avoid headches.
On a side note, I prefer using this notation for defining objects:
var CardNode = cc.Node.extend({
_card: null,
_spriteCard: null
ctor: function(card) {
this._super();
this._card = card;
this._spriteCard = new cc.Sprite(res.Card_png);
this._spriteCard.setScale(cc.winSize.width / _spriteCard.width * 0.08);
this.addChild(this._spriteCard, 1);
},
getCard: function() {
return this._card;
}
});
I believe that if you use this notation you should be able to do something like this:
var CardNode = cc.Node.extend({
ctor: function(card) {
this._super();
var _card = card;
this.getCard: function() {
return _card;
};
var _spriteCard = new cc.Sprite(res.Card_png);
_spriteCard.setScale(cc.winSize.width / _spriteCard.width * 0.08);
this.addChild(_spriteCard, 1);
}
});
And there _card and _spriteCard should work as you expect instead of be shared among instances.
Please try them and let us know!
1 Like
@mr746866
@ZippoLag solutions should working as i’m using the first type solution when extending class.
If you want to access certain variables, then you have to declare it as
_card: null,
before the ctor then access it with
this._card
There might be a problem if you don’t declare _card as null, it may reference to same _card value. Last time have people faced this problem.
@ZippoLag Thank you. Your solution did the job.
@Zinitter Thank you for your suggestion, but changing _card to this.card would make it a public variable.
The Cocos2D library is written following the style that you mentioned, with _ preceding every variable and method that should work as private. You can access them publicly anyway.
@mr746866
I know you want private variables and methods but is there any problem if it is a public variable?
Because i think we can’t really code Javascript to behave like other programming languages do.
2 Likes
You can always use IIFE to declare (kind of) private variables in javascript. Something like this
var YourScene = (function() {
var privateVar1, privateVar2;
var scene = cc.Scene.extend({
ctor: function() {
this._super();
...
}
});
return scene;
})();
1 Like
@Zinitter Indeed.
I just pointed out how you can do it, but I prefer just going with the simpler approach most of the time. You just need to keep in mind that you should always treat _ prefixed properties as private so you don’t end up messing something up when you are compiling into native, but otherwise you should embrace JS’s crazyness and just go with it. In my day job I use .Net, so I’m used to having everything strongly-typed and strictly OOP, but that doesn’t mean I’ll try to apply such rules to JS, each language has its pros and cons 
@ZippoLag
Thanks for your info.
I don’t have strong basic in JS, so i’m not very clear about those things.
But do you mean put “_” prefix will turn a property into private in JS or just for our reference?
I know if we can follow those rules on coding any language, it can cause less issues, at least it make the compiler happy like obfuscate the code with Google Closure Compiler.
We need to take care too much things and even more when come to cross platform.
That’s why i suggest if it doesn’t cause any issue, then just go with it to make our life easy 
No, putting _ won’t do anything to the property, but it’s a “best practice” to prefix private members with _. So it can be tempting to do something like this:
var myObj = {
_myPrivate : 0
};
myObj._myPrivate = 1;
But you should use self discipline and know that you shouldn’t modify _ prefixed properties as if they were public.
In most cases, it may be “ok” to do it, but if you don’t follow this rule for Cocos’ objects you’ll find bizarre problems when you attempt to compile your code for native. Because in JS in the browser the code will work, but when compiling _ prefixed members are truly private in C++, so you won’t be able to use them from outside the object.
2 Likes
@ZippoLag
Thanks for the explanation!
We should always follow “best practice” to avoid issues.
@ZippoLag
var myObj = {
_myPrivate : 0
};
myObj._myPrivate = 1;
So you mean this code will cause problems when I compile it for Android and iOS?
Im not sure if the compiler is made to handle all _ prefixed members as private, but I can say this:
- If you are handling objects that were made and defined entirely by you, trating
_ prefixed members as public in your code may be OK when compiling (even thought it’d be counter-intuitive, and you should just drop the _ from the name).
- If you try to use a
_ prefixed member from a Cocos-defined object, or an object that you’ve defined extending a Cocos class it will fail.
1 Like