Javascript é uma linguagem muito flexível.

js-logo

E apesar de muitos desenvolvedores não terem conhecimento, javascript é muito orientada a objetos. Tanto que só existem 5 tipos primitivos que não são objetos na linguagem: numérico, string, booleano, null e undefined. Sendo que os 3 primeiros ainda podem ser convertidos em objetos pela própria linguagem internamente, ou por nós mesmos.

Eu já mostrei como é a Orientação a Objetos em Javascript, usando objetos literais. Particularmente, esse é estilo que eu prefiro. Mas nem por isso é o único correto. Existem outras formas de se programar com os conceitos de objetos em javascript.

Sem Classes

Vale a pena repetir: javascript não possui classes. E não possui por que não precisa, tanto que a ECMA4 foi abandonada por isso. Ao pensar em javascript, pense diretamente em objetos (afinal, quase tudo já o é).

Funções Construtoras

Você pode criar objetos usando funções construtoras:

var tt = new Tooltip();
tt.init();

Uma maneira de chegar a este código em javascript, é definindo a nossa função construtora:

function Tooltip() {
    this.init = function() {
        //..
    }
}

O problema disso, é que sempre que instanciarmos um novo objeto, a função init será novamente criada na memória, e nem sempre isso é bom ao nosso projeto.

var tt = new Tooltip();//aloca o objeto tt, criando a função init
var tt2 = new Tooltip();//aloca o objeto tt2, criando novamente init para este objeto agora

.prototype

Se adicionarmos o método init ao prototipo do objeto, todos as instâncias herdarão esse método e não estaremos enchendo a memória com declarações repetidas.

function Tooltip() {}
Tooltip.prototype.init = function() {}

No github: https://github.com/wbruno/examples/tree/gh-pages/tt eu coloquei algumas formas diferentes de programar javascript.

Esse tooltip funciona basicamente só com css, através do pseudo seletor :hover. O papel do javascript, é procurar o conteúdo do tooltip apartir do atributo data-rel, e reescrever a marcação html do elemento que disparou o tooltip.

var Tooltip =(function(){
	"use strict";

	function Tooltip() {}
	Tooltip.prototype.init = function(objs) {
		var i = objs.length;
		while(i--) {
			var obj = objs[i],
				wrap = this.createWrap(obj),
				ttContent = this.getContent(obj);

			wrap.appendChild(ttContent);
		}
		return objs;
	};
	Tooltip.prototype.createWrap = function(obj) {
		var wrap = document.createElement('span');
		wrap.className = 'tt-wrap';
		obj.parentNode.replaceChild(wrap, obj);
		wrap.appendChild(obj);
		return wrap;
	};
	Tooltip.prototype.getContent = function(obj) {
		var rel = obj.getAttribute('data-rel');
		return document.querySelector(rel);
	};
	return Tooltip;
}());

var $ = function(selector) {
	return document.querySelectorAll(selector);
};
window.addEventListener("load", function() {
	var tt = new Tooltip();
	tt.init($('.tt'));
	tt.init($('#another'));
});

Visibilidade

Também usei o pattern de revelação nesta versão do código, mas diferente do código com objeto literal, onde apenas a função tt.init(), estava acessível ao mundo externo, aqui, todo o objeto Tooltip é público, através das suas instâncias.

for(var prop in tt) {
		console.log(prop);//init, createWrap, getContent
	}
	console.log(tt.init);//function()
	console.log(tt.createWrap);//function()
	console.log(tt.getContent);//function()

Instâncias

Quando adicionamos um método ao prototype de um objeto todas as instâncias herdarão esse método. Mas o objeto em si não. Veja a saída:

console.log(Tooltip.init);//undefined
	console.log(Tooltip.prototype.init);//function()
	console.log(tt.init);//function()

Isso por que criamos inicialmente um objeto Tooltip vazio com uma função construtora .(funções também são objetos em javascript).

E, se não tivéssemos usado o prototype:

var Tooltip =(function(){
	"use strict";

	function Tooltip() {}
	Tooltip.init = function(objs) {
		//..
	};
	Tooltip.createWrap = function(obj) {
		//..
	};
	Tooltip.getContent = function(obj) {
		//..
	};
	return Tooltip;
}());

var $ = function(selector) {
	return document.querySelectorAll(selector);
};
window.addEventListener("load", function() {
	Tooltip.init($('.tt'));
	Tooltip.init($('#another'));

	var tt = new Tooltip();
	console.log(tt.init);//undefined
	console.log(Tooltip.init);//function()
});

As funções existiriam somente no objeto Tooltip, e não nas instâncias dele. A menos que copiássemos explicitamente os métodos de Tooltip, para dentro da instância tt:

tt.init = Tooltip.init;
	console.log(tt.init);//function()

Nenhuma é mais ou menos correta

Não é mais correto ou menos errado. Funções construtoras ou objetos literais, cada forma de programar implica em estilos diferentes de codificar e resolve problemas, assim como alguns patterns só são implementados em um estilo e não no outro.

Fique a vontade para escolher qual forma mais lhe agrada, ou esteja pronto a continuar uma forma já definida pela sua equipe. O importante é ter em mente que existem diferentes formas de fazer uma mesma coisa, mas não mais ou menos correta por isso.

Demonstração

Subi no github a demonstração de todos as formas de fazer esse tooltip

https://github.com/wbruno/examples/tree/gh-pages/tt