Что такое тип? Проще говоря, тип — это присвоение определенного значения двоичной последовательности в памяти. Например, двоичная последовательность 0100 0000 0111 0000 0001 0101 0100 1011 1100 0110 1010 0111 1110 1111 1001 1110 равна 4643234631018606494, если рассматривать ее как 64-битное целое число без знака. 54 правила двоичного представления чисел с плавающей запятой (см. Приложение 1) double точность Тип с плавающей запятой — 257.331.
Большинство компьютерных языков используют переменные для хранения и представления данных. Некоторые языки определяют тип переменных. Этот тип нельзя изменить во время выполнения программы. Напротив, переменные в JavaScript и некоторых других языках могут хранить любой тип и используют нетипизированные переменные. Наличие типа переменной не имеет никакого отношения к синтаксису. Например, C# также предоставляет переменные типа var. Однако следующий оператор вызовет ошибку в C#.
вар а=1;
а="строка";
Причина в том, что ключевое слово var в C# опускает только объявление типа переменной и автоматически выводит тип переменной на основе выражения инициализации, поэтому переменная var в C# все еще имеет тип. В JavaScript вы можете в любой момент присвоить любое значение определенной переменной, поэтому переменные JavaScript не типизируются.
По методу проектирования системы типов компьютерного языка ее можно разделить на два типа: сильный тип и слабый тип. Разница между ними заключается в том, может ли неявное преобразование между разными типами быть прозрачным для пользователя во время вычислений. С точки зрения пользователя, если язык может неявно преобразовывать все свои типы, то, когда его переменные, выражения и т. д. участвуют в операциях, даже если тип неверен, они все равно могут получить правильный тип посредством неявного преобразования для пользователя. , как будто все типы могут выполнять все операции, поэтому такой язык называется слабо типизированным. Напротив, в строго типизированном языке не обязательно могут быть неявные преобразования между типами (например, C++ является строго типизированным языком, но в C++ double и int могут быть преобразованы друг в друга, но требуется приведение типов между double и любым тип указателя).
Типы могут помочь программистам писать правильные программы и выступают в качестве ограничений в реальном процессе написания программ. Общее правило состоит в том, что чем сильнее ограничение, тем меньше вероятность ошибок, но тем сложнее написать программу. Строго типизированные языки с переменными, имеющими типы, имеют самые сильные ограничения, и типичным представителем является C++. Слабо типизированные языки с нетипизированными переменными имеют самые слабые ограничения, причем типичным представителем является JavaScript. В JavaScript, поскольку ограничения относительно слабы, часто возникает эта ошибка:
вар а =200;
вар б="1";
вар с= а + б;
Вы могли бы ожидать, что c будет 201, но на самом деле это «2001», ошибка, которая никогда не возникает в строго типизированных языках. Однако именно потому, что в JavaScript нет этих ограничений, он может легко объединять числовые и строковые типы. Таким образом, ограничения и гибкость всегда представляют собой набор функций, которые разработчикам языка необходимо сбалансировать.
Тип — это ограничение, которое работает посредством проверки типа. В разных языках проверка типов работает на разных этапах, которые можно разделить на проверку во время компиляции и проверку во время выполнения. Для интерпретируемых языков, таких как JavaScript, существуют этапы, аналогичные процессу компиляции, а именно лексический анализ и синтаксический анализ. Если проверка типов интерпретируемых языков завершена во время синтаксического анализа или предыдущего этапа, ее также можно учитывать. аналогично проверке во время компиляции. Поэтому более разумным утверждением является проверка статического типа и проверка динамического типа.
Интересно, что хотя многие языки проверяют типы во время компиляции, информацию об их типах все равно можно получить во время выполнения. Например, C# использует метаданные для сохранения информации о типах. Во время выполнения пользователи могут получать и использовать типы посредством отражения.
JavaScript отдает приоритет гибкости во всех аспектах своего дизайна, поэтому он использует динамическую проверку типов и не проверяет типы активно, за исключением случаев выполнения очень небольшого количества конкретных операций. Вы можете получить информацию о типе любой переменной или выражения во время выполнения и проверить ее правильность с помощью логики программы.
В стандарте JavaScript указано 9 типов: Неопределенное значение Null Boolean String Number Завершение списка ссылок на объект
Среди них три типа дополнения списка ссылок используются только во время выполнения синтаксического анализа языка и не могут быть доступны напрямую из программы. Они не будут здесь представлены. Ниже мы можем узнать об этих шести типах:
Тип Unопределённый имеет только одно значение, unопределённое, которое является значением, когда переменной не присвоено значение. В JS глобальный объект имеет неопределенное свойство, которое представляет собой неопределенное значение. присвойте значение глобальному неопределенному свойству, чтобы изменить его значение.
Тип Null также имеет только одно значение — null, но JavaScript предоставляет ему ключевое слово null для представления этого уникального значения. Семантика типа Null — это «пустая ссылка на объект».
Логическое значение имеет два значения: true и false.
Формальная интерпретация типа String — это последовательность 16-битных целочисленных типов без знака, которая фактически используется для представления текстовой информации, закодированной в UTF-16.
Число JavaScript имеет в общей сложности 18437736874454810627 (то есть 264-253 +3) значений. Число в JavaScript хранится в формате с плавающей запятой двойной точности, за исключением того, что 9007199254740990 представляет NaN, что соответствует стандарту IEEE 754 (см. Приложение 1) и занимает 64 бита и 8 байтов.
Самый сложный тип в JavaScript — Object, который представляет собой неупорядоченную коллекцию ряда свойств. Функция — это объект, реализующий частное свойство [[call]]. Хост JavaScript также может предоставлять некоторые специальные объекты.
Ранее я говорил о типах, указанных в стандарте JS. Однако нельзя игнорировать проблему, заключающуюся в том, что стандарт JS написан для разработчиков JS. Для пользователей JS типы не обязательно должны определяться в соответствии со стандартом. , поскольку JS при выполнении операции . типы, не являющиеся объектами, будут автоматически преобразованы в соответствующие объекты, поэтому "str.length" фактически эквивалентен (new String("str")).length. С этой точки зрения он считается. Неплохая идея, чтобы оба были одного типа. Мы используем некоторые возможности языка JS для распознавания типов во время выполнения, но результаты этих методов разные. Вам нужно решить, какой из них лучше или хуже.
Typeof — это оператор в языке JS. С буквальной точки зрения он, очевидно, используется для получения типа. Согласно стандарту JavaScript, typeof получает строковое представление имени типа переменной. Существует 6 возможных результатов: строка, bool, число, неопределенное, объект, функция, а стандарт JavaScript позволяет разработчикам настраивать значение typeof некоторых объектов.
В стандарте JS есть такой список описаний:
Тип | Результат |
Неопределенный | "неопределенный" |
Нулевой | "объект" |
логическое значение | "логическое значение" |
Число | "число" |
Нить | "нить" |
Объект (собственный и не реализует [[call]]) | "объект" |
Объект (собственный и реализует [[call]]) | "функция" |
Объект (хост) | Зависит от реализации |
Следующий пример взят из Rimifon из 51js и показывает ситуацию, когда результат typeof в IE выдает «дата» и «неизвестно»:
var xml=document.createElement("xml");
вар rs=xml.recordset;
rs.Fields.Append("дата", 7, 1);
rs.Fields.Append("bin", 205, 1);
рс.Открыть();
rs.AddNew();
rs.Fields.Item("дата").Значение = 0;
rs.Fields.Item("bin").Value = 21704;
rs.Обновление();
var date = rs.Fields.Item("дата").Value;
var bin = rs.Fields.Item("bin").Value;
рс.Закрыть();
предупреждение (дата);
оповещение (корзина);
alert([тип даты, тип контейнера]);
попробуйте {предупреждение (date.getDate())} поймать (ошибка) {предупреждение (err.message)}
На самом деле существует множество критических замечаний по поводу этого метода определения, который наиболее близок к семантике типа. Один из них заключается в том, что он не может различать разные объекты New String («abc») и new Number (123) с помощью typeof. В JS-программировании часто используется большое количество различных объектов, а typeof может дать только расплывчатый результат «объект» для всех объектов, что сильно снижает его практичность.
Значение instanceof переводится на китайский язык как «является экземпляром...». В буквальном смысле это термин, основанный на объектно-ориентированном программировании на основе классов, и JS фактически не обеспечивает поддержку программирования на основе классов. языковой уровень. Хотя в стандарте JavaScript не упоминается ни слова, на самом деле конструкция некоторых встроенных объектов и настройки операторов намекают на «официальный» способ реализации классов, то есть от использования функций в качестве классов, когда действует оператор new. в функции атрибут прототипа функции устанавливается в прототип вновь созданного объекта, а сама функция используется в качестве конструктора.
Таким образом, объекты, созданные в результате новой операции одной и той же функции, считаются экземплярами класса. Эти объекты имеют общие черты: 1. Они имеют одинаковый прототип и 2. Они обрабатываются одним и тем же конструктором. Instanceof — это оператор, который проверяет, «принадлежит ли экземпляр классу» в сочетании с этим способом реализации класса. Вы также можете догадаться, что очень сложно проверить, был ли объект обработан конструктором, но гораздо проще проверить, каков его прототип. Поэтому реализация экземпляра понимается с точки зрения прототипа, то есть реализации. проверьте, что атрибут [[prototype]] соответствует прототипу конкретной функции. Обратите внимание, что [[prototype]] является частной собственностью, доступ к которой можно получить с помощью __proto__ в SpiderMonkey (который является JS-движком Firefox).
Прототип имеет смысл только для типа объекта, описанного стандартом, поэтому экземпляр экземпляра получит значение false для всех объектов, не являющихся объектами, и экземпляр экземпляра может только определить, принадлежит ли он определенному типу, но не может получить тип. instanceof также очевиден. Он может отличаться от объекта, созданного на основе определенного «класса».
На самом деле, экземпляр функции можно обмануть. Хотя частный атрибут [[prototype]] используемого ею объекта изменить нельзя, прототип функции является открытым атрибутом. Следующий код показывает, как обмануть экземпляр.
функция КлассA(){};
функция КлассB(){};
var o = new ClassA();//Создаем объект класса A
ClassB.prototype = ClassA.prototype //Заменить ClassB.prototype;
alert(o instanceof 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») | Объект | Нить | Нить | Объект |
функция привет(){} | Функция | Функция | Функция | Объект |
123 | Число | —— | Число | Число |
новыйНомер(123) | Объект | Число | Число | Объект |
новый массив (1,2,3) | Объект | Множество | Множество | Объект |
новыйМойТип() | Объект | МойТип | Объект | Объект |
нулевой | Объект | —— | Объект | Нулевой |
неопределенный | Неопределенный | —— | Объект | Неопределенный |
На самом деле, сложно сказать, какой из вышеперечисленных методов более разумен. Даже положения стандарта отражают только механизм выполнения JS, а не лучшие практики использования. Мое личное мнение состоит в том, чтобы преуменьшить значение понятия «тип» и больше сосредоточиться на ограничениях «как я хочу использовать этот объект». Использование typeof и instanceof для проверки может достичь того же эффекта, что и строго типизированный язык, где это необходимо.
Знаковый бит: используется для представления положительных и отрицательных знаков.
показатель степени: используется для представления чисел степени
мантисса (мантисса): используется для обозначения точности