일부 리터럴에서 instanceof가 false를 반환하는 이유는 무엇입니까?


284
"foo" instanceof String //=> false
"foo" instanceof Object //=> false
true instanceof Boolean //=> false
true instanceof Object //=> false
false instanceof Boolean //=> false
false instanceof Object //=> false

// the tests against Object really don't make sense

배열 리터럴과 객체 리터럴이 일치합니다 ...

[0,1] instanceof Array //=> true
{0:1} instanceof Object //=> true

왜 모두 다 그렇지 않습니까? 아니면 왜 모두 그렇지 않습니까?
그렇다면 그들은 어떤 예입니까?

FF3, IE7, Opera 및 Chrome에서 동일합니다. 따라서 적어도 일관성이 있습니다.


몇 가지를 놓쳤다.

12.21 instanceof Number //=> false
/foo/ instanceof RegExp //=> true

답변:


424

기본 요소는 Javascript 내에서 작성된 오브젝트와 다른 유형입니다. 로부터 모질라 API 문서 :

var color1 = new String("green");
color1 instanceof String; // returns true
var color2 = "coral";
color2 instanceof String; // returns false (color2 is not a String object)

코드로 기본 유형을 구성하는 방법을 찾을 수 없습니다. 아마 불가능할 수도 있습니다. 아마도 사람들이 typeof "foo" === "string"대신에 사용 하는 이유 일 것 입니다 instanceof.

이와 같은 것들을 기억하는 쉬운 방법은 "나는 제정신이고 배우기 쉬운 것이 궁금하다"고 스스로에게 묻는 것입니다. 답이 무엇이든 Javascript는 다른 일을합니다.


5
JavaScript를 싫어하는 새로운 이유가 매일 있습니다. 기한이 지났지 만이 게시물에 감사드립니다.
toniedzwiedz

57
용어가 잘못되었습니다. "literal"이라는 단어는 생성자를 사용하지 않고 데이터를 작성하기위한 구문을 나타냅니다. 결과 데이터를 참조하지 않습니다. 리터럴 구문을 사용하여 객체와 객체가 아닌 객체를 모두 만들 수 있습니다. 올바른 용어는 "프리미티브 (primitive)"로, 객체가 아닌 데이터를 나타냅니다. 일부 데이터에는 기본 표현과 객체 표현이 모두 있습니다. 문자열은 이러한 유형의 데이터 중 하나입니다.
회색 상태가

14
참고로 리터럴 구문없이 프리미티브를 작성할 수 있습니다. (new String()).valueOf();
회색 상태가

11
참고 typeof foo === 'string'것만으로는 충분하지 않습니다는 : axkibe의 답변을 참조하십시오.
Bryan Larsen

1
또한, typeof new String('')반품"object"
transang

105

나는 사용한다:

function isString(s) {
    return typeof(s) === 'string' || s instanceof String;
}

JavaScript에서 문자열은 리터럴 또는 객체 일 수 있기 때문입니다.


28
나는 btw가 짧은 것을 발견했다. function isString(s) { return s.constructor === String; }리터럴 및 문자열 객체 (적어도 V8에서는)에서 작동
axkibe

7
자바 스크립트를 좋아합니다.
Derek 朕 會 功夫

2
가능한 경우 jQuery.type (s) === 'string'( api.jquery.com/jquery.type ), jQuery.isArray (), jQuery.isFunction (), jQuery.isNumeric ()을 사용합니다.
Ivan Samygin

1
당신이 올바른있는 동안 @axkibe, 그것은이다 확대됨에 거의 없습니다typeof.
Qix-MONICA가 MISTREATED

typeof "?"를 사용할 수 있습니다 == String.name.toLowerCase () [그러나 왜 [] instanceof Array?]
QuentinUK

62

JavaScript에서 프리미티브 (부울, 널, 숫자, 문자열 및 값 undefined(및 ES6의 기호 ))를 제외한 모든 것이 오브젝트 (또는 최소한 오브젝트로 취급 될 수 있음)입니다.

console.log(typeof true);           // boolean
console.log(typeof 0);              // number
console.log(typeof "");             // string
console.log(typeof undefined);      // undefined
console.log(typeof null);           // object
console.log(typeof []);             // object
console.log(typeof {});             // object
console.log(typeof function () {}); // function

보시다시피 객체, 배열 및 값 null은 모두 객체로 간주됩니다 ( null존재하지 않는 객체에 대한 참조입니다). 함수는 특별한 유형의 호출 가능한 객체 이기 때문에 구별 됩니다. 그러나 여전히 개체입니다.

반면에 리터럴은 true, 0, ""undefined하지 개체입니다. JavaScript에서 기본 값입니다. 그러나 부울, 숫자 및 문자열에는 constructor BooleanNumber있고 String각각 추가 된 기능을 제공하기 위해 각각의 기본 요소를 랩핑합니다.

console.log(typeof new Boolean(true)); // object
console.log(typeof new Number(0));     // object
console.log(typeof new String(""));    // object

당신은 원시 값이 내 포장 할 때 볼 수있는 것처럼 Boolean, Number그리고 String생성자 각각 그들은 개체가됩니다. instanceof연산자는 (은 반환 이유입니다 개체에 대한 작동 false기본 값) :

console.log(true instanceof Boolean);              // false
console.log(0 instanceof Number);                  // false
console.log("" instanceof String);                 // false
console.log(new Boolean(true) instanceof Boolean); // true
console.log(new Number(0) instanceof Number);      // true
console.log(new String("") instanceof String);     // true

당신은 모두를 볼 수있는 typeofinstanceof값이 부울, 숫자 또는 문자열인지 테스트에 불충분 한 - typeof단지 원시 논리 값, 숫자, 문자열 작동; 및 instanceof원시 논리 값, 숫자, 문자열이 작동하지 않습니다.

