소프트웨어/JavaScript • Dhtml

new Object() 와 {} 의 차이에 대한 댓글정리문서

falconer 2007. 4. 12. 13:26
재미있는 내용이라 phpschool에서 가져왔습니다.


먼저 전 선생님이 아닙니다.
누굴 가르쳐본적도 없고, 가르치면서 일을 진행한적도 없습니다.


하지만, 고니님이 주장하는것과 제가 생각하는것이 달라,
단지, 처음부터 끝까지 거짓이 진실이 되는걸 볼수 없기 때문에 150개가 넘는 댓글을 달게 된것입니다.


어쨋든 고니님의 뜻도
-----------------------------
아뇨. 정말로 틀렸다는 것을 증명해주시기를 바라고 있습니다.
원하신다면 문서로 만들어서 대중의 심판을 받을 각오도 되어있습니다.
-----------------------------
와 같아 최대한 주관을 배제하려고 글을 올립니다.



주관이 섞인 부분은 지적해 주시면, 지우도록 하겠습니다.

만약 주관이 섞여 있다면, 위의 글들을 보시고, 해당하는 주관을 배제하시기 발바니다.


원본의 댓글들은 다음과 같습니다.

http://www.phpschool.com/gnuboard4/bbs/board.php?bo_table=tipntech&wr_id=52892&page=1

아래의 논쟁으로 부터 시작된거이며, 명제는 다음과 같습니다.










1. Core Object 인 Object 의 정의는 다음과 같다. (http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Object)

Object is the primitive JavaScript object type. All JavaScript objects are descended from Object. That is, all JavaScript objects have the methods defined for Object.

(주관배제하기 위해 해석하지 않습니다.)


2. new Object() 와 {} 는 Object 의 instance 를 만든다.

3. predefined Core Objects

Array Object
Boolean Object
Date Object
Function Object
Math Object
Number Object
RegExp Object
String Object

4. __proto__ 와 prototype 은 다르다.
prototype is for types, while __proto__ is the same for instances
(http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Inheritance)
(http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Property_Inheritance_Revisited:Determining_Instance_Relationships)

5. constructor 의 정의는
Specifies the function that creates an object's prototype.

6. prototype 의 정의는
prototype: Allows the addition of properties to all objects.






논쟁거리는

1. new Object() === {} 가 같다?
2. Object 가 {} 으로 만들어진다?
3. constructor 의 비교로 객체가 똑같다고 말할수 있다?
4. Object 는 Function 의 instance 이다?

입니다.






여기부터는 대화의 내용을 정리한것이라, 최대한 주관을 배제하려고 노력했습니다.


1. 고니님은 new Object() === {} 같다.
    다르다는 것을 증명을 해보라

-> {} 는 setter 와 getter 를  prefix 할때 사용한다.
    허나 new Object() 는 added later to any object at any time using 이다.

-> {} 문법이 말 그대로 Object initializer 라서지, 그게 new Object 와 {}가 다르다는 근거는 되지 못한다는 것

-> ie에서
   
    delete Object;
    alert({});                // instance return
    alert(new Object()); // error

    FF 에서는 core Object가 삭제되지 않아 위의 코드가 정상적으로 진행된다.

-> 행복한 고니님의 주장.. Jscript 이기 때문에, IE 에서만 동작하기 때문에 인정할수 없다.
-> 아래의 4번의 내용은 Firefox에서만 동작한다. 따라서 특정브라우저에서만 동작된다고, 본질은 무시하지 못한다.

-> 고니님 rhino 소스를 보여준다. 이래도 같지가 않은지를...
->
---------------------------------------------------------------------------

public static Scriptable newObjectLiteral(Object[] propertyIds,
                                          Object[] propertyValues,
                                          Context cx, Scriptable scope)
{
    Scriptable object = cx.newObject(scope);
    for (int i = 0, end = propertyIds.length; i != end; ++i) {
        Object id = propertyIds[i];
        Object value = propertyValues[i];
        if (id instanceof String) {
            ScriptableObject.putProperty(object, (String)id, value);
        } else {
            int index = ((Integer)id).intValue();
            ScriptableObject.putProperty(object, index, value);
        }
    }
    return object;
}


public final Scriptable newObject(Scriptable scope, String constructorName,
                                  Object[] args)
{
    scope = ScriptableObject.getTopLevelScope(scope);
    Function ctor = ScriptRuntime.getExistingCtor(this, scope,
                                                  constructorName);
    if (args == null) { args = ScriptRuntime.emptyArgs; }
    Object a = ctor.construct(this , scope, args);
    return ctor.construct(this, scope, args);
}

