[JavaScript] array의 splice 함수 정리

자바스크립트의 배열(Array) 객체에서 제공되는 함수인 splice를 이용하면 원하는 위치에 요소를 추가하거나 삭제할 수 있습니다. 먼저 splice 함수를 사용해 원하는 위치에 요소를 추가하는 것을 정리해보겠습니다. 예를 들어, 먼저 a라는 배열 객체가 다음과 같은 상태라고 하겠습니다.

사용자 삽입 이미지

이 상태에서 다음 코드를 실행하면 다음의 상태가 됩니다.

a.splice(2, 0, "7");

사용자 삽입 이미지

그럼 다시 a의 처음 상태로 돌아가 다음 코드를 실행하면 다음의 상태가 됩니다.

a.splice(0, 0, "7");

사용자 삽입 이미지

이제 다시 a의 처음 상태로 돌아가 다음 코드를 실행하면 다음의 상태가 됩니다.

a.splice(5, 0, "7");

참고로 위의 코드에서 인덱스 5 대신 5이상의 값을 사용해도 결과는 동일합니다.

사용자 삽입 이미지

이제는 splice를 이용해 추가가 아닌 삭제에 대한 예를 살펴보겠습니다. 다음 코드를 실행하면 다음의 상태가 됩니다.

a.splice(2, 1);

사용자 삽입 이미지

[JavaScript] UTF-8 코드값으로부터 String 구성하기

UTF-8은 ASCII 코드값은 1바이트로, 유럽권 문자는 2바이트로, 아시아권 문자는 3바이트로 구성함으로써 전세계 모든 언어를 처리할 수 있는 유니코드 중 하나입니다. 저는 기존에 편의상 EUC-KR을 사용했으나 이제부터는 UTF-8을 먼저 고려하고 사용해야한다고 생각하게 되었습니다.

아래의 코드는 DataView 객체에 저장된 UTF-8 코드값으로부터 String으로 구성하는 코드입니다. 변환 속도를 위해 다소 코드가 난해 합니다. 제가 개발한 서버에서 문자열 데이터를 UTF8로 인코딩된 바이너리 데이터로 웹브러우저로 보내게 되는데 이때 사용한 코드입니다.

function getStringUTF8(dataview, offset, length) {
    var s = '';

    for (var i = 0, c; i < length;) {
        c = dataview.getUint8(offset + i++);
        s += String.fromCharCode(
            c > 0xdf && c < 0xf0 && i < length - 1
            ? (c & 0xf) << 12 | (dataview.getUint8(offset + i++) & 0x3f) << 6 
            | dataview.getUint8(offset + i++) & 0x3f
            : c > 0x7f && i < length
            ? (c & 0x1f) << 6 | dataview.getUint8(offset + i++) & 0x3f
            : c
        );
    }
    
    return s;
}

짧은 코드이지만 몇일 동안 고민하고 고민하던 차에 만난... 저에게는 매우 의미있고 값진 코드입니다. ^^;

[JavaScript] String을 XMLDocument 객체로 변환하기

일반적인 XML 형식으로 구성된 문자열을 파싱(Parsing)하기 위해서 XMLDocument 객체로 변환해야 할 경우가 있습니다. 저 같은 경우 Cross Domain 문제로 인해 Proxy를 통해 통신을 하고자 했는데, 해당 Proxy 서버가 다루는 데이터가 범용인지라 이 서버를 통해 AJAX 통신을 하면 XML 객체로 받아지지 않고 Text로 받아지는 문제가 있어 부득이 String을 XMLDocument 객체로 변환해야 했습니다.

function getXmlFromString(xmlStr) {
    var parseXml;

    if (window.DOMParser) {
        var dp = new window.DOMParser();
        return dp.parseFromString(xmlStr, "text/xml");
    } else if (typeof window.ActiveXObject != "undefined" 
        && new window.ActiveXObject("Microsoft.XMLDOM")) {
        var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM");
        xmlDoc.async = "false";
        xmlDoc.loadXML(xmlStr);
        
        return xmlDoc;
    }

    return null;
}

