0

저는 경험이 많은 객체 지향 프로그래머입니다.하지만이게 나를 잡았습니다! 왜 새 f()는 할 수 있지만 새 a()는 할 수 없습니까? 나는 어떤 조언을 주셔서 감사하겠습니다.javascript 수수께끼 : 생성자, 프로토 타입 및 __proto__ 링크와 동일한 것으로 보이는 2 개의 객체

// first a few facts 
if (Object instanceof Function) console.log("Object isa Function"); 
console.log("Function.prototype is " + Function.prototype); 
/* output 
Object isa Function 
    Function.prototype is function Empty() {} 
*/ 

var f = new Function(); 
console.log("Prototype of f:" + f.prototype); 
console.log("Constructor of f:" + f.constructor); 
console.log("Prototype Link of f:" + f.__proto__); 
if (f instanceof Function) console.log("f isa Function"); 
/* output 
Prototype of f:[object Object] 
Constructor of f:function Function() { [native code] } 
Prototype Link of f:function Empty() {} 
f isa Function 
*/ 


function A() {} 
console.log("Prototype of A:" + A.prototype); 
console.log("Constructor of A:" + A.constructor); 
console.log("Prototype Link of A:" + A.__proto__); 
if (A instanceof Function) console.log("A isa Function"); 
/* 
Prototype of A:[object Object] 
Constructor of A:function Function() { [native code] } 
Prototype Link of A:function Empty() {} 
A isa Function 
*/ 

// contruct a 
var a = new A(); 
console.log("Prototype of a:" + a.prototype); 
console.log("Constructor of a:" + a.constructor); 
console.log("Prototype Link of a:" + a.__proto__); 
if (a instanceof Function) console.log("a isa Function"); 
if (a instanceof A) console.log("a isa A"); 
/* output 
Prototype of a:undefined 
Constructor of a:function A(){} 
Prototype Link of a:[object Object] 
a isa A 
*/ 

console.log("~~~~~b constructed as new f()"); 
var b = new f(); 
console.log("Prototype of b:" + b.prototype); 
console.log("Constructor of b:" + b.constructor); 
console.log("Prototype Link of b:" + b.__proto__); 
/* output 
~~~~~b constructed as new f() 
Prototype of b:undefined 
Constructor of b:function anonymous() {} 
Prototype Link of b:[object Object] 
*/ 

console.log("~~~~~b constructed as new a()"); 
a.prototype = Object.prototype; 
a.constructor = Function; 
a.__proto__ = Function.prototype; 
if (a instanceof Function) console.log("a isa Function"); 
console.log("Prototype of a:" + a.prototype); 
console.log("Constructor of a:" + a.constructor); 
console.log("Prototype Link of a:" + a.__proto__); 
/* output 
~~~~~b constructed as new a() 
a isa Function 
Prototype of a:[object Object] 
Constructor of a:function Function() { [native code] } 
Prototype Link of a:function Empty() {}  
*/ 
b = new a(); 
/* ERROR Uncaught TypeError: object is not a function*/ 

저는 출력을 제공하기 위해 최선을 다했습니다. f와 a는 프로토 타입, 생성자 및 프로토 타입 링크의 관점에서 동일하다는 것을 알아 두십시오. 마지막 행에서 a()를 새로 만들려고 할 때 ERROR가 나타나는 이유는 무엇입니까?

+2

"new"는 함수를 필요로합니다. _a_는 _A_ 생성자의 개체 인스턴스입니다. – dandavis

+0

인스턴스화 된 개체의 "prototype"속성이있을 것으로 예상되지만 올바르지 않습니다. * edit * yes 그리고 @dandavis에 의하면, 객체는 함수가 아니며 생성자로 사용할 수 없습니다. – Pointy

+1

생성자는 객체이며 함수입니다. 생성자로 호출되면 함수가 아닌 일반 객체를 반환합니다 (기본값). Plain 객체는 private ['[Prototype]]을 가지고 있지만 public * prototype * (디폴트로)을 가지고 있지 않습니다. – RobG

답변

1

오류가 지적한대로 a기능 일 것으로 예상됩니다. 즉, 호출 가능해야합니다. new 키워드에는 인스턴스를 생성하는 방법을 알고있는 함수 객체가 필요하지만 a은 그렇지 않습니다. Function.prototype에서 (__proto__을 사용하여) 상속하면 아무 것도 도움이되지 않지만 호출 가능성은 객체의 본질적인 속성입니다. Function constructor에 의해 생성되고, 이러한 생성자 함수입니다 f

당신은, new f()를 호출 할 수 있습니다.

+0

Bergi, 유용한 정보를 제공해 주셔서 감사합니다. 자바 스크립트 객체의 본질적인 속성에 대해 읽을 수있는 좋은 곳이 있습니까? 나는 기능적 이해와는 반대로 근본적인 이해를 원합니다. 다시 한 번 감사드립니다! –

+0

당신은 항상 [spec을 읽으십시오] (http://es5.github.io/), 특히 [§8.6.2 개체 내부 속성 및 방법] (http://es5.github.io/#x8.6.2) ('new'는'[[construct]]'를 ​​사용합니다). 좀 더 자세한 설명이 필요하다면, Dmitry Soshnikov는 매우 훌륭한 시리즈 [* EcmaScript in detail *] (http://dmitrysoshnikov.com/ecmascript/chapter-7-2-oop-ecmascript-implementation/)를 작성했으며, 그러나 apparantly 미완성) [ES5에] (http://dmitrysoshnikov.com/ecmascript/es5-chapter-0-introduction/). – Bergi

+0

대단히 감사합니다. 이 주제에 대해 얼마나 놀랍습니까? 어쩌면 간단한 isCallable() 구현이 필요합니다. 내가 제안한 문서에서 [[Callable]]은 객체가 함수 또는 new 연산자를 통해 호출되도록 설정해야하는 내부 속성입니다. 반면 [[Construct]]는 보통 생성자 포인터로 구현되는 것입니까? 즉, 원래의 문제는 a의 생성자가 호출 가능하지 않다는 것입니다. 또는 자체가 호출 가능하지 않거나 둘 다? –