200901_TIL

oh_ji_0·2020년 9월 1일
1

TIL

목록 보기
25/61

Today I learned

  • 화살표함수
  • 싱글톤 패턴
  • arguments 객체
  • this 키워드
  • call/apply/bind
  • rest / spread 문법

@@ 오늘은 정말 많은 개념들을 배운 것 같다. urclass에서 문서를 읽으며 습득한 내용도 많고, koans를 페어랑 진행하면서 여러가지 개념들을 익혔다. 특히 아직도 헷갈리는 this의 5가지 패턴 이외의 예외 상황들(화살표 함수, 이벤트리스너, forEach등 thisArg를 인자로 받는 함수들)에 대해서 많이 익혔고(물론 아직 헷갈리지만..), spread 문법에 대해서 다양하게 눈에 익히고 문제를 풀어봤다는 게 나름의 성과였다. 객체 구조 분할 문법도 대강은 알고 있었지만, default 값을 설정하는 것이나 변수명을 새로운 이름으로 설정하여 분할하는 법 등을 제대로 모르고 있었던 것 같다. 문제를 풀며 익힐 수 있어서 좋았다.

call/apply/bind에 대해서도 여러가지 활용법에 대해서 생각해보고 익혀보는 시간을 가졌는데, 특히 bind는 정말 활용도가 높아서 적재적소에 내가 쓸 수 있도록 머리에 익히고, 손에 익히는 시간이 필요할 것 같다는 생각이 든다.

아직은 시간이 조금 더 필요하지만, 책도 책이고 정리한 노트를 계속 복습해서 this, call/apply/bind, spread 문법에 대해선 꼭 내가 가져가야겠다는 생각이 많이 든다. 복습만이 살길이다!

화살표함수

  • 화살표 함수는 call, apply, bind 메소드를 사용하여 this를 변경할 수 없다.
window.x = 1;
const normal = function () { return this.x; };
const arrow = () => this.x;

console.log(normal.call({ x: 10 })); // 10
console.log(arrow.call({ x: 10 }));  // 1
  • 화살표 함수로 메서드를 정의하는 것은 피하는 것이 좋다.

    화살표 함수는 this 를 결정짓지 않기 때문에 메서드 정의 시 , this 가 해당 객체를 바라보지 않고, 그 상위 컨텍스트의 this 를 바라보기 때문에 의도치 않은 결과를 초래할 수 있다.
    이는 prototype 메서드를 정의할 때 또한 마찬가지이다.

  • 화살표 함수는 생성자 함수로 사용할 수 없다. 화살표 함수를 생성자 함수로 이용하면 생성자가 아니라는 오류를 반환한다.

  • addEventListener 함수를 사용할 때도 같은 이유로 일반 함수를 사용하는 것이 좋다. 일반 함수를 사용해야 this 가 이벤트에 바인딩된 요소 currentTarget을 가리킨다.

참고: Arrow function

싱글톤 패턴

  • 싱글톤 패턴 (Singleton 패턴)

싱글턴은 필요에 의해 단 하나의 객체만을 만들 때 사용합니다.

var obj = {
  a: 'hello',
  b: function() {
    alert(this.a);
  }
};

참고 : 제로초 블로그, 디자인 패턴(싱글턴, 모듈, 생성자)

arguments 객체

  • arguments 객체

    • 함수는 전달받은 매개변수를 특정한 객체 arguments를 담고 있다.

    • 유사배열 형태를 띈다

    • arguments.callee 속성(property)

      현재 실행 중인 함수를 가리킨다.

      ES5은 엄격 모드에서 arguments.callee()의 사용을 금한다.

      • 활용예시
      • 익명 재귀 함수에서 arguments.callee 사용
    • arguments.caller

      • arguments.caller 속성은 현재 실행한 함수를 적용하여 제공했었다. 이 속성은 삭제되었으며 더 이상 작동하지 않는다. (보안취약)
      • 하지만 Function.caller 는 사용할 수 있다.

