[JS] this 간단 정리

[JS] this 간단 정리

이채현

JavaScript에서 함수의 this 키워드는 다른 언어와 조금 다르게 동작한다.

엄격모드와 비엄격 모드에서도 일부 차이가 있다.

  • this는 scope와 관계가 있다.
  • 객체에도 영향을 준다.
  • this가 어디에 묶여있냐를 아는 것이 코드를 작성하는 시점, 동작하는 시점에 차이가 있을 수 있다.

(함수를 어떻게 호출했는지 상관하지 않고 this값을 설정할 수 있는 bind메서드를 도입했고, ES2015는 스스로의 this 바인딩을 제공하지 않는 화살표 함수 를 추가했습니다.)

암시적 바인딩

암시적인 this 바인딩.. 사용자가 생각하지 않은대로 동작할 수 있다.

전역 공간에서의 this

  • node.js 환경에서의 this는 global
  • 브라우저에서의 this는 window

함수

  • 함수에서의 this는 window ⇒ 전역공간에서의 this와 다르지 않다.

객체 (메서드)

  • this는 호출되는 대상의 객체를 가리키고 있다.
1
2
3
4
5
6
7
8
const obj = {
name: 'obj',
method: function() {
return this.name
}
}

obj.method() // 'obj'

명시적 바인딩

  • call(), bind(), apply()
1
2
3
4
5
6
7
8
9
10
11
12
13
const person = {
name: 'Lee',
sayName: function () {
return this.name + '입니다';
}
}

const zero = {
name: '베이스',
sayName: function () {
return this.name + '입니다';
}
}
  • call()
1
2
3
4
5
function sayFullName(firstName) {
return firstName + this.sayName()
}
const result = sayFullName.call(person, 'Chaehyeon ');
// Chaehyeon Lee입니다.
  • apply()
1
2
3
4
5
6
function sayFullName(firstName) {
return arguments[1] + this.sayName()
}

const result = sayFullName.apply(person, ['Chaehyeon ','채현 ']);
// 채현 Lee입니다.
  • bind()
    • this를 묶어서 사용가능한다.

    • React Class Component에서 사용했다.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      function sayFullName(firstName) {
      return firstName + this.sayName()
      }

      const sayFullNamePerson = sayFullName.bind(person);
      const sayFullNameZero = sayFullName.bind(zero);
      console.log(sayFullNamePerson('Chaehyeon'));

      // ChaehyeonLee입니다
[JS] 스코프 간단 정리

[JS] 스코프 간단 정리

이채현

전역 스코프 (Global)

  • 그냥 가장 바깥쪽
  • 언제 어디서나 접근 가능하기 때문에 재정의가 가능하다 ← 큰 문제
    • 그 결과, 프로그램의 실행 결과 때 내가 만든 변수들의 결과를 예측하기 어려워짐 → 팀 단위로 개발할 때 최악

지역 스코프

함수 스코프

블록 스코프

1
2
3
4
5
6
7
8
9
{
// 블록
}

function func() { // 함수 스코프 블록
}

if (true) { // 블록 스코프 블록
}

전역 객체

브라우저

⇒ window

NodeJS

⇒ Global

// this

  • 브라우저에서 호출하면 window불러옴

호이스팅 (Hoisting)

1
2
3
4
5
6
7
8
9
function foo() {
console.log(hoist); // undefined

var hoist = '호이스팅';

console.log(hoist); // 호이스팅
}

foo();
  • 첫번 째 console.log가 오류나지 않는 이유는

    • 변수 선언을 직접적으로 끌어올림
    • 그래서 위 코드와 아래 코드랑 같다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function foo() {
    var hoist; // 1. 변수 선언
    console.log(hoist); // undefined // 2. 실행

    hoist = '호이스팅'; // 3. 재할당
    console.log(hoist); // 호이스팅
    }

    foo();

애초부터 var를 안쓰면 된다.

1
2
3
4
5
6
7
8
9
function foo() {
console.log(hoist); // Cannnot access 'hoist' before initialization

let/const hoist = '호이스팅';

console.log(hoist); // 호이스팅
}

foo(); // Cannnot access 'hoist' before initialization
  • 임시적 사각지대 (TDZ)가 생긴다.
  • 내부적으로 호이스팅이 일어나지만, 사용자에게는 보이지 않는것처럼 에러를 준다.

IIFE (즉시 실행 함수 표현)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function func() {

}

func();

==>

(function () {

})();

(function (num) {
console.log(num); // 1
})(1);

함수를 괄호안에 넣고 바로 실행

  • 함수 공간을 완전히 분리할 수 있기 때문에 사용한다.
    • 그래서 let/const가 없을 때에 사람들이 외부에서 접근할 수 없게 블록스코프를 흉내내게 사용했다.
