JavaScript有五个基本数据类型:Number、String、Boolean、undefined、null;一个引用类型:Object。
通过Object.prototype.toString.call(value)方法,我们可以判断一个值的类型,它的返回值有12中,分别为:
[object Number]、[object String]、[object Boolean]、[object Undefined]、[object Null]、[object Array]、[object Date]、[object Arguments]、[object Function]、[object RegExp]、[object Object]。
由此,我们可以草率的说在JavaScript中万物皆对象。
原型
所有的引用类型都有一个__proto__属性,为隐式原型;所有的引用类型都有一个prototype属性,为显示原型。
原型链
当试图得到一个对象的属性时,如果这个对象本身不存在这个属性,那么就会去它的__proto__属性中寻找,如果还是没有,会继续向__proto__.__proto__寻找,直到Object.prototype,如果还没找到,则返回undefined。
当new一个构造函数Fn()后,得到一个构造函数的实例fn。fn是一个对象,是对象,就有__proto__属性。
由此,从构造函数开始,到它的实例,再到构造函数的prototype,再到Object的prototype,最后值null,就形成了一条链状结构。有开始,有结束,这就是一条由原型:__proto__和prototype连接起来的原型链。
在Fn构造函数创建的fn对象中,有一个属性constructor,它指向自己的构造函数本身。
instanceof
instanceof运算符,它的使用方式一般为:对象 instanceof 函数。一般用于判断对象是否和函数在同一条原型链上。
instanceof的判断规则:对象会沿着__proto__属性查找,同时函数会沿着prototype属性查找,当对象和函数查找出同一个引用时,就会返回true,如果找到终点,还没找到同一个引用,则返回false。
function instanceof(LeftObject, RightFunction) {
RightFunction = RightFunction.prototype;
LeftObject = LeftObject.__proto__;
while(true) {
if(LeftObject.__proto__ === null) return false;
if(LeftObject === RightFunction) return true;
LeftObject = LeftObject.__proto__;
}
}
在instanceof中有几个怪异的现象:
console.log(Object instanceof Function); // true
console.log(Function instanceof Object); // true
console.log(Function instanceof Function); // true
Object和Function
在JavaScript中有很多内置的对象,其中有两个:Object、Function。
因为所有的对象都能通过原型链找到Object.prototype属性,所以我们很多常用的方法都在Object.prototype上,比如:toString、valueOf等。
在JavaScript中,Object内置对象由new Function生成。原因:Object.constructor === Function。
由此,Object和Function有一下关系: