반응형

Object 객체

Object객체는 자바스크립트의 최상위 객체입니다.

 

생성

자바스크립트의 가장 기본적인 내장 객체는 Object객체입니다. 정확히는 Object생성자 함수로 만든 인스턴스입니다.

 

Object객체 생성하기 예

var object = {};

var object = new Object();

Object객체는 위 두 가지 방법으로 생성할 수 있습니다.

Object객체는 아래 처럼 일곱 가지의 메서드가 있습니다.

메서드 설명
constructor() 객체의 생성자 함수를 나타냅니다.
hasOwnProperty(name) 객체가 name속성이 있는지 확인합니다.
isPrototypeof(object) 객체가 object의 프로토타입인지 검사합니다.
propertyIsEnumerable(name) 반복문으로 열거할 수 있는지 확인합니다.
toLocaleString() 객체를 호스트 환경에 맞는 언어의 문자열로 바꿉니다.
toString() 객체를 문자열로 바꿉니다.
valueOf() 객체의 값을 나타냅니다.

 

hasOwnProperty()메서드와 propertyIsEnumerable()메서드

var object = { property: 273 };

var output = '';
output += "HOP('property'): " + object.hasOwnProperty('property') + '\n';
output += "HOP('constructor'): " + object.hasOwnProperty('constructor') + '\n';
output += "PIE('property'): " + object.propertyIsEnumerable('property') + '\n';
output += "PIE('constructor'): " + object.propertyIsEnumerable('constructor') + '\n';

console.log(output);
/*
HOP('property'): true
HOP('constructor'): false
PIE('property'): true
PIE('constructor'): false
*/

for(var key in object) {
    console.log(key) // property
    console.log(object[key]); // 273
}

위 코드를 실행하면 property속성을 검싸한 것은 모두 true를 출력하고 constructor속성을 검사한 것은 모두 false를 출력합니다.

propertyIsEnumerable()메서드를 true로 가지는 속성만 for in반복문으로 출력합니다. 

 

toString() 메서드

var object = new Object();

alert(object); // [object object]
alert(object.toString()); // [object object]

toString()메서드는 객체를 문자열로 변환하는 메서드입니다.

위 코드를 실행하면 두 출력 결과가 같습니다. toString()메서드는 객체를 문자열로 변환할 때 자동으로 호출되기 때문입니다.

 

toString() 메서드 재선언

var student = {
    name: 'shiro',
    grade: '대학교 4학년',
    toString: function() {
        return this.name + ' : ' + this.grade;
    }
};

alert(student); // shiro : 대학교 4학년

위 코드는 객체를 만들고 내부에서 toString()메서드를 선언합니다.

원래 모든 객체는 toString()메서드를 갖는데 다시 선언했기 때문에 재선언한 것입니다. 자바스크립트는 객체를 문자열로 변환할 때 자동으로 toString()메서드를 호출한다고 했으므로 shiro : 대학교 4학년을 호출하게 되는 것입니다.

 

반응형
반응형

기본 내장 객체

 

기본 자료형과 객체의 차이점

기본 자료형은 자바스크립트의 여섯가지 자료형 중 숫자, 문자열, 불 세 가지 자료형을 의미합니다. 기본 자료형과 객체의 특성이 다르므로 차이를 둡니다.

 

기본 자료형과 객체 예

var defaultNumber = 273;
var objectNumber = new Number(273);

var output = '';
output += typeof (defaultNumber) + ' : ' + defaultNumber + '\n';
output += typeof (objectNumber) + ' : ' + objectNumber;

console.log(output);
/*
number : 273
object : 273
*/

위 코드에서 기본 자료형과 객체는 자료형이 분명히 다릅니다. 하지만 두 가지 모두 값을 출력합니다.

기본 자료형의 속성이나 메서드를 사용하면 기본 자료형이 자동으로 객체로 변환되기 때문입니다.


예를 들어 기본 자료형 숫자의 속성이나 메서드를 사용할 때는 자동으로 Number객체로 변환되므로, 기본 자료형이 속성이나 메서드를 사용할 수 있는 것입니다. 따라서 기본 자료형과 객체의 차이점을 찾기가 힘듭니다.