---------------------------------------------------------------------------

소스와


4단계 .
object = new Object();
function a() {
    var object = new Object();

    var tmp;
    for(var i = 0; i < arguments[i] ; ++i){
        tmp = arguments[i].split(':');
        object[tmp[0]] = tmp[1];
    }

    return object;
};

var xx  = a();
alert(xx.__proto__.__proto__);        // null
alert(object.__proto__.__proto__);  // null
alert(object.__proto__ === xx.__proto__);    // Object 는 같다.
alert(object === xx);    // false


소스를 보여주며, 4단계에 걸쳐 퀴즈로 증명.




2. Object 가 {} 으로 만들어진다?

-> ECMA 문서에 있다고 고니님 주장.
-> Object 와 instance 간의 차이를 모르는것 같아 Object 가 {} 으로 만들어진다는 내용을 찾을수 없다. 자세한 페이자와 줄번호를 알려달라함.
-> Object 는 new Object() 를 의미하는것이다. 말꼬리 잡는것으로 고니님 주장.
    (Object 클래스 자체로 이해하고 있었군요. Object 가 생성된다는 의미를 저는 Object 객체가 생성된다라고
    사용해왔고 코드를 통해 설명할 때는 분명 new Object 를 사용했었으며, 처음부터 지금까지 계속 같은 말만 하고 있습니다.비록 표현에 오해가 있을 수 있다해도 말이죠.)

-> Java 로 쓴글을 문맥만 보고 Javascript 로 이해해야 되는지에 대한 반문


3. constructor 로 객체를 비교할수 있다?

-> 행복한 고니님의 주장은
var obj1 = new Object;
var obj2 = {};
alert(obj1.constructor === obj2.constructor);

의 결과는 true입니다. 두 객체의 생성자는 완전히 똑같은 객체이며

alert(obj1.constructor === Object);

에서 보다시피 그것은 Object 이다.

-> alert(Array.constructor);
alert(Object.constructor);
alert(Function.constructor);
alert(Number.constructor);

alert(Array.constructor === Object.constructor);
alert(Array.constructor === Object.constructor);
alert(Array.constructor === Function.constructor);
alert(Array.constructor === Number.constructor);

alert(Function.prototype.constructor.constructor);
alert(Array.prototype.constructor.constructor === Function.prototype.constructor.constructor);
alert(Array.prototype.constructor.constructor === Number.prototype.constructor.constructor);
alert(Array.prototype.constructor.constructor === Object.prototype.constructor.constructor);
alert(Object.prototype.constructor.constructor === Object.prototype.constructor.constructor);
alert(Array.prototype.constructor.constructor === Array.prototype.constructor.constructor);


Array === Object === Function === Number 

모두가 같다.? 말이 되지 않는다.

-> Array === Object는 아니죠. identity도 다르고 값도 다르니까요. 하지만 "자료구조"임에는 확실
    그게 Array와 Object의 "본질" 이라 표기
    (new Object).constructor 를 하게되면 new Object 자체의 성질을 묻는 것이고,
    (new Object).constructor.constructor 를 하게되면 (new Object 타입객체라는 인스턴스)의 성질을 묻는 겁니다.
    성질은 -> 본질을 의미한다 주장.

-> 그럼 instance 간의 비교
    new Object().constructor.constructor == new Array().constructor.constructor 가 성립되는 이유가 말이 안된다.
    따라서 constructor 로 Object 를 비교하는것은 어불성설이다.

    이유는 Object가 최상위이기 때문이다.
    Object
    |
    Array - Number - String - Function ...
    으로 되어 있고 각각의 Function 이라는 chain 으로 감싸서 서로 연결되도록 구성되어 있는것입니다.

    그래서 constructor 로 객체를 비교하는것은 무리가 있다라는 것입니다.
    constructor 를 2번 비교하는것이랑 1번비교하는것이랑의 차이는 없다.


    alert(delete Function.prototype.constructor); // prototype chain 해제
    alert(new Function().constructor.constructor);  // object return
    alert(new Object().constructor.constructor);  // object return
    alert(new Array().constructor.constructor);  // object return
    alert(new Number().constructor.constructor);  // object return
    alert(new String().constructor.constructor);  // object return

    alert(String.constructor);  // object return
    alert(Function.constructor);  // object return
    alert(Object.constructor);  // object return
    alert(Array.constructor);  // object return
    alert(Number.constructor);  // object return

