콜백함수로 넘길 함수가

어떤 객체의 프로퍼티이고, 함수 내부에서 this를 사용했다면,

콜백을 전달받은 함수에서 이 콜백함수를 호출하게되면 this의 값이 달라진다.


다음 예를 보면,

var myobj = {}
var myobj.color = "green"
var myobj.paint = function(node) {
	node.style.color = this.color
};


myobj.paint 함수를 다른 함수의 콜백인자로 넘겨보자.

var setColor = function(callback) {
	...
	if ( typeof callback === "function" ) {
		callback(node);
	}
	...
};

setColor(myobj.paint);


myobj.paint 함수 정의의 this는 setColor의 함수객체를 가리킨다. 즉 전역에 color 이라는 필드가 선언되어 있다면 그 값이 나오겠지만 선언되지 않았다면 ReferenceError exception이 발생한다.



이 상황을 해결하기 위해 myboj 객체도 인자로 같이 넘겨받아 this를 알아내는 방법이 있다.



객체 생성 시, 

생성자(Array(), Object(), String(), Boolean(), Number()) 사용을 자제하고 대신 리터럴 표기법을 사용하여 생성하자.

// 리터럴 사용
var car = { goes: "far" };

// 생성자 사용
var car = new Object();
car.goes = "far";



생성자를 사용해서 객체를 생성하면 득이 되는 것이 없다.

  1. 코드가 더 길어진다.
  2. 유효범위 판별 작업을 해야 한다.
    동일한 이름(Object()) 함수가 새로 정의되어 있는지 여부를 유효범위 체인을 따라가며 확인할 필요가 없다.




자바스크립트에서 eval()은 사악한(evil) 함수이다.


동적인 프로퍼티에 접근할 때에는 대괄호 표기법이 더 간단하고 좋다.


//안티 패턴
var obj = {name:"javascript"};
var property = "name";
alert(eval("obj."+property))
// 권장 패턴
var obj = {name:"javascript"};
var property = "name";
alert(obj[property])






setInterval(), setTimeout(), Function() 인자로 문자열을 넘기는 것도 eval()과 비슷하다.


반드시 eval()을 사용해야 한다면 

  1. new Function()으로 감싸서 사용하자.
    Function() 생성자로 감싸게되면 유효영역이 새로 만들어져 var 선언 변수들이 전역에 선언되는 경우를 막을 수 있다.
  2. eval() 호출을 즉시실행 함수로 감싸서 실행되도록 하자.
console.log(typeof un);    // undefined
console.log(typeof deux);    // undefined
console.log(typeof trois);    // undefined

var jsstring = "var un = 1; console.log(un);";
eval(jsstring);    // "1"

jsstring = "var deux = 2; console.log(deux);";
new Function(jsstring)();    // "2"    // 생성자로 생성한 함수를 바로 호출한다. 
     // 유효범위가 새로 생기므로 deux는 로컬변수가 된다.

jsstring = "var trois = 3; console.log(trois);";
(function() {
   eval(jsstring);
}()); // "3" // eval()을 함수로 감싸고 그 함수를 즉시 호출한다. trois 또한 함수의 로컬변수가 된다.

console.log(typeof un);        // "1"
console.log(typeof deux);   // "undefined"
console.log(typeof trois);    // "undefined"


eval()과 Function()의 또다른 차이


eval()은 자신의 유효범위 다음으로 자신을 감싸는 유효범위를 바라보고 있다.

하지만 Function()은 자신의 유효범위 다음으로 전역 유효범위를 바라보고 있다.

따라서 eval()은 유효범위 체인에 간섭을 일으킬 수 있다.

(function () {
	var local = 1;
	eval("local = 3; console.log(local);");    // 3이 출력된다.
	console.log(local);    // 3이 출력된다. 감싸고있는 함수의 local 변수의 값을 바꿔버린다.
}())

(function () {
	var local = 1;
	Function("console.log(typeof local);")();    // undefined가 출력된다. 
	// Function 객체의 상위 유효범위는 전역.
	// 전역에 local 변수가 없으므로 undefined.
}())

'WEB > javascript' 카테고리의 다른 글

객체 생성자의 함정  (0) 2012.07.22
자바스크립트 리터럴 표기법  (0) 2012.07.22
호이스팅(hoisting): 분산된 var 선언의 문제점  (0) 2012.07.12
자바스크립트 전역변수  (0) 2012.07.10
strict mode  (0) 2012.07.10


ECMAScript 5에 추가된 기능.


실제로 기능을 추가한 것이 아니라 제거함으로써 프로그램을 더 간단하게 만들고 오류 발생 가능성을 낮춘것.

예를들어 with를 스트릭트 모드에서 쓰면 에러가 발생한다.

function my() {
	'use strict'
	with(o) {    // error
	}
}


'use strict'  유효범위는 함수, 전역, 또는 eval()로 전달된 문자열.


ES는 추후에 스트릭트 모드만 지원하려고 계획중이다.

따라서 ES5는 개발자에게 strict mode에서 동작하는 코드를 작성하도록 권장하는 과도적인 버전.

+ Recent posts