JavaScript의 "새"키워드는 유해한 것으로 간주됩니까? [닫은]


568

다른 질문 에서, 사용자는 new키워드가 사용하기에 위험하며 사용하지 않은 객체 생성에 대한 솔루션을 제안 했다고 지적했습니다 new. 나는 그것이 사실이라고 믿지 않았다. 주로 프로토 타입, 스크립트 어 큐리 티 및 기타 우수한 자바 스크립트 라이브러리를 사용했고, 그들 모두가 new키워드를 사용했기 때문이다 .

그럼에도 불구하고 어제 나는 YUI 극장에서 Douglas Crockford의 강연을보고 있었고 정확히 같은 말을했다. 그는 new더 이상 코드에서 키워드를 사용하지 않았다고 말했다 ( Crockford on JavaScript-Act III : Function the Ultimate-50:23 분 ).

new키워드 를 사용하는 것이 '나쁜' 가요? 그것을 사용하는 장점과 단점은 무엇입니까?


90
새 키워드를 사용하는 것이 '나쁜'것은 아닙니다. 그러나 잊어 버린 경우 객체 생성자를 일반 함수로 호출합니다. 생성자가 실행 컨텍스트를 확인하지 않으면 'this'가 새 인스턴스 대신 다른 객체 (일반적으로 전역 객체)를 가리키는 것을 알 수 없습니다. 따라서 생성자는 전역 객체 (창)에 속성과 메서드를 추가하게됩니다. 'this'가 객체 함수에서 객체의 인스턴스인지 항상 확인하면이 문제가 발생하지 않습니다.
Kristian B

5
나는 이것을 이해하지 못한다. 한편으로 더 그는의 사용을 권장하지 않습니다 new. 그러나 YUI 라이브러리를 살펴보면 new어디서나 사용해야 합니다. 와 같은 var myDataSource = new Y.DataSource.IO({source:"./myScript.php"}); .
aditya_gaur

2
@aditya_gaur 객체를 초기화해야 할 init경우 Object.create접근 방식을 사용하고 메소드 를 호출하는 경우 메소드 를 해킹해야하기 때문입니다. new둘 다 사용 하는 것이 훨씬 쉽고 프로토 타입 체인을 설정하고 초기화 코드를 호출합니다.
Juan Mendes

67
나는 이것이 닫혀 있어야한다고 생각하지 않습니다. 그렇습니다. 일부 Crockford 반 팬 독에 영감을 줄 수 있지만 기본적으로 주요 언어 기능을 피하기 위해 인기있는 조언에 대해 이야기하고 있습니다. 모든 JQuery 객체가 거의 무게를 두지 않도록하는 메커니즘 (메모리가 관련된 경우)에는 'new'키워드를 사용하는 것이 포함됩니다. 팩토리 메소드를 사용하여 지속적으로 새 호출을 수행하지만 오브젝트 리터럴 만 사용하여 아키텍처 옵션 및 성능 잠재력을 크게 줄이지 마십시오. 그들은 자리를 가지고 있으며 생성자는 자리를 차지합니다. 날짜가 적고 시끄러운 조언입니다.
Erik Reppen

2
TLDR : 사용 new하는 것은 위험하지 않습니다. 생략하는 new것은 위험하기 때문에 나쁘다 . 그러나 ES5에서는 Strict Mode를 사용할 수 있습니다.이 모드 는 위험 및 기타 여러 위험으로부터 보호합니다.
jkdev

답변:


603

Crockford는 훌륭한 JavaScript 기술을 대중화하기 위해 많은 노력을 기울였습니다. 언어의 핵심 요소에 대한 그의 의견은 많은 유용한 토론을 불러 일으켰습니다. 즉,“나쁜”또는“유해한”의 선언을 복음으로 받아들이고 한 사람의 의견을 넘어서는 것을 거부하는 사람들이 너무 많습니다. 때때로 조금 실망 스러울 수 있습니다.

