유형이란 무엇입니까? 간단히 말해서, 유형은 메모리의 이진 시퀀스에 특정 의미를 할당하는 것입니다. 예를 들어, 이진 시퀀스 0100 0000 0111 0000 0001 0101 0100 1011 1100 0110 1010 0111 1110 1111 1001 1110은 64비트 부호 없는 정수 유형으로 보면 4643234631018606494입니다. 부동 소수점 숫자의 이진 표현을 위한 54가지 규칙(부록 1 참조) 정밀도 부동 소수점 유형은 257.331입니다.
대부분의 컴퓨터 언어는 데이터를 저장하고 표현하기 위해 변수를 사용합니다. 일부 언어는 변수 유형을 지정합니다(컴파일 타임이든 런타임이든). 대조적으로 JavaScript 및 일부 다른 언어의 변수는 모든 유형을 저장할 수 있으며 유형이 지정되지 않은 변수를 사용합니다. 변수 유형이 존재하는지 여부는 구문과 관련이 없습니다. 예를 들어 C#에서는 var 유형의 변수도 제공합니다. 그러나 다음 문은 C#에서 오류를 발생시킵니다.
var a=1;
a="문자열";
그 이유는 C#의 var 키워드는 변수 유형 선언만 생략하고 초기화 표현식을 기반으로 변수 유형을 자동으로 유추하므로 C#의 var 변수에는 여전히 유형이 있기 때문입니다. JavaScript에서는 언제든지 특정 변수에 값을 할당할 수 있으므로 JavaScript 변수는 유형이 지정되지 않습니다.
컴퓨터 언어 유형 시스템의 설계 방법에 따라 강한 유형과 약한 유형의 두 가지 유형으로 나눌 수 있습니다. 둘 사이의 차이점은 계산 중에 서로 다른 유형 간의 암시적 변환이 사용자에게 투명할 수 있는지 여부에 있습니다. 사용자의 관점에서 볼 때, 언어가 모든 유형을 암시적으로 변환할 수 있다면 해당 언어의 변수, 표현식 등이 연산에 포함될 때 유형이 올바르지 않더라도 암시적 변환을 통해 사용자에게 올바른 유형을 얻을 수 있습니다. , 모든 유형이 모든 작업을 수행할 수 있는 것처럼 보이기 때문에 이러한 언어를 약한 유형이라고 합니다. 대조적으로 강력한 형식의 언어에서는 형식 간에 암시적 변환이 반드시 필요하지 않을 수 있습니다. 예를 들어 C++는 강력한 형식의 언어이지만 C++에서는 double과 int를 서로 변환할 수 있지만 double과 any 사이에는 캐스트가 필요합니다. 포인터의 종류)
유형은 프로그래머가 올바른 프로그램을 작성하는 데 도움이 될 수 있으며 실제 프로그램 작성 프로세스에서 제약 조건으로 작용합니다. 일반적인 규칙은 제약 조건이 강할수록 오류가 발생할 가능성이 적지만 프로그램 작성이 더 번거롭다는 것입니다. 유형이 있는 변수가 있는 강력한 유형의 언어는 가장 강력한 제약을 가지며, 일반적인 대표자는 C++입니다. 유형이 없는 변수가 있는 약한 유형의 언어는 가장 약한 제약을 가지며, JavaScript가 대표적입니다. JavaScript에서는 제약 조건이 상대적으로 약하기 때문에 다음 오류가 발생하기 쉽습니다.
var a =200;
var b="1";
var c= a + b;
c가 201일 것이라고 예상할 수도 있지만 실제로는 강력한 형식의 언어에서는 절대 발생하지 않는 오류인 "2001"입니다. 그러나 JavaScript에는 이러한 제약이 없기 때문에 숫자 유형과 문자열 유형을 쉽게 연결할 수 있습니다. 따라서 제약과 유연성은 항상 언어 디자이너에게 균형을 맞춰야 하는 기능 집합입니다.
유형은 유형 검사를 통해 작동하는 제약 조건입니다. 다양한 언어에서 유형 검사는 다양한 단계에서 작동하며, 이는 컴파일 타임 검사와 런타임 검사로 나눌 수 있습니다. 자바스크립트와 같은 해석 언어의 경우 컴파일 과정과 유사한 단계, 즉 어휘 분석과 구문 분석이 있는데, 구문 분석이나 이전 단계에서 해석 언어의 타입 체크가 완료되면 고려해 볼 수도 있다. 컴파일 타임 검사와 유사합니다. 따라서 보다 합리적인 설명은 정적 유형 검사와 동적 유형 검사입니다.
흥미롭게도 많은 언어는 컴파일 타임에 유형을 확인하지만 런타임에 해당 유형 정보를 얻을 수 있습니다. 예를 들어 C#에서는 메타데이터를 사용하여 유형 정보를 저장합니다.
JavaScript는 디자인의 모든 측면에서 유연성을 우선시하므로 동적 유형 검사를 사용하고 매우 소수의 특정 작업을 수행하는 경우를 제외하고는 유형을 적극적으로 확인하지 않습니다. 런타임 시 변수나 표현식의 유형 정보를 얻을 수 있으며 프로그램 로직을 통해 그 정확성을 확인할 수 있습니다.
JavaScript 표준에는 9가지 유형이 지정되어 있습니다. 정의되지 않은 Null 부울 문자열 번호 개체 참조 목록 완성
그 중 세 가지 유형의 참조 목록 완성은 언어 구문 분석 런타임 중에만 사용되며 프로그램에서 직접 액세스할 수 없습니다. 여기서는 소개하지 않습니다. 아래에서는 6가지 유형에 대해 알아볼 수 있습니다.
Undefined 유형에는 변수에 값이 할당되지 않은 경우의 값인 undefine이라는 하나의 값만 있습니다. 값을 변경하려면 정의되지 않은 전역 속성에 값을 할당하세요.
Null 유형에도 null이라는 하나의 값만 있지만 JavaScript는 이 고유한 값을 나타내기 위해 null 키워드를 제공합니다. Null 유형의 의미는 "빈 개체 참조"입니다.
부울에는 true와 false라는 두 가지 값이 있습니다.
String 유형의 공식적인 해석은 16비트 부호 없는 정수 유형의 시퀀스이며 실제로 UTF-16으로 인코딩된 텍스트 정보를 나타내는 데 사용됩니다.
JavaScript의 Number에는 총 18437736874454810627(즉, 264-253 +3) 값이 있습니다. JavaScript의 Number는 배정밀도 부동 소수점 유형으로 저장됩니다. 단, 9007199254740990은 NaN을 나타내며 IEEE 754(부록 1 참조)를 준수하고 64비트와 8바이트를 차지합니다.
JavaScript에서 가장 복잡한 유형은 일련의 속성이 정렬되지 않은 컬렉션인 Object입니다. Function은 비공개 속성 [[call]]을 구현하는 Object입니다.
앞서 JS 표준에 명시된 유형에 대해 이야기했지만, JS 표준은 JS 구현자를 위해 작성되었다는 점을 예로 들 수 있습니다. , JS는 . 작업을 수행할 때 Object가 아닌 유형이 자동으로 해당 객체로 변환되므로 "str".length는 실제로 (new String("str")).length와 동일하다고 간주됩니다. 둘 다 같은 유형인 것은 나쁜 생각이 아닙니다. 런타임 유형 구별을 수행하기 위해 JS의 일부 언어 기능을 사용하지만 이러한 방법의 결과는 어느 것이 더 좋고 나쁜지 결정해야 합니다.
Typeof는 JS 언어의 연산자입니다. 문자 그대로의 관점에서 보면 JavaScript 표준에 따르면 typeof는 변수 유형 이름의 문자열 표현을 가져옵니다. bool, number, undefine, object, function 및 JavaScript 표준을 사용하면 구현자가 일부 개체의 typeof 값을 사용자 정의할 수 있습니다.
JS 표준에는 다음과 같은 설명 목록이 있습니다.
유형 | 결과 |
한정되지 않은 | "한정되지 않은" |
널 | "물체" |
부울 | "부울" |
숫자 | "숫자" |
끈 | "끈" |
객체(네이티브이며 [[call]]을 구현하지 않음) | "물체" |
객체(네이티브 및 [[call]] 구현) | "기능" |
객체(호스트) | 구현에 따라 다름 |
다음 예는 IE에서 typeof의 결과가 "date" 및 "unknown"을 생성하는 상황을 보여주는 51js의 Rimifon에서 나온 것입니다.
var xml=document.createElement("xml");
var rs=xml.recordset;
rs.Fields.Append("날짜", 7, 1);
rs.Fields.Append("bin", 205, 1);
RS.열기();
rs.AddNew();
rs.Fields.Item("날짜").Value = 0;
rs.Fields.Item("bin").Value = 21704;
RS.업데이트();
var 날짜 = rs.Fields.Item("date").Value;
var bin = rs.Fields.Item("bin").Value;
rs.닫기();
경고(날짜);
경고(빈);
Alert([날짜 유형, 저장소 유형]);
try{alert(date.getDate())}catch(err){alert(err.message)}
실제로 "type" 의미에 가장 가까운 이 판단 방법에 대해 많은 비판이 있습니다. 그 중 하나는 typeof를 사용하여 새 문자열("abc")과 새 숫자(123)를 구별할 수 없다는 것입니다. JS 프로그래밍에서는 다양한 개체가 많이 사용되는 경우가 많으며 typeof는 모든 개체에 대해 모호한 결과 "객체"만 제공할 수 있으므로 실용성이 크게 떨어집니다.
인스턴스오브(instanceof)의 의미는 중국어로 "...의 인스턴스입니다"로 번역됩니다. 문자 그대로 이해하면 클래스 기반 객체 지향 프로그래밍을 기반으로 하는 용어이며 JS는 실제로 클래스 기반 프로그래밍을 지원하지 않습니다. 언어 수준. JavaScript 표준에서는 한 마디도 언급하지 않지만 실제로 일부 내장 객체의 디자인과 연산자 설정은 클래스를 구현하는 "공식적인" 방법, 즉 new 연산자가 작동할 때 함수를 클래스로 사용하는 방법을 암시합니다. 함수에서는 함수의 프로토타입 속성이 새로 생성된 객체의 프로토타입으로 설정되고 함수 자체가 생성자로 사용됩니다.
따라서 동일한 함수의 새 작업으로 생성된 객체는 클래스의 인스턴스로 간주됩니다. 이러한 객체의 공통점은 다음과 같습니다. 1. 동일한 프로토타입을 가지며 2. 동일한 생성자에 의해 처리됩니다. 그리고 instanceof는 이러한 클래스 구현 방식과 결합하여 "인스턴스가 클래스에 속하는지 여부"를 확인하는 연산자입니다. 또한 객체가 생성자에 의해 처리되었는지 확인하는 것은 매우 어렵다고 추측할 수 있지만 해당 객체의 프로토타입이 무엇인지 확인하는 것이 훨씬 쉽습니다. 따라서 인스턴스 오브의 구현은 프로토타입의 관점에서 이해됩니다. [ [prototype]] 속성이 특정 함수의 프로토타입과 일치하는지 확인하세요. 여기서 [[prototype]]은 SpiderMonkey(Firefox의 JS 엔진)에서 __proto__를 사용하여 액세스할 수 있는 개인 속성입니다.
프로토타입은 표준에서 설명하는 Object 유형에 대해서만 의미가 있으므로, Object가 아닌 모든 객체에 대해서는 objectof가 false가 되고, instanceof는 특정 유형에 속하는지 여부만 확인할 수 있지만 유형을 얻을 수는 없습니다. instanceof는 또한 정의된 "클래스"로부터 생성된 객체를 구별할 수 있습니다.
실제로, 인스턴스of는 속일 수 있습니다. 비록 사용하는 객체의 프라이빗 속성 [[prototype]]은 변경할 수 없지만, 함수의 프로토타입은 퍼블릭 속성입니다.
함수 ClassA(){};
함수 ClassB(){};
var o = new ClassA();//클래스 A의 객체 생성
ClassB.prototype = ClassA.prototype; //ClassB.prototype 교체
경고(o ClassB 인스턴스)//진정한 속임수 성공 - -!
Object.prototype.toString은 원래 호출하기 어렵습니다. 모든 JavaScript 내장 클래스는 toString 메소드를 포함합니다. 내장 클래스가 아닌 객체의 경우 Object.prototype.toString은 의미 없는 [object Object ]만 가져올 수 있습니다. 결과. 따라서 꽤 오랫동안 이 기능의 마법적인 효과가 발견되지 않았습니다.
표준에서는 Object.prototype.toString의 설명이 3문장에 불과합니다.
1. 이 객체의 [[class]] 속성을 가져옵니다.
2. "[object ", result(1) 및 "]" 세 문자열을 연결하여 문자열을 계산합니다.
3. 결과(2)를 반환합니다.
분명히 Object.prototype.toString은 실제로 객체의 [[class]] 속성을 가져오지만 그것이 의도적인 것인지는 알 수 없습니다. 모든 JS 내장 함수 객체 String Number Array RegExp...가 모두 사용될 것입니다. new를 사용하여 객체를 생성하는 경우 [[class]] 속성이 유형을 판단하는 데 좋은 기준으로 사용될 수 있도록 [[class]] 속성을 설정하십시오.
Object.prototype.toString은 이 객체의 속성을 사용하므로 이 객체를 지정한 다음 Object.prototype.toString.call 또는 Object.prototype.toString.apply를 사용하여 유형을 가져올 수 있습니다.
Object.prototype.toString은 영리하지만 사용자 정의 함수가 [[class]]를 설정하지 않고 이 개인 속성에 프로그램에서 액세스할 수 없기 때문에 사용자 정의 함수로 생성된 객체 유형을 얻을 수 없습니다. Object.prototype.toString의 가장 큰 장점은 1과 new Number(1)을 동일한 유형의 객체로 만들 수 있다는 점입니다. 대부분의 경우 둘은 동일한 방식으로 사용됩니다.
그러나 new Boolean(false)이 bool 연산에 참여하게 되면 결과는 false와 정반대가 된다. 이때 둘을 같은 타입으로 간주하면 쉽게 오류가 발생하기 쉽다. 확인하다.
위의 세 가지 판단 방법을 비교하기 위해 여러 가지 방법을 종합적으로 비교할 수 있도록 표를 만들었습니다. 비교를 용이하게 하기 위해 여러 가지 판단 방법으로 얻은 결과를 통합했습니다.
물체 | 유형 | 인스턴스 | Object.prototype.toString | 기준 |
"알파벳" | 끈 | —— | 끈 | 끈 |
새로운 문자열("abc") | 물체 | 끈 | 끈 | 물체 |
함수 hello(){} | 기능 | 기능 | 기능 | 물체 |
123 | 숫자 | —— | 숫자 | 숫자 |
새로운번호(123) | 물체 | 숫자 | 숫자 | 물체 |
새로운 배열(1,2,3) | 물체 | 정렬 | 정렬 | 물체 |
새로운MyType() | 물체 | 마이타입 | 물체 | 물체 |
null | 물체 | —— | 물체 | 널 |
한정되지 않은 | 한정되지 않은 | —— | 물체 | 한정되지 않은 |
실제로 위의 방법 중 어느 것이 더 합리적인지 말하기는 어렵습니다. 표준의 조항조차도 최상의 사용 사례가 아닌 JS의 런타임 메커니즘만 반영합니다. 내 개인적인 의견은 "유형"의 개념을 무시하고 "이 객체를 어떻게 사용하고 싶은지"라는 제약 조건에 더 초점을 맞추는 것입니다. typeof와 instanceof를 사용하여 필요한 경우 강력한 유형의 언어와 동일한 효과를 얻을 수 있습니다.
부호 비트: 양수 및 음수 부호를 나타내는 데 사용됩니다.
지수: 거듭제곱을 나타내는 데 사용됩니다.
가수(mantissa) : 정확도를 나타내기 위해 사용