Javascript null과 undefined

null -> 아무 값도 갖고 있지 않다는 뜻. 일반적으로 예상 가능한 상황에서 값의 부재를 표현
undefined -> 보다 더 시스템적인 관점. 예기치 못한 상황에 발생한 오류성 값 / 부재를 나타내기 위함.

null == undefined;  // true
null === undefined; // false

null 과 undefined에 . 연산자나 [] 연산자를 사용하지 않도록 예외처리 해야.
Typeerror 발생

Function 유효범위

C의 block scope와 달리 javascript는 함수 유효범위를 갖는다.

function test(o) {
    var i = 0;
    if (typeof o == "object") {
        var j = 0;
        for(var k=0; k < 10; ++k) {
            console.log(k);
        }
        console.log(k);
    }
    console.log(j);
}

i, j, k 의 유효범위는 모두 같다.

var scope = "global";
function f() {
    console.log(scope); // undefined 출력
    var scope = "local";
    console.log(scope); // local 출력
}

Property로서의 변수

var 사용하면 unconfigurable한 프로퍼티
없으면 configurable

var truevar = 1;  // 삭제불가능 전역변수
fakevar = 2;      // 삭제가능 전역변수
this.fakevar = 3; // 삭제가능 전역변수
delete truevar       // false-> 삭제불가능
delete fakevar
delete this.fakevar2

'웹 프로그래밍 > Javascript' 카테고리의 다른 글

Javascript Function  (0) 2020.06.24
Javascript Array  (0) 2020.06.23
JavaScript Property  (0) 2020.06.21
JavaScript Object 생성  (0) 2020.06.19
Javascript 세미콜론  (0) 2020.05.30

JavaScript Array

Javascript의 배열

  • 정렬된 값의 집합
  • 타입이 고정되어 있지 않음
  • 배열이 밀집도가 높지 않음
    • 원소의 index가 연속적이지 않아도 됨
    • 원소 사이에 빈자리가 있어도 됨
  • Array.prototype의 프로퍼티를 상속받음.

배열 생성

  1. 배열 리터럴
  2. Array 생성자

배열 리터럴

        var empty = [];
        var primes = [2,3,5,7,11];
        var misc = [ 1.1, true, "a" ];

          // 임의의 표현식도 사용 가능 
        var base = 1024;
        var table = [base, base+1, base+2, base+3]; 

          var count = [1,,3]; // 가운데 값은 undefined
          var undefs = [,,];  // 원소는 2개 (마지막원소에 , 가능)

Array 생성자

        var a = new Array();
        var aa = new Array(10); // length
        var aaa = new Array(5,4,3,2,1, "testing, testing"); // 인자값이 배열의 원소
        console.log(aaa)

Output :

다양한 Index

        // 다양한 인덱스
        a[-1.23] = true;
        a["1000"] = 0;
        a[1.000] = 7;
        console.log(a)

Output :

희소배열

배열에 속한 원소의 위치가 연속적이지 않은 배열
원소가 undefined가 아니라 아예 없는 것

        arr = new Array(5); // 원소는 없지만 a.length의 값은 5
        arr2 = []           // length값이 0인 빈 배열
        arr3[1000] = 1;     // 하나의 원소 할당, 길이는 1000

배열의 길이

배열의 length Property : 배열의 원소 개수, 배열의 가장 큰 인덱스+1

length 값 변경 :

a = [1,2,3,4,5];
a.length = 3; // 결과가 1,2,3이 된다.
a.length = 0; // 결과 []
a.length = 5; // new Array(5)와 같은 결과

length Property 읽기전용으로 만들기 :

a = [1,2,3];
Object.defineProperty(a, "length", {writeable: false});
a.length = 0; // 값 바꿔도 배열은 변하지 않음

배열 원소 추가 제거

        a = [];
        a[0] = "zero";
        a.push("one");
        a.push("two", "three");
        console.log(a.length);
        delete a[1];
        console.log(1 in a); // false -> 지워졌다.
        console.log(a.length);

Output :

배열 순회하기

        var o = new Array(7,5,3,2);
        var keys = Object.keys(o);
        var values = [];
        for(var i = 0; i < keys.length; i++) {
            var key = keys[i];
            values[i] = o[key];
        }
        console.log(o);
        console.log(keys);
        console.log(values);

          for(var i = 0, len = keys.length; i < len; ++i) {
            // 성능향상 위해 length를 한번만 불러오기
        }