this 키워드

  • arr.forEach(callback(currentvalue[, index[, array]])[, thisArg])

    thisArg 매개변수를 forEach()에 제공한 경우 callback을 호출할 때 전달해 this의 값으로 쓰입니다.

    전달하지 않으면 undefined를 사용하며, 최종 this 값은 함수의 this를 결정하는 평소 규칙을 따릅니다.

  • 이벤트 리스너

    • GlobalEventHandlers.onclick
      • target.onclick = functionRef;
      • onclick 프로퍼티에 익명함수가 담기고, 그 안에 this를 콘솔로 찍으면 this는 해당 target 즉 메서드의 객체 html Element 를 가리킨다.
      • 이벤트가 발생할 때 내부적으로 this 가 바뀐다.
      • 이벤트 메서드에 인자가 담긴 함수를 전달하고 싶을 때 bind 혹은 익명함수를 이용한다.
  • setTimeout의 첫번째 인자에 익명함수를 넣으면 this가 window를 가리킨다.

    • 이를 변경하기 위해선 다음과 같은 방식을 이용할 수 있다.
      • .bind 이용
      • 외부에 this 를 변수에 담아 전달하거나 (비권장)
      • 화살표 함수를 이용

화살표함수

  • 메소드 선언 시 화살표 함수 사용을 피하거나 화살표 함수를 사용할 때 this 사용을 피해야 한다.
  • 화살표 함수는 this를 결정짓지 않는다. 그렇기 때문에 화살표 함수 안에서의 this 는 상위 컨텍스트의 this 를 가리킨다.

생성자 함수 안에서의 this

  • new 키워드를 이용해 호출할 경우 해당 함수를 생성자 함수라고 부른다.
  • new 키워드가 없이 호출하면?
    생성자 함수를 new 키워드 없이 호출할 경우, 해당 함수 내에서의 this는 전역 객체를 가리킨다. 전역 객체의 프로퍼티 (전역변수)로서 해당 생성자 함수 안의 프로퍼티값들이 설정되고, 결국 해당 인스턴스의 프로퍼티 값에는 해당 프로퍼티값이 설정되지 않는다. 그러므로 인스턴스의 프로퍼티를 조회하면 undefined 가 나온다.

node.js 에서의 전역객체

global 객체

  • 글로벌 스코프에 언제나 존재하는 객체
  • 자바스크립엔 글로벌 객체가 항상 정의되어 있다.
  • 브라우저에선 전역 변수를 선언하면 글로벌 객체(Window)의 프로퍼티로 등록이 되지만, Node.js에선 그렇지 않다. Node.js 에선 그 스크립트가 돌아가는 실행 컨텍스트에 국한된다.
  • worker 에서 돌아가는 코드는 글로벌 객체로 workerGlobalScope를 가진다.
  • Node.js에서는 Window를 사용할 수 없고 대신 global 을 사용해야한다.

Node.js 에서의 this

  • module.exports
    파일을 모듈로 사용할 수 있게 해주는 객체
  • module.exports 의 값은 기본적으로 {} 빈 객체이다.
  • node.js 에서 전역에서 this는 바로 module.exports를 가리킨다.
  • 전역에서 module.exports, exports, this 는 같은 곳을 바라본다.
  • node.js 의 함수 선언문 안에서의 this는 global 을 가리킨다.

call/apply/bind

  • call과 bind 는 thisArg 인자 뒤에 인자를 개별 요소로 , apply 는 array 형태로 받는다.

  • 배열을 spread 연산자로 활용해 Math.max 메소드 사용
    Math.max(...arr)

  • 유사 배열일 경우
    Math.max.apply(null, array)

    ( apply는 인자를 배열의 형태로 받기 때문에 spread 형태가 아닌 그냥 배열을 사용한다)

  • prototype 의 기능 또한 빌려쓸 수 있다.