굳이 차이점을 본다면 기본 자료형은 객체가 아니기 때문에 속성과 메서드를 추가할 수 없습니다.

 

기본 자료형에서 메서드 추가 예

var defaultNumber = 273;

defaultNumber.method = function() {
    return 'Default Method';
};

var output = defaultNumber.method() + '\n';
console.log(output); // TypeError

위 코드를 실행하면 오류가 발생합니다. 기본 자료형이기 때문에 속성과 메서드를 추가해서 사용할 수 없습니다.

기본 자료형을 객체로 변환하는 것은 일회용 옷을 입는다는 개념으로 생각하면 쉽습니다. 기본 자료형의 메서드를 사용한다는 것은 기본 자료형에 객체라는 일회용 옷을 입힌 다음 메서드를 사요하는 것입니다. 한 번 사용하면 곧바로 일회용 옷을 버립니다. 기본 자료형에 메서드를 추가했지만 이는 기본 자료형에 직접 메서드를 추가한 것이 아니라 일회용 옷에 추가한 것이므로 추가하자마자 버령집니다.

 

생성자 함수에 메서드 추가 예

var defaultNumber = 273;
var objectNumber = new Number(273);

Number.prototype.method = function() {
    return 'Method on Prototype';
};

var output = '';
output += defaultNumber.method() + '\n';
output += objectNumber.method();

console.log(output);
/*
Method on Prototype
Method on Prototype
*/

프로토타입에 메서드를 추가하면 위 코드처럼 기본 자료형에도 새로운 메서드가 생성됩니다.

반응형
반응형

클래스

 

클래스 선언과 속성

클래스는 아래 코드와 같은 형태로 선언됩니다. 속성도 this키워드를 사용해 선언합니다.

 

클래스 선언 예

// 클래스 선언
class Rectangle {
    constructor(width, height) {
        this.width = width;
        this.height = height;
    }
}

const rectangle = new Rectangle(100, 200);

 

// 생성자 함수 선언
function Rectangle(width, height) {
    this.width = width;
    this.height = height;
}
var rectangle = new Rectangle(100, 200);

 

메서드 선언 예

// 클래스 메서드 선언
class Rectangle1 {
    constructor(width, height) {
        this.width = width;
        this.height = height;
    }

    getArea() {
        return this.width * this.height;
    }
}

const rectangle1 = new Rectangle1(100, 200);

console.log(rectangle1.getArea());
// 생성자 함수 메서드 선언
function Rectangle2(width, height) {
    this.width = width;
    this.height = height;
}

Rectangle2.prototype.getArea = function() {
    return this.width * this.height;
}

var rectangle2 = new Rectangle2(100, 200);

console.log(rectangle2.getArea());

클래스의 메서드는 프로토타입 안에 선언하는 것이 아니라 클래스 안에 선언하게 됩니다. 선언 방법은 똑같습니다.

 

게터와 세터 예

class Rectangle1 {
    constructor(width, height) {
        this._width = width;
        this._height = height;
    }
    get width() {
        return this._width;
    }
    set width(input) {
        this._height = input;
    }
    get height() {
        return this._height;
    }
    set height(input) {
        this._width = input;
    }
    getArea() {
        return this._width * this._height;
    }
}

const rectangle1 = new Rectangle1(100, 200);
rectangle1.width = 200;

console.log(rectangle1.width); // 100
console.log(rectangle1.getArea()); // 20000

ECMAScript 6의 클래스는 변수를 숨길 수 없습니다. 그래서 일반적으로 개발한 사람 이외에는 만지지 말아 달라는 의미에서 _를 붙입니다. 그래서 외부에서 만지지 말라는 의미로 width와 height에 _를 붙여서 선언했습니다.

게터와 세터는 메서드를 선언할 때 앞에 get or set을 붙여 선언합니다.

get을 붙여 만든 메서드는 rectangle.width처럼 값을 가져오는 행위를 할 때 자동으로 호출되며, set을 붙여 만든 메서드는 rectangle.width = 200처럼 값을 넣는 행위를 할 때 자동으로 호출됩니다.