Output :

루프 돌릴 때 고려해야 할 점

  • 원소가 null / undefined 일 때 어떻게 처리할 지
  • 상속받은 Property 등의 고유 Property 가 아닌 값들을 어떻게 처리할 지

for in loop에서 원소 반환 순서

  • 정해져있지 않음.
  • 순서가 중요한 알고리즘에서는 for문을 통해 명시적으로 사용할 것을 권장

다차원 배열

        var table = new Array(10);
        for(var i = 0; i < table.length; ++i) {
            table[i] = new Array(10);
        }

        for(var i = 0; i < table.length; ++i) {
            for(var j = 0; j < table[i].length; ++j) {
                table[i][j] = i*j;
            }
        }
        console.log(table[5][7]);

Output :

배열 메서드

join()

* 배열의 모든 원소를 문자열로 변환, 변환한 문자를 이어붙인 결과를 return
* seperator를 지정하지않으면 , 가 기본 separator
* String.split() -> join의 반대. 문자열을 배열로
        var a = [1, 2, 3];
        console.log(a.join());
        console.log(a.join(' '));
        console.log(a.join(''));

Output :

reverse()

  • 배열의 원소 순서를 반대로 뒤집어 반환.
  • 배열안에서 직접 수행되어 배열 정렬순서 변환됨.
        var b = [1,2,3];
        b.reverse();
        console.log(b);

Output :

sort()

  • 정렬
  • undefined는 배열의 끝부분으로
  • 정렬 조건도 바꿀 수 있음
        var c = [1,2,3,4];
        c.sort();
        console.log(c);
        c.sort(function(a,b) {
            return b - a;
        })
        console.log(c);

Output :

concat()

  • concat의 전달인자를 추가한 배열 반환
        var d = [1,2,3];
        console.log(d.concat(4,5));
        console.log(d.concat([4,5]));
        console.log(d.concat([4,5], [6,7]));
        console.log(d.concat([4, [5,6]]));

Output :

slice()

  • subarray 반환
    • -1은 마지막 원소
    • 음수는 뒤에서부터 세는 것
        var e = [1,2,3,4,5];
        console.log(e.slice(0,3));
        console.log(e.slice(3));
        console.log(e.slice(1,-1));
        console.log(e.slice(-3,-2));

Output :

splice()

  • 잘라낸 후 값 return, 실제 배열 도 수정된다.
  • 값을 추가할 때도 사용 가능
  • 첫 두 인자 -> 삭제할 원소 지정 (a, b) -> a부터 시작해서 b개 삭제
  • 세번째 인자부터 추가할 값

push(), pop(), unshift(), shift()

  • push(), pop() -> 맨 뒤에서 원소 추가제거
  • unshift(), shift() -> 맨 앞에서 원소 추가 제거

'웹 프로그래밍 > Javascript' 카테고리의 다른 글

Javascript Function  (0) 2020.06.24
Javascript Scope, 변수  (0) 2020.06.23
JavaScript Property  (0) 2020.06.21
JavaScript Object 생성  (0) 2020.06.19
Javascript 세미콜론  (0) 2020.05.30

JavaScript Property

Property의 값을 가져오려면

  • . 연산자 : 연산자 우측에 Property 이름 "식별자"
  • [] 연산자 : 연산자 우측에 Property이름의 "문자열 표현식"

Property 값 생성

        var temp = {}
        console.log(temp);

        temp.newProperty = "a";
        temp["new Property"] = "b";

        console.log(temp);

output:

연관 배열로서의 객체

temp.newProperty : 식별자가 와야 함 -> 코딩할 때 fix됨.
temp.["new Property"] : 표현식을 인자로 받음 -> 프로그램 실행중 입력받은 것 사용 가능

        function addName(nameList, name, studentNumber) {
            nameList["name"] = studentNumber
        }
        // 이런 코드가 동작 한다는 뜻!

상속

객체에서 Property를 찾을 때, 고유 Property안에 찾고자 하는 Property가 없으면,
상속받은 Prototype 객체에서 해당 Property를 찾는다.

        function inherit(p) {
            if (p == null) throw TypeError();
            if (Object.create) // ECMAScript 5 이상에 정의되어 있음
                return Object.create(p);
        }

        var o = {};
        o.x = 1;
        var p = inherit(o); // 객체 o와 Object.prototype를 상속받는 객체
        p.y = 2;
        var q = inherit(p); // 객체 p와 o, Object.prototype을 상속받는 객체.
        q.z = 3;
        var s = q.toString(); // q 는 Object.prototype을 상속받았기 때문에 toString 사용가능

        var result = q.x + q.y; // 값은 3 
        console.log(result);

