[JS] this

Haegu·2023년 9월 10일
  • 다른 언어에서의 this : 클래스에서만 사용 가능, 클래스로 생성한 인스턴스 객체
  • 자바스크립트에서의 this : 어디서든 사용 가능, 함수와 객체(메서드) 구분하는 유일한 기능
  • 알아보자!
      1. 상황에 따라 this가 바라보는 대상 달라짐 -> 왜?
      1. 예상과 다른 대상을 바라보고 있을 경우, 그 원인 효과적으로 추적하는 방법

1. 상황에 따라 달라지는 this

자바스크립트에서 this는 실행 컨텍스트가 생성될 때 함께 결정됨
실행 컨텍스트는 함수를 호출할 때 생성되므로, this는 함수를 호출할 때 결정

함수를 어떤 방식으로 호출하느냐에 따라 값이 달라짐

1-1. 전역 공간에서의 this

: 전역 객체 가리킴

왜? 전역 컨텍스트를 생성하는 주체가 전역 객체

  • 전역 객체

    • 자바스크립트 런타임 환경에 따라 다른 이름과 정보 가짐
    • 브라우저 환경 전역객체 : window
      console.log(this); // { alert: f(), atob: f(), blur: f(), btoa: f(), ... } 
      console.log(window); // { alert: f(), atob: f(), blur: f(), btoa: f(), ... } 
      console.log(this === window); // true
    • Node.js 환경 전역객체 : global
      console.log(this); // { process: {title: 'node', version: 'v01.13.0', ... } } 
      console.log(window); // { process: {title: 'node', version: 'v01.13.0', ... } } 
      console.log(this === global); // true
      업로드중..
  • 전역공간에서 선언한 a, window.a, this.a

    var a = 1;
    console.log(a);			// 1
    console.log(window.a);	// 1
    console.log(this.a);	// 1
    // 스코프체인에서 a검색 -> 
    // 가장 마지막에 도달하는 전역 스코프의 L.E === 전역객체의 프로퍼티에서 a 발견 -> 
    // 1반환
    • 전역변수 선언 시 자바스크립트 엔진은 이를 전역객체의 프로퍼티로도 할당함
    • 변수이자 객체의 프로퍼티
    • 자바스크립트의 모든 변수는 특정 객체(실행 컨텍스트의 Lexical Environment)의 프로퍼티로서 동작
    • 전역 컨텍스트의 L.E가 GlobalEnv 참조
    • GlobalEnv가 전역 객체 참조
  • 전역변수 선언이랑 window 프로퍼티에 직접 할당한 거랑 같은 거 아냐?

    • 대부분의 경우엔 맞음

      var a = 1;
      window.b = 2;
      console.log(a, window.a, this.a); // 1 1 1
      console.log(b, window.b, this.b); // 2 2 2
      
      window.a = 3;
      b = 4;
      console.log(a, window.a, this.a); // 3 3 3
      console.log(b, window.b, this.b); // 4 4 4
    • 전혀 다른 경우 : 삭제 명령
      전역변수 선언 시 삭제 명령해도 삭제 안됨
      -> 전역객체의 프로퍼티로 할당
      -> 전역객체의 프로퍼티의 configurable 속성 (변경 및 삭제 가능성) false로 정의
      (사용자의 의도치 않은 삭제 방지 차원)

      var a = 1;
      delete window.a; // false
      console.log(a, window.a, this.a); // 1 1 1
      
      var b = 1;
      delete b; // false (window.b)
      console.log(b, window.b, this.b); // 2 2 2
      
      window.c = 3;
      delete window.c; // true
      console.log(c, window.c, this.c); // Uncaught ReferenceError: c is not defined
      
      window.d = 4;
      delete c; // true (window.c)
      console.log(c, window.c, this.c); // Uncaught ReferenceError: c is not defined

1-2. 메서드로서 호출 시 그 메서드 내부에서의 this

함수 vs. 메서드

var func = function (x) { // func라는 변수에 익명함수 할당
  console.log(this, x);
};
func(1); // 함수 호출 // Window { ... } 1 // 전역객체 Window 출력