new키워드가 제공하는 기능을 사용하면 각 오브젝트를 처음부터 작성하는 것보다 몇 가지 장점이 있습니다.

  1. 프로토 타입 상속 . 클래스 기반 OO 언어에 익숙한 사람들은 종종 의심과 비난을 함께 살펴 보았지만 JavaScript의 기본 상속 기술은 간단하고 놀랍도록 효과적인 코드 재사용 수단입니다. 그리고 새로운 키워드는 그것을 사용하는 정식 (및 사용 가능한 크로스 플랫폼) 수단입니다.
  2. 공연. 이것은 # 1의 부작용입니다 : 내가 작성하는 모든 객체에 10 가지 방법을 추가 할 경우, 내가 단지 수동으로 각각의 새로운 객체에 각각의 방법을 지정하는 생성 기능을 쓰기 또는 난에 할당 할 수 생성 기능 prototype을 사용 new하여 새 객체를 찍는 데 사용 합니다. 프로토 타입의 모든 방법에 필요한 코드가 더 빠를뿐만 아니라 각 방법에 대한 별도의 속성으로 각 객체를 벌룬하는 것을 피할 수 있습니다. 많은 오브젝트가 작성 될 때 느린 기계 (또는 특히 느린 JS 인터프리터)에서 이는 시간과 메모리를 크게 절약 할 수 있습니다.

그리고 네, new다른 대답으로 설명 할 수있는 중요한 단점이 있습니다. 사용하지 않는 경우 코드가 경고없이 중단됩니다. 다행히도 이러한 단점은 쉽게 완화됩니다. 함수 자체에 약간의 코드 만 추가하면됩니다.

function foo()
{
   // if user accidentally omits the new keyword, this will 
   // silently correct the problem...
   if ( !(this instanceof foo) )
      return new foo();

   // constructor logic follows...
}

이제 new실수로 오용하여 발생하는 문제에 대해 걱정할 필요 가 없는 장점이 있습니다 . 깨진 코드가 자동으로 작동한다고 생각하면 검사에 어설 션을 추가 할 수도 있습니다. 또는 일부 의견에 따르면 검사를 사용하여 런타임 예외를 도입하십시오.

if ( !(this instanceof arguments.callee) ) 
   throw new Error("Constructor called as a function");

(이 코드 조각은 생성자 함수 이름을 하드 코딩하는 것을 피할 수 있습니다. 이전 예제와 달리 실제로 객체를 인스턴스화 할 필요가 없으므로 수정하지 않고 각 대상 함수에 복사 할 수 있습니다.)

