- 小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
目录
- 8种数据类型
typeof无法区分 [] {} nullinstanceof只能用于判断对象是否从属关系constructor会被改写判断类型不准确Object.prototype.toString.call/apply最准确`- ECMA 封装的类型判断
isArray
一 8种数据类型
JS 是一种
弱类型或者说动态类型,这就意味着你不需要提前声明变量的类型,在程序运行的过程中,类型会被自动确定。这就意味着你可以使用同一个变量保存不同类型的数据
var a = 1; // Number
a = '1'; // String
a = [1]; // Array
a = {a:1}; // Object
1) 8 种数据类型
- 值类型(
栈内存) - 引用类型(
栈内存(指针)->堆内存)
最新的 ECMAScript 标准定义了
8 种数据类型:
-
(
值类型)7中原始类型:- Number
- String
- Boolean
- Null
- Undefined
- BigInt
- Symbol
-
(
引用类型) Object
2) Symbol
Symbol 是ES6新增的一种基本数据类型。我们可以
通过调用内置函数 Symbol() 创建,这个函数会动态的生成一个匿名、全局唯一的值。
var a = Symbol();
var b = Symbol();
a === b // false
var c = Symbol('c'); // Symbol(c)
Symbol 函数栈不能用 new 命令,因为Symbol 是原始数据类型,不是对象。可以接受一个字符串作为参数,为新创建的 Symbol 提供描述,用来显示在控制台或者作为字符串的时候使用,便于区分。
var c = new Symbol('c');
3) 基本数据和引用数据的区别
3.1) 基本数据类型
- 按值访问,可操作保存在变量中实际的值
- 值被保存在
栈内存中,占据固定大小的空间
3.2) 引用数据类型
- 引用类型的值是按引用访问的
- 保存在
堆内存中的对象,不能直接访问操作对象的内存空间
二 typeof 无法区分 [] {} null
typeof 命令可以判断所有 JS 中的基本数据类型
(Null, Undefined, Boolean, String, Number), 虽然 null 使用 typeof 返回的是 object 字符串, 但是无碍 它的基本使用, 但是在一些复杂的场景比如 object 与 null, array 与 object, function 与 object 等等的类型区分, typeof 就会显得心有余力不足了.
typeof 1; // 'number'
typeof '1'; // 'string'
typeof null; // 'object'
typeof undefined; // 'undefined'
typeof true; // 'boolean'
typeof Symbol('11') // 'symbol'
typeof 1n; // 'bigint'
typeof {} // 'object'
typeof [1]; // 'object'
typeof new Function() // 'function'
注意:
typeof {} // 'object'
typeof [] // 'object'
typeof(() => {}) // 'function'
typeof 'a' // 'string'
typeof new String('a') // 'object'
typeof undefined // 'undefined'
typeof null // 'object'
typeof Symbol() // 'symbol'
三 instanceof 只能用于判断对象是否从属关系
- 只能用来判断
(两个对象是否属于原型链的关系),不一定能获取对象的具体类型 Instanceof不适用判断原始类型的值,只能用于判断对象是否从属关系
[1] instanceof Array; // true
[1] instanceof Object; // true
function a(){}
var b = new a();
b instanceof a; //true
b instanceof Object; //true
1) 注意:空对象{}的判断问题
let obj1 = {}
obj1 instanceof Object // true
let obj2 = Object.create(null)
obj2 instanceof Object; // false
let obj222 = Object.create(Object)
obj222 instanceof Object; // true
let obj3 = Object.create({})
obj3 instanceof Object; // true
四 constructor 会被改写 判断类型不准确
每一个实例对象都可通过constructor来访问它的构造函数,其实也是根据原型链的原理来的。
(new Function).constructor === Function; // true
(1).__proto__.constructor === Number; // true
(1).constructor === Number; // true
'1'.constructor === String; // true
'1'.__proto__.constructor === String; // true
[1].__proto__.constructor === Array; // true
var abc = new RegExp();
abc.constructor === RegExp; // true
由于 undefined 和null是无效的对象,因此是没有constructor属性的,这两个值不能用这种方法判断.
undefined.__proto__.constructor // Cannot read property '__proto__' of undefined
null.__proto__.constructor // Cannot read property '__proto__' of undefined
注意: constructor 会被改写,因此判断类型也是不准确的
[1].__proto__.constructor = String;
[1].__proto__.constructor === Array; // false
五 Object.prototype.toString.call/apply最准确`
Object.prototype.toString方法返回对象的类型字符串,最准确。- 因为实例对象有可能会自定义toString方法,会覆盖Object.prototype.toString,所以在使用时,最好加上call
Object.prototype.toString.apply('5') // '[object String]'
Object.prototype.toString.call('5') // '[object String]'
Object.prototype.toString.call(5) // '[object Number]'
Object.prototype.toString.call([5]) // '[object Array]'
Object.prototype.toString.call(true) // '[object Boolean]'
Object.prototype.toString.call(undefined) // '[object Undefined]'
Object.prototype.toString.call(null) // '[object Null]'
Object.prototype.toString.call(new Function()); // '[object Function]'
Object.prototype.toString.call(new Date()); // '[object Date]'
Object.prototype.toString.call(new RegExp()); // '[object RegExp]'
Object.prototype.toString.call(new Error()); // '[object Error]'
Object.prototype.toString.call(null).slice(8, -1) // "Null" Object.prototype.toString.call(3).slice(8, -1) // "Number"
六 isArray 与 判断null undefined
Array.isArray([]); // true
var isNull = function (obj) {
return obj === null;
};
isNull(null); // true
var isUndefined = function (obj) {
return obj === void 0; // void null // void undefined
}
isUndefined(undefined); // true
1) 转字符串
String(null) // 'null'
String(undefined) // 'undefined'
String(true) // 'true'
String(1) // '1'
String(-1) // '-1'
String(0) // '0'
String(-0) // '0'
String(Math.pow(1000,10)) // '1e+30'
String(Infinity) // 'Infinity'
String(-Infinity) // '-Infinity'
String({}) // '[object Object]'
String([1,[2,3]]) // '1,2,3'
参考
总结
-
Symbol通过调用内置函数 Symbol() 创建,这个函数会动态的生成一个匿名、全局唯一的值 -
Symbol最大的用处就是:避免对象的键被覆盖 -
typeof无法区分 [] {} null -
Instanceof不适用判断原始类型的值,只能用于判断对象是否从属关系 -
constructor会被改写,因此判断类型也是不准确的 -
instanceof适合自定义对象,也可以用来检测原生对象,在不同的iframe 和 window间检测时失效,还需要注意Object.create(null)对象的问题 -
constructor基本能判断所有类型,除了null和undefined,但是constructor容易被修改,也不能跨iframe使用 -
Object.prototype.toString.apply能判断所有类型,最准确