상속

상속은 extends키워드로 구현합니다.

 

상속 예

class Rectangle1 {
    constructor(width, height) {
        this._width = width;
        this._height = height;
    }
    get width() {
        return this._width;
    }
    set width(input) {
        this._height = input;
    }
    get height() {
        return this._height;
    }
    set height(input) {
        this._width = input;
    }
    getArea() {
        return this._width * this._height;
    }
}

class Square extends Rectangle1 {
    // 생성자
    constructor(length) {
        // 부모의 생성자 (constructor 메서드)를 호출합니다.
        super(length, length);
        console.log(this) // _width: 100, _height: 100
    }
    // width 또는 height를 변경하면 둘 다 변경되도록 재선언 합니다.
    set width(input) {
        this._width = input;
        this._height = input;
    }
    set height(input) {
        this._width = input;
        this._height = input;
    }
}

const square = new Square(100);
console.log(square.getArea()); // 10000

 

반응형

'JavaScript | TypeScript > Javascript 시작하기' 카테고리의 다른 글

[ Javascript ] Object 객체  (1) 2022.06.16
[ Javascript ] 기본 내장 객체  (0) 2022.06.15
[ Javascript ] 상속  (0) 2022.06.14
[ Javascript ] 캡슐화  (0) 2022.06.14
[ Javascript ] 프로토타입  (0) 2022.06.13
반응형

상속

상속은 기존의 생성자 함수나 객체를 기반으로 새로운 생성자 함수나 객체를 쉽게 만드는 것을 뜻합니다.

기존의 객체를 기반으로 생성하기 때문에 상속으로 새로 만들어지는 객체에는 기존 객체의 특성이 모두 있습니다. 이를 기존의 객체에서 유산(속성과 메서드)을 물려받는 것과 비슷하다고 하여 상속이라는 이름을 사용합니다.

 

생성자 함수 Square 선언 예

function Square(length) {
    this.width = length;
    this.height = length;
}

Square.prototype.getArea = function() {
    return this.getWidth() * this.getHeight();
};

위 코드를 캡슐화하고 싶지만 비슷한 코드를 만들때마다 캡슐화를 진행한다면 코드가 너무 복잡해집니다.

이럴때 바로 상속을 이용합니다.

 

상속 예

function Rectangle(w, h) {
    var width = w;
    var height = h;

    // 메서드
    this.getWidth = function() { return width; };
    this.getHeight = function() { return height; };
    this.setWidth = function(w) {
        if(w < 0) {
            throw '음수'
        } else {
            width = w;
        }
    };
    this.setHeight = function(h) {
        if(h < 0) {
            throw '음수'
        } else {
            height = h;
        }
    };
}

Rectangle.prototype.getArea = function() {
    return this.getWidth() * this.getHeight();
};

var rectangle = new Rectangle(5, 7);

rectangle.setWidth(Number(prompt('가로길이 입력')));
rectangle.setHeight(Number(prompt('세로길이 입력')));

console.log("Area: " + rectangle.getArea());

// 상속
function Square(length) {
    this.base = Rectangle;
    this.base(length, length);
}
Square.prototype = Rectangle.prototype;
Square.prototype.constructor = Square;

// var square = new Square(5);

var square = new Square(Number(prompt('값 입력')));
console.log(square.getArea());

// 상속 확인하기
console.log(square instanceof Rectangle); // true

생성자 함수 Square내부에서 작성한 것은 base 속성에 생성자 함수 Rectangle을 넣고 실행한 것과 생성자 함수 Square의 프로토타입에 Rectangle의 프로토타입을 넣은 것 두가지 입니다. 전자를 사용해서 Rectangle객체의 속성을 Square객체에 추가했으며, 후자를 사용해 Rectangle객체의 프로토타입이 가진 속성 또는 메서드를 Square객체의 프로토타입에 복사했습니다. 

 

참고로 생성자 함수 Square의 프로토타입 constructor()메서드에 Square를 다시 넣는 부분이 없어도 정상작동을 합니다.

