본문 바로가기
JavaScript/JavaScript 수업

JavaScript 수업 | [deep dive] 10~

by 히욤 2021. 9. 13.

안물어본다!! 

위의 메모리 구조를 사용하고 있을지 모른다.

Heap, Call stack 안나온다. 모른다.

V8엔진이나, 스파이더 몽키,.. 엔진마다 다르다. 하지만 표준은 아니다. (ECMAScript)

원시값들은 내부적으로 객체 프로퍼티에 저장된다.

Heap은 논리적인 개념임...

 

객체를 상태로 가지고 있을 경우 불변성을 유지해야한다.

push, pop, shift, unshift 사용해서는 안된다!

 

원시값을 담은 변수는 수정하면 주소값이 바뀜.

객체를 담은 변수는 수정해도 주소값은 그대로임.

따라서 객체가 변경되었는지 확인할 방법이 없음

그래서 요즘엔 객체를 불변값으로 사용하려고 하고있다.

 

 

  • Number.isNaN, isNaN

Number.isNaN: NaN일때만 true

isNaN: 숫자로 변환한 다음 NaN인지 

 

  • 함수 이름

함수 표현식을 사용할 때는 기명함수를 사용하지 않는게 좋다

화살표 함수는 무명 함수 표현식을 사용해야함.

 

 

  • 프로퍼타입 기반 객체지향 = 자바스크립트

객체 리터럴(표현식)로 객체를 생성할 수 있음.

객체에 프로퍼티를 추가하거나 삭제하는게 가능함! 따라서 히든 클래스라는 비효율적인 방법으로 관리하게 된다..

하지만 동적으로 추가하고 삭제하는 것은 조금 느리긴하지만, 체감하기 어려운 정도니 자유롭게 써먹자~

히든클래스 세부적으로는 몰라도 된다~ 표준도 아니다. V8이 그렇게 만들어졌다!

객체를 만드는 함수는 ordinary object create 인데, 표준은 그걸 상세하게 알려주진 않음.

회사가 자기 재량 것 만들면된다!

 

  • 클래스 기반 객체지향 = 자바

클래스를 먼저 정의해야 객체를 생성할 수 있음.

클래스를 이미 생성했으면 객체에 프로퍼티를 추가하거나 삭제하는게 불가능함.

 

 

 

 

10장

 

프로퍼티 축약 표현

용어를 알아두자. 되게 많이 사용된다!

객체 리터럴의 프로퍼티 값은 변수에 할당된 값, 즉 식별자 표현식일 수도 있다.

ES6에서 프로퍼티 값으로 변수를 사용하는 경우, 변수 이름과 프로퍼티 키가 동일한 이름일 때 프로퍼티 키를 생략할 수 있다.

이때 프로퍼티 키는 변수 이름으로 자동 생성된다.

 

계산된 프로퍼티 이름

객체리터럴 내부에서도 만들 수 있게 되었다

 

메서드 축약 표현

ES5 때 function키워드를 작성해서 썼는데,

function 무조건 쓰지 않는 ES6문법을 따라야함.

 

일반함수, 생성자함수, 메서드함수의 미묘한 차이 => this와 관련있다.

 

메서드가 아님

  // ES5
  var obj = {
    name: "Lee",
    sayHi: function () { // 그냥 함수
      console.log("HI " + this.name);
    },
  };
  obj.sayHi();

 

 

메서드임

  // ES6
  const obj = {
    name: "Lee",
    sayHi() { // 메서드
      console.log("HI " + this.name);
    },
  };
  obj.sayHi();

=> ECMAScript는 위를 메서드라고 판단함.

 

 

 

 

11장 원시 값과 객체의 비교

 

  • 원시 타입(기본형/ 기본타입) == primitive

변경 불가능한 값이다. immutable

원시값은 한번 만들어지면 바꿀 수 없다.

변경 불가능하다는 것은 변수가 아니라 값에 대한 진술이다.

 

원시 값은 변경 불가능하다

=> 원시 값 자체를 변경할 수 없다. 

