[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] 주의해야 할 ‘변수에 대한 호이스팅(hoisting)’

자바스크립트에서 변수에 대한 호이스팅이라는 개념이 있습니다. 함수 안에 정의된 모든 변수는 선언된 그 위치에 상관없이 함수의 윗부분으로 끌어올려(hoist)된다라는 개념입니다. 여기서 주의할 점은 자바스크립트에서 함수도 객체 변수이며 이 함수가 호이스팅될때입니다.. 함수를 정의하고 선언하는 방법을 크게 2가지로 구분할 수 있습니다.

  • 표현식에 의한 정의
  • 선언문에 의한 정의

먼저 표현식에 의한 정의의 예는 다음과 같습니다.

var bar = function() {
     // 표현식에 의한 함수 정의 
}; 

다음은 선언문에 의한 정의의 예입니다.

function foo() { 
    // 선언문에 의한 함수 정의
} 

이러한 함수 정의가 함수 안에서 이루어질때 호이스팅에 차이가 발생하게 됩니다.

function test() { 
    alert(typeof foo); 
    alert(typeof bar); 

    function foo() { 
        // 선언문에 의한 함수 정의 
    } 
    
    var bar = function() {
         // 표현식에 의한 함수 정의 
    }; 
} 

test();

위의 코드를 실행해 보면 처음에는 “function”이라는 메세지가 표시되고 다음에는 “undefined”라는 메세지가 표시됩니다. 이는 표현식에 대한 함수 정의시에 함수 객체가 호이스팅될때 함수의 코드부분은 호이스팅되지 않지만 선언문으로 함수가 정의될 경우에는 함수의 코드부분까지도 호이스팅된다는 것을 알 수 있습니다. 

[JavaScript] 클래스 상속

자바스크립트에서 클래스의 상속 개념을 정리해 보고자 합니다. 먼저 크기값(width, height) 만을 갖는 Rectangle라는 클래스가 있고 이 클래스를 상속받으면서 위치값(x, y)를 갖는 PositionedRectangle 클래스를 만들어 보는 예를 통해 정리하고자 합니다. (이 글은 인사이트의 자바스크립트 완벽가이드 내용을 읽고 이해하여 짧게 요약한 글입니다)

가장 먼저 Rectangle이라는 클래스 정의 코드입니다.
function Rectangle(w, h)
{
    this.width = w;
    this.height = h;
}

Rectangle.prototype.area = function()
{
    return this.width * this.height;
}

Rectangle.prototype.toString = function() 
{
    return "[" + this.width + ", " + this.height + "]";
}

생성자 함수에서 크기값에 대한 인자 w, h를 받습니다. 그리고 area라는 매서드와 toString이라는 매서드를 정의하고 있습니다. 이후에 Rectangle 클래스를 상속받아 toString 함수를 재정의할때 부모 클래스의 toString을 호출하는 방법을 살펴보도록 하겠습니다.

자, 이제 PositionedRectangle이라는 클래스를 Rectangle 클래스를 상속받아 정의하는 코드를 보겠습니다.
function PositionedRectangle(x, y, w, h)
{
    Rectangle.call(this, w, h);
    
    this.x = x;
    this.y = y;
}

3번 코드에서 상속받을 Rectangle 클래스를 지정합니다. 그리고 PositionedRectangle의 부모 클래스가 Rectangle이라는 것을 명확히 하도록 다음 코드를 추가합니다.

PositionedRectangle.prototype = new Rectangle();

위의 코드의 문제점은 PositionedRectangle의 생성자 함수까지도 Rectangle로 지정된다는 점입니다. PositionedRectangle의 생성자 함수를 다시 자기의 것으로 지정되도록 다음 코드를 추가합니다.

PositionedRectangle.prototype.constructor = PositionedRectangle;

또 한가지 문제가 있는데, 그것은 중복된 데이터입니다. PositionedRectangle는 Rectangle로부터 상속을 받았으므로 Rectangle의 width와 height 데이터를 갖습니다. 그런데 이 값이 각각 2개씩 중복(PositionedRectangle에 하나, PositionedRectangle.prototype에 하나)되어 갖고 있습니다. 해서 중복되지 않도록 제거해 주는 코드가 필요합니다.

delete PositionedRectangle.prototype.width;
delete PositionedRectangle.prototype.height;

이제 옵션으로 PositionedRectangle 자신의 함수를 추가하는 코드입니다.

PositionedRectangle.prototype.contains = function(x y)
{
    return (x > this.x && x < this.x + this.width 
        && y > this.y && y < this.y + this.height);
}

끝으로 부모 클래스의 메서드 함수를 재정의할때 부모 클래스의 메서드 함수를 호출하는 방법입니다. toString 함수를 예로 정리하면, PositionedRectangle에 다음처럼 toString 함수를 재정의할 수 있습니다.

PositionedRectangle.prototype.toString = function()
{
    return "(" + this.x + ", " + this.y + ") " 
        + Rectangle.prototype.toString.apply(this);
}

[JavaScript] 함수 인자의 타입 검사

자바스크립트에서 함수를 만들어 사용할때 그 함수의 인자에 대한 타입은 암묵적인 약속입니다. 이 말은 “이 함수의 인자의 타입은 … 이다”라는 개념에 지나지 않다는 의미입니다. 그러한 개념에서 벗어나 보다 엄격하게 그 타입을 지키도록 하는 방어책이 필요할때 아래의 예를 참고하고자 이 글로 정리해 둡니다.

function sum(a /* Array */)
{
    var isArray = (a instanceof Array);
    var isLikeArray = (a && typeof a == "object" && "length" in a);
  
    if(isArray || isLikeArray)
    {
        var total = 0;
    
        for(var i=0; i        {
            var element = a[i];
            if(!element) continue;
            if(typeof element == "number") 
                total += element;
            else 
                throw new Error("원소는 숫자여야 함");
        }

        return total;
    }
  
    throw new Error("인자는 배열이어야 함");
 }

var a = [1,2,3,4,5];
try 
{
    document.write(sum(a));
} 
catch(e)
{
    document.write(e.message);
}

3번 코드가 전달 받은 인자의 타입이 배열인지를 확인하는 것이고 4번은 배열과 비슷한 객체인지, 즉 length 프로퍼티를 제공하는지를 확인하는 코드입니다. 14번 코드는 배열의 원소가 숫자인지를 확인하는 코드입니다.

이 코드는 인사이트의 JavaScript 완벽 가이드라는 책의 코드를 조금 변형한 것입니다. 자바스크립트에 관해 좋은 책이라고 생각합니다.