[JavaScript] 보다 더 정확한 타입(type)을 얻는 함수

자바스크립트에는 해당 객체값에 대한 타입을 얻는 예약어로 typeof를 지원합니다. 그러나 요놈이 그다지 정확치 않는 녀석인지라 이보다 더 정확한 타입을 얻을 필요가 있을 시에 다음 함수를 사용할 수 있습니다.

function getType(x) {
    if (x == null) {
        return 'null';
    }

    var t = typeof x;
    if (t != "object") {
        return t;
    }

    var c = Object.prototype.toString.apply(x);
    c = c.substring(8, c.length - 1); // [object ?]의 특성을 이용함

    if (c != "Object") {
        return c;
    }

    if (c.constructor == "Object") {
        return c;
    } else {
        var s = x.constructor.toString();
        var i = s.indexOf("(");
        return s.substring(9, i); // function ?( ... 의 특성을 이용함
    }

    return "unknown type";
}

위의 코드에 대한 테스트는 아래와 같습니다.

function CTR(a) {
    this.a = a;
};

document.write(typeof CTR + " , " + getType(CTR));

var c = new CTR(1);
document.write(typeof c + " , " + getType(c));
        
document.write(typeof new Date() + " , " + getType(new Date()));
document.write(typeof new Array() + " , " + getType(new Array()));
document.write(typeof 1 + " , " + getType(1));
document.write(typeof "hi" + " , " + getType("hi"));
document.write(typeof this.document + " , " + getType(this.document));

실행 결과는 다음과 같습니다.

사용자 삽입 이미지

실행결과에 대한 각 라인의 첫번째는 자바스크립트에서 제공하는 typeof를 사용한 것이고 두번째는 보다 더 정확한 타입을 얻을 수 있는 getType 함수를 사용한 것입니다.

[JavaScript] 배열인가, 아닌가?


자바스크립트는 데이터 타입을 명시적으로 지정하는 것이 불가능한 언어이므로, 자바스크립트를 이용해 타 개발자가 사용하는 API를 개발하기 위해서는 API의 견고함을 유지하기 위해 변수의 데이터 타입을 검사하여 API가 받고자 하는 데이터 타입이 아닐 경우 예외 처리를 해주는 것이 필요합니다. 예를 들어서 어떤 함수가 있다고 할때, 이 함수가 어떤 배열을 인자로 받아 배열을 구성하는 원소를 모두 합한 값을 반환하고하 할때를 예로 들어 생각해 보겠습니다.

function sum(a) {
    var isArray = (a instanceof Array);
    var isLikeArray = (a && typeof a == "object" && "length" in a
        && (typeof a.length == "number"))

    if (isArray || isLikeArray) {
        var total = 0;
        for (var i = 0; i < a.length; i++) {
            var element = a[i];
            if (!element) continue;
            if (typeof element == "number") {
                total += element;
            } else {
                throw new Error("Element in array have to be number.");
            }
        }

        return total;
    } else {
        throw new Error("Argument have to be array.");
    }
}

2번 코드는 전달 받은 인자가 완벽한 배열 타입인지를 검사하는 것이고 3, 4번 코드는 인자가 최소한 객체이면서 length라는 프로퍼티를 가지고 있는지를 검사하면서 이 length의 타입이 숫자라는 것까지 검사하고 있습니다.

이제 인자가 배열(또는 배열로 간주할 수 있는 객체)로 판단되므로 이 배열을 구성하는 원소의 합을 구할 수 있는데, 11번 코드에서 배열을 구성하는 원소의 데이터 타입이 숫자일 경우에만 합산을 하고 그렇지 않다면 예외를 던지도록 하고 있습니다. 실제 사용 코드는 다음과 같습니다.

alert(sum([1, 2, 3, 4, 5]));