[CookBook] 자바스크립트 객체



1. 자바스크립트 객체 정의하기


함수 생성자와 new 연산자를 활용해 새로운 인스턴스를 생성한다. 또한, 인스턴스 생성 시 함수 내부로 전달되는 this(scope)에 대해 알아본다.



function User(/*string*/uid, /*string*/uname) {
    
    // this 객체 User 생성자(class)의 인스턴스가 아니라면...
    if (!(this instanceof User)) return null;

    this.uid = uid;
    this.uname = uname;

    this.constructor = this.constructor;
    return this;
}

// this.constructor === User
console.debug(new User('mohwa', 'mohwaName').uid);
console.debug(new User('mohwa', 'mohwaName').uname);
console.debug(new User('mohwa', 'mohwaName').constructor);


try
{
    // this.constructor === Window
    User('mohwa', 'mohwaName');
    console.debug(window['uid']);
    console.debug(window['uname']);
}
catch(e){
    console.debug('error=' + e.message);
}


1. 자바스크립트에서 함수는 객체이다.

http://mohwaproject.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%8A%A4%EC%BD%94%ED%94%84


2. Javascript new 단항 연산자의 객체 인스턴스 생성 프로세스

http://mohwaproject.tistory.com/entry/javascript-new-%EC%97%B0%EC%82%B0%EC%9E%90%EC%9D%98-%EA%B0%9D%EC%B2%B4-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-%EC%83%9D%EC%84%B1-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4





2. 객체 맴버를 비공개로 만들기


"특권 메서드(Closure 활용)"란? 비공개 맴버(private)에 접근 가능하며, 그 자신은 public 인 메서드(getter(), setter()와 동일)



function User(/*string*/uid, /*string*/name) {

    // this 객체 User 생성자(class)의 인스턴스가 아니라면...
    if (!(this instanceof User)) return null;

    this.uid = uid;

    var name = name;

    // 특권 메서드
    this.getName = function () {
        return name;
    }

    this.constructor = this.constructor;

    return this;
}

console.debug(new User('mohwa', 'mohwaName').uid);
console.debug(new User('mohwa', 'mohwaName').name);
console.debug(new User('mohwa', 'mohwaName').getName());

javascript private member 
http://mohwaproject.tistory.com/entry/javascript-private-member






3. 프로토타입(객체)으로 객체 확장하기


"프로토타입" 상속을 통해 어떤 객체(내장, 생성된)든 확장 가능하다.


또한, 프로그램 안에서 재사용될 메서드(보통 프로토 타입 맴버에 할당한다. 이유는 생성자 내부의 인스턴스 맴버와 다르게 생성 시 한번만 실행되기 때문이다.)와 같은 경우 효율을 위해 인스턴스 맴버가 아닌 프로토타입 맴버에 추가시킨다.



function User1(/*string*/uid, /*string*/name) {

    // this 객체 User 생성자(class)의 인스턴스가 아니라면...
    if (!(this instanceof User1)) return null;

    // 인스턴스 맴버
    this.uid = uid;
    this.name = name;

    this.constructor = this.constructor;

    console.log('Instance members=' + this.uid);

    return this;
}

// 프로토타입 맴버(재 사용 메서드 추가)
User1.prototype.getId = function () {
    console.log('Prototype members=' + this.uid);
    return this.uid;
}

var mohwa1 = new User1('mohwa1', 'mohwaName1');
var mohwa2 = new User1('mohwa2', 'mohwaName2');
var mohwa3 = new User1('mohwa3', 'mohwaName3');

// 한번만 실행된다.
mohwa3.getId();

String.prototype.trim = function () {
    return this.replace(/^\s+|\s+$/g, '');
}

console.log('    mohwa    '.trim());


자바스크립트 프로토타입 체인

http://mohwaproject.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-prototype-%EC%B2%B4%EC%9D%B8


자바스크립트 상속(클래스 방식 상속)

http://mohwaproject.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%83%81%EC%86%8D-5






4. 객체 기능 상속하기



자바스크립트 기본 상속


function User3(/*string*/uid, /*string*/name) {

    // this 객체 User 생성자(class)의 인스턴스가 아니라면...
    if (!(this instanceof User3)) return null;

    // 인스턴스 맴버
    this.uid = uid;
    this.name = name;

    return this;
}

// 프로토타입 맴버
User3.prototype.getId = function () {
    return this.uid;
}

