2012-02-27 3 views
35

Javascrpt에서 생성자가 작동하는 방법에 대해 매우 혼란 스럽습니다. 몇 년 동안 언어를 사용 했음에도 불구하고 (마치 LISP의 준 명령 버전 인 것처럼) 나는 객체가 어떻게 동작하는지에 대해 더 알고 싶다.JavaScript에서`new`는 무엇을합니까?

function Foo(x) { 
    return { 
     bar: function() { return x; } 
    }; 
} 

myFoo = Foo(5)myFoo = new Foo(5)를 호출의 차이점은 무엇입니까 :

이 코드를 감안할 때? 또는 다른 말로하면, 정확히 정확히 자바 스크립트 의 생성자는을 수행합니까?

+13

Google 검색 결과를 이해하지 못했고 더 나은 설명을 원하면 여기에 귀하의 snarky 코멘트가 어떤 도움이됩니까? –

+0

@ChrisSobolewski OP가 그것에 대해 이해할 수없는 것을 모른다면 어떻게 도와 드릴까요? 무엇이 불분명한지 모르는 경우 어떻게 명확히 할 수 있습니까? – Jeff

+0

@ChrisSobolewski, 어떤 사람들은이 사이트의 목적이 당신이 이해하지 못하는 것들을 정리한다는 것을 잊어 버립니다. 정확한 정보를 얻을 수 있고 그것을 이해했기 때문에. 이 사이트는 일을 정리하는 데 완벽하게 작동합니다. –

답변

44

myFoo = Foo(5)myFoo = new Foo(5)을 호출하는 것의 차이점은 무엇입니까? 이 객체를 반환하기 때문에

는 그 코드에 대한 차이가 없다, 그리고 spec는 말한다 :

  • 결과가 [[전화] 내부를 호출의 결과하자 F의 속성 인 objthis 값으로 제공하고 [[Construct]]으로 전달되는 인수 목록을 args로 제공합니다.
  • Type(result)Object 인 경우 결과는입니다.

이 함수는 결과 인 Object를 반환하므로 그 결과가 사용됩니다. 이 객체를 반환하지 않은 경우 당신은 차이를 느낄 것, 또는 예를 들어, this를 확인하는 경우는로 재 작성하는 경우 :

function Foo(x) { 
    if (!(this instanceof Foo)) { return new Foo(x); } 
    this.bar = function() { return x; }; 
} 
// Now instanceof works. 
alert((new Foo) instanceof Foo); 

자바 스크립트에 new을하지 무엇을

, 어쨌든?

new 연산자 함수가 새로 그 원형이 기능의 속성이다 prototypeObject 생성 this 바인딩하여 호출되게.

사용자 정의 함수에 대한

new f(a, b, c) 

언어 사양은 실제로 두 작업, [[Call]][[Construct]]과 기능을 정의하는,

// Create a new instance using f's prototype. 
var newInstance = Object.create(f.prototype), result; 

// Call the function 
result = f.call(newInstance, a, b, c), 

// If the result is a non-null object, use it, otherwise use the new instance. 
result && typeof result === 'object' ? result : newInstance 

주에 해당하므로 일부 코너 경우가 있습니다 new이 이상하게 행동합니다.

는 예를 들어, 바인딩 및 내장 기능 :

var g = f.call.bind(f); 

호출하는 함수를 정의해야한다, 너무 g는 모든면에서 f와 동일해야합니다, f 호출하지만

new g() 

이 때문에

TypeError: function call() { [native code] } is not a constructor 

을 생산 내장 함수 Function.prototype.call을 지원합니다. [전화]은 아니지만 [0120]는이 아닙니다.

Function.prototype.bindnew 및 일반 전화와 다르게 작동합니다. this 값은 호출 될 때 항상 thisValue의 경계이지만, new을 사용할 때 새로 생성 된 인스턴스입니다.

+1

이것은 유익한 내용이지만 정확한 질문에는 대답하지 않습니다. – benekastah

+3

@benekastah, 두 가지 질문이 있습니다. 제목에 하나, 텍스트에 하나. 나는 그 제목에 먼저 대답했고, 이제 그 텍스트에있는 것을 대답하도록 편집했다. –

+1

그렇게 했어. 나는 이의 제기를 철회한다. :) – benekastah

12

이 특정 예에서 최종 결과에는 차이가 없습니다.

Foo 함수가 개체 인스턴스을 반환하기 때문입니다.

new 연산자 (또는 기술적 인 undefined 가치있는 아무것도 반환하지 않음) 생성자의 프로토 타입 함수가 프리미티브 값을 반환에만 에서 상속 새로 생성 된 개체를 반환합니다. 예를 들어

:

function Foo() { 
    return 5; // or "", or null, or no return statement at all (undefined) 
} 

var foo = new Foo(); 
typeof foo; // "object" 
foo instanceof Foo; // true 
Foo.prototype.isPrototypeOf(foo); // true 

당신은 객체, 단순히 폐기 생성자의 프로토 타입에서 상속 새로 생성 된 개체를 반환 할 때 : 또한

function Foo() { 
    return {}; 
} 

var foo = new Foo(); 
typeof foo; // "object" 
foo instanceof Foo; // false 
Foo.prototype.isPrototypeOf(foo); // false 

참조 :

5

이 경우 새 개체를 반환 할 때 차이가 없습니다. 이 구문으로

function Foo(x){ 
    this._x = x; 
} 

Foo.prototype.bar = function() { 
    return this._x; 
} 

당신이 호출 할 때마다 new Foo_x의 속성과 새로운 객체를 생성합니다 :으로 다시 작성할 수 있습니다. 이점은 bar 함수가 한 번 저장되고 Foo의 여러 인스턴스에 다시 사용된다는 것입니다. 질문에있는 코드로 Foo()을 여러 번 호출하면 모든 인스턴스에 대해 막대 기능이 만들어집니다. 따라서 프로토 타입에 직접 함수를 붙이는 대신 함수를 메모리에 가볍게 붙이면됩니다.

프로토 타입 작동 방식에 대한 전체 설명은 MDC에서 확인할 수 있습니다.