4. 고니님 Object 는 Function 의 instance 이다. 주장
   
   
    alert(Object.__proto__ === Function.prototype);
    alert(Object.__proto__ === Object.prototype);
    alert(Array.__proto__ === Function.prototype);
    alert(Array.__proto__ === Object.prototype);

-> __proto__ 와 prototype 이 같다고 생각하시는지 질문.

  alert(new Object().__proto__ === new Object().prototype);

  왜 위의 코드는 왜 다른지.


-> instanceof 로 고니님 반증
    delete Function.prototype.constructor;
    alert(Object instanceof Function);
    alert(Object.__proto__ === Function.prototype);
    alert(Object.__proto__ === Object.prototype);
    alert(Array.__proto__ === Function.prototype);
    alert(Array.__proto__ === Object.prototype);


-> 명제에서 __proto__ 와 prototype 은 다르다는걸 모르고 계속적으로 비교

    alert(Object.prototype.__proto__); // null -> function 의 상속이 아니다. 라는 증명

    alert(Function.prototype.__proto__.__proto__); //null
    alert(Array.prototype.__proto__.__proto__); // null
    alert(String.prototype.__proto__.__proto__); // null
    alert(Object.prototype); // object
    alert(Function.prototype.__proto__); // object
    alert(Array.prototype.__proto__); // object
    alert(String.prototype.__proto__); // object

    따라서, Object 가 최상위객체이며, function(){} 으로 prototype chain 만 구성한다.

    즉, Object 는 Function 의 instance 가 아니다.
    고로, 고니님이 주장하는 내용은 주관,고집 이다. 라고 주장





여기까지이며, 원문의 댓글과 정리된 내용이 뜻이 다름이 있으면 관련된 내용에 대해 배제하시기 바랍니다.

감사합니다.
  License
본 게시물은 LGPL을 따릅니다. [ LGPL 안내 ]

   행복한고니   07-03-29 02:48  
아.... 길다~ 수고하셨습니다.
쪽지 확인하시고 제 글도 한번 읽어주세요. ^^

______________________________________________________________

아... 그리고 __proto__ 와 생성자의prototype을 비교하는 것은 님께서 링크했던 바로 그 MDC 문서에 있는 내용입니다. MDC 문서작성자가 누군지 몰라도 잘 몰랐나보네요. ㅎㅎ

http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Property_Inheritance_Revisited:Determining_Instance_Relationships

chris와 Engineer의 관계가 인스턴스와 생성자가 아니라고 하시다면 할말 없죠 뭐... 그 고집을 누가 당하겠습니까. ^^

제 글을 다시한번 읽어보세요. 한번이라도 생성자라는 표현없이 __proto__ 와 prototype의 관계를 설명했는지... __proto__에 대해 말씀하시기 이미 오래전에 코드도 보여줬는데 뜬금없는 아래의 코드는 뭐람... -_-;;

남이 한말을 이해도 못하고
alert(new Object().__proto__ === new Object().prototype);
가 올바른 거냐고 물으시면 곤란하죠.

______________________________________________________________

나머지는 적었다가 그냥 지웁니다.

글 자체에는 관여안하려 했는데, 자신이 제 의도를 잘라먹고 이해한 것을 마치 제가 이해를 잘못 한 것처럼 적어놓아서 그 부분만 짚었습니다.

진실은 보시는 분들이 판단하시리라 믿습니다. :)
     
   숨어지내리   07-03-29 12:16  
댓글 있으리라 짐작 했습니다. ^^

-----------------------------------------------------------------------
진실은 보시는 분들이 판단하시리라 믿습니다. :)
-----------------------------------------------------------------------

제가 필히 말하고 싶습니다. 중간에 왜곡이란게 들어가지만 않다면요.. 정.말.로.!!
   피곤해   07-03-29 09:32  
좋은 정보 감사합니다.. ^^;

근데, json에 대한 설명해둔 국내 자료 같은 것은 없나요??
json 봐 두어야 하는데.. 마땅한 것이 눈에 띄지 않네요..
   oneorzero   07-03-29 11:29  
음....예전에 이런건 아니지만 다른 논쟁거리때문에 다툰(싸움?의견충돌?ㅎㅎ)기억이 있습니다.
결론은...어쨋거나 어떤결과가 나오든 기분이 나쁘지만 그만큼 많이 생각하고 알고있는걸 다시생각하는
계기가 되더군요.
   navyism   07-03-29 11:51  