// 프로토타입 객체에 new User3() 객체연결(가장 기본적인 상속 구조)
function clon1(target) {

    target = target || function () { ; };

    var f = function () {
        return this;
    };

    var slice = Array.prototype.slice;
    // 객체 상속
    f.prototype = new target(slice.call(arguments, 1)[0], slice.call(arguments, 1)[1]);

    return new f();
}

var clonObject1 = clon1(User3, 'mohwa1', 'mohwaName1');
console.log(clonObject1.uid);
console.log(clonObject1.name);
console.log(clonObject1.getId);


자바스크립트 상속 1

http: //mohwaproject.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%83%81%EC%86%8D-1

        

자바스크립트 상속 2

http://mohwaproject.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%83%81%EC%86%8D-2




함수 인스턴스 맴버 빌려쓰기(상속)


function User3(/*string*/uid, /*string*/name) {

    // this 객체 User 생성자(class)의 인스턴스가 아니라면...
    if (!(this instanceof User3) && !(this instanceof clon2)) return null;

    // 인스턴스 맴버
    this.uid = uid;
    this.name = name;

    return this;
}

// 함수 인스턴스 맴버 빌려쓰기(상속)
function clon2(target) {

    if (!(this instanceof clon2)) return null;
                
    target = target || function () { ; };

    // 인스턴스 맴버 복사
    target.apply(this, Array.prototype.slice.call(arguments, 1));

    return this;
}

var clonObject2 = new clon2(User3, 'mohwa1', 'mohwaName1');
console.log(clonObject2.uid);
console.log(clonObject2.name);
// 인스턴스 맴버만 복사되었기 때문에 프로토타입 맴버인 getId() 메서드는 사용할 수 없다.
console.log(clonObject2.getId);


자바스크립트 상속 3 http://mohwaproject.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%83%81%EC%86%8D-3 

자바스크립트 상속 4 http://mohwaproject.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%83%81%EC%86%8D-4





함수(원형) 복사 및 함수 프로토타입 맴버 복사.

프로토타입 맴버(객체)에 객체를 연결하는 방법이 아닌 다른 방법으로 해당 함수가 가진 모든 맴버(인스턴스, 프로토타입)를 복사하는 방법(하지만 억지스러운 면이 없지 않다.)



function User3(/*string*/uid, /*string*/name) {

    // this 객체 User 생성자(class)의 인스턴스가 아니라면...
    if (!(this instanceof User3)) return null;

    // 인스턴스 맴버
    this.uid = uid;
    this.name = name;

    return this;
}

function clon3(target) {

    target = target || function () { ; };

    // 함수(User3 원형)복사
    var f = target;
    // 프로토타입 맴버 복사
    f.prototype = target.prototype;

    return f;
}

var clonObject3 = new (clon3(User3))('mohwa2', 'mohwaName2');
console.log(clonObject3.uid);
console.log(clonObject3.name);
console.log(clonObject3.getId);


자바스크립트 상속 5 http://mohwaproject.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%83%81%EC%86%8D-5

자바스크립트 상속 6 http://mohwaproject.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%83%81%EC%86%8D-6






프로토타입 맴버에 User3 객체를 연결했으며, "예제 1번"의 상속 계념과 거의 동일하지만 다른점으로는 "객체" 가 아닌 "함수" 를 반환해 구현 했다는 점이다.


function User3(/*string*/uid, /*string*/name) {

    // this 객체 User 생성자(class)의 인스턴스가 아니라면...
    if (!(this instanceof User3)) return null;

    // 인스턴스 맴버
    this.uid = uid;
    this.name = name;

    return this;
}

function clon4(target) {

    target = target || function () { ; };

    var f = function () {
        return this;
    };

    var slice = Array.prototype.slice;
    // User3 객체를 연결
    f.prototype = new target(slice.call(arguments, 1)[0], slice.call(arguments, 1)[1]);

    return f;
}

var clonObject4 = new (clon4(User3, 'mohwa3', 'mohwaName3'))();
console.log(clonObject4.uid);
console.log(clonObject4.name);
console.log(clonObject4.getId);​





5. 새로운 속성을 정의하여 객체 확장하기


Object.defineProperty 메서드(ECMAScript5)를 활용해 객체 속성을 정의한다.



// 속성 정의
var obj1 = {};
Object.defineProperty && Object.defineProperty(obj1, 'datas', {
    value: {
        uid: 'mohwa',
        name: 'mohwaName'
    },
    // 속성 변경 유/무
    writable: true,
    // for in 반복문 검사 유/무
    enumerable: true,
    // 이미 지정한 속성의 설정 변경 유/무
    configurable: false
});