하지만 직접 square객체의 constructor()메서드를 출력해보면, 생성자 함수 Square가 아니라 생성자 함수 Rectangle을 가리킵니다. 따라서 프로토타입의 생성자 함수를 재정의한 것입니다.

 

여러 곳에서 활용되므로, 자식이 부모의 속성과 메서드를 물려받는 것이라고 알고 넘어가줍니다.

 

반응형

'JavaScript | TypeScript > Javascript 시작하기' 카테고리의 다른 글

[ Javascript ] 기본 내장 객체  (0) 2022.06.15
[ Javascript ] 클래스  (0) 2022.06.15
[ Javascript ] 캡슐화  (0) 2022.06.14
[ Javascript ] 프로토타입  (0) 2022.06.13
[ Javascript ] 생성자 함수  (0) 2022.06.13
반응형

캡슐화

캡슐화는 잘못 사용될 수 있는 객체의 특정 부분을 사용자가 사용할 수 없게 막는 기술입니다.

 

예를 들어 사각형을 의미하는 Rectangle객체를 만든다고 가정해봅니다. 아래 코드처럼 생성자 함수 Rectangle을 만들 수 있습니다. 그리고 사각형의 수많은 속성 중 넓이를 구하는데 필요한 width속성과 height속성을 지정했습니다.

 

생성자 함수 Rectangle 선언 예

function Rectangle(width, height) {
    this.width = width;
    this.height = height;
}

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

var rectangle = new Rectangle(5, 7);

console.log("Area : " + rectangle.getArea()); // Area : 35

getArea()메서드를 통해 35를 출력합니다. 그런데 width속성이나 height속성에 음수값을 넣으면 코드 적으로는 문제가 없지만 길이를 구하는데, 음수가 나오는 것은 불가능 합니다.

 

잘못된 속성의 사용 예

function Rectangle(width, height) {
    this.width = width;
    this.height = height;
}

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

var rectangle = new Rectangle(5, 7);
rectangle.width = -2;

console.log("Area : " + rectangle.getArea()); // Area : -14

위 코드처럼 코드에는 문제가 없지만 길이를 구하는데 마이너스라는 불가능한 숫자가 등장합니다.

물론 음수를 넣지 않으면 문제가 되지 않겠지만, 코드를 직접 생성한 사람 이외에 사람이 사용한다면 아무것도 모르고 그냥 사용할 수 있습니다. 자신이 만들고도 시간이 조금 지나면 까먹는게 현실입니다.

세상에는 여러 사람들이 있기 때문에 문제가 일어날 수 있다는 것을 알고 있어야 합니다.

다시한번 말하자면, 캡슐화란 이렇게 잘못 사용될 수 있는 객체의 특정 부분을 사용자가 사용할 수 없게 만드는 기술입니다.

 

캡슐화 예

function Rectangle(w, h) {
    var width = w;
    var height = h;

    // 메서드
    this.getWidth = function() { return width; };
    this.getHeight = function() { return height; };
    this.setWidth = function(w) { width = w; };
    this.setHeight = function(h) { height = h; };
}

var rectangle = new Rectangle(5, 7);

생성자 함수 내에서 변수 width와 height를 정의했습니다. 이제 외부에서는 지역 변수 width와 height를 사용할 수 없고 오직 get과 set형태의 메서드를 사용해야합니다.

 

게터(getter)와 세터(setter) 예

function Rectangle(w, h) {
    var width = w;
    var height = h;

    // 메서드
    this.getWidth = function() { return width; };
    this.getHeight = function() { return height; };
    this.setWidth = function(w) {
        if(w < 0) {
            throw '음수'
        } else {
            width = w;
        }
    };
    this.setHeight = function(h) {
        if(h < 0) {
            throw '음수'
        } else {
            height = h;
        }
    };
}

Rectangle.prototype.getArea = function() {
    return this.getWidth() * this.getHeight();
};

var rectangle = new Rectangle(5, 7);
rectangle.setWidth(-2);

console.log("Area: " + rectangle.getArea()); // Uncaught 음수

위 코드를 실행하면 U ncaught 음수라는 오류가 발생합니다. setWidth()메서드로 음수를 넣었기 때문에 발생하는 오류입니다.