Output :

상속받은 Prototype Property를 바꾸고 싶을 때

상속받은 Property 가 read only 라면 수정 불가.
그렇지 않다면 두 가지 경우의 수

  • 고유 Property로 재정의 된다. // 기본
  • Prototype Property 의 값이 재설정된다. // setter method가 정의되어있을 경우

Property 접근 에러

존재하지 않는 Property에 접근하는 경우

  • 에러 발생하지 않음. -> undefined return

존재하지 않는 객체의 Property에 접근하는 경우

  • 에러 발생
        var temp2 = o.a;
        console.log(temp2) // undefined
        var length = o.a.length; // undefined에서 Property를 찾으려 해서 error

Output :

에러 방지

        var len = temp2 && temp2.a && temp2.length

객체 o에 Property p를 설정할 수 없는 경우

  • p가 o의 고유 Property이고 readonly일 경우
    • 읽기전용 Property p 에는 값 설정할 수 없다.
  • p가 상속된 Property 이고 readonly일 경우
    • 동일한 이름의 고유 Property로 감출 수 없음.
  • p가 고유 Property도, 상속받은 Property도 아닌데 extensible 속성이 false일 경우.

프로퍼티 삭제하기

delete 연산자. Property의 값이 아니라 Property 자체를 지움

delete book.author;
delete book["main title"];
  • delete 연산자는
    • 고유 프로퍼티만 지울 수 있다.
    • 삭제에 성공, 프로퍼티가 존재하지 않아 영향을 미치지 못한 경우, return true를 한다.
o = {x:1}
delete o.x; // 삭제 성공 return true
delete o.x; // 존재하지 않아 return true
delete o.toString; // 고유프로퍼티가 아니라 아무일도 안일어나고 true
delete 1; // 말도 안 되지만 return true
* configurable 속성이 false 인 프로퍼티는 지우지 않는다.

아래는 nonreconfigurable

        delete Object.prototype; // 지울 수 없음
        var x = 1;
        delete this.x; // 지울 수 없음
        function f() {}
        delete this.f; // 지울 수 없음

프로퍼티 검사

주어진 이름의 프로퍼티가 있는지 검사할 필요가 있을 때

  • in 연산자
  • hasOwnProperty()
  • propertyIsEnumerable() : 추가적으로 enumerable 속성까지 true여야
  • 단순히 Property에 접근
        var oo = {x : 1};
        console.log("x" in oo);
        console.log("y" in oo);
        console.log("toString" in oo);

        console.log(oo.hasOwnProperty("x"));
        console.log(oo.hasOwnProperty("y"));
        console.log(oo.hasOwnProperty("toString"));

        var ooo = inherit({y : 2});
        ooo.x = 1;
        console.log(ooo.propertyIsEnumerable("x")); // 고유 프로퍼티 열거 가능 -> true
        console.log(ooo.propertyIsEnumerable("y")); // 상속받은 프로퍼티 -> false
        console.log(ooo.propertyIsEnumerable("toString")); // 내장프로퍼티, 열거불가능 -> false

Output:

!== 와 === 연산자

  • undefined 와 null 을 구분할 수 있음.

프로퍼티 열거하기

for / in loop

        var o = {x:1, y:2, z:3};
        for(p in o) {
            console.log(p, o[p]);
        }

Output :

상속받은 Property 생략, method 생략

        for(p in o) {
            if(!o.hasOwnProperty(p))
                continue;
        }

        for(p in o) {
            if(typeof o[p] === "function")
                continue;
        }

프로퍼티 Getter / Setter

ECMAScript 5 에서는 Property의 값을 getter / setter method로 대체할 수 있음.
단순히 값을 값는 "Data Property" 와 다른 "Accessor Property" 라고 한다.

  • 프로그램이 객체의 Accessor Property에 접근하면 getter method의 반환 값이 Property 접근 표현식의 값이 됨.
  • 프로그램이 객체의 Accessor Property의 값을 바꾸려고 하면 getter method가 실행된다. = 오른쪽의 값이 method의 인자로 전달된다.

getter / setter 존재 유무로 읽기전용, 쓰기전용 결정.
특이한 것 : setter 만 있으면 쓰기전용. read 하려고 하면 있음에도 undefined return

