js의 특성

이재근·2022년 5월 19일
0
post-thumbnail

js의 자료형과 js만의 특성.

js는 느슨한 타입(loosely typed)의 동적(dynamic)언어입니다.

js의 변수는 어떤 특정 타입과 연결되지 않으며, 모든 타입의 값으로 할당 (및 재할당)이 가능합니다.

let foo = 42 // foo가 숫자

foo = 'bar' // foo가 이제 문자열

foo = true // foo가 이제 불리언

이 num str 을 서로 바꿔줄 수 있는데

let 변수 = parseInt(문자); //문자를 정수형 숫자로 변환해줌

let 변수 = parseFloat(문자); //문자를 실수형 숫자로 변환해줌

let 변수 = Nember(문자); //문자를 정수&실수형 숫자로 변환해줌

등을 사용합니다.

'==, ==='

==과 ===을 이용해 동급인가 아닌가 boolean을 알 수 있는데

==은 특정 타입(srt, num)인가와 대소문자를 무시하고 같은 문자, 숫자일 경우 같음(true)로 인정하지만

===는 형이 같은지. 대소문자는 일치하는지 를 모두 확인한 후 같은 형의 문자(숫자)일 경우 같음을 인정(true)해 줍니다.

느슨한 타입의 동적 언어의 문제점과 보완점.

1.유연성과 편리함을 갖춘 대신 안정성과 신뢰성이 떨어진다.
소스 코드가 외부에 노출되어 악용 될 가능성이 있다.

2.자바스크립트는 컴파일 과정이 아닌 런타임 과정에서 에러를 확인할 수 있기 때문에 프로그래머가 버그를 발견하고 대처하기가 쉽지 않다. 일일이 log를 확인하지않는 한 런타임 과정에서 문제가 발견된다.

보완점 1. https://를 사용하여 데이터를 암호화 시키고 쿠키 설정을 안전하게 하는 것.
api에 집중하여 보안을 강화 시킨다.

2. 런타임 과정에 가능한 한 여러 변수를 입력해보고 중간 중간 log를 띄워 확인해 본다.

undefined와 null의 차이.

undefined와 null 둘 다 '값없음'을 나타내는 타입인데

undefined는 어떤 설정도 하지 않았을 떄 값이 없음을 나타내는 타입이라고 할 수 있고

null은 true나 false처럼 어떤 상태를 말하는데 그 상태가 '없음'을 말할 때 null을 사용합니다. 실제 반환값이 null이 나오기 위해서는 코드에서 let a = null과 같은 타입 지정을 해준 후 이 a의 타입을 요청했을 때 반환 값이 null이 나오게 됩니다.

js 객체와 불변성이란?

js의 특징적 자료형 '객체'

Boolean 타입
Null 타입
Undefined 타입
Number 타입
BigInt 타입
String 타입
Symbol 타입
객체 (속성의 컬렉션)

js에는 위와같이 8가지의 자료형이 존재하는데, 일곱 개는 오직 하나의 데이터(문자열, 숫자 등)만 담을 수 있어 '원시형(primitive type)'이라 부릅니다.

이와 다르게 객체는 원시형과 달리 다양한 데이터를 담을 수 있습니다.

객체는 중괄호 {…}를 이용해 만들 수 있습니다. 중괄호 안에는 ‘키(key): 값(value)’ 쌍으로 구성된 프로퍼티(property) 를 여러 개 넣을 수 있는데, 키엔 문자형, 값엔 모든 자료형이 허용됩니다.

let user = new Object(); // '객체 생성자' 문법
let user = {}; // '객체 리터럴' 문법

입력할 때는 다음과 같은 모양으로

let user = { // 객체
name: "John", // 키: "name", 값: "John"
age: 30 // 키: "age", 값: 30
};

값을 꺼내올 때는 다음과 같은 모양으로 꺼내옵니다.

console.log(user.name); // John
console.log( user.age ); // 30

불변 객체를 만드는 방법.

먼저 불변객체를 만들기 전에 불변 객체의 뜻에 대해 잠깐 알고가자.

불변 객체(immutable object)란 생성 후 상태를 바꿀 수 없는 객체를 말한다.

재할당은 가능하지만, 한번 할당하면 내부 데이터를 변경할 수 없는 객체이며

객체에 값을 할당하면 내부 데이터를 변경시킬 수 없는 객체입니다.

원시 타입일 경우 불변 객체를 만드는 방법은 다음과 같습니다.