set형태의 메서드로만 width속성과 height속성에 값을 입력할 수 있기 때문에, width속성과 height속성에 음수가 들어가는 일은 없게 되었습니다.

:: throw 키워드 : 강제로 오류를 발생시키는 키워드

 

캡슐화의 개념

  • get형태의 메서드와 같이 값을 가져오는 메서드를 게터(getter)라고 합니다.
  • set형태의 메서드와 같이 값을 입력하는 메서드를 세터(setter)라고 합니다.
  • 게터와 세터 자체가 캡슐화가 아닌 만일의 상황을 대비해서 특정 속성이나 메서드를 사용자가 사용할 수 없게 숨겨두는 것이 캡슐화입니다.

 

반응형
반응형

프로토타입

프로토타입은 생성자 함수로 생성된 객체가 공통으로 가지는 공간입니다. 

 

생성자 함수 구성 예

function Student(name, korean, math, english, science) {
    this.name = name;
    this.korean = korean;
    this.math = math;
    this.english = english;
    this.science = science;
}

 

프로토타입으로 메서드 생성하기 예

function Student(name, korean, math, english, science) {
    this.name = name;
    this.korean = korean;
    this.math = math;
    this.english = english;
    this.science = science;
}

Student.prototype.getSum = function() {
    return this.korean + this.math + this.english + this.science;
};
Student.prototype.getAverage = function() {
    return this.getSum() / 4;
};
Student.prototype.toString = function() {
    return this.name + '\t' + this.getSum() + '\t' + this.getAverage();
};

var student = new Student('shiro', 98, 34, 65, 77);

console.log(student.getSum()); // 274
console.log(student.getAverage()); // 68.5
console.log(student.toString()); // shiro 274 68.5

메서드는 모두 프로토타입 안에 넣어줍니다. 프로토타입은 우리가 만드는 것이 아니라, 함수 안에 자동으로 만들어지는 arguments와 마찬가지로 자바스크립트의 모든 함수는 변수 prototype을 갖습니다. ( prototype은 객체입니다. )

 

생성자 함수를 사용한 객체 배열 생성하기 예

function Student(name, korean, math, english, science) {
    this.name = name;
    this.korean = korean;
    this.math = math;
    this.english = english;
    this.science = science;
}

Student.prototype.getSum = function() {
    return this.korean + this.math + this.english + this.science;
};
Student.prototype.getAverage = function() {
    return this.getSum() / 4;
};
Student.prototype.toString = function() {
    return this.name + '\t' + this.getSum() + '\t' + this.getAverage();
};

var output = '이름 \t 점수 \t 평균 \n';
var students = [];
students.push(new Student('shiro', 98, 34, 65, 77));
students.push(new Student('AAA', 32, 43, 55, 66));
students.push(new Student('BBB', 44, 32, 12, 12));

for(var i in students) {
    output += students[i].toString() + '\n';
}

console.log(output);
/*
이름    점수    평균 
shiro  274    68.5
AAA    196    49
BBB    100    25
*/

프로토타입을 사용하면 기존 객체에 추가로 메서드를 제공할 수 있습니다.

 

new 키워드

new키워드로 함수를 호출하면 객체를 위한 공간을 만들고 this키워드는 해당 공간을 의미하게 됩니다.

 

new 키워드 예

function Constructor(value) {
    this.value = value;
}

var constructor = new Constructor('New');

console.log(constructor.value); // New

코드를 실행하면 New를 출력합니다. 

 

new 키워드를 사용하지 않을 경우

function Constructor(value) {
    this.value = value;
}

var constructor = Constructor('New');

console.log(value); // New

위 코드처럼 new키워드를 사용하지 않고, 일반 console.log()에 value변수를 사용하면 정상적으로 실행됩니다.

위에서 언급했듯이 일반적으로 this키워드를 사용하면 window객체를 나타냅니다. 따라서 일반적으로 함수를 호출하듯이 new키워드를 사용하지 않으면, 함수를 실행하는 동안 window객체에 속성을 추가한 것이 되어버립니다. 따라서 위코드처럼 실행이 이루어집니다.

 