John Resig는 간단한 "클래스"인스턴스화 게시물 에서이 기술에 대해 자세히 설명 하고 기본적으로이 동작을 "클래스"에 빌드하는 수단을 포함합니다. 확실히 가치가 읽기 ... 그의 곧 책이기 때문에 자바 스크립트 닌자의 비밀 이 많은 다른 "유해한"금을 숨겨 발견 자바 스크립트 언어의 기능을합니다 ( with, 특히 우리의 사람들을 위해 계몽이 처음 기각 사람 이처럼 엄청나게 조정 된 기능입니다.


96
if (! (this instanceof arguments.callee)) throw Error ( "생성자로 불리는 생성자"); //보다 일반적인 생성자 이름에 대한 지식이 필요하지 않으므로 사용자가 코드를 수정하도록하십시오.

5
성능이 걱정되고 실제로 그럴만한 이유가 있다면 점검을 전혀하지 마십시오. 을 사용 new하거나 래퍼 함수를 ​​사용하여 기억하십시오. 나는 의심 당신이 중요한 시점에 있다면 당신의 창조 호출 ... 어쨌든 지역화 할 수 있도록, 당신은 같은 메모이 제이션 이미 소진 다른 최적화를했습니다 있음
Shog9

65
사용 arguments.callee당신이 호출 된 적이 있는지 확인하기 위해 new그렇게 잘되지 않을 수 있기 때문에, arguments.callee엄격 모드에서 사용할 수 없습니다. 함수 이름을 사용하는 것이 좋습니다.
Sean McMillan

69
식별자의 철자가 틀리면 코드가 깨집니다. 식별자를 사용하지 않아야합니까? new코드에 작성하는 것을 잊어 버릴 수 있기 때문에 사용하지 않는 것은 내 예제와 마찬가지로 어리 석습니다.
Thomas Eding

16
당신이 엄격 모드를 설정하면, 경우에 당신은 당신이 사용하려고 할 때 예외를 얻을 것이다 새로운 사용하는 것을 잊지 : yuiblog.com/blog/2010/12/14/strict-mode-is-coming-to-town 즉 각 생성자에 check 인스턴스를 추가하는 것보다 쉽습니다.
stephenbez

182

나는 그의 Crockfords 책 "자바 스크립트 : 좋은 부분"의 일부를 읽었습니다. 나는 그가 그를 물린 모든 것을 해로운 것으로 간주한다는 느낌을 얻습니다.

스위치 넘어짐 정보 :

스위치 케이스가 다음 케이스로 넘어 가지 않도록 절대 허용하지 않습니다. 한 번 넘어지는 것이 때때로 유용한 이유에 대해 활발한 연설을 한 후 의도하지 않은 넘어짐으로 인해 코드에서 버그가 발견되었습니다. (페이지 97, ISBN 978-0-596-51774-8)

++ 및-

++ (증가) 및-(감소) 연산자는 예외적 인 속임수를 장려하여 잘못된 코드에 기여하는 것으로 알려져 있습니다. 바이러스 및 기타 보안 위협을 가능케하는 데있어 결함이있는 아키텍처에 이어 두 번째입니다. (122 페이지)

새로운 정보 :

당신은 포함시키지 않으면 생성자 함수를 호출 할 때 접두사를, 다음 이이 새 개체에 바인딩되지 않습니다. 안타깝게도 이것은 전역 객체에 바인딩되므로 새 객체를 보강하는 대신 전역 변수를 방해 할 수 있습니다. 정말 나쁘다. 컴파일 경고가없고 런타임 경고가 없습니다. (페이지 49)

더 있지만, 당신이 사진을 얻을 바랍니다.

당신의 질문에 대한 나의 대답 : 아니요, 그것은 해롭지 않습니다. 그러나 문제가 생겼을 때 사용을 잊어 버린 경우. 좋은 환경에서 개발하고 있다면 그 사실을 알게됩니다.

최신 정보

이 답변이 작성된 후 약 1 년 후에 엄격 모드 를 지원하는 ECMAScript 5 판이 릴리스되었습니다 . 엄격 모드에서는 this더 이상 전역 객체에 바인딩되지 않고에 바인딩됩니다 undefined.


3
완전히 동의 해. 해결책 : 사용자가 어떻게 객체를 인스턴스화해야하는지 문서화하십시오. 예제를 사용하면 사용자가 잘라 내기 / 붙여 넣기를 할 수 있습니다. 모든 언어에는 오용되어 비정상적이고 예기치 않은 동작을 유발할 수있는 구성 / 기능이 있습니다. 유해하지 않습니다.
nicerobot

45
항상 대문자로 생성자를 시작하고 다른 모든 함수는 소문자로 시작하는 규칙이 있습니다.

61
나는 Crockford가 유해한 것으로 간주하지 않는다는 것을 깨달았습니다 ... 변수를 증가시키는 것을 잊었 기 때문에 무한 루프를 만든 시간을 모르겠습니다 ...
some

5
++,-도 마찬가지입니다. 그들은 내가 가장 분명한 언어로 의도 한 것을 정확하게 표현합니다. 나는 사랑 해요! 스위치 폴 스루는 일부에게는 분명 할 수 있지만, 나는 그것에 대해 지쳤습니다. 나는 그들이 더 명확 할 때 그것들을 사용합니다 (왜냐하면 말장난을 일으킬 수 없었습니다).
PEZ

30
Crockford에 대한 나의 대답 : 프로그래밍은 어렵다. 쇼핑하러 가자. esh!
Jason Jackson

91

동적 언어 인 Javascript는 다른 언어가 당신을 막을 수있는 곳을 엉망으로 만드는 방법입니다.

new엉망이 될 수있는 기초 와 같은 기본적인 언어 기능을 피하는 것은 신발이 더러워 질 수 있으므로 지뢰밭을 걷기 전에 반짝이는 새 신발을 벗는 것과 같습니다.

함수 이름은 소문자로 시작하고 실제로 클래스 정의 인 '함수'는 대문자로 시작하는 규칙을 사용합니다. 결과는 '구문'이 잘못되었다는 정말 매력적인 시각적 단서입니다.

var o = MyClass();  // this is clearly wrong.

이 좋은 명명 습관 외에도 도움이됩니다. 모든 함수가 작업을 수행 한 후에는 이름에 동사가 있어야하지만 클래스는 객체를 나타내며 동사가없는 명사 및 형용사입니다.

var o = chair() // Executing chair is daft.
var o = createChair() // makes sense.

SO의 구문 색상이 위의 코드를 어떻게 해석했는지 흥미 롭습니다.


8
예, 구문 색상에 대해 똑같은 생각을했습니다.
BobbyShaftoe

4
'function'이라는 단어를 입력하지 않은 경우 모든 비용을 피해야합니다. 다른 시간에 나는 여러 줄 if / then 문에서 중괄호를 사용하지 않았습니다. 이제 중괄호를 사용하지 않고 한 줄 조건부 만 작성하십시오.
Hal50000

"이것은 분명히 틀렸다" . 왜? 내 수업 (간단히 수행 if (! this instanceof MyClass) return new MyClass())의 경우 실제로는 new-less 구문을 선호 합니다. 왜? 함수생성자 함수 보다 일반적 이기 때문에 . 생략 new하면 생성자 함수를 일반 함수로 쉽게 변경할 수 있습니다. 추가 new하면 코드가 필요한 것보다 더 구체적으로 작성됩니다. 따라서 유연성이 떨어집니다. 호출자가 구현을 선택할 수 있도록 List대신 권장되는 Java와 비교하십시오 ArrayList.
Stijn de Witt

41

나는 자바 스크립트를 초보자이므로 아마도 이것에 대한 좋은 견해를 제공하는 데 너무 익숙하지 않을 수도 있습니다. 그러나 나는이 "새로운"것에 대한 견해를 공유하고 싶다.

나는 "new"라는 키워드를 사용하는 것이 너무나 자연스럽고 이상하게 보이는 공장 디자인 패턴 인 C # 세계에서왔다.

Javascript로 처음 코드를 작성할 때 YUI 패턴의 키워드와 같은 "새"키워드와 코드가 있다는 사실을 알지 못하므로 재난을 겪는 데 오랜 시간이 걸리지 않습니다. 내가 작성한 코드를 다시 볼 때 특정 줄이 무엇을하는지 추적하지 못합니다. 더 혼란스러운 것은 코드를 "건조 실행"할 때 내 마음이 실제로 객체 인스턴스 경계 사이를 통과 할 수 없다는 것입니다.

그런 다음 "새로운"키워드를 찾았습니다. "별도의"것입니다. 새로운 키워드로 물건을 만듭니다. 새로운 키워드가 없다면, 내가 호출하는 함수가 그에 대한 강한 단서를 제공하지 않으면 그것을 만드는 것과 혼동하지 않을 것입니다.

예를 들어, var bar=foo();어떤 막대가 될 수 있는지에 대한 단서가 없습니다 .... 반환 값입니까 아니면 새로 만든 객체입니까? 그러나 var bar = new foo();나는 바가 객체라는 것을 알고 있습니다.


3
합의, 나는 공장 패턴이 makeFoo ()와 같은 명명 규칙을 따라야한다고 생각
pluckyglen

3
+1- '신규'의 존재는 분명한 의도 진술을 제공합니다.
belugabob

4
JS의 거의 모든 것이 객체 일 때이 응답은 이상합니다. 모든 함수가 객체 일 때 함수가 객체임을 확실히 알아야하는 이유는 무엇입니까?
Joshua Ramirez

@JoshuaRamirez 요점이 아닙니다 typeof new foo() == "object". 그것은 그의 new반환의 인스턴스를 foo, 당신은 당신이 호출 할 수 있습니다 알고 foo.bar()foo.bang(). 그러나이 쉽게 사용에 의해 완화 될 수 JsDoc의 @return 나는 (단어를 피하는 절차 적 코드를 옹호 아니에요 있음 new)
후안 멘데스

1
@ JuanMendes Hmm ... 귀하의 게시물은 귀하의 코드베이스에 명시적인 키워드로 인해 새로운 것을 좋아하는 것 같습니다. 나는 그것을 파낼 수 있습니다. 이것이 내가 모듈 패턴을 사용하는 이유입니다. createFoo, NewFoo 또는 MakeFoo라는 함수를 사용할 것입니다. 명시 적 인 한 중요하지 않습니다. 그 내부에서 함수에서 반환되는 객체 리터럴 내에서 클로저로 사용되는 변수를 선언합니다. 그 객체 리터럴은 결국 객체가되고 함수는 구성 함수일뿐입니다.
Joshua Ramirez

39

새로운 것에 대한 또 다른 경우 는 Pooh Coding 입니다. 푸우는 그의 배를 따릅니다. 내가 가서 말 과 함께 당신이하지 사용하는 언어 에 대해 그것.

언어를 유지하는 사람들이 격려하려는 관용구의 언어를 최적화 할 가능성이 있습니다. 언어에 새 키워드를 넣으면 새 인스턴스를 만들 때 명확하게 생각하는 것이 좋습니다.

언어의 의도에 따라 작성된 코드는 각 릴리스에서 효율성이 향상됩니다. 그리고 언어의 핵심 구성을 피하는 코드는 시간이 지남에 따라 어려움을 겪을 것입니다.

편집 : 그리고 이것은 성능을 뛰어 넘습니다. "도대체 그들이 왜 그랬는지 내가 들어 시간을 계산 (또는 상기) 할 수없는 것을 ?" 이상한 코드를 찾을 때 코드를 작성할 당시에는 "좋은"이유가 있다는 것이 종종 밝혀졌습니다. 언어의 타오를 따르는 것은 몇 년 후 코드를 조롱하지 않은 가장 좋은 보험입니다.


3
푸우 코딩 링크에 대한 하나는 - 지금은 ... 내 대화로이 일을하기 위해 변명을 찾아야
Shog9

롤! 나는 그 분야에서 수년간의 경험을 가지고 있으며 어려움을 겪지 않을 것이라고 확신 할 수 있습니다. 그들은 종종 robowiki.net에서 나를 Pooh라고 부릅니다. =)
PEZ 2016

