1. 구조 분해 할당

배열이나 객체를 분해하여 저장된 값을 개별 변수에 원하는대로 담을 있는 문법입니다.

2. 배열 분해 할당하기

1) 배열 분해 할당

var arr = ["kim", "park", "lee"];

var [a, , c, d = "empty"] = arr; //배열 구조 분해 할당

console.log(a, c, d); // kim lee empty
arr 배열에 "kim", "park", "lee" 값이 들어있고, arr 배열을 구조 분해 할당해서 변수 a, c, d에 삽입합니다.
배열에 순서와 선언된 변수 순서에 맞게 분해 할당됩니다.
해당 자리가 비어있다면, 할당되지 않으며, 값이 할당되지 않았을 경우 디폴트 값을 설정할 수 있습니다.

 

2) "..." 연산자로 나머지 값 저장하기

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

var [n1, n2, ...narr] = numbers;

console.log(n1, n2, narr);// 1 2 [3, 4, 5, 6, 7, 8, 9, 10]
배열의 앞 부분 몇개와 나머지 값들을 배열에 저장할 때 사용합니다.  

 

3) 배열 합치기

var a1 = [1, 2, 3];
var a2 = [4, 5, 6];
var a3 = [...a1, ...a2];

console.log(...a3, ...a2); //1 2 3 4 5 6 4 5 6
console.log(a3); //[1, 2, 3, 4, 5, 6]
"..." 연산자는 배열을 펼치는 연산자입니다. "..." 연산자를 사용해서 a1배열과 a2배열을 합쳐서 a3배열을 만들 수 있습니다. 

 

3. 객체 분해 할당하기

1) 객체 분해 할당

var person = {
    id: 35,
    name: "lee",
    age: 21,
    hobby: ["reading", "game", "bike ride"]
};

var {name, id, age, hobby, join = false} = person;

console.log(id, name, age, hobby, join); // 35 "lee" 21 ["reading", "game", "bike ride"] false

객체 분해 할당은 배열 분해 할당 방법과 비슷하다. 차이가 있다면 분해 할당을 선언하는 부분이 [ ... ]이 아니고 { ... } 입니다.
그리고 디폴트 값을 선언할 수 있으며, key 값만 맞다면 변수 선언의 순서가 달라도 상관없습니다. 

 

2) 객체의 나머지 연산

var person = {
    id: 35,
    name: "lee",
    age: "21",
    hobby: ["reading", "game", "bike ride"]
};

var {id, ...data} = person;

console.log(id, data); // 35 {name: "lee", age: "21", hobby: Array(3)}
배열 분해 할당과 마찬가지로 "..." 연산자를 통해 기본 변수와 객체에 원하는 만큼 나누어 할당할 수 있습니다. 

 

3) 객체 합치기

var person = {
    id: 35,
    name: "lee",
    age: "21",
    hobby: ["reading", "game", "bike ride"]
};

var extraInfo1 = {
    nationality: "KOREA",
    introduce: "Hi !"
};

var extraInfo2 = {
    a: "GOOD",
    b: "NICE"
};


var info = {...person, extraInfo2, ...extraInfo1};

console.log(info);
/*
{
  age: "21"
  extraInfo2: {a: "GOOD", b: "NICE"}
  hobby: ["reading", "game", "bike ride"]
  id: 35
  introduce: "Hi !"
  name: "lee"
  nationality: "KOREA"
}
*/

 

4) 중첩 객체 분해 할당

let config = {
    option: {
        a: true,
        b: false
    },
    arr: ["GOOD", "PERSON"],
};

var {
    option: {
        a,
        b
    },
    arr: [str1, str2],
    name = "app"
} = config;

console.log(name, a, b, str1, str2); // app true false GOOD PERSON

참조 :

https://ko.javascript.info/destructuring-assignment

1. 객체를 만드는 두가지 방법

1) 객체 리터럴을 이용한 방법

객체 리터럴은 {...}을 사용해서 객체를 생성합니다. 
var obj = {
    name: "kim",
    getName: function () {
        console.log(this.name);
    }
};

console.log(obj.name);
obj.getName();


2) 생성자 함수를 이용하는 방법

1) 관례상 함수 이름의 첫글자는 대문자로 시작합니다.
2) 함수 호출 시 "new" 연산자를 붙여서 실행합니다.
function Person(name) {
    this.name = name;
    this.showName = function () {
        console.log(`My name is ${this.name}`);
    };
}

var person = new Person("Son");
person.showName();

 

2-1) 함수 앞에 new를 붙일 경우

new Person("name")을 사용해서 함수를 실행하면 아래와 같은 알고리즘이 동작합니다.
1) 빈 객체를 생성하고 this가 빈 객체를 가리키게 합니다.
2) 함수를 실행합니다. 
3) this를 반환합니다.
function Person(name) {
// 빈 객체가 생성되고 this에 저장합니다.
// this = {};

// 함수가 실행됩니다. 
// this는 객체({})기 때문에 this.name = name 구문은 객체에 name 값을 넣는 것과 같습니다.
    this.name = name;
    this.showName = function () {
        console.log(`My name is ${this.name}`);
    };
    
// return this;
}

