code: function ( type, fn, context ) {
  
  		var events = this._events = this._events || {},
  			contextId = context && context !== this && Util.stamp(context);
  
  		if (contextId) {
  			// store listeners with custom context in a separate hash (if it has an id);
  			// gives a major performance boost when firing and removing events (e.g. on map object)
  
  			var indexKey = type + '_idx',
  				indexLenKey = type + '_len',
  				typeIndex = events[indexKey] = events[indexKey] || {},
  				id = Util.stamp(fn) + '_' + contextId;
  
  			if (!typeIndex[id]) {
  				typeIndex[id] = {fn: fn, ctx: context};
  
  				// keep track of the number of keys in the index to quickly check if it's empty
  				events[indexLenKey] = (events[indexLenKey] || 0) + 1;
  			}
  
  		} else {
  			// individual layers mostly use "this" for context and don't fire listeners too often
  			// so simple array makes the memory footprint better while not degrading performance
  
  			events[type] = events[type] || [];
  			events[type].push({fn: fn});
  		}
  
  		this.fire( 'onlistener', {
  			type: type,
  			fn: fn,
  			context: context
  		});
  	}
docs: attach listener (without syntactic sugar now)