기완형님이 하시는 S55 스터디를 다녀왔습니다. 열정적인 강의에 폭풍 감동 ㅠㅠ 하지만 내용에는 멘붕~ @,.@ 스터디를 들으며 생긴 몇 가지 궁굼한 점들이 있어서 남겨 봅니다. 물론 물어 볼 수도 있지만 직접 찾아보지 않으면 기억에 남지 않으니 나름대로 공부해 봤습니다. 저 같은 자바스크립트 입문자 분들에게 도움이 되지 않을 가 싶습니다.
질문1) [[Prototype]] 과 prototype 은 같은 것인가?
자바스크립트 객체는 기본적으로 해시맵 구조이므로 아무런 키를 넣어서 만들 수 있습니다. 다만 생성시 기본 할당되는 키가 있는 데 [[Prototype]] 과 같은 것들입니다. 저는 단순히 설명 만 듣고 오브젝트에 키 값으로 [[Prototype]] 가 정말 있는 줄 알았습니다. [[Prototype]]는 사용자가 직접 접근 할 수 있는 키가 아닌 처리기가 해석시 사용하는 키입니다. 즉, var obj = {}; obj.[[Prototype]]; 처럼 사용 할 수 는 없습니다.
prototype 속성으로 접근 할 수 있느나 아무곳에서 쓸 수 있는 것은 아닙니다. 아래 코드와 같이 함수객체에만 사용 할 수 있습니다.
var obj = {}; obj.prototype; // undefined var fn = function(){}; fn.prototype; // Object {} var iFn = new fn(); iFn.prototype // undefined
질문2) var foo; foo를 지우고 싶다 어떻해야 하나?
결론부터 말하면 삭제 할 수 없습니다.
bar = 1; //1 delete bar; //true var foo = 1; //undefined delete foo; //false
var 키워드는 해당 함수의 스코프 영역에 변수를 등록합니다. 그래서 저는 [[Scope]] 에 접근 할 수 있으면 해당 변수도 delete 할 수 있을거라 생각 했는데 (그렇게 배운 것 같은데;;) 우선 [[Scope]] 에 접근할 수 없으며 변수 또한 delete 할 수 없습니다.
참고 : http://perfectionkills.com/understanding-delete/
어디에 써 먹을 것인가?
힘들게 공부 했으니 써먹을 궁리를 해야겠지요. 제 경우는 아무래도 어플리케이션 보다는 그래픽 쪽이므로 뭔가 그래픽적으로 멋진 결과물을 만드는 것에 포커스 하고 있습니다. 먼저 어제 배운내용을 Unity3D 에 적용해봤습니다.
Unity3D
#pragma strict function Start() { Debug.Log(this); //Cube (First) Debug.Log(rotate); // CompilerGenerated.__First_Start$callable0$5_19__ } function Update() { rotate(1, 0, 0); } function rotate(x, y, z) { this.transform.Rotate( Vector3(x, y, z) ); }
먼저 유니티에서도 호이스팅은 잘 작동합니다. 하지만 아래와 같은 코드는 에러가 납니다.
function Update() { rotate(1, 0, 0); function rotate(x, y, z) { this.transform.Rotate( Vector3(x, y, z) ); } }
함수 안에서 함수를 생성 할 수 없으며 심지어 프로토타입도 없습니다.@..@ 아무래도 모양만 자바스크립이지 컴파일러가 전혀 달라서 작동하는 방식 또한 다른 것 같습니다. (이러면 곤란한데…)
Canvas
function Start() { canvas = document.getElementById('cube'); canvasWidth = canvas.width; canvasHeight = canvas.height; if (canvas.getContext){ context = canvas.getContext('2d'); timer = setInterval(Update, 1000 / 60); } } function Update() { rotate(1); } function rotate(r){ context.clearRect(0, 0, canvasWidth, canvasHeight); context.translate(canvasWidth/2, canvasHeight/2); context.rotate(Math.PI / 180 * r); context.translate(-canvasWidth/2, -canvasHeight/2); context.fillStyle = "blue"; context.fillRect(canvasWidth/2 - 50, canvasHeight/2 - 50, 100, 100); } Start();
동일한 코드를 Canvas 를 이용해서 구현해보았습니다. 소스를 만들면서 다시 멘붕에 빠집니다. Start 함수에서 지정한 canvas, context 등의 변수는 분명 함수 안에서 선언된 지역변수 입니다. 그런데 어떻게 rotate 함수 안에서 참조가 되는 것 일까요? 참고로 어느정도 예상하시겠지만 var 로 변수를 선언하면 rotate 에서 참조 되지 않습니다.
흠 그래서 고민하다 똑똑한 저는 어제 배운 EC 가 생각 났습니다. Start 함수가 실행되고 있고 그 안에서 rotate 가 실행되니 EC 체인을 따라서 참조 하는 건가??? 물론 아닙니다. 그래서 또 어디서 줏어 들은 크롬의 V8 엔진이 생각 납니다. 그래! V8 은 모든 변수 참조를 미리 만든다고 했지 그럼 ie 에서 테스트 해보자! 그러나 ie8 에서는 Canvas 가 안됩니다;;;;;
결국 미궁으로 빠져 버렸습니다.
결론
확실한건 자바스크립트는 처리기에 따라서 다르게 작동한다는 것 입니다. 그리고 아무래도 제가 무서운 놈과 마주 했다는 사실 입니다. ㅎㅎㅎ
참고 : 지돌스타님의 http://blog.jidolstar.com/category/JavaScript 글들을 함께 보니 더욱 좋네요.
canvas는 var로 선언된게 아니라서 global에 키로 잡혀서 참조가 가능한것 같습니다.
네 var 로 선언하지 않는 모든 변수는 global 에 잡히는 것이였군요. 그렇다는 것은
위의 코드는 결국 아래와 같이 볼 수 있겠네요.