判断数据类型

typeof

typeof null 返回类型错误,返回object

引用类型,除了function返回function类型外,其他均返回object。

其中,null 有属于自己的数据类型 Null , 引用类型中的 数组、日期、正则 也都有属于自己的具体类型,而 typeof 对于这些类型的处理,只返回了处于其原型链最顶端的 Object 类型,

1. 原始值类型
    typeof '';           //'string'
    typeof 1;            //'number'
    typeof true;         //'boolean'
    typeof null;         //'object'
    typeof undefined;    //'undefined'
    typeof Symbol;       //'function'
    typeof Symbol();     //'symbol'
2. 引用数据类型    
    typeof function(){}  //'function'
    typeof Date          //'function'
    typeof RegExp        //'function'
    typeof []            //'object'
    typeof {}            //'object'

instanceof

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

注意:

如果表达式 obj instanceof Foo 返回 true ,则并不意味着该表达式会永远返回 true

因为 Foo.prototype 属性的值有可能会改变,改变之后的值很有可能不存在于 obj 的原型链上,这时原表达式的值就会成为 false

另外一种情况下,原表达式的值也会改变,就是改变对象 obj 的原型链的情况,

虽然在目前的ES规范中,我们只能读取对象的原型而不能改变它,但借助于非标准的 __proto__ 伪属性,是可以实现的。

比如执行 obj.__proto__ = {} 之后,obj instanceof Foo 就会返回 false 了

在这里需要特别注意的是:instanceof 检测的是原型

[] 的原型指向Array.prototype,间接指向Object.prototype, 因此 [] instanceof Array 返回true, [] instanceof Object 也返回true。

instanceof 只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型。

原理:

function myInstanceof(leftValue, rightValue) {
	let leftProto = Object.getPrototypeOf(leftValue), // 获取对象的原型
			rightProto = Object.getPrototypeOf(rightValue) // 获取构造函数的 prototype 属性
	// 判断构造函数的prototype 对象
	while(true) {
		if(!leftProto) return false;
		if(leftProto === rightProto) return true;
		// 如果都不符合,将继续去查找左边变量的原型,赋值给左变量的原型
		leftProto = Object.getPrototypeOf(leftProto)
	}
}

toString

Object.prototype.toString.call('') ;   // [object String]

Object.prototype.toString.call(1) ;    // [object Number]

Object.prototype.toString.call(true) ; // [object Boolean]

Object.prototype.toString.call(Symbol()); //[object Symbol]

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([]) ; // [object Array]

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 global] window 是全局对象 global 的引用

总结****

数据类型位置其他
字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol存储在栈中的简单数据段,他们的值直接存储在变量访问的位置。 在内存中占据固定大小,保存在栈内存中。原始值是不可更改的:任何方法都无法更改一个原始值
对象(Object)、数组(Array)、函数(Function)、日期(Date)、正则(RegExp)存储在堆中的对象,存储在变量处的值是一个指针,指向存储对象的内存处。可修改的
上次更新:
作者: sirius.cheng