var obj = { // obj라는 변수에 객체 할당
  method: func // method 프로퍼티에 func 함수 할당
};
obj.method(2); // 메서드 호출 // { method: f } 2  // obj 출력
  • 공통점 : 미리 정의한 동작 수행하는 코드 뭉치
  • 차이점 : 독립성
    • 함수 : 그 자체로 독립적인 기능 수행
    • 메서드 : 자신을 호출한 대상 객체에 관한 동작 수행
      • 객체의 프로퍼티에 할당된 함수 -> 객체의 메서드로서 호출할 때만 메서드로 동작
  • 메서드로서 호출 - 점 표기법, 대괄호 표기법
    함수 이름 앞에 객체가 명시돼 있는 경우 메서드로 호출, 아닌 경우 함수로 호출

    var obj = {
      method: function (x) { console.log(this, x); }
    };
    obj.method(1);		// 점 표기법    // { method: f } 1
    obj['method'](2);	// 대괄호 표기법 // { method: f } 2
  • 메서드 내부에서의 this
    this에는 호출한 주체에 대한 정보 담김
    어떤 함수를 메서드로서 호출하는 경우 호출 주체는 함수명 앞 객체

    var obj = {
      methodA: function () { console.log(this); },
      inner: {
        methodB: functioin () { console.log(this); }
      }
    };
    obj.methodA();				// { methodA: f, inner: {...} } ( === obj)
    obj['methodA']();			// { methodA: f, inner: {...} } ( === obj)
    
    obj.inner.methodB();		// { methodB: f } 				( === obj.inner)
    obj.ineer['method']();		// { methodB: f } 				( === obj.inner)
    obj['inner'].methodB();		// { methodB: f } 				( === obj.inner)
    obj['inner']['methodB']();	// { methodB: f } 				( === obj.inner)

1-3. 함수로서 호출 시 그 함수 내부에서의 this

  • 함수 내부에서의 this
    • 어떤 함수를 함수로서 호출할 경우, this 지정되지 않음 -> 전역객체 바라봄
      this에는 호출한 주체 정보 담기는데,
      함수로서 호출하는 것은 호출 주체(객체 지향 언어에서의 객체)를 명시하지 않고
      개발자가 코드에 직접 관여해서 실행 -> 호출 주체의 정보 알 수 없음
      -> 함수에서의 this 전역객체 가리킴 => 설계상 오류
  • 메서드의 내부함수에서의 this

    • outer 메서드 내부에 있는 함수 innerFunc를 함수로서 호출 -> 전역객체 바인딩
    • 같은 함수 innerFunc를 메서드로서 호출(.or[]) -> 호출 구문 앞 객체 바인딩
    • 같은 함수라도 바인딩되는 this의 대상이 달라짐
    var obj1 = { // (1) 객체 생성, 객체 내부에 outer라는 프로퍼티에 익명함수 연결
      outer: function () { // (3) obj1.outer 함수의 실행 컨텍스트가 생성되면서 호이스팅하고, 스코프 체인 정보 수집하고, this 바인딩 => this에 obj1 바인딩
        console.log(this); // (4) obj1 객체 정보 출력				
        var innerFunc = function () { // (5) 호이스팅된 변수 innerFunc는 outer 스코프 내에서만 접근 가능한 지역변수, 이 지역변수에 익명함수 할당
          // (7) innerFunc 함수의 실행 컨텍스트가 생성되면서 호이스팅, 스코프 체인 수집, this 바인딩 => 함수로서 호출되어 this 지정 X => 자동으로 스코프체인상 최상위 객체인 전역객체 Window 바인딩 
          console.log(this); // (8) Window 객체 정보 출력 // (12) obj2 객체 정보 출력
        }
        innerFunc(); // 전역객체 Window // (6) innerFunc 함수로서 호출 
    
        var obj2 = { // (9) 호이스팅된 변수 obj2는 outer 스코프 내애서만 접근 가능한 지역변수, 이 지역변수에는 다시 객체 할당, 그 객체에는 innerMethod라는 프로퍼티 있으며, 변수 innerFunc와 연결된 익명함수 연결
          // (11) innerMethod 함수의 실행 컨텍스트 생성 => 메서드로서 호출되어 객체 obj2 바인딩
          innerMethod: innerFunc // (12)
        };
        obj2.innerMethod(); // obj2 // (10) obj2.innerMethod 메서드로서 호출
      }
    };
    obj1.outer(); //  obj1 // (2) obj1.outer 메서드로서 호출
  • 메서드의 내부 함수에서의 this를 우회하는 방법
    1 ) 상위 스코프 this 저장해서 내부 함수에서 활용

    var obj = {
      outer: function () {
        console.log(this); // (1) { outer: f }
        var innerFunc1 = function () {
          console.log(this);  // (2) Window { ... } 전역객체
        };
        innerFunc1();
    
        var self = this; // outer 스코프에서 this 저장 (self 변수 사용 우회)
        var innerFunc2 = function () {
          console.log(self); // (3) { outer: f } // 객체 obj
        };
        innerFunc2();
      }
    };
    obj.outer();
    • 호출 주체가 없을 때는 자동으로 전역객체 바인딩하지 않고
      호출 당시 주변 환경의 this를 그대로 상속받아 사용하고 싶어!
    • 변수 검색 시 가장 가까운 스코프 L.E찾고 없으면 상위 스코프 탐색하는 것 처럼
    • 현재 컨텍스트에 바인딩된 대상이 없으면 직전 컨텍스트의 this를 바라보게