var person = new Person("Son");
person.showName();

생성자 함수를 사용하는 이유는 객체를 재사용하기 위함입니다. 리터럴 객체를 만드는 방법보다 수고를 덜 수 있지요.

var person01 = new Person("kim");
var person02 = new Person("park");
var person03 = new Person("lee");

2-2) 생성자 함수의 return문

생성자 함수에서 명시적으로 return문을 사용할 경우 다음과 같은 값을 반환합니다.

return문이 없을 경우

this를 반환한다.

return 값이 객체일 경우

해당 객체를 반환한다.

return 값이 기본 변수일 경우

기본 변수 반환을 무시하고 this를 반환한다. 

참조

https://ko.javascript.info/constructor-new

1. this

javascript의 this는 다른 언어의 this와 동작하는 방식이 조금 다릅니다.
javascript에서 대부분의 경우 this는 함수를 호출하는 방법에 따라 결정됩니다.

즉, 함수를 호출 할 때 마다 this가 가리키는 값이 다를 수 있습니다. 

 

2. 전역에서 this를 호출 했을 경우

console.log(this); // window
전역에서의 this는 기본적으로 window 객체를 가리킵니다. 

 

3. 함수 안에서 this를 호출 했을 경우

function doSomething(){
    return this; 
}

console.log(doSomething()); // window
console.log(window.doSomething()); // window
this를 결정하는 건 대부분 함수가 호출될 때, 이루어집니다. (bind 함수와 arrow 함수 제외 )
그리고 함수를 호출한 객체가 무엇이냐에 따라 this가 결정됩니다.

 

4.  메소드에서 this를 호출 했을 경우

function doSomething(){
    return this; 
}

var obj = {
    doSomething : doSomething
};

console.log(doSomething()); // window
console.log(obj.doSomething()); // obj
this를 결정하는 것은 함수를 호출한 객체가 무엇이냐에 따라 달라진다고 했었습니다. 따라서
doSomething 함수를 obj의 메소드로 등록하고 obj.doSomething()을 호출 했기 때문에 this는 obj가 됩니다.
(전역에서 선언되었을 경우 함수라 부르고, 객체에 속한 함수를 메소드라고 부릅니다.)
하지만 여기서 주의해야 할 점이 있습니다. 

 

var a = 10;
var obj = {
    a : 20,
    doSomething : function (){

        function func(){
            console.log(this.a); // 10
        }
    
        func();
    
        console.log(this.a); //20
    }
};

obj.doSomething();
doSomething 메소드 안에서 선언된 func 함수지만 호출해보면 console.log(this.a)에 10이 찍힙니다. 
이유는 obj 객체와 func 함수는 아무런 관련이 없는 함수이기 때문입니다.
위에서 설명했다시피 함수에서의 this는 기본적으로 window입니다.

그래서 메소드 내 함수에서 this를 가리키려면 self 변수에 객체의 this를 저장해서 접근합니다. 
var a = 10;
var obj = {
    a : 20,
    doSomething : function (){
        var self = this; // obj this를 저장한다.

        function func(){
            console.log(self.a); // 20
        }
    
        func();
    
        console.log(this.a); //20
    }
};

obj.doSomething();

 

5. 생성자에서 this를 호출 했을 경우

var age = 10;

function Person(){
    console.log(this.age);
}

var p = new Person(); 

Person();


/*

출력
--------
undefined
10

*/
Person함수는 window객체에 속한 함수입니다. 그래서 그냥 호출하면 this.age는 전역 변수의 age 값을 가리키게 됩니다.
하지만 Person 함수를 new 키워드를 통해 생성하면 새로운 객체가 만들어지면서 this는 window가 아닌 생성한 객체를 가리키게 되고, 함수의 내용은 생성자가 됩니다. 

그래서 생성자 호출 시 새로 생성한 객체에는 age 값이 없기 때문에 undefined가 출력됩니다.

 

6. bind 메서드

ECMAScript 5에서 Function.prototype.bind를 새롭게 도입했습니다.
bind 메서드란 함수 내의 this를 영구적으로 지정하는 메서드입니다.
var a = 10;
function func(){
    console.log(this.a);
}

func(); // 10

//func함수의 this를 obj 객체로 바인딩한다.
var obj = { a : 20 };
var new_func = func.bind(obj);

new_func(); // 20


var obj2 = { a : 30 };
var new_func2 = new_func.bind(obj2); // obj로 바인딩 된 함수를 다시 obj2로 바인딩한다.

//이미 바인딩 된 함수의 this는 변하지 않는다.
new_func2(); // 20  

 

7. 에로우 함수