다행히이 문제에 대한 간단한 해결책이 있습니다. 의 기본 구현 toString(즉, 기본적으로 정의 된대로 Object.prototype.toString)은 [[Class]]기본 값과 객체 의 내부 속성을 반환 합니다.

function classOf(value) {
    return Object.prototype.toString.call(value);
}

console.log(classOf(true));              // [object Boolean]
console.log(classOf(0));                 // [object Number]
console.log(classOf(""));                // [object String]
console.log(classOf(new Boolean(true))); // [object Boolean]
console.log(classOf(new Number(0)));     // [object Number]
console.log(classOf(new String("")));    // [object String]

[[Class]]값 의 내부 속성은 값보다 훨씬 유용 typeof합니다. 우리는 다음과 같이 Object.prototype.toString자신의 (더 유용한) 버전의 typeof연산자 를 만드는 데 사용할 수 있습니다 .

function typeOf(value) {
    return Object.prototype.toString.call(value).slice(8, -1);
}

console.log(typeOf(true));              // Boolean
console.log(typeOf(0));                 // Number
console.log(typeOf(""));                // String
console.log(typeOf(new Boolean(true))); // Boolean
console.log(typeOf(new Number(0)));     // Number
console.log(typeOf(new String("")));    // String

이 기사가 도움이 되었기를 바랍니다. 프리미티브와 랩핑 된 객체의 차이점에 대한 자세한 내용은 다음 블로그 게시물을 참조하십시오. JavaScript 프리미티브의 비밀 생활


6
+1, altough null기본 값입니다 ( typeof연산자 만 혼동합니다)
Bergi

33

생성자 속성을 사용할 수 있습니다.

'foo'.constructor == String // returns true
true.constructor == Boolean // returns true

18
변수를 테스트 할 때이 기술은 특정 상황에서 실패 할 수 있습니다. 앞의 현재의 윈도우에 내재 참조가 StringBoolean위의 예는 사용자가 테스트하는 경우이므로 constructor(팝업이나 프레임 등)를 다른 윈도우에서 생성 된 문자열 변수의 속성은 것 하지 단순히 동일하게 String, 윌 같아야 thatOtherWindowsName.String.
Michael Mathews

그리고 이것을 다루지 않고 적절한 부울 결과를 반환합니까?
Chris Noe

5
String의 자손을 전달하면 실패합니다.
Bryan Larsen

1
@MichaelMathews :이 문제를 해결하기 위해 작동합니다.Object.prototype.toString.call('foo') === '[object String]'
rvighne

@BryanLarsen 및 @MichaelMathews 사용에 문제가 d.constructor == String있습니까? 예를 들어, 등식 연산자가 느슨합니다.
dotnetCarpenter

7
 typeof(text) === 'string' || text instanceof String; 

당신은 이것을 사용할 수 있습니다, 그것은 두 경우 모두에 작동합니다

  1. var text="foo"; // typeof가 작동합니다

  2. String text= new String("foo"); // instanceof가 작동합니다


3

이는 ECMAScript 사양 섹션 7.3.19 3 단계 에서 정의됩니다 .If Type(O) is not Object, return false.

즉, Objin Obj instanceof Callable이 객체가 아닌 경우, instanceof의지는 false직접 단락 됩니다.


1

나는 가능한 해결책을 생각해 냈다고 생각합니다.

Object.getPrototypeOf('test') === String.prototype    //true
Object.getPrototypeOf(1) === String.prototype         //false

-1

https://www.npmjs.com/package/typeof

instanceof(생성자 이름) 의 문자열 표현을 리턴합니다.

function instanceOf(object) {
  var type = typeof object

  if (type === 'undefined') {
    return 'undefined'
  }

  if (object) {
    type = object.constructor.name
  } else if (type === 'object') {
    type = Object.prototype.toString.call(object).slice(8, -1)
  }

  return type.toLowerCase()
}

instanceOf(false)                  // "boolean"
instanceOf(new Promise(() => {}))  // "promise"
instanceOf(null)                   // "null"
instanceOf(undefined)              // "undefined"
instanceOf(1)                      // "number"
instanceOf(() => {})               // "function"
instanceOf([])                     // "array"

-2

나를 위해 혼란에 의한

"str".__proto__ // #1
=> String

그래서 "str" istanceof String반환해야 trueistanceof는 다음과 같이 작동하는 방법 때문에 :

"str".__proto__ == String.prototype // #2
=> true

표현의 결과 # 1 # 2의 서로 충돌하므로 그 중 하나가 잘못되었습니다.

# 1이 잘못되었습니다

__proto__비표준 속성으로 인해 발생한다는 것을 알고 있으므로 표준 속성을 사용하십시오.Object.getPrototypeOf

Object.getPrototypeOf("str") // #3
=> TypeError: Object.getPrototypeOf called on non-object

이제 식 # 2# 3 사이에 혼동이 없습니다


2
# 1은 정확하지만 때문이다 속성 접근 ,되는 상자의 각 오브젝트에 유사한 유형의 원시 값 Object("str").__proto__이상 Object("str") instanceof String.
Jonathan Lonowski 2016 년

@JonathanLonowski이 점을 지적 해 주셔서 감사합니다. 몰랐어요
mko

-8

또는 다음과 같이 자신의 기능을 만들 수 있습니다.

function isInstanceOf(obj, clazz){
  return (obj instanceof eval("("+clazz+")")) || (typeof obj == clazz.toLowerCase());
};

용법:

isInstanceOf('','String');
isInstanceOf(new String(), 'String');

둘 다 true를 반환해야합니다.


14
나는 평가를 본다. 악.
Aaria Carter-Weir 19:51에
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.