2) this를 바인딩하지 않는 함수 (화살표 함수)

  • ES6에서는 함수 내부에서 this가 전역객체를 바라보는 문제 보완하고자
    this 바인딩 하지 않는 화살표 함수 arrow function 도입
  • 화살표 함수는 실행 컨텍스트를 생성할 때 this 바인딩 과정 자체가 빠짐
    -> 상위 스코프 this 그대로 활용 가능
var obj = {
  outer: function () {
    console.log(this);		// (1) { outer: f }
    var innerFunc = () => {
      console.log(this);	// (2) { outer: f }
    };
    innerFunc();
  }
};
obj.outer();

3) call, apply 메서드 활용해 명시적으로 this 지정 (뒤에서 계속...)


1-4. 콜백 함수 호출 시 그 함수 내부에서의 this

제어권을 가지는 함수(메서드)가 콜백 함수에서의 this 결졍
정의하지 않은 경우 전역객체 참조

콜백 함수 : 함수 A의 제어권을 다른 함수 B(또는 메서드 B)에게 넘겨주는 경우 함수 A

함수 A는 함수 B의 내부 로직에 따라 실행됨
함수 A의 this도 함수 B의 내부 로직에서 정한 규칙 따라 결정됨

콜백 함수도 함수라 this가 전역객체 참조하지만,
제어권을 받은 함수에서 콜백 함수에 별도로 this 될 대상을 지정한 경우 그 대상 참조

setTimeout(function () { console.log(this); }, 300); // 0.3초 뒤 전역객체 출력

[1, 2, 3, 4, 5].forEach(function (x) {
  console.log(this, x); // 콜백 함수의 첫번째 인자로 삼아 함수 실행 // 전역객체와 배열 각 요소 총 5회 출력
});

document.body.innerHTML += '<button id="a">클릭</button>';
document.body.querySelector('#a')
  .addEventListener('click', function (e) { // addEventListner 메서드는 콜백 함수를 호출할 때 자신의 this 상속하도록 정의 // . 앞부분이 this
    console.log(this.e); // 클릭 발생마다 그 이벤트 정보를 콜백 함수의 첫 번째 인자로 삼아 함수 실행 // 클릭 시 지정한 엘리먼트와 클릭 이벤트 정보 담긴 객체 출력
  });

1-5. 생성자 함수 내부에서의 this

객체지향 언어에서는

  • 클래스 class : 생성자 (구체적인 인스턴스를 만들기 위한 일종의 틀)
    (공통 특성모아 인간 집합 정의 ex. 직립 보행, 언어 구사, 도구 사용)
  • 인스턴스 instance : 클래스를 통해 만든 객체
    (공통점도 있지만 저마다 개성 존재 가능 ex. 인간 클래스에 속하는 각 사람들)

  • 생성자 함수 : 어떤 공통된 성질을 지니는 객체들을 생성하는데 사용하는 함수
  • 생성사 함수 호출 방법
    • new 명령어와 함께 함수를 호출하면 해당 함수가 생성자로서 동작
  • 어떤 함수가 생성자 함수로서 호출된 경우
    내부에서의 this는 곧 새로 만들 구체적인 인스턴스 자신이 됨
    • 생성자 함수를 호출하면
      생성자의 prototype 프로퍼티를 참조하는 __proto__ 라는 프로퍼티가 있는 객체(인스턴스)를 만들고
      미리 준비된 공통 속성 및 개성을 해당 객체(this)에 부여
      -> 구체적인 인스턴스가 만들어짐