Accessor Property의 정의

        var oo = {
            // Data Property
            data_prop: value,
            get accessor_prop() { /* 함수 몸체 */},
            set accessor_prop(value) { /* 함수 몸체 */ }
        }

Example : 2차원 좌표와 극좌표를 가지는 Property

        var p = {
            x: 1.0,
            y: 1.0,
            get r() {
                return Math.sqrt(this.x*this.x + this.y*this.y);
            },
            set r(newValue) {
                console.log("in setter : ", newValue);
                var oldValue = Math.sqrt(this.x*this.x + this.y*this.y);
                var ratio = newValue / oldValue;
                this.x *= ratio;
                this.y *= ratio;
                console.log("now x : ", this.x);
                console.log("now y : ", this.y);
            },

            get theta() {
                return Math.atan2(this.y, this.x);
            }
        }

        var q = inherit(p);
        q.x = 1; q.y = 1;
        console.log(q.r);
        console.log(q.theta);
        q.r = 777
        console.log(q.r);
        console.log(q.theta);

Output

Example : 일련번호 생성

        var serialnum = {
            $n: 0, // 프로퍼티 이름의 $는 private 프로퍼티라는 힌트

            get next() {return this.$n++;},
            set next(n) {
                if(n>=this.$n) this.$n++;
                else throw "serial number can only be set to a larger value";
            }
        }

Property 속성

이름, 값, 그리고 속성

  • value
    • 데이터 프로퍼티의 값도 속성으로 본다.
  • writeable
    • 값 변경 가능 여부
  • enumerable
    • 열거가능 여부
  • configurable
    • 3가지 속성 변경 가능한지.

Property의 3가지 속성 값을 질의하고 설정할 수 있도록 하는 ECMAScript 5 API

라이브러리 만들 때 중요

  1. 프로토타입 객체에 method 추가 , 추가된 method를 내장 method처럼 열거할 수 없게 만들기 위해
  2. 변경, 삭제 불가한 프로퍼티를 정의, 객체를 고정(lock down) 시키기 위해

접근자 Property의 속성 표현 위해 Property descriptor라는 객체 사용.

데이터 Property의 Property descriptor

  • value, writeable, enumerable, configurable 등의 Property를 가짐

접근자 Property의 Property descriptor

  • get, set, enumerable, configurable

객체의 특정 Property에 대한 Property descriptor객체
-> Object.getOwnPropertyDescriptor() 를 통해 얻을 수 있음.

        console.log(Object.getOwnPropertyDescriptor({x:1}, "x"));

          // 없는 Property거나 상속받은 Property 는 undefined
        console.log(Object.getOwnPropertyDescriptor({}, "x"));
        console.log(Object.getOwnPropertyDescriptor({}, "toString"));

Output

getOwnPropertyDescriptor 는 고유 프로퍼티만 검사 가능.
상속된 프로퍼티를 검사하고 싶으면 프로토타입 chain을 명시적으로 순회해야함.

프로퍼티의 속성 설정, 임의의 속성으로 새 프로퍼티를 만들기 위해

Object.defineProperty()

        console.log(o);
        Object.defineProperty(o, "x", {value : 1,
                                        writeable: true,
                                        enumerable: false,
                                        configurable: true})
        console.log(Object.getOwnPropertyDescriptor(o, "x"));

Output

동시에 여러개

        var p = Objet.defineProperties({}, {
            x: {value:1, writeable: true, enumerable:true, configurable: true},
            y: {value:1, writeable: true, enumerable:true, configurable: true},
            r: {get: function() {
                return Math.sqrt(this.x*this.x + this.y*this.y);
            },
            writeable: true,
            configurable: true}
        })

객체 속성

모든 객체는 prototype, class, extensible 속성을 가지고 있음.

Extensible 속성

객체에 새 프로퍼티를 추가할 수 있는지 여부
목적 : 잠겨있는 객체의 상태를 고정, 외부에서 변경하는 것을 막는 것.

객체 직렬화

  • JSON.stringify()
  • JSON.parse()

'웹 프로그래밍 > Javascript' 카테고리의 다른 글

Javascript Function  (0) 2020.06.24
Javascript Scope, 변수  (0) 2020.06.23
Javascript Array  (0) 2020.06.23
JavaScript Object 생성  (0) 2020.06.19
Javascript 세미콜론  (0) 2020.05.30

+ Recent posts