JS 부울에 사용자 정의 속성이 나쁜 습관입니까?


41

JS에서는 사용자 정의 속성이있는 부울을 반환 할 수 있습니다. 예 : Modernizr은 비디오 지원을 테스트 할 때 반환 true하거나 false반환 된 부울 (Bool은 JS의 첫 번째 클래스 개체)에 지원되는 형식을 지정하는 속성이 있습니다. 처음에는 조금 놀랐지 만 아이디어가 마음에 들기 시작했고 왜 그것이 조금만 사용되는 것 같습니까?

기본적으로 무언가가 참인지 거짓인지 알고 싶은 모든 시나리오를 다루는 우아한 방법처럼 보이지만 사용자 정의 반환 객체를 정의하거나 콜백 함수를 사용하지 않고 정의 할 수있는 추가 정보에 관심이있을 수 있습니다 더 많은 매개 변수를 승인하십시오. 이렇게하면 더 복잡한 데이터를 반환하기위한 용량을 손상시키지 않으면 서 매우 보편적 인 함수 서명을 유지할 수 있습니다.

내가 상상할 수있는 세 가지 주장이 있습니다.

  1. 인터페이스가 명확하고 까다 롭지 않은 것이 더 좋을 때 좀 드물거나 예기치 않은 일입니다.
  2. 이것은 짚맨 논쟁 일지 모르지만 약간의 사례가 있기 때문에 일부 JS 최적화 프로그램, uglifier, VM에서 또는 사소한 정리 언어 사양 변경 후 조용히 역화되는 것을 상상할 수 있습니다.
  3. 간결하고 명확하며 일반적인 방식으로 정확하게 동일한 작업을 수행하는 것이 좋습니다.

그래서 내 질문은 추가 속성으로 부울을 사용하지 않는 강력한 이유가 있습니까? 트릭이나 간식입니까?


플롯 트위스트 경고.

위는 완전한 영광의 원래 질문입니다. Matthew Crumley와 senevoldsen이 지적한 바와 같이 그것은 거짓 (거짓?) 전제에 기초합니다. 훌륭한 JS 전통에서 Modernizr 이하는 일은 언어 트릭이며 더러운 것입니다. 기본 bool이있는 JS로 정리합니다. 거짓으로 설정하면 소품을 추가하려고 시도한 후에도 거짓으로 유지됩니다 (자동 실패). 맞춤형 소품을 가질 수 있지만 객체 인 것은 항상 진실입니다. Modernizr은 부울 거짓 또는 진실한 부울 객체를 반환합니다.

내 원래의 질문은 트릭이 다르게 작동한다고 가정했기 때문에 대부분의 인기있는 답변은 (완벽하게 유효한) 코딩 표준 측면을 처리합니다. 그러나 나는 가장 유용한 전체 트릭을 해제하는 답변 (및 방법을 사용하는 것에 대한 궁극적 인 주장)을 발견하여 그중 하나를 받아들입니다. 모든 참가자들에게 감사합니다!


35
부울 유형을 확장하는 것은 고전적인 wtf 입니다.
hlovdal

7
JS에서는 null지원되지 않으면 방금 반환 할 수 있으며 형식은 배열로 반환 될 수 있습니다 . 목록은 JS에서 진실한 것으로 간주되며 null허위입니다.
jpmc26


3
이 질문에 대답하기 전에 : 자바 스크립트에는 "부울"과 "부울"사이에 큰 차이가 있습니다. 그것들은 같지 않으며 부울을 대문자로하지 않는 대답은 유효하지 않습니다.
Pieter B

2
Modernizr만큼 인기있는 도서관에서 야생에서 이와 같은 것을보고 기뻐
Chris Nielsen

답변:


38

단일 책임 및 최소한의 놀람과 같은 일반적인 디자인 원칙 외에도 JavaScript와 관련하여 좋은 생각이 아닌 이유가 있습니다 . 일반적인 경우에는 작동하지 못하게하는 a booleanBooleanJavaScript의 차이 가 큽니다.

boolean는 객체가 아닌 기본 유형이며 사용자 정의 특성을 가질 수 없습니다. true.toString()배후에서 작동하는 식은 로 바뀝니다 (new Boolean(true)).toString().

