Properties & Javascript

Il y a quelques mois j'avais fait un petit tuto sur comment coder orienté objet avec javascript : http://www.k33g.org/?q=node/42. Ce qui me manquait, c'était la notion de propriétés (je viens de .Net). Et bien, c'est possible ! Je vous livre 3 méthodes différentes (qui ne fonctionne pas forcément sur tous les navigateurs, mobiles compris)

Habituellement, on fait comme ceci :

    function Human(name){
		var _name = name;
	
		this.getName = function(){return _name;};
		this.setName = function(value){_name = value;};
    }
    
    H = new Human("Donald");
    alert(H.getName());

...

Mais il est possible de faire ceci :

	//OK sous Webkit et Mozilla, pas testé sous Webkit mobile
	//KO sous IE
	
    function Human(name){
		var _name = name;
	
		this.__defineGetter__("Name",
			function(){
				return _name;
			});
		this.__defineSetter__("Name",
			function(value){
				_name = value;
			});
    }
    
    H = new Human("Donald");
    alert(H.Name);

Ou bien ceci :

	//OK sous Webkit et Mozilla, KO sous Webkit mobile
	//KO sous IE
	
    function Human(name){
		var _name = name;

		Object.defineProperty(this, "Name", {
			get: function() { return _name; },
			set: function(value) { _name = value;}
		});		

    }
	
    H = new Human("Donald");
    alert(H.Name);

Si vous êtes prêts à abandonner le concept de variables privées, il y a aussi cette solution :

	//OK sous Webkit et Mozilla, pas testé sous Webkit mobile
	//KO sous IE
	
    function Human(name){
		this._name = name;
    }
    
    Human.prototype = {
	    get Name() { return _name; },
	    set Name(value) { _name = value;}	
    }
	
    H = new Human("Donald");
    alert(H.Name);

L'avantage c'est que vous devez pouvoir l'utiliser facilement dans du code Mootools (reste à tester).
Je ne connaissais pas, et personnellement, ça me plaît beaucoup.

Mais, si vous voulez rester compatibles "tous navigateurs" je vous propose de le faire "à la jQuery" (et ça vous fera économiser quelques get et set) :
cet exemple est faux (cf. commentaires)

    function Human(name){
		this._name = name;
		
		this.Name = function(){
			if(arguments[0]!=null){//setter
				this._name = arguments[0]
				return null;
			}else{//getter
				return this._name;
			}
		}; 		
    }
    
    H = new Human();
    H.Name("Donald");
    alert(H.Name());

cet exemple est juste (cf. commentaires)

        function Human(name){
            this._name = name;
             
            this.Name = function(){
                if(arguments && arguments.length > 0){//setter
                    this._name = arguments[0]
                    return null;
                }
                return this._name;//getter

            };      
        }
         
        H = new Human();
        H.Name("Donald");
        alert(H.Name());

@+ P.

Comments

get et set et arguments

Bonjour,

Ne serait-il pas plus judicieux de faire:

this.Name = function(){
if(arguments && arguments.length > 0){
this._name = arguments[0];
}

return this._name;
};

En effet, dans la version que vous proposez, nous ne pouvons même plus affecter une propriété à null, ce qui peut être embêtant.

De plus, lors du setter, vous renvoyez une valeur null, autant renvoyer la valeur courante de la propriété (utile dans un cas comme if(a.Name(getValeur)){ ... } else { ... }) )

Cordialement

Bien vu ! Je vais corriger

Bien vu ! Je vais corriger l'article, comme ça il y a aura la mauvaise méthode, et la bonne (la votre), dans mon cas si on affecte null, on va se retrouver avec un undefined, et en plus le else est inutile. Merci pour la remarque.


Warning: INSERT command denied to user 'kgkyojmt001'@'10.0.75.168' for table 'drp_watchdog' query: INSERT INTO drp_watchdog (uid, type, message, variables, severity, link, location, referer, hostname, timestamp) VALUES (0, 'php', '%message in %file on line %line.', 'a:4:{s:6:\"%error\";s:12:\"user warning\";s:8:\"%message\";s:243:\"UPDATE command denied to user 'kgkyojmt001'@'10.0.75.168' for table 'drp_node_counter'\nquery: UPDATE drp_node_counter SET daycount = daycount + 1, totalcount = totalcount + 1, timestamp = 1369359896 WHERE nid = 47\";s:5:\"%file\";s:60:\"/homez.312/kgkyojmt/www/modules/statistics/statistics.module\";s:5:\"%line\";i:54;}', 3, '', 'http://www.k33g.org/?q=node/47', '', '54.224.75.101', 1369359896) in /homez.312/kgkyojmt/www/includes/database.mysql.inc on line 128

Warning: INSERT command denied to user 'kgkyojmt001'@'10.0.75.168' for table 'drp_watchdog' query: INSERT INTO drp_watchdog (uid, type, message, variables, severity, link, location, referer, hostname, timestamp) VALUES (0, 'php', '%message in %file on line %line.', 'a:4:{s:6:\"%error\";s:12:\"user warning\";s:8:\"%message\";s:383:\"INSERT command denied to user 'kgkyojmt001'@'10.0.75.168' for table 'drp_accesslog'\nquery: INSERT INTO drp_accesslog (title, path, url, hostname, uid, sid, timer, timestamp) values('Properties & Javascript', 'node/47', '', '54.224.75.101', 0, 'c49c2ca045cbd0411d8200ca2f1b5c6b', 864, 1369359896)\";s:5:\"%file\";s:60:\"/homez.312/kgkyojmt/www/modules/statistics/statistics.module\";s:5:\"%line\";i:64;}� in /homez.312/kgkyojmt/www/includes/database.mysql.inc on line 128

Warning: INSERT command denied to user 'kgkyojmt001'@'10.0.75.168' for table 'drp_watchdog' query: INSERT INTO drp_watchdog (uid, type, message, variables, severity, link, location, referer, hostname, timestamp) VALUES (0, 'php', '%message in %file on line %line.', 'a:4:{s:6:\"%error\";s:12:\"user warning\";s:8:\"%message\";s:1300:\"UPDATE command denied to user 'kgkyojmt001'@'10.0.75.168' for table 'drp_sessions'\nquery: UPDATE drp_sessions SET uid = 0, cache = 0, hostname = '54.224.75.101', session = 'messages|a:1:{s:5:\\"error\\";a:2:{i:0;s:333:\\"user warning: UPDATE command denied to user 'kgkyojmt001'@'10.0.75.168' for table 'drp_node_counter'\\nquery: UPDATE drp_node_counter SET daycount = daycount + 1, totalcount = totalcount + in /homez.312/kgkyojmt/www/includes/database.mysql.inc on line 128