[JS] 자료 다루기

[JS] 자료 다루기

이채현

객체

Object.keys()

  • 객체의 키들이다~~라는 느낌으로 객체의 키들이 배열로 반환된다.
1
2
3
4
5
6
7
8
const object1 = {
a: 'somestring',
b: 42,
c: false
};

console.log(Object.keys(object1));
// expected output: Array ["a", "b", "c"]

Object.values()

  • 객체의 값들이다~~라는 느낌으로 객체의 Value들이 배열로 반환된다.
1
2
3
4
5
6
7
8
const object1 = {
a: 'somestring',
b: 42,
c: false
};

console.log(Object.values(object1));
// expected output: Array ["somestring", 42, false]

Object.entries()

  • 객체를 인자로 받아, key와 value를 쌍으로 가진 배열을 반환한다.
  • for…in와 같은 순서로 주어진 객체 자체의 enumerable 속성을 가짐
    • 인덱스마다 배열을 가져서, 첫번째가 key, 두번째가 value이다.
      • 배열안에 배열
1
2
3
4
5
6
7
8
9
10
11
12
const object1 = {
a: 'somestring',
b: 42
};

for (const [key, value] of Object.entries(object1)) {
console.log(`${key}: ${value}`);
}

// expected output:
// "a: somestring"
// "b: 42"

배열

요소 추가와 제거

  • unshift ⇒ 배열의 앞에 요소 추가

  • push ⇒ 배열의 끝에 요소 추가

  • shift ⇒ 배열의 앞에 요소 제거

  • pop ⇒ 배열의 끝에 요소 제거

  • splice ⇒ 배열의 인덱스를 기반으로 요소 추가 및 제거

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    array.splice(start[, deleteCount[, item1[, item2[, ...]]]])

    const months = ['Jan', 'March', 'April', 'June'];
    months.splice(1, 0, 'Feb');
    // inserts at index 1
    console.log(months);
    // expected output: Array ["Jan", "Feb", "March", "April", "June"]

    months.splice(4, 1, 'May');
    // replaces 1 element at index 4
    console.log(months);
    // expected output: Array ["Jan", "Feb", "March", "April", "May"]

요소 병합

  • concat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const array1 = ['a', 'b', 'c'];
const array2 = ['d', 'e', 'f'];
const array3 = array1.concat(array2);

console.log(array3);
// expected output: Array ["a", "b", "c", "d", "e", "f"]

const alpha = ['a', 'b', 'c'];

alpha.concat(1, [2, 3]);
// 결과: ['a', 'b', 'c', 1, 2, 3]

--------

const newArr = [...array1, ...array2];
// ['a', 'b', 'c', 'd', 'e', 'f']

고차 함수로 조작 (내장 메서드)

  • 대표적으로 map, filter, reduce

map

1
2
3
4
5
const langs = ['JS', 'HTML', 'CSS'];

const newLangs = langs.map(lang => lang + ' 언어');
console.log(newLangs);
// [ 'JS 언어', 'HTML 언어', 'CSS 언어' ]

filter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const langs = ['JS', 'HTML', 'CSS', 0, 1, 2, 3];

const numbers = langs.filter(lang => {
if (typeof lang === 'number') {
return true;
}
});
console.log(numbers);
// [ 0, 1, 2, 3 ]

const strings = langs.filter(lang => {
if (typeof lang === 'string') {
return lang;
}
})
console.log(strings)
// [ 'JS', 'HTML', 'CSS' ]
const isNumber = function (el) {
if (typeof el === 'number') {
return true;
}
}
const numbers = langs.filter(isNumber);
console.log(numbers)

const isString = (el) => typeof el === 'string';
const strings = langs.filter(isString)
console.log(string)

// [ 0, 1, 2, 3 ]
// [ 'JS', 'HTML', 'CSS' ]

reduce

  • 그전에 전형적인 명령어 프로그래밍 방식
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// argument로 받거나
// 인자에 spread형식으로 받거나...

function sumTotal() {
let temp = 0;
for (let i = 0; i < arguments.length; i++) {
temp = temp + arguments[i];
}
return temp;
}

console.log(sumTotal(1, 2, 3, 4, 5, 6, 7));
// 28
function sumTotal(...numbers) {
let temp = 0;
// reduce((누적값, 현재값){},초기값)
return numbers.reduce((total, current) => total + current, 0);
// 첫번째는 초기값(total(0))+ 인자(1)이 total로 들어가고
// 그 다음 total(1)+인자(cur(2))
}

console.log(sumTotal(1, 2, 3, 4, 5, 6, 7));

요소 정렬

sort

1
2
3
4
5
6
7
8
9
10
const numbers = [4, 2, 5, 1, 3];

