설모의 기록
Classes Emit 본문
What's up with the IIFE
The js generated for the class could have been:
클래스를 이용해 생성된 코드이다.
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype.add = function (point) {
return new Point(this.x + point.x, this.y + point.y);
};
The reason its wrapped in an Immediately-Invoked Function Expression (IIFE) i.e.
즉시 실행함수 표기법으로 감싸진 이유는
(function () {
// BODY
return Point;
})();
has to do with inheritance. It allows TypeScript to capture the base class as a variable _super e.g.
상속을 사용하기 위해서이다. 상속은 타입스크립트가 기본 클래스의 멤버변수를 가지도록 한다.
var Point3D = (function (_super) {
__extends(Point3D, _super);
function Point3D(x, y, z) {
_super.call(this, x, y);
this.z = z;
}
Point3D.prototype.add = function (point) {
var point2D = _super.prototype.add.call(this, point);
return new Point3D(point2D.x, point2D.y, this.z + point.z);
};
return Point3D;
})(Point);
Notice that the IIFE allows TypeScript to easily capture the base class Point in a _super variable and that is used consistently in the class body.
즉시실행함수는 _super 변수를 통해 타입스크립트가 Point 클래스를 쉽게 잡을 수 있도록 하고 클래스 안에서 일관되게 사용된다.
__extends
You will notice that as soon as you inherit a class TypeScript also generates the following function:
너는 너가 클래스를 빨리 상속할수록 아래의 함수가 생성될 것임을 알것이다.
var __extends = this.__extends || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
};
Here d refers to the derived class and b refers to the base class. This function does two things:
d 클래스는 파생클래스이고 b 클래스는 기본 클래스이다. 이 함수는 아래의 두가지 일을 한다.
- copies the static members of the base class onto the child class i.e. for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
- sets up the child class function's prototype to optionally lookup members on the parent's protoi.e. effectively d.prototype.__proto__ = b.prototype
- 기본 클래스의 정적 멤버들을 자식 클래스에 복사한다.
- 부모클래스의 프로토타입의 멤버들을 보며 자식클래스의 프로토타입을 선택적으로 설정한다.
People rarely have trouble understanding 1, but many people struggle with 2. So an explanation is in order.
1은 이해하기 어렵겠지만 많은 사람들이 순서대로 설명한 것을 보고 발버둥친다.
d.prototype.__proto__ = b.prototype
After having tutored many people about this I find the following explanation to be simplest. First we will explain how the code from __extends is equivalent to the simple d.prototype.__proto__ = b.prototype, and then why this line in itself is significant. To understand all this you need to know these things:
많은 사람들을 가르쳐준 후에 나는 다음과 같은 설명이 가장 간단하다는 것을 알았다. 첫번째로 우리는 어떻게 __extends 코드가 d.prototype.__proto__ = b.prototype 와 동등한지 설명할 것이고, 왜 이게 중요한지를 설명할 것이다. 이것들을 이해하기 위해서는 아래의 것들을 알아야한다.
- __proto__
- prototype
- effect of new on this inside the called function
- effect of new on prototype and __proto__
All objects in JavaScript contain a __proto__ member. This member is often not accessible in older browsers (sometimes documentation refers to this magical property as [[prototype]]). It has one objective: If a property is not found on an object during lookup (e.g. obj.property) then it is looked up at obj.__proto__.property. If it is still not found then obj.__proto__.__proto__.property till either: it is found or the latest .__proto__ itself is null. This explains why JavaScript is said to support prototypal inheritance out of the box. This is shown in the following example, which you can run in the chrome console or Node.js:
자바스크립트에서의 모든 객체는 __proto__ 멤버를 가지고 있다. 이 멤버는 브라우저에서 자주 접근하지 않는다 (가끔 문서들은 이것을 마법같은 이 프로퍼티를 prototype 이라고 추론한다) . 이것은 단 하나의 목적을 가진다. 만약 찾아볼 때 객체가 __proto__ 프로퍼티를 가지고 있지 않다면 obj.__proto__.property 에서 찾는다. 만약 이것마저 못 찾는다면 obj.__proto__.__proto__.property 도 마찬가지다. 그것은 발견되었거나 __proto__ 가 null 이다. 이것은 왜 자바스크립트가 기본 프로토타입 상속을 제공하는지를 말해준다. 이것은 아래의 예제에서 보여지는 크롬 콘솔이나 node.js 에서 실행시킬 수 있다.
var foo = {}
// setup on foo as well as foo.__proto__
foo.bar = 123;
foo.__proto__.bar = 456;
console.log(foo.bar); // 123
delete foo.bar; // remove from object
console.log(foo.bar); // 456
delete foo.__proto__.bar; // remove from foo.__proto__
console.log(foo.bar); // undefined
Cool so you understand __proto__. Another useful information is that all functions in JavaScript have a property called prototype and that it has a member constructor pointing back to the function. This is shown below:
너는 이제 __proto__ 를 이해했을 것이다. 다른 유용한 정보는 자바스크립트에서의 모든 함수는 prototype 이라는 프로퍼티를 가지며 함수를 가지기는 생성자 멤버를 가진다.
function Foo() { }
console.log(Foo.prototype); // {} i.e. it exists and is not undefined
console.log(Foo.prototype.constructor === Foo); // Has a member called `constructor` pointing back to the function
Now let's look at effect of new on this inside the called function. Basically this inside the called function is going to point to the newly created object that will be returned from the function. It's simple to see if you mutate a property on this inside the function:
new 로 인해 호출된 함수 내에서 this 에 대해 보자. 기본적으로 호출된 함수에서의 this 는 함수에서 반환될 새로 생성된 객체를 가리킨다. 그것은 만약 너가 this 의 프로퍼티를 변하게 하는 것은 간단하다.
function Foo() {
this.bar = 123;
}
// call with the new operator
var newFoo = new Foo();
console.log(newFoo.bar); // 123
Now the only other thing you need to know is that calling new on a function assigns the prototype of the function to the __proto__ of the newly created object that is returned from the function call. Here is the code you can run to completely understand it:
너가 알아야할 것은 new 로 함수를 부르는 것은 함수의 prototype 을 새로 생성된 객체의 __proto__ 에 할당하는 것이다. 아래의 코드는 잘 이해될 것이다.
function Foo() { }
var foo = new Foo();
console.log(foo.__proto__ === Foo.prototype); // True!
That's it. Now look at the following straight out of __extends. I've taken the liberty to number these lines:
그게 다다. __extends 가 없는 것을 봐라.
1 function __() { this.constructor = d; }
2 __.prototype = b.prototype;
3 d.prototype = new __();
Reading this function in reverse the d.prototype = new __() on line 3 effectively means d.prototype = {__proto__ : __.prototype} (because of the effect of new on prototype and __proto__), combining it with the previous line (i.e. line 2 __.prototype = b.prototype;) you get d.prototype = {__proto__ : b.prototype}.
d.prototype = new __() 를 거꾸로 읽는 것은 d.prototype 에 __proto__ 아니면 __.prototype 이 들어가는 것과 마찬가지다. 이것을 2번줄과 결함하면 d.prototype 에 __proto 아니면 b.prototype 이 들어가는 것을 알 수 있다.
But wait, we wanted d.prototype.__proto__ i.e. just the proto changed and maintain the old d.prototype.constructor. This is where the significance of the first line (i.e. function __() { this.constructor = d; }) comes in. Here we will effectively have d.prototype = {__proto__ : __.prototype, d.constructor = d} (because of the effect of new on this inside the called function). So, since we restore d.prototype.constructor, the only thing we have truly mutated is the __proto__ hence d.prototype.__proto__ = b.prototype.
하지만 우리는 d.prototype.__proto__을 원하고 proto 는 변하고 예전정보인 d.prototype.constructor 를 유지할 것이다. 이건 첫번째 줄의 significance 가 어디서 유래됐는지이다. new 의 효과로 함수내의 this 의 영향때문에 d.prototype = {__proto__ : __.prototype, d.constructor = d} 가 된다. 따라서 우리가 d.prototype.constructor 를 저장할 때부터 우리가 돌연시킨 단 하나는 d.prototype.__proto__ = b.prototype 때문에 __proto__ 이다.
d.prototype.__proto__ = b.prototype significance
The significance is that it allows you to add member functions to a child class and inherit others from the base class. This is demonstrated by the following simple example:
자식클래스의 멤버함수를 추가하고 다른 기본클래스를 상속하는 것을 허락한다. 아래의 예제를 통해서 입증한다.
function Animal() { }
Animal.prototype.walk = function () { console.log('walk') };
function Bird() { }
Bird.prototype.__proto__ = Animal.prototype;
Bird.prototype.fly = function () { console.log('fly') };
var bird = new Bird();
bird.walk();
bird.fly();
Basically bird.fly will be looked up from bird.__proto__.fly (remember that new makes the bird.__proto__ point to Bird.prototype) and bird.walk (an inherited member) will be looked up from bird.__proto__.__proto__.walk (as bird.__proto__ == Bird.prototype and bird.__proto__.__proto__ == Animal.prototype).
글 출처 : https://basarat.gitbooks.io/typescript/content/docs/classes-emit.html
'언어 > TypeScript' 카테고리의 다른 글
Symbol (0) | 2018.01.03 |
---|---|
Promise (0) | 2018.01.02 |
Classes Super (0) | 2017.12.28 |
TypeScript Class (0) | 2017.12.28 |
TypeScript Index Signature (0) | 2017.12.28 |
Comments