유사배열 다루기

  • 해당 메서드가 어떤 데이터 형을 반환하는지 유심히 봐야한다.
  • Array.prototype.slice.apply(유사배열, [0, 1]) 와 같은 코드를 작성시 slice 메소드의 결과로 배열을 반환해야하기 때문에 0번 프로퍼티의 값이 배열 형태로 반환된다.
  • Array.prototype.slice.apply(유사배열, [0]) 와 같이 slice로 단순 복사하여 반환해보면 숫자로 프로퍼티 값을 갖는 배열 요소는 반환되지만 문자열 키값을 갖는 프로퍼티 (예를 들어, length) 는 배열에서 제외된 채 반환된다.
  • 유사 배열 뿐 아니라 문자열 또한 배열 메서드를 활용하여 변환시킬 수 있다.

.bind()

  • bind는 함수를 실행하지 않고 this 컨텍스트를 담은 함수를 리턴한다.
  • func.bind(thisArg[, arg1[, arg2[, ...]]])
  • thisArg 뒤에 대상 함수의 인수 앞에 사용될 인수 적용 (optional)

rest / spread 문법

  • 구조 분해할당
  • 배열 구조 분해
var foo = ["one", "two", "three"];
var [one, two, three] = foo;
console.log(one); // "one"
console.log(two); // "two"
console.log(three); // "three"
  • 기본값 설정
var a, b;

[a=5, b=7] = [1];
console.log(a); // 1
console.log(b); // 7
  • 변수값 교환하기
var a = 1;
var b = 3;

[a, b] = [b, a];
console.log(a); // 3
console.log(b); // 1
  • 일부 반환값 무시
function f() {
  return [1, 2, 3];
}

var [a, , b] = f();
console.log(a); // 1
console.log(b); // 3

//모두 무시하기
[,,] = f();
  • 나머지 요소의 오른쪽 뒤에 쉼표가 있으면 syntaxError 가 발생한다.
  • 객체 구조 분해
var o = {p: 42, q: true};
var {p, q} = o;

console.log(p); // 42
console.log(q); // true

({a, b} = {a:1, b:2}) //var {a, b} = {a:1, b:2}
  • {a, b} = {a:1, b:2}는 유효한 독립 구문이 아니다. 좌변의 {a, b}의 객체 리터럴이 아닌 블록으로 간주되기 때문이다.

  • ({a, b} = {a:1, b:2})는 var {a, b} = {a:1, b:2}와 일치한다.

  • ({a, b} = {a:1, b:2}) 표현식 앞에는 세미콜론이 있어야 한다.

  • 새로운 변수 이름으로 할당

var o = {p: 42, q: true};
var {p: foo, q: bar} = o;

console.log(foo); // 42
console.log(bar); // true
  • 객체 구조 할당 기본값 설정
var {a = 10, b = 5} = {b: 3};

console.log(a); // 10
console.log(b); // 3
  • 기본값 갖는 새로운 이름의 변수에 할당
var {a: aa = 10, b: bb = 5} = {a: 3};

console.log(aa); // 3
console.log(bb); // 5
  • 함수 매개변수의 기본값 설정
function drawES2015Chart({size = 'big', cords = { x: 0, y: 0 }, radius = 25} = {}) {
  console.log(size, cords, radius);
  // 차트 그리기 수행
}

drawES2015Chart({
  cords: { x: 18, y: 30 },
  radius: 30
});
  • 중첩 객체 및 배열의 구조분해
var metadata = {
    title: "Scratchpad",
    translations: [
       {
        locale: "de",
        localization_tags: [ ],
        last_edit: "2014-04-14T08:43:37",
        url: "/de/docs/Tools/Scratchpad",
        title: "JavaScript-Umgebung"
       }
    ],
    url: "/en-US/docs/Tools/Scratchpad"
};

var { title: englishTitle, translations: [{ title: localeTitle }] } = metadata;

console.log(englishTitle); // "Scratchpad"
console.log(localeTitle);  // "JavaScript-Umgebung"
  • computed property name
let key = "z";
let { [key]: foo } = { z: "bar" };

console.log(foo); // "bar"
  • key 값에 대괄호로 변수를 담아서 활용할 수 있다.

  • 객체의 key 값이 자바스크립트 식별자 명에 부합하지 않는 키값일 경우, 구조 분해를 활용하려면 다른 변수 명으로 바꿔서 사용해야 한다.

profile
기본에 충실하고 싶습니다. #Front-end-developer

0개의 댓글