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

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

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

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



답변

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, 특히 우리의 사람들을 위해 계몽이 처음 기각 사람 이처럼 엄청나게 조정 된 기능입니다.


답변

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

스위치 넘어짐 정보 :

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

++ 및-

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

새로운 정보 :

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

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

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

최신 정보

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


답변

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

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

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

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

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

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

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


답변

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

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

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

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

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


답변

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

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

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

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


답변

새 키워드없이 생성자를 호출하는 문제를 완화하는 방법에 대한 게시물을 작성했습니다.
주로 교훈적이지만 모든 생성자에 관계없이 작동하는 생성자를 만드는 방법을 보여 주며 모든 생성자에서 테스트 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);


답변

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

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

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

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

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

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

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

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