2022. 12. 19. 17:56ㆍjs
26.1 함수의 구분.
ES6이전까지 함수는 구분없이 사용되었음. 그래서 new 연산자로 함께 사용하던지, 일반 함수로 호출 하던지.
객체에 바인딩 되어 메서드로 호출되던지 어떤 방식으로도 호출 가능하였다.
[1, 2, 3].map(function (item){
return item * 2;
});
ES5 까지에서 모든 함수는 callable 이면서 constructor이다.
하지만 위와 같은 방식을 사용하기 때문에 내부적으로 이 로직이 어떤 행위인지를 판단해야 했고
당연하게 성능적인 부분에서 손해를 불러왔으며 또한 개발자들의 실수를 유발 시킬 수 있는 코드가 되었다
따라서 ES6에서 함수의 구분을 나누게 되었다고 볼 수 있다!
ES6 에서 함수의 구분
Constructor | prototype | super | arguments | |
---|---|---|---|---|
일반 함수 (Normal) | O | O | X | O |
Method. | X | X | O | O |
Arrow function | X | X | X | X |
와 같이 구분 할 수 있다 .
26.2 메서드
메서드 ES6 이후에 메서드는 메서드 축약 표현으로 정의된 함수만 메서드라고 의미한다.
const obj = {
x : 1,
foo() {
// method
return "foo";
},
argu : function () {
// not method
return "argue";
},
}
ES6에서 메서드는 non-constructor 이기 때문에 생성자 함수로 호출 불가능하다.
그렇기에 프로토 타입이 존재하지 않는다.
또한 표준 빌트인 객체가 제공 하는 프로토 타입 메서드와 정적 메서드는 모두 non-constructor다.
ES6 메서드의 경우 내부 슬롯에 [[HomeObject]]를 가지고 있기 때문에 (자신을 바인딩한 객체를 가르키는 공간)
super 로써 호출 가능하다.
es6 메서드가 아닌 함수의 경우 super 키워드를 사용 할 수 없고 이유는 [[HomeObject]]가 존재 하지 않기 때문이다 .
26.3 화살표 함수
26.3.1 화살표 함수의 정의
arrow function. const name = () => {} 의 로직으로 기존 함수의 정의방식보다
간략하게 정의 할 수 있다. 내부동작 또한 기존 함수보다 간략 함은 물론이고 this가 전역을 가르키는 문제를 해결 할 수 있기 때문에
사용하는것을 잘 익혀두는것이 좋을듯 하다 .
26.3.2 화살표 함수와 일반 함수의 차이.
3.2.1 화살표 함수의 경우 non-constructor이기 때문에 new 키워드를 이용하여 호출 불가능하다 .
3.2.2 중복된 매개변수 이름을 선언 할 수 없다.
3.2.3 함수 자체의 this, argument, super, new.target 등의 바인딩을 가지지 않는다
26.3.3 this
class Child{
constructor() {
window.addEventListener("resize", () => {
console.log("arrow function");
this.resize()
console.log("ended");
});
window.addEventListener("resize", this.resize);
}
resize() {
console.log(this);
}
}
new Child();
와 같은 테스트 함수를 만들 었을때
화살표 함수로 호출 하는 것과 일반 함수를 통해 호출 하는것의 차이를 확인해 보았다.
고차 함수의 인수로 전달되어 고차 함수 내부에서 호출되는 콜백함수 또한 중첩함수 라고 할 수 있다.
여기서 콜백함수 내부의 this의 경우 일반함수로 호출이 되고 일반함수의 호출인 경우 this는 전역 객체를 가르키고 있다는 것을
확인 할 수 있었다.
위와 같은 문제를 해결 하기 위해서
add() {
const that = this;
return arr.map(function (item) {
return that.prefix + ' ' + item;
});
}
와 같이 사용을 하거나 this.bind(); 와 같은 기능들을 사용 하게 된다.
es6 의 경우 이러한 문제를 해결하기 위해서 나왔다고 봐도 무방할 정도인 화살표 함수의 경우
this를 참조하게 되면 상위 스코프의 this를 참조한다 이를 lexical this라고 함!
따라서 () => {this.resize()}의 경우 부모의 this를 참조하여 거기에 존재하는 resize() 를 호출 할 수 있게 되었다.
따라서 콜백함수나 여러 방면에서 this가 타입에러를 발생하는것을 막을 수 있게 되었다.!
화살 표 함수와 동일하게
prototype.bind(this) 와 같은 방식으로도 화살표 함수와 같은 동작을 할 수 있다
*/
화살표 함수는 함수 자체의 바인딩을 가지지 않음으로 prototype.call, prototype.apply, prototype.bind 메서드를
이용해도 this 가 교체되지 않는다는 사실을 기억하도록 하자
// 교체 되지 않는것이지 사용불가능 하다는 뜻은 아니다!
es6 메서드를 동적 추가하고 싶다면 객체 리터럴을 바인딩한후 프로토타입의 constructor프로퍼티와
생성자 함수의 연결을 재설정 해주면 된다.
function Person(name) {
this.name = name;
}
Person.prototype = {
constructor : Person,
sayHi() {
console.log(`HI ${this.name}`);
}
};
메서드를 정의할때는 축약표현을 사용해야 하는것이 화살표 함수를 사용하는 것 보다 옳을 수 있다.
super
화살표 함수의 경우 함수 자체에 super 바인딩을 가지지 않음으로 super 를 참조하면 '
상위 스코프의 super 를 참조한다.
위에서 this가 없기 때문에 자신을 실행시킨 this를 찾아와서 사용하는것과 같은 로직을 따르는듯 하다 .
화살표 함수의 경우 자기자신에 arguments가 들어오지 않음으로
가변함수를 구현 하기 위해서는 Rest파라미터를 이용해야 한다고 한다 .
26.4 Rest 파라미터
26.4.1 기본문법.
... 을 붙여 정의한 매개변수 를 의미하고 함수에 전달된 인수의 목록을 배열로 전달받는다.
function foo(...rest) {
console.log(rest);
}
function foo2(a, ...rest) {
console.log(a, rest);
}
일반 매개변수와 Rest파라메터는 함께 사용 할 수 있다 먼저 들어온 인자부터 채워지고 나머지를 받아오는 방식으로
동작함.
매개변수의 개수를 가져오기 위해서 foo.length에 영향을 주지 않음으로 length의 값에 변화가 없다.
따라서 이를 통해서 코드를 구현하고 있다면 동작에 차질이 생길 수 있을듯 하다 .
26.4.2
Rest파라미터와 arguments객체
Rest파라미터의 경우 인자를 배열로 받아오게 되고 arguments의 경우 유사 배열임으로
map과 같은 기능들을 사용하기 위해서 arguments의 경우 배열로 형변환을 해줘야 하는 작업이 필요했으나 Rest의 경우
function test(...rest) {
return rest.filter((item) => item > 10);
}
와 같이 바로 사용 할 수 있다는 장점이 있다.
또한 화살표함수의 경우 자기자신의 arguments 가 존재하지 않기 때문에 Rest 를 항상 이용해 줘야 한다,
26.5 매개변수의 기본값
매개변수의 기본값
(x = 10, y = 10) 과 같이 사용하는 것을 의미
인수가 없을때 와 undefined를 전달 했을 경우에만 값을 변경해주는 방식으로
Rest의 경우 불가능한 방식이다.;