var Cat = function (name, age) { // Cat이란 변수에 익명 함수 할당
  this.bark = '야옹'; // this에 접근해서 bark, name, age 프로퍼티에 각각 값 대입
  this.name = name;
  this.age = age;
};
var choco = new Cat('초코', 7); // new 명령어와 함께 Cat 함수 호출하여 변수 choco, nabi에 각각 할당
// 생성자 함수 내부에서의 this는 choco 인스턴스를 가리킴
var nabi = new Cat('나비', 5);
// 셍상지 힘스 내부에의 this는 nabi 인스턴스를 가리킴
console.log(choco, nabi); // 각각 Cat 클래스의 인스턴스 객체 출력

/*
Cat { bark: '야옹', name: '초코', age: 7 }
Cat { bark: '야옹', name: '나비', age: 5 }
*/

2. 명시적으로 this를 바인딩하는 방법

규칙을 깨고 this에 별도의 대상을 바인딩하는 방법

2-1. call 메서드

: 메서드의 호출 주체인 함수를 즉시 실행 명령

Function.prototype.call(thisArg[, arg1[, arg2[, ...]]])

첫 번째 인자: this로 바인딩, 나머지 인자들 : 호출할 함수의 매개변수

임의의 객체를 this로 지정 가능

var func = function (a, b, c) {
  console.log(this, a, b, c);
};

func(1, 2, 3);					// Window{ ... } 1 2 3
func.call({ x: 1 }, 4, 5, 6);	// { x: 1 } 4 5 6
var obj {
  a: 1,
    method: function (x, y) {
      console.log(this.a, x, y);
    }
};
                 
obj.method(2, 3); 					// 1 2 3
obj.method.call({ a: 4 }, 5, 6); 	// 4 5 6

2-2. apply 메서드

: 메서드의 호출 주체인 함수를 즉시 실행 명령 (call 메서드와 기능 동일)

Function.prototype.apply(thisArg[, argsArray])

첫 번째 인자: this로 바인딩, 두번째 인자 배열: 호출할 함수의 매개변수

임의의 객체를 this로 지정 가능

var func = function (a, b, c) {
  console.log(this, a, b, c);
};
func.apply({ x: 1 }, 4, 5, 6);	// { x: 1 } 4 5 6

var obj {
  a: 1,
    method: function (x, y) {
      console.log(this.a, x, y);
    }
};
                 
obj.method.apply({ a: 4 }, 5, 6); 	// 4 5 6

2-3. call / apply 메서드의 활용

유사배열객체 array-like object에 배열 메서드를 적용

객체에는 배열 메서드 직접 적용할 수 없음
키가 () 또는 양의 정수인 프로퍼티가 존재하고 length 프로퍼티의 값이 () 또는 양의 정수인 객체
즉, 배열의 유사한 객체의 경우 (유사배열객체)
call 또는 apply 메서드를 이용해 배열 메서드를 차용할 수 있음

var obj = {
  0: 'a',
  1: 'b',
  2: 'c',
  length: 3
};
Array.prototype.push.call(obj, 'd'); // 배열 메서드인 push를 객체 obj에 적용해 프로퍼티 3에 'd' 추가
console.log(obj);	// { 0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4 }

var arr = Array.prototype.slice.call(obj); // slice 메서드를 적용해 객체를 배열로 전환
console.log(arr);	// { 'a', 'b', 'c', 'd' }

slice(시작 인덱스값, 마지막 인덱스값)
: 시작값부터 마지막값의 앞부분까지 배열 요소를 추출하는 배열 메서드
매개변수 아무것도 넘기지 않을 경우 원본 배열의 얕은 복사본 반환

arguments. NodeList에 배열 메서드를 적용

함수 내부에서 접근 가능한 arguments 객체도 유사배열객체이므로 배열로 전환해서 활용 가능

function a () {
  var argv = Array.prototype.slice.all(arguments);
  argv.forEach(function (arg) {
    console.log(arg);
  });
}
a(1, 2, 3);

document.body.innerHTML = '<div>a</div><div>b</div><div>c</div>';
var nodeList = document.querySelectorAll('div');
var nodeArr = Array.prototype.slice.call(nodeList);
nodeArr.forEach(function (node) {
  console.log(node);
});

문자열에 배열 메서드 적용 예시