public class BaseObject {

private final int value;

public BaseObject(final int value) {
    this.value = value;
}

원시 타입만 있는 경우 final 키워드를 사용해 불변 객체로 만들 수 있습니다.

참조 타입이 있는 경우

참조 타입이 있는 경우에는 경우의 수가 나뉘는데

(1) 참조 변수가 일반 객체인 경우

이 상황은 위의 예제를 고쳐보면 될 것입니다.
따라서 이는 참조 변수인 Age도 불변객체로 만들어 해결할 수 있습니다.

public class Animal {

private final Age age;

public Animal(final Age age) {
    this.age = age;
}

// getter

}

class Age {

private final int value;

public Age(final int value) {
    this.value = value;
}

// getter

}

(2) Array일 경우
public class ArrayObject {

private final int[] array;

public ArrayObject(final int[] array) {
    this.array = Arrays.copyOf(array,array.length);
}


public int[] getArray() {
    return (array == null) ? null : array.clone();
}

}
배열일 경우에는 생성자에서 배열을 받아 copy해서 저장하도록 했고,
getter를 clone을 반환하도록 하면 됩니다.
배열을 그대로 참조하거나, 그대로 반환할 경우 외부에서 배열 내부값을 변경시킬 수 있기 때문에, clone을 반환하게 되면 외부에서 값을 변경시킬 수 없습니다.
만약 원시 타입 배열이 아니고, Animal[]과 같은 형태라면 해당 객체는 불변객체이어야 합니다.

마지막으로

3) List인 경우
List인 경우에도 Array와 마찬가지로 생성시 생성자 인자를 그대로 참조하지 않고, 새로운 List를 만들어 값을 복사하도록 해야합니다. 그리고 getter를 통해 값 추가/삭제가 불가능하도록 Collection의 unmodifiableList 메서드를 사용했습니다.

여기서 Animal은 앞서 만든 불변객체입니다.

public static void main(String[] args) {
List animals = new ArrayList<>();
animals.add(new Animal(new Age(1)));

ListObject listObject = new ListObject(animals);

for (Animal animal : listObject.getAnimals()) {
    System.out.print(animal.getAge().getValue());
}
System.out.println();
// Output: 1

animals.add(new Animal(new Age(2))); // List인 animals에는 추가되지만 listObject의 List에는 추가되지 않는다

for (Animal animal : listObject.getAnimals()) {
    System.out.print(animal.getAge().getValue());
}
System.out.println();
// Output: 1

}

얕은 복사와 깊은 복사

얕은 복사(shallow copy)란?

객체를 직접 대입하는 경우 참조에 의한 할당이 이루어지므로 둘은 같은 데이터(주소)를 가지고 있다.
이것이 얕은 복사이다.

깊은 복사(Deep copy)
깊은 복사는 주소값을 참조하는 것이 아닌, 새로운 메모리 공간에 값을 복사하는 것이기 때문에 원본 배열이 변경되어도 복사된 배열에 전혀 상관이 없다.
따라서 배열을 복사한 후에 한쪽 값을 수정해도 다른 배열에 영향을 끼치지 않는다.

만드는 방법에 대해 궁금해진다면 다음의 링크를 따라가 보자.
https://woovictory.github.io/2020/04/22/Java-Array-Copy/

호이스팅과 TDZ는 무엇일까 ?

호이스팅은 함수 안에 있는 선언들을 모두 끌어 올려 해당 함수 유효 범위의 최상단에 선언하는 것을 말합니다.

Temporal Dead Zone(TDZ)이란?

선언 전에 변수를 사용하는 것을 비 허용하는 개념상의 공간입니다.

TDZ는 const, let, class는 TDZ에 영향을 받습니다. 즉 const, let, class는 선언 전에 변수를 사용하는것을 허용하지 않습니다.

반대로 var, function, import의 선언은 TDZ의 영향을 받지 않습니다. 특히 var 변수는 선언 전에도 사용할 수 있는 점에서 var 변수 사용을 피해 예기치 못한 오류를 방지하는 것이 좋습니다.

변수가 먼저 선언이 된 경우, 초기화에 따라서 TDZ가 생깁니다. 특히 let,const와 var는 초기화 시점이 다릅니다. var는 암묵적으로 undefined로 초기화 된 상태에서 자바스크립트 코드를 읽기 때문에, TDZ에서 에러가 나지 않습니다.

함수 선언식과 함수 표현식의 차이

주요 차이점은, 호이스팅에서 차이가 발생합니다.

함수 선언식은 함수 전체를 호이스팅 합니다. 정의된 범위의 맨 위로 호이스팅되서 함수 선언 전에 함수를 사용할 수 있다는 것입니다.