반응형
반응형

생성자 함수

생성자 함수는 new키워드로 객체를 생성할 수 있는 함수를 의미합니다. 객체를 생성할 때 사용하는 함수라고 생각하면 됩니다.

 

용어

  • 인스턴스 : 생성자 함수를 기반으로 생성한 객체를 인스턴스라고합니다.
  • 프로토타입 : 생성자 함수로 생성한 객체들이 공동으로 갖는 공간입니다. 일반적으로 메서드를 이러한 공간에 선언합니다.

 

생성자 함수 생성 형태

function Student() { }

이렇게 생성한 함수는 아래코드처럼 new키워드로 객체를 생성합니다.

 

객체 생성

function Student() { }

var student = new Student();

 

생성자 함수의 이름

생성자 함수의 이름은 일반저그올 대문자로 시작합니다. 대문자로 시작하지 않아도 문제는 없지만 개발자 대부분이 지키는 규칙이기 때문에 따르는 것이 좋습니다. 자바스크립트에서 기본적으로 제공하는 생성자 함수도 모두 대문자로 시작합니다.

 

생성자 함수 안에서는 this키워드를 통해 생성자 함수로 생성될 객체의 속성을 지정합니다.

 

속성 생성하기 예

function Student(name, korean, math, english, science, test) {
    this.name = name;
    this.korean = korean;
    this.math = math;
    this.english = english;
    this.science = science;
    this.테스트 = test;
}

var student = new Student('shiro', '국어', '수학', '영어', '과학', '테스트');

console.log(student);
/*
english: "영어"
korean: "국어"
math: "수학"
name: "shiro"
science: "과학"
테스트: "테스트"
*/

 

메서드 생성하기 예

function Student(name, korean, math, english, science, test) {
    this.name = name;
    this.korean = korean;
    this.math = math;
    this.english = english;
    this.science = science;
    this.테스트 = test;

    // 메서드
    this.getSum = function() {
        return this.korean + this.math + this.english + this.science;
    };

    this.getAverage = function() {
        return this.getSum() / 4;
    };

    this.toString = function() {
        return this.name + '\t' + this.getSum() + '\t' + this.getAverage();
    };
}

var student = new Student('shiro', 96, 98, 100, 100, '테스트입니다.');

console.log(student.getSum()); // 394
console.log(student.getAverage()); // 98.5
console.log(student.toString()); // shiro 394 98.5

메서드를 생성하는 방법도 속성을 만드는 방법과 같습니다. this키워드로 속성을 생성하고 함수를 넣어줍니다.

 

생성자 함수를 사용한 객체 배열 생성

function Student(name, korean, math, english, science) {
    this.name = name;
    this.korean = korean;
    this.math = math;
    this.english = english;
    this.science = science;

    // 메서드
    this.getSum = function() {
        return this.korean + this.math + this.english + this.science;
    };

    this.getAverage = function() {
        return this.getSum() / 4;
    };

    this.toString = function() {
        return this.name + '\t' + this.getSum() + '\t' + this.getAverage();
    };
}

var students = [];
students.push(new Student('shiro', 98, 99, 100, 86));
students.push(new Student('AAA', 78, 66, 90, 100));
students.push(new Student('BBB', 67, 77, 70, 100));
students.push(new Student('CCC', 45, 88, 60, 66));

var output = '이름\t총점\t평균\n';
for(var i in students) {
    output += students[i].toString() + '\n';
}
console.log(output);
/*
이름    총점    평균
shiro  383    95.75
AAA    334    83.5
BBB    314    78.5
CCC    259    64.75
*/

실행하면 각각 학생의 총점과 평균을 출력합니다.

 

용어 정리

 

Student()함수는 new키워드로 객체를 생성하므로 생성자 함수(constructor)입니다. 그리고 Student 생성자 함수로 만든 객체 student를 객체(Object)또는 인스턴스(Instance)라고 부릅니다.

반응형
반응형

전개 연산자를 사용한 배열 테크닉

전개 연산자를 사용하면 배열을 복제하거나 병합할 수 있습니다.

 