배열처럼 인덱스와 length 프로퍼티를 지니는 문자열도 모든 배열 메서드를 적용 가능
단, 문자열의 경우 length 프로퍼티가 읽기 전용이기 때문에
원본 문자열에 변경을 가하는 메서드 (push, pop, shift, unshift, splice 등)는 에러를 던지며
대상이 반드시 배열이어야 하는 경우 (concat)는 에러는 나지 않지만 제대로 된 결과 얻을 수 없음

var str = 'abc def';

Array.prototype.push.call(str, ', pushed string');
// Error: Cannot assign to read only property 'length' of object [object String]

Array.prototype.concat.call(str, 'string'); // [String {"abc def"}, "string"]

Array.prototype.every.call(str, function(char) { return char !== ''; }); // false
Array.prototype.some.call(str, function(char) { return char === ''; }); // true

var newArr = Array.prototype.map.call(str, function(char) {return char + '!'; });

console.log(newArr);	// ['a!', 'b!', 'c!', ' !', 'd!', 'e!', 'f!']

var newStr = Array.prototype.reduce.apply(str, [
  function(string, char, i) { return string + char + i; },
  ''
]);

console.log(newStr);	// "a0b1c2 3d4e5f6"

사실 call/apply 이용해 형 변환 하는 것은 'this를 원하는 값으로 지정해서 호출한다'는 본래의 메서드 의도와 다름..
slice 메서드는 배열 형태로 복사 하기 위해 차용됐을 뿐 의도 파악하기 어려움

=> Array.from 메서드 : ES6 유사배열객체 또는 순회 가능한 모든 종류의 데이터 타입을 배열로 전환

ES6 Array.from 메서드

var obj = {
  0: 'a',
  1: 'b',
  2: 'c',
  length: e
};
var arr = Array.from(obj);
console.log(arr);			// ['a', 'b', 'c']

생성자 내부에서 다른 생성자를 호출

생성자 내부에 다른 생성자와 공통된 내용이 있을 경우
call/apply 이용해 다른 생성자를 호출하면 간단하게 반복 줄일 수 있음

function Person(name, gender) {
  this.name = name;
  this.gender = gender;
}
function Student(name, gender, school) {
  Person.call(this, name, gender);
  this.school = school;
}
function Employee(name, gender, company) {
  Person.apply(this, [name, gender]);
  this.company = company;
}
var by = new Student('보영', 'female', '단국대');
var jn = new Employee('재난', 'male', '구골');

여러 인수를 묶어 하나의 배열로 전달하고 싶을 때 apply활용

  • 최대/최솟값을 구하는 코드를 직접 구현
var numbers = [10, 20, 3, 16, 45];
var max = min = numbers[0];
numbers.forEach(function(number) {
  if (number > max) {
    max = number;
  }
  if (number < min) {
    min = number;
  }
});
console.log(max, min);	// 45 3
  • 여러 인수를 받는 메서드 (Math.max, Math.min)에 apply를 적용
var numbers = [10, 20, 3, 16, 45];
var max = Math.max.apply(null, numbers);
var min = Math.min.apply(null, numbers);
console.log(max, min);		// 45 3
  • ES6의 펼치기 연산자 활용
    ES6에서 펼치기 연산자 spread operator 이용하면 apply를 적용하는 것보다 더욱 간편하게 작성 가능
const numbers = [10, 20, 3, 16, 45];
const max = Math.max(...numbers);
const min = Math.min(...numbers);
console.log(max, min);		// 45 3

call/apply 메서드
: 명시적으로 별도의 this를 바인딩하면서 함수 또는 메서드를 실행하는 방법
this 예측하기 어려워 코드 해석 방해
ES5이하에서는 대안 없기에 광범위하게 활용


2-4. bind 메서드

Function.prototype.bind(thisArg[, arg1[, arg2[, ...]]])
  • ES5 추가된 기능
  • call과 비슷
  • 즉시 호출하진 않음
  • 넘겨 받은 this 및 인수들을 바탕으로 새로운 함수 반환 메서드
  • 다시 새로운 함수를 호출할 때 인수를 넘기면 그 인수들은
    기존 bind 메서드를 호출할 때 전달했던 인수들의 뒤에 이어서 등록됨
  • bind 메서드 목적
    • 함수에 this를 미리 적용
    • 부분 적용 함수 구현

this 지정과 부분 적용 함수 구현

