typeof 运算符
typeof 运算符返回参数的类型。当咱们想要别离解决不同类型值的时候,或者想疾速进行数据类型测验时,十分有用。
它反对两种语法模式:
- 作为运算符:typeof x。
- 函数模式:typeof(x)。
括号有的时候时必须的,如果不加上括号将会因为优先级的问题得不到咱们想要的后果。例如:
typeof 'string' === true; // false
typeof ('string' === true); // "boolean"
对 typeof x 的调用会以 字符串 的模式返回数据类型:
typeof undefined // "undefined"
typeof 0 // "number"
typeof 10n // "bigint"
typeof true // "boolean"
typeof "foo" // "string"
typeof Symbol("id") // "symbol"
typeof Math // "object" (1) // 任何其余对象
typeof null // "object" (2)
typeof alert // "function" (3) // 函数对象
最初三行可能须要额定的阐明:
- Math 是一个提供数学运算的内建 object。
- typeof null 的后果是 “object”。这是官网抵赖的 typeof 的行为上的谬误,这个问题来自于 JavaScript 语言的晚期,并为了兼容性而保留了下来。null 相对不是一个 object。null 有本人的类型,它是一个非凡值。
- typeof alert 的后果是 “function”,因为 alert 在 JavaScript 语言中是一个函数。在 JavaScript 语言中没有一个特地的“function”类型。函数隶属于 object 类型。然而 typeof 会对函数辨别看待,并返回 “function”。这也是来自于 JavaScript 语言晚期的问题。从技术上讲,这种行为是不正确的,但在理论编程中却十分不便。
另外 typeof 解决包装类型的时候会返回对应的原始数据类型。然而不举荐这样写。例如:
typeof Number(1); // "number"
typeof Boolean(true); // "boolean"
typeof String('string'); // "string"
typeof 运算符区别对待 Object 类型和 Function 类型
从技术角度讲,函数在 ECMAScript 中是对象,不是一种数据类型。然而,函数也的确有一些非凡的属性,因而通过 typeof 运算符来辨别函数和其余对象是有必要的。
typeof 运算符对 null 的解决
这个 bug 是第一版 Javascript 留下来的,javascript 中不同对象在底层都示意为二进制,而 javascript 中每种数据类型应用 3bit 示意,会把二进制前三位都为 0 的判断为 object 类型。
- 000 示意 Object 类型的数据。
- 001 示意 Int 类型的数据。
- 010 示意 Double 类型的数据。
- 100 示意 String 类型的数据。
- 110 示意 Boolean 类型的数据。
因为 null 代表空指针,大多数平台中值为 0x00,因而 null 的类型标签就成了 0,所以执行 typeof 时会返回‘object’。
instanceof 运算符
判断一个变量是数组还是对象
首先咱们试着用 typeof 运算符进行测试。
const arr = [0, 1, 2];
console.log(typeof arr) // "object"
发现输入后果为 ”object”,这并不是咱们冀望的后果。
所以应用 typeof 运算符并不能直接判断一个变量时对象还是数组类型。实际上,typeof 运算符在判断根本数据类型时会很有用,然而在判断援用市局类型时,却显得很吃力。
接下来咱们试着用 instanceof 运算符进行测试。
instance 运算符用于通过查找原型链来检测某个变量是否为某个类型数据的实例。应用 instanceof 运算符能够判断一个变量时数组还是对象。
const a = [0, 1, 2];
console.log(a instanceof Array); // true
console.log(a instanceof Object); // true
const b = {name: 'xx'};
console.log(b instanceof Array); // false
console.log(b instanceof Object); // true
有一点须要注意,a 同时还隶属于 Object 类。因为从原型上来讲,Array 是继承自 Object 的。instanceof 在查看中会将原型链思考在内。
因而咱们在判断一个变量时数组还是对象时,应该先判断数组类型,而后再去判断对象类型。如果先判断对象,那么数组值也会被判断为对象类型,这无奈满足要求。
咱们能够失去以下的封装函数。
function getDataType (o) {if (o instanceof Array) return 'Array'
if (o instanceof Object) return 'Object'
return 'others'
}
另一种思路:判断构造函数
判断一个函数是否时数组或者对象,从另一个角度讲,就是判断变量的构造函数时 Array 类型还是 Ojbect 类型。因为一个对象的实例都是通过构造函数生成的,所以,咱们能够直接判断一个变量的 constructor 属性。
const a = [0, 1, 2];
console.log(a.constructor === Array); // true
console.log(a.constructor === Object); // false
const b = {name: 'xx'};
console.log(b.constructor === Array); // false
console.log(b.constructor === Object); // true
咱们能够失去以下的封装函数。
function getDataType (o) {
const constructor = o.__proto__.constructor || o.constructor
if (constructor === Array) return 'Array';
if (constructor === Object) return 'Object';
return 'others'
}
Object.prototype.toString 函数
应用 Object.prototype.toString.call() 办法来揭示类型
每种援用类型都会间接或者间接继承自 Object 类型,因而它们都蕴含 toString()函数。不同数据类型的 toString()类型返回值也不一样,所以通过 toString()函数能够精确判断值的类型。
- 对于 number 类型,后果是 [object Number]
- 对于 boolean 类型,后果是 [object Boolean]
- 对于 null:[object Null]
- 对于 undefined:[object Undefined]
- 对于数组:[object Array]
- 对于对象:[object Object]
- ……等(可自定义)
Symbol.toStringTag
能够应用非凡的对象属性 Symbol.toStringTag 自定义对象的 toString 办法的行为。
let user = {[Symbol.toStringTag]: "User"
};
alert({}.toString.call(user) ); // [object User]
所以,如果咱们想要获取内建对象的类型,并心愿把该信息以字符串的模式返回,而不只是查看类型的话,咱们能够用 {}.toString.call 代替 instanceof。
总结