Boolean(자본 B와 함께) 대상이지만, 잘 사용하는 것은 거의 없으며 a로 사용되는 boolean것은 확실히 그중 하나가 아닙니다. 그 이유는 모든 객체가 부울 컨텍스트 로 변환되기 때문에 value와 관계없이 모든 Boolean것이 "true" 이기 때문 true입니다. 예를 들어 다음을 시도하십시오.

var answer = new Boolean(false);
if (answer) {
  console.log("That was unexpected.");
}

따라서 일반적으로 JavaScript의 부울에 속성을 추가하여 논리적으로 동작하도록하는 방법은 없습니다. Modernizr은 "true"값에 속성을 추가하기 때문에 속성을 사용할 수 있습니다. 이러한 속성은 예상 한 방식으로 작동합니다 (즉, if 문에서 작동 함). 비디오가 전혀 지원되지 않으면 Modernizr.video실제 boolean값이 false되며 속성을 추가 할 수 없습니다.


18
Modernizr의 접근 방식은 속성이있는 객체만이 이미 true조건부로 평가된다는 것을 고려할 때 다소 이상 합니다. 왜 명시 적으로 Boolean?를 사용 합니까?
Arturo Torres Sánchez

건전한 기술적 인 주장에 감사드립니다. 내 빠른 테스트에 결함이있는 것 같습니다 : jsbin.com/hurebi/3/edit?js,console . 심지어 사용자 정의 소품을 추가 한 후 false이 엄격하게 '거짓'과 falsy (모두의 =====작업 등)하지만 실제로 당신이 실제로 원시 부울에 소품을 추가 할 수 없습니다. Bool과 bool의 구별은 분명히 나를 피했다.
konrad

@ ArturoTorresSánchez 반환 방식은 명목상 동일한 유형입니다.
Jared Smith

1
@ ArturoTorresSánchez 그렇기 때문에 "명 목적으로"한정자를 추가했습니다. P
Jared Smith

1
@konrad 참고로, 기본적으로 JavaScript는 시도 할 때 불평하지 않고 프리미티브에 속성을 추가 할 수있게합니다. 엄격 모드를 사용하면 문제가 해결되고 TypeError속성을 추가하려고하면 a가 발생합니다 ( jsbin.com/yovasafibo/edit?js,console 참조 ).
Matthew Crumley

59

축하합니다. 객체를 발견했습니다. 이것을하지 않는 이유 를 가장 놀랍게 하는 원리 라고합니다 . 디자인에 놀란 것은 좋지 않습니다.

이 정보를 함께 묶는 데 아무런 문제가 없지만 Bool에 왜 숨기고 싶습니까? 이 모든 정보를 기대할 수있는 곳에 넣으십시오. 부울이 포함되어 있습니다.


1
LOL 예, 제 질문에서 객체를 확실한 대안으로 언급했습니다. JS가 약한 타이핑 객체는 덜 놀랍지 만 여전히 혼란스럽고 어쨌든 문서를 확인해야하지만 놀랍지 않은 원리는 좋은 지적입니다. 사용법에 관해서 Modernizr은 좋은 예입니다. 균일 한 참 / 거짓 결과를 가진 대규모 테스트 모음이 있고 지금 만 더 많은 정보를 전달해야합니다. 부울 주위에 주로 여분의 래퍼를 생성하여 전체 라이브러리를 변경하거나 부울을 향상시킵니다. IMO는 멍청하지 않습니다.
konrad

1
사용법에 대해 조금 더. 부울 값 반환을 고수하면 모든 함수를 전달하여 any (), all (), filter ()와 같은 작업을 쉽게 나열 할 수 있습니다. JS의 강력한 타이핑이나 공식적인 인터페이스의 부족을 다소 번거롭지 않은 비용으로 우회합니다.
konrad

1
"전통적인"것은 나에게 강한 주장처럼 보이지 않습니다.
Robert Harvey

질문을 편집했습니다. 가장 놀랍게 여겨지는 원리는 다음과 같습니다. :-)
konrad

16

