8주차 01/17 화

하이·2023년 1월 17일
0

수업

목록 보기
13/41
post-custom-banner

JavaScript

함수

: Reference Type(Object)
: property를 가지고 있음

console.dir()

함수객체는 일반객체가 가지지 않는 특수한 property가 자동으로 붙는다

① arguments : 유사배열객체
(현재는 Rest parameter를 더 많이 이용)

② caller :

③ length : parameter가 몇개인가요?

function sum(a,b){
}

=> a,b 2개

④ name : sum

⑤ prototype : 함수(객체)를 이용해서 객체를 생성할 수 있음 (new)
: 이 함수를 생성자함수 라고 함
: 이렇게 만들어진 객체의 [[prototype]]
: 이 [[prototype]] 내장슬롯의 값을 가지고 있는 property가 바로 prototype
: constructor만 가지고 있는 property - 함수선언문, 함수표현식, 클래스



// 일반객체
var obj = {
    name : '홍길동'
}
console.dir(obj);

// 함수선언문
function myFunc(number) {
    return 2 * number;
}

console.dir(myFunc);    // 얘가 위에 myFunc를 지징하는 건 아님


function sum() {
    // arguments 유사배열객체가 있음
    // 유사배열객체는 배열과 유사한 객체임
    // 배열과 생긴게 똑같고, 비슷하게 사용 가능
    // 진짜 배열은 아님
    // 배열이 가지는 여러기능을 다 가지고 있진 않음
 
    // arguments 함수객체의 property
    // 가변인자함수를 구현하기 위해서 사용
    let result = 0;
    for(let i=0; i<arguments.length; i++){
        result += [i];
    }
    return result;
}
console.log(sum(10,20));
console.log(sum(10,20,30));
console.log(sum(10,20,40,50,60));


/ 3.

// ES6에 들어오면서
// 별도의 Rest parameter라는 걸 도입함
// 특히 Arrow function은 arguments가 없음
function sum(...agrs) {

    // args로 표현되는 Rest parameter는 Array.
    let result = 0;
    for(let i=0; i<arguments.length; i++){
        result += arguments[i];
    }
    return result;
}
console.log(sum(10,20));
console.log(sum(10,20,30));
console.log(sum(10,20,40,50,60));


JavaScript
: 멀티패러다임 언어
1. 함수기반 언어
2. prototype언어(상속개념)
3. 객체지향 개념(객체기반 언어)

  • ES6에서 class가 도입.
    하지만 객체지향의 class와는 다르게 동작 (실제로는 생성자 함수로 동작)

생성자함수를 이용한 객체생성의 문제

=> Prototype으로 해결하자

앞의 그림을 조금 더 효율적으로 만들어 보자.
=>

4.

function Circle(radius) {
    this.radius = radius;

    Circle.prototype.getArea = function(){
        return Math.PI * this.radius ** 2;
    }
}
const circle1 = new Circle(2);
const circle2 = new Circle(5);

// 같다. => 내용이 같은지 비교
// 단, 타입이 다르면 일단 타입을 맞추고 같은지 비교
// 타입이 같고, 내용이 같은지 비교
console.log(circle1.radius === circle2.radius);
console.log(circle1.getArea === circle2.getArea);


function Circle(radius) {
    this.radius = radius;

    Circle.prototype.getArea = function(){
        return Math.PI * this.radius ** 2;
    }
    Circle.prototype.name = '홍길동'
}
const circle1 = new Circle(2);
const circle2 = new Circle(5);

console.log(circle1.name, circle2.name);

circle1.name = '신사임당'

console.log(circle1.name, circle2.name);

circle1.__proto__.name = '신사임당'
console.log(circle1.name, circle2.name);


모든 객체는 하나의 (상위)prototype객체를 가짐
[[prototype]]
이런 (상위)prototype객체는 생성자함수와 연결되어 있음

console.log(circle1.constructor === Circle);
// console.log(circle1.__proto__.constructor === Circle); 위를 좀 더 자세히 쓴 버전


function Circle(radius) {
    this.radius = radius;

    Circle.prototype.getArea = function(){
        return Math.PI * this.radius ** 2;
    }
    Circle.prototype.name = '홍길동'
}
const circle1 = new Circle(2);
const circle2 = new Circle(5);

console.dir(circle1);


// prototype은 결국 상속구조를 나타내기 위한 방법
const obj ={}   // 객체 literal로 만든 객체
const parent = {x : 1}

obj.__proto__=parent

console.log(obj.x);


var obj = {
    name : '홍길동'
}
console.dir(obj);


  1. 코드 & 그림

  1. [[prototype]] 코드에서 사용 X
    proto코드에서 사용을 지양 X
    Object의 함수를 제공 - getPrototypeof()
// 유일한 예외가 하나 있음
// 객체를 만들 때 이렇게도 만들 수 있음(예외적인 경우)