1
이 주석이 표시되는지는 모르지만 Pooh Coding 링크는 죽었습니다.
Calvin

고마워요 우리는 지난주에 robowiki.net을 새로운 위키로 이전했고, 현재는 오래된 컨텐츠를 이용할 수 없습니다. 나는 그 오래된 링크가 작동하도록 서둘러 보겠습니다.
PEZ

24

새 키워드없이 생성자를 호출하는 문제를 완화하는 방법에 대한 게시물을 작성했습니다.
주로 교훈적이지만 모든 생성자에 관계없이 작동하는 생성자를 만드는 방법을 보여 주며 모든 생성자에서 테스트 new하기 위해 상용구 코드 를 추가하지 않아도 this됩니다.

http://js-bits.blogspot.com/2010/08/constructors-without-using-new.html

기술의 요지는 다음과 같습니다.

/**
 * Wraps the passed in constructor so it works with
 * or without the new keyword
 * @param {Function} realCtor The constructor function.
 *    Note that this is going to be wrapped
 *    and should not be used directly 
 */
function ctor(realCtor){
  // This is going to be the actual constructor
  return function wrapperCtor(){
    var obj; // object that will be created
    if (this instanceof wrapperCtor) {
      // Called with new
      obj = this;
    } else {
      // Called without new. Create an empty object of the
      // correct type without running that constructor
      surrogateCtor.prototype = wrapperCtor.prototype;
      obj = new surrogateCtor();
    }
    // Call the real constructor function
    realCtor.apply(obj, arguments);
    return obj;
  }

  function surrogateCtor() {}
}

