[ 자바스크립트 ] typeof VS Object.prototype.toString 🕔 2017. 12. 7. 01:04
[ Javascript ] typeof VS Object.prototype.toString
1. 기본적인 사용법 ( How to use )
<button onclick="testing()"> Click me </button> <p id="demo1"> </p> <p id="demo2"> </p> <script type="text/javascript"> function testing (){ var text = "어쩌구저쩌구... blah blah blah... "; demo1.innerHTML = typeof text; demo2.innerHTML = Object.prototype.toString.call( text ); } </script>
Object.prototype.toString() 함수를 이용하려면, call() 함수를 사용해서 불러와야(call) 한다는 거!!
To use "Object.prototype.toString", call it using "call" function.
2. 문자 테스트 ( Test string )
<button onclick="testing()"> Click me </button> <p id="demo1"> </p> <p id="demo2"> </p> <script type="text/javascript"> function testing (){ var str = String( "blah blah blah... " ); demo1.innerHTML = typeof str; demo2.innerHTML = Object.prototype.toString.call( str ); } </script>
<button onclick="testing()"> Click me </button> <p id="demo1"> </p> <p id="demo2"> </p> <script type="text/javascript"> function testing (){ var str = new String( "blah blah blah... " ); demo1.innerHTML = typeof str; demo2.innerHTML = Object.prototype.toString.call( str ); } </script>
new String()이라고 작성하면, typeof 는 string 이 아니라 object 이라고 알려준다는 거!!
When you use "String()" with "new", typeof tells you that it's object, not string.
3. 숫자 테스트 ( Test number )
<button onclick="testing()"> Click me </button> <p id="demo1"> </p> <p id="demo2"> </p> <script type="text/javascript"> function testing (){ var num = 123; demo1.innerHTML = typeof num; demo2.innerHTML = Object.prototype.toString.call( num ); } </script>
<button onclick="testing()"> Click me </button> <p id="demo1"> </p> <p id="demo2"> </p> <script type="text/javascript"> function testing (){ var num = Number( 123 ); demo1.innerHTML = typeof num; demo2.innerHTML = Object.prototype.toString.call( num ); } </script>
<button onclick="testing()"> Click me </button> <p id="demo1"> </p> <p id="demo2"> </p> <script type="text/javascript"> function testing (){ var num = new Number( 123 ); demo1.innerHTML = typeof num; demo2.innerHTML = Object.prototype.toString.call( num ); } </script>
4. 배열 테스트 ( Test array )
<button onclick="testing()"> Click me </button> <p id="demo1"> </p> <p id="demo2"> </p> <script type="text/javascript"> function testing (){ var arr = [ "a", "b", "c" ]; demo1.innerHTML = typeof arr; demo2.innerHTML = Object.prototype.toString.call( arr ); } </script>
배열은 무조건 object 이라고 알려준다는 거!!
If it's an array, typeof always tells you that it's object, not array.
여기까지만 읽다보면, Object.prototype.toString 함수가 모든 문제를 해결해 줄 것 같지만...
If you just read this far, it seems that "Object.prototype.toString" would solve all the problems. But...
5. 그 밖의 것들 ( Other things )
<button onclick="testing()"> Click me </button> <p id="demo1"> </p> <script type="text/javascript"> function testing (){ var style = demo1.style; demo1.innerHTML = Object.prototype.toString.call( style ); } </script>
결과가 브라우저마다 다르게 나온다는 거!!
The result is different on each browser.
Chrome & Opera & Safari : [object CSSStyleDeclaration]
Firefox : [object CSS2Properties]
Internet Explorer : [object MSStyleCSSProperties]
<button onclick="testing()"> Click me </button> <p id="demo1"> </p> <script type="text/javascript"> function testing (){ var proto = document.__proto__; demo1.innerHTML = Object.prototype.toString.call( proto ); } </script>
Chrome & Opera : [object HTMLDocument]
Firefox & Explorer & Safari : [object HTMLDocumentPrototype]
6. 해결 방안 ( Solution )
그래서 getTypeof() 이라는 함수를 하나 만들어보았다.
So, I wrote "getTypeof" function.
일단, 아래의 세 함수를 먼저 작성한다.
Firstly, write the following three functions.
function getFunctionName ( fn ){ if ( typeof fn !== 'function' ){ if ( document.defaultView.alert == fn ) return 'alert'; return ""; } var name = ""; if ( !! (function x (){}).name ){ name = fn.name; } else { name = Function.prototype.toString.call( obj ); name = /^function[^\(]+/.exec( str )[ 0 ].substr( 7 ).trim(); } return name.replace( /anonymous[\s]*|bound (?=\w)/i, '' ); } function isNode ( obj ){ return obj && typeof obj.nodeType == 'number' && typeof obj.nodeName == 'string'; } function isElement ( obj ){ return isNode(obj) && obj.nodeType === 1; }
그러고 나서, getTypeof() 함수를 작성한다.
Then, write "getTypeof" function.
첫번째 방법 ( First way )
function getTypeof ( obj ){ var str; var typeA = typeof obj; if ( typeA == 'undefined' ) return 'Undefined'; if ( obj === null ) return 'Null'; var toString = function ( obj ){ var str = Object.prototype.toString.call( obj ); return str.substr( 8, str.length - 9 ); }; var typeB = toString( obj ); var doc = document; var view = doc.defaultView; switch ( true ){ case ( obj == view.alert ) : return 'Function'; case ( obj == doc ) : return 'Document'; case ( obj == view ) : return 'Window'; case ( obj == doc.__proto__ ) : return 'DocumentPrototype'; case ( obj == view.__proto__ ) : return 'WindowPrototype'; case isNode( obj ) : var name = obj.nodeName; switch ( obj.nodeType ){ case 1 : return name.charAt( 0 ) + name.substr( 1 ).toLowerCase(); case 2 : return 'Attribute'; // attribute of element case 3 : return 'Text'; case 8 : return 'Comment'; // case 9 : return 'Document'; case 10 : return 'DocumentType'; // document.doctype case 11 : return 'Fragment'; // document.createDocumentFragment() /* * if it's xml file, not html... * * case 4 : return 'CDATASection'; * case 5 : return 'EntityReference'; * case 6 : return 'Entity'; * case 7 : return 'ProcessingInstruction'; * case 12 : return 'Notation'; */ } return; case ( typeA == 'string' || typeB == 'String' ) : return 'String'; case ( typeA == 'number' || typeB == 'Number' ) : return 'Number'; case ( obj.constructor && obj == obj.constructor.prototype ) : var ctor = obj.constructor; if ( typeof ctor == 'function' ){ str = getFunctionName( ctor ); } else { str = typeB; } return str + 'Prototype'; default : if ( typeof obj.length == 'number' ){ if ( 'callee' in obj ) return 'Arguments'; if ( 'cssText' in obj ) return 'CSSStyle'; // style of element if ( typeof obj.item == 'function' ){ /* * childNodes :: NodeList , children :: HTMLCollection , classList :: DOMTokenList * * NodeList :: function item() , * HTMLCollection :: function item() , function namedItem() , * DOMTokenList :: function item() , function add() , function remove() , function toggle() , */ if ( 'toggle' in obj ) return 'DOMTokenList'; if ( 'namedItem' in obj ) return 'HTMLCollection'; if ( 'item' in obj ) return 'NodeList'; } } if ( typeB == 'DocumentConstructor' || typeB == 'Window' ){ // Document in safari 5.1.7 , Window in firefox return 'Function'; } return typeB; } }
두번째 방법 ( Second way )
위의 내용에서 몇 줄을 수정한 것이다.
문자일 경우,
글자 하나 없이, 띄어쓰기만 잔뜩 들어있거나, 아니면 아예 아무것도 없는 빈 문자열인지를
구별해줘야 할 때가 있기 때문이다.
숫자일 때에도 마찬가지이다.
일반적인 숫자가 아닌, NaN이나 Infinity로 나오는 경우를 따로 구분해야 할 때가 있다.
This is slightly modified on the above.
When it's a string,
sometimes, it's necessary to distinguish whether it is an empty string, or all that whitespaces.
It's true when the numbers, too.
Because it may be "NaN" or "Infinity".
function getTypeof ( obj ){
var str;
var typeA = typeof obj;
if ( typeA == 'undefined' ) return 'Undefined';
if ( obj === null ) return 'Null';
var toString = function ( obj ){
var str = Object.prototype.toString.call( obj );
return str.substr( 8, str.length - 9 );
};
var typeB = toString( obj );
var doc = document;
var view = doc.defaultView;
switch ( true ){
case ( obj == view.alert ) : return 'Function';
case ( obj == doc ) : return 'Document';
case ( obj == view ) : return 'Window';
case ( obj == doc.__proto__ ) : return 'DocumentPrototype';
case ( obj == view.__proto__ ) : return 'WindowPrototype';
case isNode( obj ) :
var val = obj.nodeValue;
var name = obj.nodeName;
switch ( obj.nodeType ){
case 1 : return name.charAt( 0 ) + name.substr( 1 ).toLowerCase();
case 2 : return 'Attribute'; // attribute of element
case 3 : return ( /\S/ ).test( val ) ? 'Text' : ( val == '' ? 'EmptyText' : 'SpaceText' ); // whitespaces
/* Or, simply...
* case 3 : return 'Text';
*/
case 8 : return 'Comment';
// case 9 : return 'Document';
case 10 : return 'DocumentType'; // document.doctype
case 11 : return 'Fragment'; // document.createDocumentFragment()
/*
* if it's xml file, not html...
*
* case 4 : return 'CDATASection';
* case 5 : return 'EntityReference';
* case 6 : return 'Entity';
* case 7 : return 'ProcessingInstruction';
* case 12 : return 'Notation';
*/
}
return;
case ( typeA == 'string' || typeB == 'String' ): return /\S/.test(obj) ? typeB : ( obj == '' ? 'EmptyString' : 'SpaceString' );
case ( typeA == 'number' || typeB == 'Number' ) : return isFinite( obj ) ? typeB : obj.toString();
/* Or, simply...
*
* case ( typeA == 'string' || typeB == 'String' ) : return 'String';
* case ( typeA == 'number' || typeB == 'Number' ) : return 'Number';
*/
case ( obj.constructor && obj == obj.constructor.prototype ) :
var ctor = obj.constructor;
if ( typeof ctor == 'function' ){ str = getFunctionName( ctor ); }
else { str = typeB; }
return str + 'Prototype';
default :
if ( typeof obj.length == 'number' ){
if ( 'callee' in obj ) return 'Arguments';
if ( 'cssText' in obj ) return 'CSSStyle'; // style of element
if ( typeof obj.item == 'function' ){
/*
* childNodes :: NodeList , children :: HTMLCollection , classList :: DOMTokenList
*
* NodeList :: function item() ,
* HTMLCollection :: function item() , function namedItem() ,
* DOMTokenList :: function item() , function add() , function remove() , function toggle() ,
*/
if ( 'toggle' in obj ) return 'DOMTokenList';
if ( 'namedItem' in obj ) return 'HTMLCollection';
if ( 'item' in obj ) return 'NodeList';
}
}
if ( typeB == 'DocumentConstructor' || typeB == 'Window' ){ // Document in safari 5.1.7 , Window in firefox
return 'Function';
}
return typeB;
}
}
이 내용이 도움이 되셨다면, 아래의 하트 버튼을 눌러주세요 *^^*
If this article is helpful to you, please click the heart button below. :)
'JAVASCRIPT > 그외' 카테고리의 다른 글
[ 비공개 ] defineGetter (0) | 2017.07.04 |
---|---|
[ 자바스크립트 ] window의 속성 목록 (1) | 2017.04.30 |
[ 자바스크립트 ] document의 속성 목록 (0) | 2017.04.28 |
[ 미완성 ] getElementsByClassName (0) | 2017.02.28 |
[ 자바스크립트 ] classList (0) | 2016.09.27 |