console.log(obj1.datas.uid);
console.log(obj1.datas.name);


var obj2 = {};
// get, set 옵션을 사용 시 value 옵션을 함께 사용할 수 없다.
Object.defineProperty && Object.defineProperty(obj2, 'datas', {
    get: function () {
        return value;
    },
    set: function (newValue) {
        value = newValue;
    }
});

obj2.datas = {};
console.log(obj2.datas.uid);
console.log(obj2.datas.name);

// 여러 개의 속성 한번에 정의
var obj3 = {};
Object.defineProperties && Object.defineProperties(obj3, {
    'datas1': {
        value: {
            uid: 'mohwa1',
            name: 'mohwaName1'
        },
        writable: true
    },
    'datas2': {
        value: {
            uid: 'mohwa2',
            name: 'mohwaName2'
        },
        writable: true
    }
});

console.log(obj3.datas1.uid);
console.log(obj3.datas2.uid);


ECMAScript5 객체 속성 추가

http://dol2156.tistory.com/archive/20120516






6. 객체 속성 열거하기



var propertys = '';
var obj = {
    uid: 'mohwa',
    name: 'mohwaName'
}

// Object.keys 속성 사용(ECMAScript5)
propertys = Object.keys && Object.keys(obj).join(',');

console.log(propertys);

// Object.getOwnPropertyNames 속성 사용(ECMAScript5)
propertys = Object.getOwnPropertyNames && Object.getOwnPropertyNames(obj).join(',');

console.log(propertys);

// for in문 검색 결과(기본)
propertys = (function () {

    var ownPropety = Object.hasOwnProperty;
    var _propertys = [];
    for (var n in obj) {
        if (ownPropety.call(obj, n)) {
            _propertys.push(n);
        }
    }

    return _propertys;
})().join(',');


console.log(propertys);





7. 속성 추가 및 속성 서술자 변경 금지


Object.seal 메서드(ECMAScript5)를 활용해 객체 속성이 추가되는 것은 물론 속성 서술자가 변경되는 것을 막는다.



var obj = {
    uid: 'mohwa',
    name: 'mohwaName'
}

// 속성 추가 및 서술자 변경 금지
// 객체 속성의 추가, 삭제를 막는다.(수정은 가능)
if (Object.seal) {
    Object.seal(obj);
}

try {
    // 수정 됨
    obj.uid = 'new mohwa';
    // 추가 안됨
    obj.uid2 = 'new mohwa';

    console.log('retuls1=' + obj.uid);
    console.log('retuls1=' + obj.uid2);

    // 삭제 안됨
    delete obj.uid;

    console.log('retuls1=' + obj.uid);

}
catch (e) {
    console.log(e);
}

var obj = {
    uid: 'mohwa',
    name: 'mohwaName'
}

// 속성 불변 객체 만들기

// 객체 속성의 모든 기능(추가, 수정, 삭제)를 막는다.
if (Object.freeze) {
    Object.freeze(obj);
}

try {

    // 수정 안됨
    obj.uid = '';

    // 추가 안됨
    obj.uid2 = '';

    console.log('retuls2=' + obj.uid);
    console.log('retuls2=' + obj.uid2);

    // 삭제 안됨
    delete obj.uid;

    console.log('retuls2=' + obj.uid);


}
catch (e) {
    console.log(e);
}




8. 일회성 객체와 네임스페이스


자바스크립트 모듈 과 네임스페이스 http://mohwaproject.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B0%95%EC%A2%8C-10-%EB%AA%A8%EB%93%88-%EA%B3%BC-%EB%84%A4%EC%9E%84%EC%8A%A4%ED%8E%98%EC%9D%B4%EC%8A%A4






9. prototype.bind 함수(주어진 함수의 유효범위를 다룬다)



window.name = 'WindowName';

var objObject = {
    name: 'objObjectName',
    getNewName: function () {
        return (function (that) {
            console.log('result3=' + that.name);
        })(this);
    }
};

if (!Function.prototype.bind) {
    Function.prototype.bind = function (scope) {
             
        var fn = this;
        return fn.apply(scope, arguments);
    }
}

// 유효범위(obj11)
objObject.getNewName();
// 유효범위(window)
objObject.getNewName.bind(this)();




10. 객체 메서드 체인 패턴


자바스크립트 (Singleton, Factory, Chain, Interator) Pattern 구현 http://mohwaproject.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Singleton-Factory-Chain-Interator-Pattern-%EA%B5%AC%ED%98%84