11548 sujets

JavaScript, DOM et API Web HTML5

Bonjour,

Je suis face à un script que j'ai du mal à comprendre, j’essaye d'apprendre les différents design pattern, mais là je dois avouer que je bloque un peu sur quelques portions du script.

Ici en l’occurrence il s'agit du design pattern OBSERVER (ou pub/sub).

http://www.dustindiaz.com/basement/javascript-observer-class.html


if ( !Array.prototype.forEach ) {
				Array.prototype.forEach = function(fn, thisObj) {
			    	var scope = thisObj || window;
			    	for ( var i=0, j=this.length; i < j; ++i ) {
			        	fn.call(scope, this[i], i, this);
			    	}
				};
			}
			if ( !Array.prototype.filter ) {
				Array.prototype.filter = function(fn, thisObj) {
			    	var scope = thisObj || window;
			    	var a = [];
			    	for ( var i=0, j=this.length; i < j; ++i ) {
			        	if ( !fn.call(scope, this[i], i, this) ) {
			            	continue;
			        	}
			        	a.push(this[i]);
			    	}
			    	return a;
				};
			}
		
			function Observer() {
				this.fns = [];
			}
			Observer.prototype = {
				subscribe : function(fn) {
					this.fns.push(fn);
				},
				unsubscribe : function(fn) {
					this.fns = this.fns.filter(
						function(el) {
							if ( el !== fn ) {
								return el;
							}
						}
					);
				},
				fire : function(o, thisObj) {
					var scope = thisObj || window;
					this.fns.forEach(
						function(el) {
							el.call(scope, o);
						}
					);
				}
			};
			
			/*********************************
			 *** Decorator Implementation ***
			*********************************/
				
			var o = new Observer;
			var f1 = function(data) {
				console.log('f1 received data: '+data);
			};
			
			var f2 = function(data) {
				console.log('f2 received even more data: '+data);
			};
			
			o.subscribe(f1);
			o.subscribe(f2);
			
			
			window.onload = function() {
				var un = document.getElementById('unsubscribe');
				var fire = document.getElementById('fire');
				
				var remove = function() {
					console.log('f1 was unsubscribed');
					o.unsubscribe(f1);
				};
				var notify = function() {
					o.fire('huzzah!');
				};
				
				un.onclick = remove;
				fire.onclick = notify;
			};
			
		//-->


J'ai du mal à comprendre d'ou vient 'el' dans les fonctions 'unsubscribe' et 'fire' puisque que seul fn est transmis à ces fonctions. Serait-ce 'this' dans 'fn.call(scope, this[i], i, this);' de 'foreach' et 'filter' ?

Pour moi Filter renvois 'a' qui est un tableau, auquel on a enlevé la fonction qu'on ne veut plus déclencher.

C'est call qui doit me perturber, je comprends le principe du design pattern pub/sub, mais j'ai du mal à comprendre le script tel qu'il est là.

Donc si un expert Javascript passe par là, je ne serais pas contre une petite leçon. Voir une ressource pédagogique pour m'aider à avancer.

Merci
[/i][/i][/i][/i]
Modifié par rs459 (30 Oct 2011 - 21:12)
rs459 a écrit :
J'ai du mal à comprendre d'ou vient 'el' dans les fonctions 'unsubscribe' et 'fire' puisque que seul fn est transmis à ces fonctions. Serait-ce 'this' dans 'fn.call(scope, this[i], i, this);' de 'foreach' et 'filter' ?


Bonjour,

Oui c'est exactement ça.

this.fns = this.fns.filter(callback) // retourne un nouveau tableau à jour
filter -> execute callback(this[i], i, this); sur chaque élement du tableau (this étant le tableau)

call est ici inutile puisqu'on ne passe pas de contexte en second argument de filter, le contexte d'invocation est donc le contexte global.

callback.call(window, this[i], i, this);
est absolument équivalent à
callback(this[i], i, this);
dans ce cas de figure.
[/i][/i][/i][/i]