에로우 함수에서 this는 자신을 감싼 lexical context입니다. 전역에서는 window를 가리킵니다.
에로우 함수 또한 한번 this를 지정하면 변하지 않습니다.
var func = (() => {
    console.log(this);
});
func(); // window


//obj의 func 메소드로 대입
var obj = {func: func};
obj.func(); // window


//obj 객체로 this를 바인딩
var new_func = func.bind(obj);
new_func(); // window

 


참조

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/this

1. 실행 컨텍스트란?

자바스크립트 코드가 실행되고 있는 구역 또는 범위에 대한 정보를 저장하고 있는 객체입니다.

자바스크립트 엔진은 스크립트 혹은 함수를 실행할 때 새로운 컨텍스트를 만들고, 실행 스택에 쌓습니다. 

실행 스택이란 실행 컨텍스트가 생성될 때 마다 실행 컨텍스트를 쌓고 마지막으로 쌓인 실행 컨텍스트 부터 차례대로 실행하는 후입선출 자료구조입니다.

 

2. 실행 컨텍스트의 종류

1) Global Exception Context
자바스크립트 엔진이 실행될 때 가장 먼저 만드는 실행 컨텍스트입니다.
전역 컨텍스트라고 하며, window 객체를 만들고 전역 컨텍스트의 this를 window 객체로 할당합니다.

그리고 이후에 생성되는 모든 전역 변수, 함수는 window 객체에 저장됩니다.

2) Function Execution Context
함수가 호출되면, 함수의 실행 컨텍스트가 생성됩니다.

3) Eval Function Exception
사용되지 않음

 

실행 컨텍스트의 구조

ExecutionContext = {
    LexicalEnvironment : { 
    	EnvironmentRecords : {
           //function or variable
        },
        outer : (LexicalEnvironment),
        ThisBinding : (object)
    },
    
    VariableEnvironment : {(LexicalEnvironment와 동일한 구조)}
}

 

3. 실행 컨텍스트의 두가지 단계

모든 실행 컨텍스트는 Create 단계 Execution 단계를 통해 생성됩니다.

1) Create 단계

Create 단계에서 LexicalEnvironment 컴포넌트 VariableEnvironment 컴포넌트를 생성합니다.
두 컴포넌트가 생성될 때, VariableEnvironment 컴포넌트는 LexicalEnvironment 컴포넌트를 참조합니다.
그러다가 자바스크립트의 코드에 따라 참조가 바뀌기도 합니다.
executionContext.LexicalEnvironment = executionContext.VariableEnvironment;

 

 

1.1) LexicalEnvironment 

LexicalEnvironment 컴포넌트는 변수나 함수 등의 식별자를 저장하는 EnvironmentRecords 객체와 외부 LexicalEnvironment 컴포넌트를 참조하는 outer 그리고 this로 구성됩니다. 
outer는 스코프 탐색을 위해 사용됩니다.

LexicalEnvironment 컴포넌트는 3가지 동작을 합니다.

1) 변수와 함수의 저장공간을 메모리에 할당
실행 컨텍스트 내에서 선언된 변수와 함수의 저장공간을 메모리에 할당하고 EnvironmentRecords라는 객체에 저장합니다.

2) 외부 실행 컨텍스트의 LexicalEnvironment를 저장
코드를 실행하다가 특정 변수나 함수를 마주하면 LexicalEnviromemt에서 찾는데 찾지 못했을 경우 외부 LexicalEnvironment 에서 찾습니다. (scope chain)

3) 실핼 컨텍스트의 This 값을 지정
this 값은 이 단계에서 결정됩니다. 전역 실행 컨텍스트의 this 는 global object입니다. 

this 값은 함수를 호출한 객체를 가리키게 됩니다. 

 

this를 이해하기 위해 간단한 소스를 보겠습니다.

var player = {
    lastName : 'son',
    firstName : 'heung min',
    name : function(){
       console.log(`${this.lastName} ${this.firstName}`);
    }
}

player.name(); // son heung min

var getName = player.name;

getName(); // undefined undefined
// == window.getName()
player.name()은 player 객체가 호출했기 때문에 this값은 player 객체입니다.

getName()은 player.name 함수를 대입받았고, 그대로 실행 했기 때문에 this값은 window 객체를 가리킵니다.

 

정리하면 Create 단계에서는
1) 변수, 함수, 인자를 만들고 EnvronmentRecords에 저장합니다.
2) 외부 실행 컨텍스트를 가리킵니다. (Scope Chain)
3) 실행 컨텍스트 내에 선언된 변수와 함수를 찾아 메모리에 할당합니다. (호이스팅)
4) this가 결정됩니다.

2) Execution 단계

실행 컨텍스트 내에 코드들을 위에서 한줄 씩 읽으면서 선언해 두었던 변수에 값이 할당됩니다.

 


참조

https://velog.io/@imacoolgirlyo/JS-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%9D%98-Hoisting-The-Execution-Context-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85-%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-6bjsmmlmgy

https://meetup.toast.com/posts/129

 

+ Recent posts