내가 그것에 반대하는 주된 주장은 단일 책임 원칙 이며, 부울은 무언가 true또는 false이유가 아니라 왜 또는 어떻게 또는 다른 것이 아닌지 말해야한다는 것입니다. 다른 정보를 사용하여 해당 정보 나 다른 정보를 전달해야한다는 것이 저의 확고한 믿음입니다.


자바 스크립트에서 부울 또는 부울 (대문자 B 포함)을 의미합니까?
Pieter B

그러나 이것을 정의하는 객체가 있고 다른 것들이 동일한 원칙을 위반하지 않습니까?
Casey

1
@Casey 아니오 그 객체의 목적이 원래의 불리언과 다를 것이기 때문입니다. 그리고 트랜잭션의 상태와 이유를 전달하는 것은 하나의 책임이 있습니다.
J. Pichardo

1
@Casey 문제는이 정보 자체를 포함하는 것이 SRP를 위반하는 것이 아닙니다. 부울이 이미 가지고있는 책임과 결합 된 경우에만 문제가됩니다. 참 또는 거짓을 나타냅니다. JavaScript의 Boolean셰 나니 건에도 불구하고.
Jacob Raihle

10

전체 이유 때문에이 부울 값은 그것이 사실인지 거짓 사실이다라고, 난 당신이 꽤 많이로부터 전체 목적을 훼손으로, 아이디어를 싫어하는 위키 백과

컴퓨터 과학에서 부울 데이터 유형은 논리 및 부울 대수의 진리 값을 나타내는 두 가지 값 (일반적으로 true 및 false로 표시됨)을 갖는 데이터 유형 입니다.

(나의 대담한)


1
정확하지만 필요에 따라 다르게 지시 할 수 있음
svarog

8
@ svarog 내가 볼 수있는 유일한 능력은 숙련되지 않은 코드 디자이너입니다. 부울 다른 것을 반환 해야하는 경우 클래스, 튜플 또는 목록 또는 특정 코드에 맞는 것을 만드십시오.
MatthewRock

당신이 예를 반환하는 경우
svarog

부울 프리미티브가 아닌 부울 객체에 대한 질문이라고 생각합니다. 개체가 값이 아닙니다.
Pieter B

1
true 또는 false 이외의 값을 사용할 수 있으면 부울 아닙니다. 이름이 주어진 것은 바보입니다.
쓸모없는

2

JS에서 의미를 가질 수 없기 때문에 JS에서 거의 모든 객체에 속성을 첨부 할 수 있습니다 (부울 포함)

그게 어떻게 나쁜거야?

한편으로, 부적절한 (예를 들어) 부울에 더 관련성이없는 데이터를 첨부 할 수 있습니다. 왜 다른 개발자가 거기에 있어야하는지 예상하지 않습니까?! 부울은 단지 진실과 거짓입니다.

부울 값을 처리하는 데 도움이되는 관련 유용한 속성을 첨부하는 것이 반점입니다 ( Java가 수행 ).

예를 들어, 부울 값을 문자열로 변환하는 함수 dirty, 값이 변경되면 true로 설정된 플래그, 값이 변경 될 때 발생할 수있는 감시자 및 이벤트 콜백 등을 연결할 수 있습니다.

그러나 반환 된 부울 (Bool은 JS의 첫 번째 클래스 객체)에는 지원되는 형식을 지정하는 속성이 있습니다.

부울에 저장해서는 안되지만 부울 세트 또는 부울이 포함 된 속성 세트를 사용하는 것 같습니다. 더 나은 접근 방식은 모든 형식과 지원 세부 정보가있는 객체를 반환하는 것입니다.

{
    isSomethingSupported: true,
    isSomethingElseSupported: false,
    ....
}

1
부울 또는 부울을 의미합니까 (대문자 B 사용)?
Pieter B

1

JavaScript에서는 사용자 정의 속성으로 부울을 만들 수 없습니다. 다음은 실패합니다 (적어도 FF).

    var x = false;
    x.foo = "bar";
    console.log(x.foo);

부울을 사용하거나 상속 할 수 있지만 Matthew Crumley는 다른 결과를 제공합니다. Boolean이다 유형 Object . JS가 표현식의 부울 값을 필요로 할 때 스펙 함수를 사용하여 변환 하며 결과는 항상 그 결과 ToBoolean를 요구합니다 . 따라서 값 은 ! https://jsfiddle.net/md7abx5z/3/ 예제에서이를 확인할 수 있습니다 .Objecttruenew Boolean(false)true

