예시

var observer = {
	handlers: {}, // 각 모듈에 등록할 핸들러들을 담아줌
	
	// 상태 변화가 발생할때 실행할 이벤트들을 등록
	// context도 같이 받아 내부에서 this를 적절히 사용할수 있게 실행
	register: function(eventName, handler, context) {
		let handlerArray = this.handlers[eventName];
		if (handlerArray === "undefined") {
			handlerArray = this.handlers[eventName] = [];
		}
		// handlers 배열에 관리
		handlerArray.push({
			handler: handler,
			context: context
		});
	}

	// 등록한 핸들러를 해제해줌
	unregister: function(eventName, handler, context) {
		// 걍 handlerArray에서 splice해주면 되는거라 코드는 적지 않겠음
	}

	// 특정 상태가 변화되었을때 이벤트들을 알림해줄 함수
	notify: function(eventName, data) {
		const handlerArray = this.handlers[eventName];
		for (let i = 0; i < handlerArray.length; i++) {
			let currentHandler = handlerArray[i];
			// 핸들러를 바로 호출하지 않고 call을 쓰는데 위 register에 등록한
			// context 객체를 내부에서 this로 사용하게끔 전달하기 위함
			currentHandler["handler"].call(currentHandler["context"], data);
		}
	}
};
// 여기에 사장, 팀장, 개발자가 있다
let boss = new Person();
let manager = new Person();
let programmer = new Person();

// 사장님이 말할때 옵저버의 이벤트를 발생시키도록 넣고
boss.speak = function(comment) {
	alert(comment);
	observer.notify("bossSpeak", comment);
}

// 팀장님은 사장님의 얘기를 담아둔다
// 옵저버로 등록해 사장님이 언제든지 얘기할때 담아둘수 있도록 구현한 것
// 옵저버 알림이 그냥 manager.listen으로 수행하게 했다면 this가 manager인지 모름
// 그래서 알림 notify에선 context도 같이 받아서 call하여 manager라는걸 알게 해줌
// 이 부분이 context 내부에서 this를 활용하기 위함이다, 이런건 참 까다롭다
manager.listen = function(comment) {
	this.bossComment = comment;
}
observer.register("bossSpeak", manager.listen, manager);

// 개발자는.. 그냥 말씀따윈 무시하도록 구현
programmer.drop = function(comment) {
	return comment;
}
observer.register("bossSpeak", programmer.drop, programmer);

// boss가 이제 말하기 시작하면 아래처럼 매니저와 프로그래머에게도 알림이 가서 작동
boss.speak("Blah Blah Blah...");
// manager.listen("Blah Blah Blah...");
// programmer.drop("Blah Blah Blah...");