const obj = Object.create();    // 객체를 만들 때 내가
// 상위 prototype 객체를 지정해서 만들 수 있음
// null을 주면, 상위 prototype객체를 사용하지 않는다는 의미
// 이렇게 되면, __proto__를 아예 사용할 수 없음
// 그래서 __proto__를 코드에 직접적으로 사용하는 것은 바람직하지 않음. 권장 X
// 객체 literal로 생성
const obj = {};

const parent = {
    x : 1
}

// 상위 prototype객체를 얻어오기 위해서 아래처럼 하는 건 좋지 않음
// obj.__proto__
Object.getPrototypeOf(obj)  // prototype객체를 획득

// obj의 prototype객체를 parent로 설정
Object.setPrototypeOf(obj, parent);

console.log(obj.x);


prototype객체는 생성자함수를 정의하고 실행하면 생성자함수객체 생성(pro????????) + 생성자함수의 prototype객체 생성

생성자함수가 아닌 non-constructor함수는 prototype이 없음
① method
② Arrow-function

// 11.
// non-constructor인 arrow function을 하나 만들어서
// 진짜 이 함수객체의 prototype객체가 생성되지 않는지 확인해보자

const person = (name) => {
    this.name = name;
};

// person은 함수객체
console.log(person.prototype);


// 지금까지 한 내용을 바탕으로 전체적인 그림을 그려보자

function Circle(radius) {
    this.radius = radius
}

const circle1 = new Circle(5);
console.dir(circle1);


13.

// 13.
// 하, 이렇게 막 쓰는 건 x
// 좀 

function foo() {
    x = 10;     // 에러가 아닌, 전역변수로 만들자
                // window 객체의 property로 등록
                // 암묵적 저녁(Implicit Global 이라고 함
                // 자바스크립트 특유의 특징
}

foo();
console.log();


var x = 100;

if(true){
    let x = '홍길동'
}

function myFunc() {
    console.log('hello');

    function aa() {
        
    }
}

Stricit mode

-- 엄격, 진지
: use, Strict
① 묵시적 전역이 안 됨
② 변수 property의 삭제가 안 됨
③ Strinct mode에서는 일반 함수에서 this.사용시
-> window(전역객체) 0

JavaScript(ECMAScript 2015)

: 언어의 기본특성, 성질에 대해 알아보고 있음
그럼, 이런 걸 다 알아야 Front-End web Application을 만들 수 있나요? 전혀(어느정도) 몰라도 상관 X

application 구현 - libarary.Framework 이용

Closure

: JavaScript 고유의 개념은 아님
: 일반적인 함수형 언어의 특징
: 함수와 그 함수가 선언된 lexical 환경의 조합
: closer은 함수 -- 필기 놓침

lexical scope

  • static scope : 어디에서 사용되느냐가 아니라 어디에서 선언이 됐느냐에 따라 scope가 결정

JavaScript code는 4가지로 분류
① 전역코드 : global 영역(전역)존재하는 코드

② 함수코드 : 함수 내부에 존재하는 소스코드
(중첩함수 내부까지는 포함하지 않음)

③ eval 코드 : eval(소스코드)이라는 built-in 함수. 인자로 code를 넣을 수 있음

➃ module 코드 : module scope안에 있는 소스코드

  • 이렇게 코드를 나누는 이유
    : 특정 type의 코드가 실행되면 execution context가 생성(실행 컨텍스트)

    • 소스코드의 type을 나누는 이유
      : 소스코드 타입에 따라 execution context생성과 동작하는 방식이 다르기 때문
    • 전역코드
      : 전역변수를 관리하기 위해 최상위 scope인 전역 scope가 생성
      : var keyword로 변수를 선언 -> window객체에 property로 등록
      : 전역에서 선언한 함수도 window객체에 property로 등록
      -> 작업을 하기 위해 전역execution context가 생성
    • 함수코드
      : local scope가 생성, 지역변수, 매개변수
      : scope chain도 만들어져야함
      : 함수execution context 가 생성
    • execution context
      : 소스코드를 실행하는데 필요한 환경을 제공
      : 실행한 결과를 관리하는 메모리 영역

식별자, scope 같은 것들은 excution context의 lexical Environment(렉시컬 환경)
코드 실행순서는 execution context Stack에서 관리

  1. closer

const x =1;

function outer(){
    const x = 10;

    const inner = function() {
        console.log(x);
    }
    return inner;   // 함수가 함수를 리턴하고 있음
}

const result = outer();

result();           // 1이 돼야 우리가 알고있는 정상적인
                    // execution context stack의 동작임
                    // but, 10이 찍힘. 왜?
                    // 이 현상을 closer라고 부름



// 클로져를 이용한 간단한 응용

let num = 0;

const increase = function () {
    return ++num;
}

console.log(increase());    // 1
console.log(increase());    // 2
console.log(increase());    // 3

num = 10;
// 간단한 카운터를 만들 수 있음


19.

const increase = (function () {
    let num = 0;
    
    return function () {
        return ++num;
    }
}());

console.log(increase());    
console.log(increase());    
console.log(increase());

profile
기록의 즐거움 😆💻
post-custom-banner

0개의 댓글