Modernizr에서 작동하는 유일한 이유는 부수적입니다. Boolean조건이 참일 때만 개체를 만듭니다 . 그들이 거짓을 평가할 때 그들은 단지 보통을 반환 false합니다. 어쨌든 결과가 참일 때만 Boolean 객체를 반환 하고 거짓 일 때는 결코 반환하지 않기 때문에 작동합니다 .


1

컨텍스트가 변경되었음을 이해하지만 JS를 예로 사용하면서 읽은 원래 질문에 대답하고 싶지만 JS에만 국한되지는 않습니다.

부울에 속성을 추가해도 속성이 값을 보유하는 변수가 아니라 true / false와 관련이있는 경우 문제가되지 않습니다. 예를 들어, toYesNoString 메소드를 추가하는 것이 좋으며, hasChildren 값에 numberOfChildren을 추가하는 것은 좋지 않으며 questionMissed studentPassed도 아닙니다. 다양한 문자열 반복 이외의 부울에 추가 할 수있는 것은 많지 않습니다. 내가 이해할 수있는 유일한 속성은 originalExpression입니다. 그러나 이론에 추가하는 것이 반드시 나쁜 생각은 아닙니다.


0

코드를 보면 실제로 부울 사용자 정의 속성을 제공하는 것이 아니라 다른 서명을 가진 리턴 메소드를 갖는 메소드에 관한 것입니다.

False이면 프리미티브 False를 얻습니다. True이면 Javascript에서 정의에 따라 true로 해석되는 객체를 반환합니다.

따라서 내 의견으로는 귀하의 질문은 부울 사용자 정의 속성을 제공하는 것이 좋은지 여부가 아니라 여러 반환 서명이있는 메소드를 갖는 것이 좋은지 여부에 관한 것이어야합니다.


0

주어진 예 에서 지원되는 모든 비디오 형식 의 배열반환 할 수 없었 습니까?

  • 빈 배열은 "비디오 형식이 지원 되지 않음"을 의미하며 , 이는 " 비디오가 지원 되지 않음"을 의미 합니다.
  • 그렇지 않으면 비디오 형식 이 지원되는 경우 일반적으로 비디오 가 지원됩니다.

적어도 배열을 사용하는 것이 "custom booleans"를 갖는 것보다 다소 덜 놀라운 것이라고 말하고 싶습니다.

Javascript에서 빈 배열은 거짓으로 간주 되지만 비어 있지 않은 배열은 진실 이므로 약간의 행운으로 배열로 전환 할 수 있으며 편집 하기 전과 같이 모든 것이 작동 합니다. JavaScript에서 객체의 개수 : P


빈 배열은 if 문에서 false로 평가되지 않습니다. if ([]) console.log ( '거짓이 아님'); 예를 들어 Chrome에서 'not false'를 인쇄합니다. typeof [] === 'object'이므로 빈 배열이 거짓이 아닙니다. 참조 developer.mozilla.org/en-US/docs/Glossary/Truthy를 참조하십시오.
joshp

@ joshp oops, 당신 말이 맞아, 내 나쁜. 수정
daniero

비록 그 유형의 것이 어떤 것도 증명할 수 있을지 모르겠다. ""유형이 "string"있지만 실제로 거짓입니다
daniero

1
반면에 [].lengthlength가 0인 경우 거짓이며 , 타이핑이 더 많지 않으며 내 의견으로는 if([])그것이 효과가 있다고해도 의도를 더 잘 나타내는 것입니다.
IllusiveBrian

@daniero typeof [] === 'object'에 대한 요점은 모든 Object가 진실하고 심지어 새로운 Boolean (false)이라는 것입니다. 일부 기본 유형 (예 : 문자열 ""및 숫자 0)은 거짓이지만 typeof에 관한 한 객체가 아닙니다. 기억하는 또 다른 방법 일뿐입니다. 아무것도 증명하는 것이 아닙니다. 증명은 사양 또는 테스트 중 원하는 방식으로 이루어집니다.
joshp
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.