배열 복제

ECMAScript5까지의 자바스크립트는 배열을 복제할 때 아래 코드처럼 사용해야 했습니다.

:: 코드가 복잡하기 때문에, 함수로 만들어 사용하는 것이 일반적입니다.

 

배열 복제 예

var array = [1, 2, 3, 4, 5];

var newArray = [];
for(var i = 0; i < array.length; i++) {
    newArray[i] = array[i];
}
console.log(array); // 1, 2, 3, 4, 5
console.log(newArray); // 1, 2, 3, 4, 5

그런데 ECMAScript6에서 추가된 전개 연산자를 사용하면 아래 코드처럼 깔끔하게 배열의 내용을 복제할 수 있습니다.

 

전개 연산자를 사용한 배열 복제

var array = [1, 2, 3, 4, 5];

const newArray = [...array];

console.log(newArray); // 1, 2, 3, 4, 5

 

배열 복제 확인 [ 배열 복제가 제대로 됐는지 확인하기 위한 코드 ]

var array = [1, 2, 3, 4, 5];

const newArray = [...array];

array[0] = 52;
array[1] = 222;

console.log(array); // 52, 222, 3, 4, 5
console.log(newArray); // 1, 2, 3, 4, 5

두 배열이 서로 다른 결과를 출력하므로 복제가 제대로 이루어진 것을 확인할 수 있습니다.

 

배열 병합

전개 연산자를 사용하면 배열을 병합할 수 있습니다.

 

전개 연산자를 사용한 배열 병합 예

const arrayA = [1, 2, 3, 4, 5];
const arrayB = [52, 555, 23, 44, 12];

const newArray = [...arrayA, ...arrayB];

console.log(newArray); // 1, 2, 3, 4, 5, 52, 555, 23, 44, 12

 

 

전개 연산자를 사용한 배열 병합2 예

const array = [522, 33, 77, 123, 11];

const arrayA = [1, 2, 3, 4, 5, ...array];
const arrayB = [...array, 1, 2, 3, 4, 5];

console.log(arrayA); // 1, 2, 3, 4, 5, 522, 33, 77, 123, 11
console.log(arrayB); // 522, 33, 77, 123, 11, 1, 2, 3, 4, 5

배열을 선언하면서 곧바로 기존 배열의 요소를 앞 또는 뒤쪽에 추가할 수 있습니다.

 

반응형
반응형

참조 복사와 값 복사

 

기본 자료형의 값 복사 - 깊은 복사 예

var value = 10;
var newValue = value;

value = 273;

console.log(value); // 273
console.log(newValue); // 10

위 코드처럼 값을 복사하고 변경했을 때, 다른 값에 전혀 영향을 주지 않으므로 55, 100이 출력됩니다.

 

객체(배열 포함)의 참조 복사 - 얕은 복사 예

var array = [1, 2, 3, 4];
var newArray = array;

array[0] = 33;

console.log(array); // [33,2, 3, 4]
console.log(newArray); // [33,2, 3, 4]

이전과는 다르게 array와 newArray배열의 값도 바뀌었습니다.

 

기본 자료형의 값 복사

자바스크립트는 기본 자료형(숫자, 문자열, 불)을 복사할 때 값을 완전히 복사합니다.

 

위에있는 깊은 복사 예 처럼 값을 복사하면 아래처럼 나옵니다.

깊은 복사

위처럼 value값만 변경이 되어 두 개의 변수가 완전한 독립성을 갖는 것을 '값 복사' or '깊은 복사'라고 부릅니다.

 

객체의 참조 복사

객체를 변수에 저장하면, 실제 값을 저장하는 것이 아니라 '객체를 메모리 어디인가에 만들고, 객체가 메모리 위의 어디에 있는지'라는 참조(reference)를 저장하게 됩니다.

 

참조할당

참조 할당

이 상태에서 array[0] = 33을 추가하면 '참조되는 위치의 값'이 변경됩니다. array와 newArray는 같은 메모리 위치를 참조하기 때문에 newArray[0]을 출력해도 33을 출력하게 되는 것입니다.

