Skip to Content

面试导航 - 程序员面试题库大全 | 前端后端面试真题 | 面试

Javascript类型判断

Type Judgment

In JavaScript, there are 7 built-in types, which are:

  • Null (null)
  • Undefined (undefined)
  • Boolean (boolean)
  • Number (number)
  • String (string)
  • Object (object)
  • Symbol (symbol)

Strictly speaking, JavaScript has 6 primitive types (value types):

  • Null (null)
  • Undefined (undefined)
  • Boolean (boolean)
  • Number (number)
  • String (string)
  • Symbol (symbol)

In addition, there is a special primitive type:

  • BigInt, used to represent integers larger than the range of Number.

These primitive types are immutable, while the Object type is a complex type that can contain multiple values.

What is typeof

typeof is an operator in JavaScript used to check the type of a variable. It returns a string that indicates the type of the given value.

Next, we will use the typeof operator to see the type of values; it returns the string value of the type. Interestingly, these seven types and their string values do not correspond one-to-one:

console.log(typeof 777); // number console.log(typeof 3.14); // number console.log(typeof 0); // number console.log(typeof Infinity); // number console.log(typeof Number('moment')); // number console.log(typeof 77n); // bigint console.log(typeof '1'); // string console.log(typeof typeof 1); // string typeof returns a string console.log(typeof String(777)); // string console.log(typeof true); // boolean console.log(typeof false); // boolean console.log(typeof Boolean(5)); // boolean // Boolean() converts based on whether the argument is truthy or falsy typeof !!1 === 'boolean'; // Calling ! (logical NOT) twice is equivalent to Boolean() console.log(typeof Symbol()); // symbol console.log(typeof Symbol('foo')); // symbol console.log(typeof Symbol.iterator); // symbol console.log(typeof { a: 1 }); // object console.log(typeof [1, 2, 4]); // object console.log(typeof new Date()); // object console.log(typeof /regex/); // object console.log(typeof null); // object console.log(typeof function () {}); // function console.log(typeof class T {}); // function

You may have noticed that the null type is quite special, typeof null === 'object', the correct return should be 'null', but this bug has existed for nearly twenty years in JavaScript and may never be fixed.

In the original implementation of JavaScript, values in JavaScript were represented by a type label and the actual data value. The type label for objects is 0. Since null represents a null pointer (most platforms have a value of 0x00), the type label for null is also 0, which is why typeof null returns "object".

console.log(typeof function () {}); // function

In the code above, the output is 'function', indicating that function is also a built-in type in JavaScript. However, in the specification, it is actually a subtype of object. Specifically, functions are callable objects, which have an internal property [[call]] that allows them to be called.

function f() {} console.log(f.__proto__.constructor === Function); // true console.log(f.__proto__.__proto__.constructor === Object); // true // Functions are not only objects but can also have properties console.log(f.name); // f console.log(f.arguments); // null because no parameters were passed

By using the prototype method to determine, functions are indeed subclasses of Object.

Now let’s look at arrays. JavaScript supports arrays, and arrays are also objects. More precisely, they are also a subtype of object, and the elements of an array are indexed in numerical order, with its length property being the number of elements.

const foo = []; console.log(foo.__proto__.constructor === Array); // true console.log(foo.__proto__.__proto__.constructor === Object); // true

The new Operator

  • All constructor functions called with new will return non-primitive types; the return is either object type or function. Most return objects, but a notable exception is Function, which returns a function.
const str = new String('777'); const num = new Number(777); const func = new Function(); console.log(typeof str); // object console.log(typeof num); // object console.log(typeof func); // function

Undefined and Undeclared

  • A variable is undefined when it does not hold a value. At this point, typeof returns undefined:
var a; console.log(tyoeof a); // undefined

Most developers tend to equate undefined with undeclared, but in JavaScript, they are completely different. A variable declared in the scope but not yet assigned a value is undefined. In contrast, a variable that has not been declared in the scope is undeclared.

In the example above, bar is not defined can easily be mistaken for bar is undefined. However, undefined and is undefined are two different things, but typeof handles undeclared and returns undefined, for example:

