数据类型
- 基本数据类型: Null、Undefined、Number、String、Boolean、Symbol(ES6新增)。
- 简单的数据段,值不可变;
- 存在栈中 ,占据的空间大小固定;
- 直接按值存放,直接访问。
- 引用数据类型:Object。
- 值可变,可动态地添加属性;
- 引用地址存在栈中,引用值存在堆内存,引用地址在栈中占据的空间大小固定,引用值的大小会改变;
- 按引用访问;
栈内存一般存储大小已知或有范围上限的变量,由系统分配空间;堆内存一般存储大小未知的变量,由代码分配空间。因此null代表空指针,使用typeof检测类型的时候,结果是“object”,但它存放在栈中,且不是以Object为原型创建出来的。
数据类型检测
返回一个字符串,表示未经计算的操作数的类型。能够检测出除null之外的基本数据类型,对于object,只能检测出function。
类型 | 结果 |
---|---|
Undefined | undefined |
Null | object |
Number | number |
Boolean | boolean |
String | string |
Symbol | symbol |
Function对象 | function |
其他对象 | object |
例:
typeof 1; //"number"
typeof undefined; //"undefined"
typeof true; //"boolean"
typeof '123'; //"string"
typeof Symbol(42); //"symbol"
typeof function(){}; //"function"
typeof []; //"object"
typeof {}; //"object"
typeof null; //"object"
测试构造函数的prototype
属性是否出现在对象的原型链中的任何位置。
- 基本数据类型判断无效。由于基本数据类型的创建不会调用Object构造函数,没有
__proto__
(原型链)指向Object.prototype
(原型对象),因此需要实例方式创建的变量才有效。而对象在字面创建时,Js 引擎会解析并把这个对象的__proto__
指向Object.prototype
,因此对象的字面创建有效。 - 出现在对象的原型链中的任何位置,检测结果都为true,因此既能判断是否是直接类的实例,也能判断时候是父类的实例。
- 不能检测 null 和 undefined。
例:
/** 基本数据类型与对象实例 **/
1 instanceof Number; // false,无效
new Number(1) instanceof Number; // true,typeof new Number(1) 为object
{} instanceof Object; // 报错:Uncaught SyntaxError: Unexpected token instanceof。原因是{}被解析为块语句,而不是对象。
({}) instanceof Object; // true
function(){} instanceof Object; // 报错:Function statements require a function name。原因是{}被解析为函数声明,而不是对象。
(function(){}) instanceof Object; // true
/** 原型链任何位置 **/
[] instanceof Array; // true
[] instanceof Object; //true
/** 其他对象检测 **/
new Date() instanceof Date; // true
new RegExp() instanceof RegExp; // true
...
`constructor是用来初始化对象,指向创建当前对象的构造函数,因此能够判断实例对象由哪个构造函数创建出来的。
- 与instanceof 相比,constructor较为不稳定。因为构造函数的
prototype
(原型对象)被重写会影响constructor
,而不影响instanceof的判断。 - 能够检测基本数据类型(null与undefined除外 )
/** constructor 、 __proto__和 prototype 的关系 **/
function Person(){};
var person = new Person();
person.constructor === Person; //true,person对象的构造函数是Person函数
person.__proto__ === Person.prototype; //true,person对象的原型链指向Person的原型对象
Person.prototype.constructor === Person; //true,Person的原型对象的构造函数是它本身
person.__proto__.__proto__ === Object.prototype; //true
person.__proto__.__proto__.constructor === Object; //true
person.__proto__.__proto__.__proto__ === null; //true
/** 构造函数的prototype被重写的影响 **/
function Person(){};
var person1 = new Person();
Person.prototype = {
name: '张三',
age: 18,
}; //constructor被覆盖,消失了
var person2 = new Person();
person1.constructor === Person; //true
person2.constructor === Person; //false
person2.constructor === Object; //true,继承关系,顺着原型链往上一级找父对象的构造函数
person1 instanceof Person; //true
person2 instanceof Person; //true
/** 基本数据类型的检测 **/
var a = 1;
a.constructor === Number; //true
(1).constructor === Number; // true,对于数字需要加上(),否则小数点会解析错误
任何对象都有toString()
方法,调用时返回格式"[object type]
",type
为对象的类型,任何数据类型的判断都可以通过Function.prototype.call
的形式,即 Object.prototype.toString.call()
来判断,传递要检查的对象作为第一个参数 。但是它不能检测非原生构造函数的构造函数名
类型 | 结果 |
---|---|
Undefined | [object Undefined] |
Null | [object Null] |
Number | [object Number ] |
Boolean | [object Boolean] |
String | [object String] |
Symbol | [object Symbol] |
Function | [object Function] |
Array | [object Array] |
Date | [object Date] |
RegExp | [object RegExp] |
Error | [object Error] |
document | [object HTMLDocument] |
Window | [object Window] |
非原生构造函数 | [object Object] |
/** 各数据类型的判断**/
Object.prototype.toString.call(1); //[object Number]
Object.prototype.toString.call("1"); //[object String]
Object.prototype.toString.call(true); //[object Boolean]
Object.prototype.toString.call(null); //[object Null]
Object.prototype.toString.call(undefined); //[object Undefined]
Object.prototype.toString.call(Symbol(0)); //[object Symbol]
Object.prototype.toString.call({}); //[object Object]
Object.prototype.toString.call([]) ; // [object Array]
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(document) ; // [object HTMLDocument]
Object.prototype.toString.call(window) ; //[object Window]
/** 非原生构造函数判断 **/
function Person(){};
var person = new Person();
Object.prototype.toString.call(person); //[object Object]
用Object.prototype.toString.call()封装一个判断类型的方法,如下:
function type(value){
var typeName = Object.prototype.toString.call(value);
return typeName.match(/(?<= )\b[a-zA-Z]*\b/)[0].toLocaleLowerCase();
}
type(); //undefined
type(null); //null
type(1); //number
type(true); //boolean
type({}); //object
type([]); //array
type(new Date()); //date
type(new function(){}); //function
参考文章:
JS基本数据类型和引用数据类型的区别及深浅拷贝
帮你彻底搞懂JS中的prototype、__proto__与constructor(图解)
js数据类型的检测总结,附面试题–封装一个函数,输入任意,输出他的类型