=> 하지만 변수 값은 변경 가능하다! 변수는 언제든 재할당 할 수 있다.

 

원시 값이 변경가능하다면 신뢰성이 없다.

var a = 1; 
var b = a; 
a = 2; 
b = ? // 기대하는 값 1
// 메모리 셀에 1이 저장되어 있고 a, b가 같은 곳을 가리키고 있다.
// 다음 a가 새로운 메모리 셀을 참조해야 원하는 값을 얻을 수 있다.

메모리가 값을 다루는 기본적인 방식!

두 가지 방법 중 엔진마다 선택이 다르다.

재할당이 일어날 때만 식별자가 다른 메모리 주소를 가리키게 하면 된다.

 

즉 원시값이 재할당 되면, 값이 복사되어 전달된다고 생각하면 된다.

값에 의한 전달.

 

 

 

  • 객체 타입(참조 타입) == object

변경 가능한 값이다. mutable

객체는 원시값에 비해서 시간복잡도도 크고 공간복잡도고 크다!

크기도 크고 복잡하다.

 

<과제>

function isEqueal(obj1, obj2) {
  // 두 객체의 동일한 프로퍼티가 있고, 값도 다 똑같은지 확인해라
}
function deepCopy(obj) {
  // 입력 객체를 깊은 복사해서 만든 값을 반환함
}

 

얕은복사

built in으로 복사하면 전부 얕은복사이다.

{...obj}

얕은 복사: 객체를 한 단계 까지만 복사

Object.assign도 얕은 복사임
스프레드 연산자로 얕은복사

 

 

깊은 복사 

깊은 복사: 객체에 중첩되어 있는 객체까지 모두 복사

 

 

 

12장 함수

 

 

 

return 의미 2개

함수 몸체 바깥으로 값을 전달하는 것,

함수를 종료함

 

매개변수는 var키워드로 선언되었다고 봐야함

 

  function add(x, y) {
    // 매개변수는 var로 선언된것으로 봐야함.
    var x = 1;
    var y;

    return x + y; // NaN
  }
  add(1); // 인수 갯수를 조금 줌

 

위와 같이 인수 갯수를 조금 준다면.. arguments length를 확인한다.

arguments객체는 유사배열 객체다

  function add(x, y) {
    if (arguments.length < 2) throw new TypeError("Error!");

    return x + y;
  }
  console.log(add(1));

 

단, 화살표 함수는 arguemnts 객체를 가지지 않는다...

  const add = (...args) => {
    if (args.length < 2) throw new TypeError("Error!");
    return x + y;
  };
  console.log(add(1));

 

타입스크립트를 사용하면 다음과 같이 하면 된다.

  const add = (x: Number, y:Number) => {
    return x + y;
  };
  console.log(add(1));

 

 

  var add = function (x, y) {
    return x + y;
  };

  console.log(add(1, 2)); 
  // ()는 함수 호출 연산자, add는 식별자로 함수 객체를 가리켜야한다.

 

함수 선언문 vs 함수 리터럴

함수 리터럴 : function () {}; 

함수 표현식 : var x = function () {};

 

함수 선언문과 함수 리터럴은 거의 성능이 비슷하다.

혼용하지만 않으면 된다.

하지만 화살표 함수를 사용하는게 best다.

 

 

함수 vs 연산자

Math.pow vs **

 

함수는 매개변수가 필요하다. 매개변수의 순서와 갯수를 알고있어야함.

연산자는 그런 정보가 필요없다.

 

 

변수 할당은 잘 고려해서 해야함.

  $.ajax({ // 이 객체는 변경되지 않음
    method: "POST",
    url: "/user",
    data: { id: 1, name: "Lee" },
    cache: false,
  });
  
  //----------------------
  
  var opt = { // 변경될 여지가 있음.
    method: "POST",
    url: "/user",
    data: { id: 1, name: "Lee" },
    cache: false,
  };
  // 비순수함수
  $.ajax(opt);

 

 

즉시 실행 함수

한번 밖에 사용할 수 없음.