var func = function (a, b, c, d) {
  console.log(this, a, b, c, d);
};
func(1, 2, 3, 4);		// Window{ ... } 1 2 3 4

var bindFunc1 = func.bind({ x: 1 });
bindFunc1(5, 6, 7, 8);	// { x: 1 } 5 6 7 8

var bindFunc2 = func.bind({ x: 1 }, 4, 5);
bindFunc2(6, 7);		// { x: 1 } 4 5 6 7
bindFunc2(8, 9);		// { x: 1 } 4 5 8 9

name 프로퍼티

  • bind 메서드 적용해서 새로 만든 함수 특징
    • name 프로퍼티에 동사 bind 수동태 bound 접두어 붙음
    • call / apply 추적하기 쉬움
var func = function (a, b, c, d) {
  console.log(this, a, b, c, d);
};
var bindFunc = func.bind({ x: 1 }, 4, 5);
console.log(func.name);		// func
console.log(bindFunc.name);	// bound func

상위 컨텍스트의 this를 내부함수나 콜백 함수에 전달하기

메서드의 내부함수에서 메서드의 this를 그대로 바라보게 하기 위한 방법

  • self
  • call, apply, bind 메서드 이용 추천
  • 내부 함수에 this 전달 call
var obj = {
  outer: function () {
    console.log(this);
    var innerFunc = function () {
      console.log(this);
    };
    innerFunc.call(this);
  }
};
obj.outer();
  • 내부함수에 this 전달 bind
var obj = {
  outer: function () {
    console.log(this);
    var innerFunc = function () {
      console.log(this);
    }.bind(this);
    innerFunc();
  }
};
obj.outer();
var obj = {
  logThis: function () {
    console.log(this);
  },
  logThisLater1: function () {
    setTimeout(this.logThis, 500);
  },
  logThisLater2: function() {
    setTimeout(this.logThis.bind(this), 1000);
  }
};
obj.logThisLater1();	// Window { ... }
obj.logThisLater2();	// obj { logThis: f, ... }

2-5. 화살표 함수의 예외사항

ES6 새롭게 도입된 화살표 함수는 실행 컨텍스트 생성 시 this를 바인딩 과정 제외
화살표 함수에는 this가 아예 없다!
접근할 시 스코프체인상 가장 가까운 this에 접근

  • 화살표 함수 내부에서의 this
  • 별도의 변수로 this를 우회하거나 call/apply/bind 적용할 필요가 없음
var obj = {
  outer: function () {
    console.log(this);
    var innerFunc = () => {
      console.log(this);
    };
    innerFunc();
  }
};
obj.outer();

2-6. 별도의 인자로 this를 받는 경우 (콜백 함수 내에서의 this)

콜백 함수를 인자로 받는 메서드 중 일부는 추가로 this로 지정할 객체(thisArg)를 인자로 지정할 수 있는 경우 있음
thisArg 값 지정하면 콜백 함수 내부에서 this 값을 원하는 대로 변경할 수 있음
여러 내부 요소에 대해 같은 동작을 반속 수행해야 하는 배열 메서드에 많이 포진
ES6에서 새로 등장한 Set, Map 메서드에도 일부 존재

  • forEach 메서드
var report = {
  sum: 0, // 프로퍼티
  count: 0,
  add: function () { // 메서드
    var args = Array.prototype.slice.call(arguments); // 배열 변환 
    args.forEach(function (entry) { // 순회
      this.sum += entry; //
      ++this.count;
    }, this); // 바인딩
  },
  average: function () { 
    return this.sum / this.count;
  }
};
report.add(60, 85, 95);
console.log(report.sum, report.count, report.average());	// 240, 3, 80
  • 콜백 함수와 함께 thisArg를 인자로 받는 메서드
Array.prototype.forEach(callback[, thisArg])
Array.prototype.map(callback[, thisArg])
Array.prototype.filter(callback[, thisArg])
Array.prototype.some(callback[, thisArg])
Array.prototype.every(callback[, thisArg])
Array.prototype.find(callback[, thisArg])
Array.prototype.findIndex(callback[, thisArg])
Array.prototype.flatMap(callback[, thisArg])
Array.prototype.from(arrayLike[, callback[, thisArg]])
Set.prototype.forEach(callback[, thisArg])
Map.prototype.forEach(callback[, thisArg])

profile
사용자 경험을 위해 모험을 떠나는 해구

0개의 댓글