var foo; console.log(typeof foo); // undefined console.log(typeof bar); // undefined

Both return "undefined" as is, and typeof bar does not throw an error because typeof has a special safety mechanism.

Internal Property [[class]]

In the previous examples, using typeof for judgment, whether it is null, Object, Array, etc., all return "object". So is there a mechanism to determine what specific type of value it is? The answer is yes.

All objects for which typeof returns object (such as arrays) contain an internal property [[class]], which we can think of as an internal classification, rather than a class in the traditional object-oriented sense. This property cannot be accessed directly and is generally viewed through Object.prototype.toString(...). For example:

console.log(Object.prototype.toString.call([1, 2, 3])); // [object Array] console.log(Object.prototype.toString.call(1)); // [object Number] console.log(Object.prototype.toString.call('moment')); //[object String] console.log(Object.prototype.toString.call(true)); //[object Boolean] console.log(Object.prototype.toString.call(null)); // [object Null] console.log(Object.prototype.toString.call(undefined)); // [object Undefined] console.log(Object.prototype.toString.call(function f() {})); // [object Function] console.log(Object.prototype.toString.call(class C {})); // [object Function] console.log(Object.prototype.toString.call(new Date())); // [object Date] console.log(Object.prototype.toString.call(Symbol())); // [object Symbol] console.log(Object.prototype.toString.call(new Boolean(1))); // [object Boolean] console.log(Object.prototype.toString.call(new RegExp())); // [object RegExp]

In the example above, the internal [[class]] property value of an array is Array, and the value of a regular expression is RegExp. In most cases, the internal [[class]] property of an object corresponds to the built-in native constructor that created the object, but this is not always the case. For example, some primitive types, such as null and undefined, do not have native constructors like Null() and undefined(), but their internal [[class]] property values are still Null and Undefined.

Other primitive types, such as strings, numbers, and booleans, behave differently. Since primitive type values do not have properties and methods like .length and .toString(), they need to be wrapped in objects to access them. At this point, JavaScript automatically wraps primitive types into an object. For example, var foo = 'moment'; actually performs var foo = new String('moment');, turning it into an object that has its own properties and methods. If you want to get the primitive type value from the wrapped object, you can use the valueOf() function, for example:

var foo = new String('moment'); console.log(foo); // [String: 'moment'] console.log(foo.valueOf()); // moment console.log(typeof foo.valueOf()); // string

Custom typeof

typeof is very useful, but it is not as universal as needed. For example, typeof [] is "object", as well as typeof new Date() and typeof /abc/, etc.

To explicitly check the type, MDN provides a custom type(value) function that mainly mimics the behavior of typeof, but for non-primitive types (i.e., objects and functions), it returns more detailed type names whenever possible.

function type(value) { // If the passed value is null, return null if (value === null) { return 'null'; } const baseType = typeof value; // If it is a primitive type if (!['object', 'function'].includes(baseType)) { return baseType; } // Symbol.toStringTag usually specifies the "display name" of the object's class const tag = value[Symbol.toStringTag]; if (typeof tag === 'string') { return tag; } // If it is a function, and its source code starts with the class keyword if (baseType === 'function' && Function.prototype.toString.call(value).startsWith('class')) { return 'class'; } // The name of the constructor; for example, `Array`, `GeneratorFunction`, `Number`, `String`, `Boolean`, or `MyCustomClass` const className = value.constructor.name; if (typeof className === 'string' && className !== '') { return className; } // If there is no suitable method to get the type of the value, return directly return baseType; }

References

Summary

The typeof operator is used to check the type of a variable, returning a string that represents the data type. For primitive types (such as number, string, etc.), the return value is clear, but for object types (such as null, arrays, regular expressions, etc.), typeof returns "object", leading to some special cases. To solve this ambiguity, you can use Object.prototype.toString.call() to accurately determine the actual type of an object. In addition, typeof cannot determine arrays, null, and classes, requiring additional handling.

Last updated on:
Copyright © 2025Moment版权所有粤ICP备2025376666