사용 방법은 다음과 같습니다.

// Create our point constructor
Point = ctor(function(x,y){
  this.x = x;
  this.y = y;
});

// This is good
var pt = new Point(20,30);
// This is OK also
var pt2 = Point(20,30);

6
피하는 arguments.callee것이 굉장합니다!
Gregg Lind

2
surrogateConstructor이어야합니다 surrogateCtor(또는 그 반대).
David Conrad

비슷한 Crockford에서 영감을 얻은 유틸리티 모음을 유지 관리했으며 새 프로젝트를 시작할 때 구현을 찾기 위해 항상 실행해야한다는 것을 알았습니다. 그리고 이것은 프로그래밍의 기본 부분 인 객체 인스턴스화를 마무리합니다. 이 모든 작업이 우연한 인스턴스화 코드를 가능하게하는 것입니까? 솔직히이 래퍼의 독창성을 높이 평가하지만 부주의 한 코딩을 유발하는 것 같습니다.
Joe Coder 2016 년

1
@ joecoder 나는 이것이 교훈적 목적만을위한 것이라고 언급했지만, 나는이 편집증 스타일의 코딩을 구독하지 않습니다. 그러나 클래스 라이브러리를 작성하는 경우 예, 발신자에게 투명한 방식으로이 기능을 추가 할 것입니다.
Juan Mendes

22

새 키워드를 사용하지 않는 이유는 간단합니다.

전혀 사용하지 않으면 실수로 실수로 인한 함정을 피할 수 있습니다. YUI가 사용하는 구성 패턴은 새로운 키워드를 완전히 피할 수있는 방법의 예입니다. "