함수 표현식은 별도의 변수에 할당하게 되는데, 변수는 선언부와 할당부를 나누어 호이스팅 하게 됩니다. 선언부만 호이스팅하게 됩니다.

Execution Context

Execution Context 는 자바스크립트의 핵심 개념으로, 코드를 실행하기 위해 필요한 환경이다.
더 자세히 말하자면, 실행할 코드에 제공할 환경 정보들을 모아놓은 객체이다.
자바스크립트의 동적 언어로서의 성격을 가장 잘 파악할 수 있는 개념.
모든 코드는 특정한 실행 컨텍스트 안에서 실행된다.
javascript는 어떤 execution context가 활성화되는 시점에 선언된 변수들을 위로 끌어올리고(hoisting), 외부 환경 정보를 구성하고, this값을 설정하는 등의 동작을 수행하는데, 이로 인해 다른 언어에서는 발생할 수 없는 특이한 현상들이 발생한다.

자바스크립트의 주요한 실행 컨텍스트에는 두 가지가 있다.

Global Execution Context
디폴트 실행 컨텍스트로, 자바스크립트 파일이 엔진에 의해 처음 로드되었을 때 실행되기 시작하는 환경이다.

Fuction Execution Context
우리가 execution context를 따로 구성하는 방법은 함수를 실행하는 것 뿐이다. 함수가 호출되고 실행됨에 따라서 해당 함수 안에서 생성되는 컨텍스트. 각각의 함수는 고유의 실행 컨텍스트를 가진다. 그리고 전역 실행 컨텍스트에 언제나 접근할 수 있다.

callstack

call은 호출을 뜻한다.
stack은 출입구가 하나뿐인 깊은 우물 같은 데이터 구조다.

따라서 callstack은 자바스크립트가 함수 호출을 기록하기 위해 사용하는 우물 형태의 데이터 구조이다.

항상 맨 위에 놓인 함수를 우선으로 실행된다. 이런 식으로 자바스크립트 엔진은 가장 위에 쌓여있는 context와 관련 있는 코드들을 실행하는 식으로 전체 코드의 환경과 순서를 보장한다.

스코프 체인(scope chain)이란?

스코프 체인(Scope Chain)은 일종의 리스트로서 전역 객체와 중첩된 함수의 스코프의 레퍼런스를 차례로 저장하고, 의미 그대로 각각의 스코프가 어떻게 연결(chain)되고 있는지 보여주는 것을 말한다.

하지만 스코프 체인(scope chain)을 이해하려면 실행 컨텍스트(execution Context)를 이해해야하는데이는 위의 글로벌 실행 컨텍스트, 펑션 실행 컨텍스트를 의미한다.

은닉화(Information Hiding)란 ?

정의
외부 객체로부터 '속성 값(데이터, 멤버 변수값)'을 감추는 특성

조건

접근제어자 private로 감춘다. (private - class내에서만 접근가능)

private를 사용하는 이유 ?

외부로부터 데이터를 보호(캡슐화)하기 위해서
인스턴스 변수는 private로 하여 외부에서 접근하지 못하도록 하고, 메서드는 public으로 하여 직접 접근은 막고 메서드를 통한 간접 접근 허용

외부에는 불필요한, 내부적으로만 사용되는 , 부분을 감추기 위해서

접근 방법

setter : 수정한다.

getter : 읽는다.

이상 js의 기본 개념들이다. 위 만해도 내용이 적지않지만 이 외에도 특성이 많이 있으니 부지런히 하나씩 찾아보도록 하자. 시간이 된다면 정리해서 추후 업로드하도록 하자.

실습과제
let b = 1;

function hi () {

const a = 1;

let b = 100;

b++;

console.log(a,b);

}

//console.log(a);

console.log(b);

hi();

console.log(b);
콘솔에 찍힐 b 값을 예상해보고, 어디에서 선언된 “b”가 몇번째 라인에서 호출한 console.log에 찍혔는지, 왜 그런지 설명해보세요.
주석을 풀어보고 오류가 난다면 왜 오류가 나는 지 설명하고 오류를 수정해보세요.

먼저 console.log 상에 표시되는 값은 각 1(b) , 1(a) , 101(b) , 1(b)

이다 1로 찍힌 b는 펑션 hi 전의 let b = 1 이고

주석을 풀면 오류가 나는 것은 a 를 지정해주지 않았는데 a를 호출하기 때문이다.

a를 값을 지정해주면 오류가 해결될 것이다.

profile
하루 고생하면 코드가 나 대신 일해준다.

0개의 댓글