뭐 잘은 모르지만 두분의 글을 참 재미있게(?) 읽고 있습니다.

제 이해가 맞다면...
이야기의 시작은 행복한고니님이 {}는 new Object를 이용하여 object를 생성한다라는 의견을 말씀하셨던 것이고, 숨어지내리님은 {}과 new Object는 다르다라는 반론을 제기하신 것 같습니다.

var obj1 = new Object;
var obj2 = {};
alert(obj1.constructor === obj2.constructor);

이에 대해 행복한고니님은 위의 예제로 생성자를 비교함으로써 서로 같다라는 것을 증명하려하셨고, ECMA-262문서를 근거로 제시하셨죠.
호기심이 생겨 ECMA-262문서를 찾아보니 아래와 같은 내용이 있었습니다.

* Semantics
The production ObjectLiteral : { } is evaluated as follows:
1. Create a new object as if by the expression new Object().
2. Return Result(1).

짧은 영어로는 {}가 new Object에 의해 객체를 생성한다라는 뜻이 맞긴 맞는 것 같습니다.
이것은 굳이 이 문서를 찾아보지 않더라도 {}의 생성자를 확인해보면 쉽게 알 수 있는 내용입니다.

function Object() {
    [native code]
}

이에 대해 숨어지내리님은 아래와 같은 예제를 알려주셨습니다.

delete Object;
alert({}); 
alert(new Object());

Object를 삭제하고도 {}는 객체를 만들어 냅니다. 결국 {}는 new Object에 의한 것이 아니다라는 것이죠.
약간 응용해보면 아래와 같이 생각해볼 수도 있습니다.

delete Array;
alert([]); 
alert(new Array());

물론 결과는 같습니다.
Array는 삭제되었지만 []는 배열을 만들어냈습니다.
생성자를 확인해보면 역시나 Array로 되어있고요.

여기서 약간 논지가 흐려지고 있는 것 같은데요...
1. {}로 만들어 진 것과 new Object로 만들어 진 것은 서로 같다/다르다.
2. {}는 new Object를 이용하여 객체를 만든다/만들지 않는다.

서로 어떤 것을 주장하고 계신걸까요?
재미있게 읽기만 하다가 잠시 헷갈려서 글을 남겨봅니다...
     
   숨어지내리   07-03-29 11:57  
ㅎㅎㅎ ^^; 고니님으로 충분합니다.

이미 제의견은 답글로 달려 있고, rhino 소스에 대한 저의 생각과 증명을
문서정리에도 포함했으니, 댓글과 정리문서를
확인해 보세요..^^

ps. 저 nalog 잘 사용하고 있는데..ㅋㅋ ^^;; 한번 뜯어봐야겠다. (농담입니다. ^^)
          
   navyism   07-03-29 13:08  
뭐 누구 편들자는 것은 아닌 것 아시죠?^^;;
               
   숨어지내리   07-03-29 13:34  
네.. ^^ 그래서 조크 날린겁니다.
          
   행복한고니   07-03-29 14:01  
증명이 안될텐데요? ^^
님이 처음에 하셨던 바로 그 실수를 또 하십니까?

아래 코드로 증명하셨다고 하셨습니다.
____________________________________
object = new Object();
function a() {
    var object = new Object();

    var tmp;
    for(var i = 0; i < arguments[i] ; ++i){
        tmp = arguments[i].split(':');
        object[tmp[0]] = tmp[1];
    }

    return object;
};

var xx  = a();
alert(xx.__proto__.__proto__);        // null
alert(object.__proto__.__proto__);  // null
alert(object.__proto__ === xx.__proto__);    // Object 는 같다.
alert(object === xx);    // false
____________________________________
identity하고 equality를 혼동하지는 않으셨으면 좋겠습니다.

object2 = new Object();
var xxx = a();

alert(object === object2);
alert(xxx === xx);

또한, 테스트 할 때는 다른 것도 해보시라고 누누히 말씀드렸었습니다. 같은 방식으로 만들어도 identity는 다릅니다. 당연한 것이 서로 다른 객체니까요. 사실 __proto__를 저런 식으로 중첩(2개 이상)해서 사용하는 것 자체에도 의미가 없기는 하지만 그 부분을 제쳐두고라도 논리가 틀렸습니다.

지금 숨어지내리님은 본인 스스로 적절하지 않은 소스라고 말씀하신 것을 다시 반복하고 계십니다.
               
   comefeel   07-03-29 14:11  
