typeof
typeof
一般被用于判断一个变量的类型,我们可以利用 typeof
来判断number
, string
, object
, boolean
, function
, undefined
, symbol
这七种类型。
let s = new String('abc');
typeof s === 'object' // true
s instanceof String // true
typeof 的原理
js
在底层是怎么存储数据的类型信息呢?或者说,一个js
的变量,在它的底层实现中,它的类型信息是怎么实现的呢?
js
在底层存储变量的时候,会在变量的机器码的低位1-3
位存储其类型信息。
-
000
:对象 -
010
:浮点数 -
100
:字符串 -
110
:布尔 -
1
:整数 -
null
:所有机器码均为0
-
undefined
:用−2^30
整数来表示
所以,
typeof
在判断null
的时候就出现问题了,由于null
的所有机器码均为0
,因此直接被当做了对象来看待。
然而用instanceof
来判断的话:
null instanceof null // TypeError: Right-hand side of 'instanceof' is not an object
null
直接被判断为不是object
,这也是JavaScript
的历史遗留bug
。
判断类型的方法:Object.prototype.toString
一个不错的判断类型的方法,就是Object.prototype.toString
,我们可以利用这个方法来对一个变量的类型来进行比较准确的判断。
Object.prototype.toString.call(1) // "[object Number]"
Object.prototype.toString.call('hi') // "[object String]"
Object.prototype.toString.call({a:'hi'}) // "[object Object]"
Object.prototype.toString.call([1,'a']) // "[object Array]"
Object.prototype.toString.call(true) // "[object Boolean]"
Object.prototype.toString.call(() => {}) // "[object Function]"
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call(undefined) // "[object Undefined]"
Object.prototype.toString.call(Symbol(1)) // "[object Symbol]"
普通对象与函数对象
JavaScript
中,万物皆对象!(Function.prototype.__proto__ === Object.prototype
)但对象也是有区别的。分为普通对象和函数对象,Object
、Function
是JS
自带的函数对象。原文
var o1 = {};
var o2 = new Object();
var o3 = new f1();
function f1(){};
var f2 = function(){};
var f3 = new Function('str','console.log(str)');
console.log(typeof Object); //function
console.log(typeof Function); //function
console.log(typeof f1); //function
console.log(typeof f2); //function
console.log(typeof f3); //function
console.log(typeof o1); //object
console.log(typeof o2); //object
console.log(typeof o3); //object
在上面的例子中 o1 o2 o3 为普通对象,f1 f2 f3 为函数对象。怎么区分,其实很简单,凡是通过new Function()
创建的对象都是函数对象,其他的都是普通对象。f1,f2,归根结底都是通过 new Function()
的方式进行创建的。
Function Object
也都是通过New Function()
创建的。
原型对象
在JavaScript
中,每当定义一个对象(函数也是对象)时候,对象中都会包含一些预定义的属性。
其中每个
函数对象
都有一个prototype
属性。在chrome
和firefox
中,每个对象都有_ _proto_ _
属性,指向的原型对象。
同时,在默认情况下,所有的原型对象都会自动获得一个
constructor
(构造函数)属性,这个属性(是一个指针)指向prototype
属性所在的函数。(构造函数)
Person.prototype.constructor == Person
person1.constructor == Person
Person.prototype.constructor == Person
在 Person 创建的时候,创建了一个它的实例对象并赋值给它的 prototype。
原型对象(
Person.prototype
)是 构造函数(Person
)的一个实例。
function Person() {};
console.log(Person.prototype) //Person{}
console.log(typeof Person.prototype) //Object
console.log(typeof Function.prototype) // Function,这个特殊
console.log(typeof Object.prototype) // Object
console.log(typeof Function.prototype.prototype) //undefined
上文提到凡是通过
new Function( )
产生的对象都是函数对象。因为 A 是函数对象,所以Function.prototype
是函数对象。
var A = new Function ();
Function.prototype = A;
Object.prototype.__proto__ === null
函数对象
所有函数对象的_ _proto_ _
都指向Function.prototype
,它是一个空函数。(Empty function
)
Number.__proto__ === Function.prototype // true
Number.constructor == Function //true
Boolean.__proto__ === Function.prototype // true
Boolean.constructor == Function //true
String.__proto__ === Function.prototype // true
String.constructor == Function //true
所有的构造器都来自于Function.prototype
,甚至包括根构造器Object
及Function
自身。
// 所有的构造器都来自于Function.prototype,甚至包括根构造器Object及Function自身
Object.__proto__ === Function.prototype // true
Object.constructor == Function // true
// 所有的构造器都来自于Function.prototype,甚至包括根构造器Object及Function自身
Function.__proto__ === Function.prototype // true
Function.constructor == Function //true
Array.__proto__ === Function.prototype // true
Array.constructor == Function //true
RegExp.__proto__ === Function.prototype // true
RegExp.constructor == Function //true
Error.__proto__ === Function.prototype // true
Error.constructor == Function //true
Date.__proto__ === Function.prototype // true
Date.constructor == Function //true
Math
,JSON
是以对象形式存在的,无需new
。它们的_ _proto_ _
是Object.prototype
。
Math.__proto__ === Object.prototype // true
Math.construrctor == Object // true
JSON.__proto__ === Object.prototype // true
JSON.construrctor == Object //true
instanceof
在typeof
在检测object
类型的时候,总是会返回object
,所以js
提供了另外一个接口来实现对对象类型的判断,那就是我们的instanceof
。
instanceof复杂用法
function Foo() {};
console.log(Object instanceof Object); // true
左边的
Object
的_ _proto_ _
指向Function.prototype
,Function.prototype
指向Object.prototype
。
console.log(Function instanceof Object); // true
左边的
Function
的_ _proto_ _
指向Function.prototype
,而Function.prototype
的__proto_ _
指向Object.prototype
,所以返回true
。
console.log(Function instanceof Function); // true
console.log(Number instanceof Number); // false
console.log(String instanceof String); // false
console.log(Foo instanceof Function); // true
console.log(Foo instanceof Foo); // false
instanceof操作符的机制
function instance_of (L, R){
var O = R.prototype; //右边表达式的显示原型
var L = L._proto_; //左边的表达式的隐式原型
//从原型链向上寻找
while(true){
if(L === null){
return false;
};
if(O === L){
return true;
};
L = L._proto_;
}
}
参考文章
https://juejin.im/post/5b0b9b9051882515773ae714
https://juejin.im/post/59cbc479518825790e5cb581
https://www.jianshu.com/p/dee9f8b14771