var foo = function () {
    var pub= { };
    return pub;
}
var bar = foo();

또는 당신은 이렇게 할 수 있습니다 :

function foo() { }
var bar = new foo();

그러나 그렇게하면 누군가 키워드 를 사용하는 것을 잊어 버릴 위험 있으며이 연산자는 모두 모호합니다. AFAIK이 작업을 수행하는 것 외에는 이점이 없습니다.

하루의 끝에서 : 그것은 방어적인 것입니다. 새로운 진술을 사용할 수 있습니까? 예. 코드가 더 위험 해 집니까? 예.

C ++을 작성했다면 포인터를 삭제 한 후 포인터를 NULL로 설정하는 것과 비슷합니다.


6
아니요. "new foo ()"를 사용하면 생성자와 같은 일부 속성이 반환 된 객체에 설정됩니다.

34
자, 이것을 명확히하기 위해 : "새"를 사용해서는 안됩니다. 농담하는 거지?
Bombe

16
@Bombe : 다른 언어에서는 "new"를 잊어 버리면 오류가 발생합니다. Javascript에서는 계속 트럭 운송을 계속합니다. 당신은 잊을 수없고 결코 실현할 수 없습니다. 그리고 단순히 erroroneous 코드를 찾고 못해 잘못가는 모든 뭐죠에 분명합니다.
Kent Fredric

3
@ Greg : 프로토 타입 체인을 사용하는 첫 번째 기술을 어떻게 사용할 수 있는지 알지 못합니다. 객체 리터럴은 훌륭하지만 프로토 타입이 제공하는 성능과 다른 이점을 두려워하지 않는 것은 약간 어리석은 것처럼 보입니다.
Shog9

5
@Bombe-당신과 당신의 코드를 사용하는 사람은 결코 실수를하지 않기 때문에 "new"를 사용해야합니까? 농담하는 거지?
Greg Dean

20

"신규"가 코드에 명확성을 더한다고 생각합니다. 그리고 명확성은 모든 가치가 있습니다. 함정이 있다는 것을 아는 것이 좋지만, 명확성을 피하여 피하는 것은 나에게 길처럼 보이지 않습니다.


16

사례 1 : new필요하지 않으며 피해야합니다

var str = new String('asd');  // type: object
var str = String('asd');      // type: string

var num = new Number(12);     // type: object
var num = Number(12);         // type: number

사례 2 : new필수입니다. 그렇지 않으면 오류가 발생합니다

new Date().getFullYear();     // correct, returns the current year, i.e. 2010
Date().getFullYear();         // invalid, returns an error

5
경우 1의 경우 생성자를 함수로 호출하면 형식 변환을 의도하는 경우에만 (그리고 선체 객체에 같은 변환 방법이 있는지 알 수 없음 toString()) 의미가 있습니다. 다른 모든 경우에는 리터럴을 사용하십시오. 아니 String('asd') , 단순히 'asd', 그리고 하지 Number(12) , 단순히 12.
PointedEars

1
이 규칙에 한 가지 예외가 될 것 @PointedEars Array: Array(5).fill(0) 이상 읽을 분명히 [undefined, undefined, undefined, undefined, undefined].fill(0)하고(var arr = []).length = 5; arr.fill(0);
yyny

@YoYoYonnY 내 진술은 대답의 사례 1과 관련하여 이루어졌으며 이는 원시 유형에 new해당하는 객체 유형에 대해 생성자를 사용하는 것을 나타냅니다 . 제안하는 리터럴 은 호출 (try )과 동일 하지 않으며 나머지는 구문 오류입니다.) 그렇지 않으면 맞지 않습니다. 부적합한 구현 을 고려하면 모호 할 수 있습니다. 따라서 에뮬레이트 된 ). Array0 in …Array(5) Array.prototype.fill(…)
PointedEars

12

다음은 new연산자 를 사용하거나 반대하는 두 가지 가장 강력한 주장을 요약 할 수있는 가장 간단한 요약입니다 .