답글 그만 다세요 ..
   공대여자   07-03-29 11:59  
tip/tech 에 좋은 글 올라오는건 좋은데...
이런 글이 '포럼'에 올라가야합니다!

움.. 그런데 자바스크립트는 대부분이 객체로 알고있는데..
어쨌든 누가 결론좀.
     
   숨어지내리   07-03-29 12:14  
이것도 하나의 tip이라고 할수 있습니다.

Basic(기본)을 모르고 안다고 할수 있겠습니까? ^^

많은분들의 tip & tech 중 tip 이라고 생각하면 좋을거 같은데요..
   불친절한코더씨   07-03-29 12:31  
포럼에 올렸야하는거 같은데요.
   딸기키우자   07-03-29 13:39  
다시 시작 하시는 건가요 아래 글 1/3 정도 읽다가 포기 했슴^^;
너무나 자기주장이 강한 분들이라고 생각이 드는군요!
이런 분류의 사람들 사이에서는 결론이 잘 나질 않죠!



"이세상에 완전한것은 없다" 가 생각나는 1人

고운하루들 보내세요
   comefeel   07-03-29 14:12  
답글 그만 다세요.
   버럭오행   07-03-29 14:37  
결국 전 2시간동안 다 읽었습니다. 아 재밌네요.
나의 부족함을 느끼게해주는 글과 댓글이네요.
   BL   07-03-30 00:57  
전.. 아는게 없어서 읽어도 이해도 잘 안되지만..
아무튼 논쟁은 좋은데,
글 중간 중간에 인신공격이 들어가 있는거 같아서 보기 안타까웠습니다.
   ε♡з   07-03-30 06:37  
xx하니 xx가 맞다. 이건 하나의 이론이죠.
진실을 따지는건 '숨어지내리'님의 주장이 최상위에 있다고 자부하는겁니다.
신만이 할 수 있는걸 어찌..
언제든 자신도 틀릴수 있다는 자세가 필요할것 같네효.
잘은 모르지만 JS가 자체적으로 발전함에 따라 이론이 뒤틀려질수도 있겠죠?

‘반증가능성(Falsiability)’이 있을 때에만 진정 과학적이라고 할 수 있다. 즉, 한 주장이 틀릴 수 있음을 객관적으로 증명할 수 있을 때에만 ‘과학적’이라고 할 수 있다는 것이다. - 칼포퍼

반증가능성을 일체 무시하고 진실을 따지는건 비과학적이고 종교적입니다. ㄳㄳ
물론 fact를 따질순 있는데.. 고수분들끼리도 분분한 내용이기에.. (전 x도 몰라서 ^^ 히히)
   maggot   07-03-30 11:34  
저도 원글에 답글좀 달아볼려고 rhino 소스 보다가 comfeel 님의 중재로 포기했습니다만
ECMA 는 스펙이고, 구현은 각 벤더에 따라 달라지는거 아닐까 싶습니다
같은 스펙을 놓고도, rhino, jscript, spidermonkey 각각 미세한 차이(상용으로 확장구현된 엔진은 더 심함)가 존재할 터인데...
문제는 core object, Object, function, Function 등 각 용어에 대해 말하는 분과 듣는 분의 이해가 서로 다른 것 같다~ 라는데 있는것 같기도 합니다
여하튼 이런 논쟁이 소모적인 양상이 되기보다는 두 분의 적절한 배려로 인해 발전적인 방향이 되면 좋겠네요
     
   낭망백수   07-03-31 13:13  
지금 comfeel 님이 중재중이신 모양인가요? ^^;;;
          
   maggot   07-04-01 02:14  
달리 마땅한 단어가 없어서리...
답글달지 마세요를 두분의 논쟁이니 두분께 맡겨라는 뜻으로
저는 받아들였더랬습니다
아... 그리고 오늘이 4월 1일이니 미리 연습 좀 해 두어야 겠네요
퍼덕~ 퍼덕~
   에리카v   07-04-04 23:41  
뒤늦게 읽긴했는데.. 앞에글부터.. 사실 자바스크립트는 깊게 공부해본적이 없어서.. 참아쉽네요.
이해가 되는 내용이었다면 좋았을텐데
   치즈버거   07-04-05 15:00  
저도 글을 다 보진 않았지만..
이런 질문을 하고 싶네요
두분 각자의 주장을 기반으로 코딩을 했을때, 문제점/장점 이 있는건가요?
아니면 그저 논리적으로 '주장을 위한 주장' 인가요?