그렇기 때문에 두 개의 배열은 독립적이지 않습니다. 이처럼 독립적이지 않게 복사되는 것을 '참조복사'또는 '얕은복사'라고 부릅니다. 따라서 '객체 또는 배열을 어떻게 깊게 복사를 할 것인가'가 정말 중요한 문제입니다.

 

객체의 깊은 복사

객체의 깊은 복사를 할 때는 새로운 객체를 만들고, for in 반복문으로 원본 객체에 반복을 돌리며 키와 값을 하나하나 옮겨줍니다.

 

객체 복사 예

// 객체를 복제하는 함수
function clone(obj) {
    var output = {};
    for(var i in obj) {
        output[i] = obj[i];
    }
    return output;
}

var original = { a: 10, b: 20 };
var referenced = original;
var cloned = clone(original);

// 변경
original.a = 20;

console.log(JSON.stringify(referenced, null, 2));
/*
{
    "a": 20,
    "b": 20
}
*/
console.log(JSON.stringify(cloned, null, 2));
/*
{
    "a": 10,
    "b": 20
}
*/

얕은 복사한 객체는 원본을 변경했을 때 값이 함께 변경되었지만, 깊은 복사한 객체는 원본을 변경해도 영향을 주지 않습니다.

일반적으로 모든 프로그래밍 언어에서 같은 현상이 일어나며, 깊은 복사를 할 때는 clone이라는 이름의 기능을 활용하게 되므로 'clone'이라는 단어 자체를 기억해두면 좋습니다.

 

반응형
반응형

함수를 사용한 객체 생성

객체를 개별적으로 만드는것은 특성을 정확히 반영할 수 있는 반면, 시간이 오래걸리고 어렵습니다. 하지만 틀을 잡고 만들면 형태도 같고 쉽고 빠르게 만들어 낼 수 있습니다.

 

객체를 생성하는 함수 틀 예

function makeStudent(name, korean, math, english, science) {
    var willReturn = {};

    return willReturn;
}

 

객체를 생성하는 함수 예

function makeStudent(name, korean, math, english, science) {
    var willReturn = {
        이름: name,
        국어: korean,
        수학: math,
        영어: english,
        과학: science,

        // 메서드
        getSum: function() {
            return this.국어 + this.수학 + this.영어 + this.과학
        },
        getAverage: function() {
            return this.getSum() / 4;
        },

        toString: function() {
            return this.이름 + '\t' + this.getSum() + '\t' + this.getAverage();
        }
    };
    return willReturn;
}

위 코드에 makeStudent()함수를 사용하면 객체를 틀에서 찍어내듯이 만들어낼 수 있습니다.

 

함수를 사용한 객체 생성

function makeStudent(name, korean, math, english, science) {
    var willReturn = {
        이름: name,
        국어: korean,
        수학: math,
        영어: english,
        과학: science,

        // 메서드
        getSum: function() {
            return this.국어 + this.수학 + this.영어 + this.과학
        },
        getAverage: function() {
            return this.getSum() / 4;
        },

        toString: function() {
            return this.이름 + '\t' + this.getSum() + '\t' + this.getAverage();
        }
    };
    return willReturn;
}

var students = [];
students.push(makeStudent('사람1', 98,100,55,76));
students.push(makeStudent('사람2', 98,54,55,100));
students.push(makeStudent('사람3', 98,88,46,89));
students.push(makeStudent('사람4', 98,44,78,88));
students.push(makeStudent('사람5', 98,12,87,98));

var output = '이름 \t 총점 \t 평균\n';
for(var i in students) {
    output += students[i].toString() + '\n';
}
console.log(output);

/*
이름 	 총점 	 평균
사람1    329    82.25
사람2    307    76.75
사람3    321    80.25
사람4    308    77
사람5    295    73.75
*/

위 코드처럼 함수를 사용하면 객체를 쉽게 만들 수 있습니다. 생성자 함수를 사용하면 기능이 많은 객체를 쉽게 만들수 있기 때문에 실제로 이러한 방법은 잘 사용하지 않습니다.

 

반응형

+ Recent posts