반대론 new

  1. new연산자를 사용하여 객체로 인스턴스화되도록 설계된 함수는 일반 함수로 잘못 호출되면 치명적인 영향을 줄 수 있습니다. 이 경우 함수의 코드는 의도 한대로 로컬 객체의 범위가 아니라 함수가 호출되는 범위에서 실행됩니다. 이로 인해 전역 변수 및 속성이 심각한 결과로 덮어 쓰기 될 수 있습니다.
  2. 마지막으로, 객체를 생성하기 위해 호출 할 수 있도록 객체를 작성 function Func()하고 호출 Func.prototype하고 추가하기 때문에 new Func()일부 프로그래머에게는 아키텍처 및 스타일상의 이유로 다른 객체 상속 스타일을 사용하는 것이보기 흉한 것 같습니다.

이 주장에 대한 자세한 내용은 Douglas Crockford의 훌륭하고 간결한 책 Javascript : The Good Parts를 확인하십시오. 실제로 어쨌든 확인하십시오.

찬성론 new

  1. new프로토 타입 할당과 함께 연산자를 사용하는 것이 빠릅니다.
  2. 전역 네임 스페이스에서 생성자 함수의 코드를 실수로 실행하는 것과 관련된 사항은 생성자 함수에 코드를 포함하여 코드가 올바로 호출되는지 여부와 그렇지 않은 경우이를 확인하는 경우 쉽게 방지 할 수 있습니다. , 원하는대로 통화를 적절하게 처리합니다.

이 기술에 대한 간단한 설명과 그가 주장하는 상속 모델에 대한 일반적인 설명은 John Resig의 게시물 을 참조하십시오 .


반대 인수에 대한 업데이트 : # 1은 'use strict';mode (또는 링크의 메소드)를 사용하여 완화 할 수 있습니다. # 2 ES6에 synatic sugar가 있지만 동작은 이전과 동일합니다.
ninMonkey

9

나는 pez와 여기에 동의합니다.

그렉 딘이 묘사 한 YUI 패턴이 완전히 숨겨져 있는 "새"라는 것은 자기 설명적인 객체 생성이라는 것이 분명합니다 .

누군가가 쓸 수 var bar = foo;있거나 var bar = baz();baz가 객체 생성 방법이 아닌 가능성 은 훨씬 더 위험합니다.


8

실수로 사용하는 것을 잊어 버려서 문제를 일으킬 수 있기 때문에 상속 체인을 망쳐 서 언어를 이해하기 어렵 기 때문에 new는 악하다고 생각합니다.

JavaScript는 프로토 타입 기반 객체 지향입니다. 그러므로 모든 객체는 반드시 다른 객체로부터 생성되어야합니다 var newObj=Object.create(oldObj). 여기서 oldObjnewObj 의 프로토 타입 ( "프로토 타입 기반")이라고합니다. 이것은 newObj 에서 속성을 찾지 못하면 oldObj 에서 검색 됨을 의미 합니다. 기본적으로 newObj 는 빈 객체이지만 프로토 타입 체인으로 인해 oldObj의 모든 값이있는 것으로 보입니다 .

반면 var newObj=new oldObj()newObj 의 프로토 타입 은 oldObj.prototype 이므로 불필요하게 이해하기 어렵습니다.

트릭은 사용하는 것입니다

Object.create=function(proto){
  var F = function(){};
  F.prototype = proto;
  var instance = new F();
  return instance;
};

이 기능 안에 있으며 여기서 만 새로운 기능을 사용해야합니다. 그런 다음 Object.create () 메소드 를 사용하십시오 . 이 방법은 프로토 타입 문제를 해결합니다.


7
솔직히 말해서, 나는이 기술에 열광하지 않습니다. 새로운 것을 추가하지 않으며, 당신의 대답에서 알 수 있듯이 목발이 될 수도 있습니다. IMHO는 프로토 타입 체인과 객체 인스턴스화를 이해하는 것이 JavaScript를 이해하는 데 중요합니다.하지만 직접 사용하는 것이 불편하다면 도우미 기능을 사용하여 세부 사항을 처리하는 것이 좋습니다. 하기. FWIW : 이것에 대한 (좀 더 유용한) 변형은 ECMAScript 5th ed의 일부입니다. std이며 일부 브라우저에서 이미 사용 가능 하므로 맹목적으로 재정의하지 않도록주의해야합니다!
Shog9

BTW : 왜이 ​​CW를 만들 었는지 잘 모르겠지만, 내가 만든 서식 수정으로 다시 게시하려면 해당 확인란을 피하십시오 ...
Shog9

2
불필요하게 이해하기 어려운가? var c = new Car()같은 일을 같이하다var c = Object.create(Car.prototype); Car.call(c)
후안 멘데스
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.