전역변수 안쓰려고.. 예전에는 즉시 실행 함수를 씀

지금은 클로저를 만들기 위해서 사용한다.

 

함수 리터럴을 평가해 함수 객체를 생성해야 즉시 실행 함수를 사용할 수 있다.

(function () {
  // ...
}());

// ESLint
// 화살표함수는 아래와 같이 괄호를 바깥에 써줘야함.
(function () {
  // ...
})();

두 번째 방법을 사용하자

 

 

 

 

재귀 함수

반복문 보다는 재귀가 가독성이 더 좋다.

재귀는 선언형에 속한다.

사실 재귀는 반복문 보다는 리소스를 많이 사용한다.

 

 

 

중첩 함수

중첩은 우리에게 큰 의미가 있다!

함수는 함수 내부에서도 정의할 수 있다.

 

외부함수 내에서만 사용할 수 있게 만들어서, 

재사용과 가독성의 관점에서 중첩함수를 사용할 수 있다.

외부함수는 중첩함수의 로직에 강하게 의존하고있다.

 

 

콜백 함수

함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수를 콜백 함수이라고 한다

고차함수 HOF

 

고차함수는 여러가지 다양한 함수 콜백함수로 입력받을 수 있따.

중첩함수를 내부에 선언하지 않고 외부에서 받자.

현 상황에서 무엇을 해야할 지 모르니까 콜백함수 받자!

재사용과 가독성도!!

 

// for문을 감추어 함수로 선언함.
function repeat(n, f) { // HOF
  for (var i = 0; i < n; i++) {
    f(i); // i를 전달하며 f를 호출
  }
}

// Callback function1
var logAll = function (i) {
  console.log(i);
};

repeat(5, logAll); // 0 1 2 3 4

// Callback function2
var logOdds = function (i) {
  if (i % 2) console.log(i);
};

repeat(5, logOdds); // 1 3

// Callback function3
// 익명 함수 리터럴은 repeat 함수를 호출할 때 마다 평가되어 함수 객체를 생성
repeat(5, function (i) {
  if (i % 2) console.log(i);
}); // 1 3

 

 

- predicate : true / false를 반환하는 함수

 

 

비동기 함수

// 비동기 함수
setTimeout(function (){
    console.log('1초 경과');
}, 1000);

setTimeout은 비동기 함수로서 브라우저에게 1초뒤에 콜백함수를 불러달라고 전달해준다.

자바스크립트 엔진은 싱글 스레드이기때문에 한번에 한가지 일밖에 하지 못한다.

하지만 브라우저는 멀티스레드라서 여러가지 일을 할 수 있다.

만약 setTimeout이 콜백을 하지않고 본인이 1초를 센다면, setTimeout이후의 코드는 실행되지 못하고 1초가 지나야한다.

따라서 브라우저가 콜백함수를 받고 1초 뒤에 그를 실행해준다. 

 

 

 

순수함수 비순수함수

 

  • 순수함수

테스트하기 편하다. 동일한 입력, 동일한 출력

외부상태를 바꾸지 않는다. 즉 부수효과가 발생하지 않는다.

 

  • 비순수함수

테스트하기 어렵다.

외부상태를 바꾸고, 그 사실을 알아차리기가 어렵다.

외부상태에 의존한다.

 

 

순수함수로만 애플리케이션을 만드는건 어렵다.

하지만 순수함수로만 만들 수 있다면? 순수함수로 만들도록 노력하자.

 

  var counter = {
    n: 0,
    increase() { // 비순수함수
      this.n += 1;
    },
  };
  counter.increase();
  counter.n = -100; // 문제!!

 

외부 상태 n에 의존하는 비순수함수다.

따라서 n을 수정할 수 있는 것은 increase만 가능하게 하면 됨 => 클로저로 해결가능!

 

 

 

 

 

 

 

 

 

 

 

'JavaScript > JavaScript 수업' 카테고리의 다른 글

JavaScript 수업 | 6장~9장  (0) 2021.09.08
JavaScript 수업 | 1~5장  (0) 2021.09.06