const orderNumbers = numbers.sort((a, b) => a - b)
console.log(orderNumbers);
// [ 1, 2, 3, 4, 5 ]

const strings = ['마', '가', '라', '나', '다'];
const orderStrings = strings.sort((a, b) => a.localeCompare(b));
console.log(orderStrings);
//[ '가', '나', '다', '라', '마' ]

값 검색

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const strings = ['마', '가', '라', '나', '다'];

const result = strings.find((string) => string === '나');
console.log(result);
// 나 ///없으면 undefinded

const result = strings.findIndex((string) => string === '나');
console.log(result);
// 3

const result = strings.indexOf('나'); // 왼쪽부터,,, lastIndexOf()
console.log(result);
// 3

const result = strings.includes('나');
console.log(result);
// true
[JS] Object 객체

[JS] Object 객체

이채현

객체 생성

일반적으로 생성 할 수 있는 객체

싱글 리터럴 (Literal) 객체

1
2
3
4
const object = {
property: 'value',
method: function () {},
}

생성자 함수 객체 // PascalCase

1
2
3
4
5
function NewObject(name) {
this.name = name;
}

const newObject = new NewObject(’Lee’);

파스칼 케이스 → 암묵적, 명시적 생성자 함수

Object.Create()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const newObject2 = Object.create(Object.prototype, {
name: {
value: 'lee',
writable: true, // 덮어쓸 수 있는지
enumerable: true, // forin문과 같은 것으로 열거할 수 있는지
configurable: true, // 객체 기술자를 수정할 수 있는지
},
});
// const newObject2 = Object.create(프로토타입, 객체 서술자(기술자));

newObject2.name = 'Kim';

for (const key in newObject2) {
console.log(key);
}

프로퍼티 열거

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const obj = {
prop1: 'value1',
prop2: 'value2',
prop3: 'value3',
prop4: 'value4',
};

const prop = 'prop';
const prop1 = 'prop1';

obj.prop1 // value1
obj['prop1'] // value1
obj[prop + 1] // value1
obj[prop1] // value1

for (const key in obj) {
console.log(key); // prop1, prop2, prop3, prop4
console.log(obj[key]); // value1, value2, value3, value4
}

체인닝 방지를 위해

블록 스코프 내에 변수가 없으면 그 위로 찾아 간다…

1
2
3
4
5
6
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(obj[key]); // value1, value2, value3, value4
}
}
// 상속되거나 확장되어 사용 된 객체의 상위에서 꺼내오지 않도록 하는 방어문

프로퍼티 조작

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const person = {
firstName: "Chaehyeon",
location: "Korea",
}

// 추가
person.lastName: "Lee"
// 수정
person.lastName: "lee"
// 삭제
delet person.location;

person; // { firstName: "Chaehyeon", lastName: "lee" }

// const는 재할당을 막는 것... 그래서 가능

프로퍼티 접근자 (getter, setter)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 추가, 수정, 삭제 등을 접근해서 조작할 때 안전하게 하기 위해
const person = {
_firstName: "Chaehyeon",
lastName: "Lee",

get firstName() {
return this._firstName.toUpperCase();
}

set firstName(newFirstName) {
if (typeof newFirstName !== 'string') {
this._firstName = 'undefinedName';

return;
}

this._firstName = newFirstName;
}

get fullName() {
return this._firstName + this.lastName + '입니다'.
}
}

// console.log(person.firstName); // CHAEHYEON
// console.log(person.fullName); // LeeChaehyeon입니다

person.firstName = 12345;
console.log(person.firstName); // UNDEFINDEDNAME

인스턴스

OOP

인스턴스 === 유일한, 고유한 객체?

객체 하나하나가 곧 인스턴스이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const me = {
name: 'chaehyeon',
age: 26,
locaiton: 'korea',
};

const me2 = {
name: 'chaehyeon',
age: 26,
locaiton: 'korea',
};

console.log(me === me2); // false
console.log(me.name === me2.name); // true

// 객체 그 자체를 비교할 때에는 객체의 메모리 주소를 본다.
// 당연히 메모리주소는 다르다

생성자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const me = {
name: 'chaehyeon',
age: 26,
locaiton: 'korea',
};

// 객체를 자주 만들고 싶을 때 -> 생성자 함수
function Person(name, age, location) {
this.name = name;
this.age = age;
this.location = location;

this.getName = function () {
return this.name + ' 입니다';
}
}
// 여기서 this는 "생성 될" 인스턴스를 가리킨다.

const me2 = new Person('ChaehyeonLee', 26, 'korea');
// Person { name: 'ChaehyeonLee', age: 26, location: 'korea' }

const you new Person('Kim', 20, 'korea');
// Person { name: 'Kim', age: 20, location: 'korea' }