JavaScript数组、函数、对象三者之间的相互关系(二)
继续上周还没有结束的话题
先来说说数组与对象的联系
在javascript对象被定义为属性和值的集合。最直接的表现便是对象字面量:var obj={a:3,b:“hello”,c:[1,2,3]}。相比传统的面向对象的语言,这种方式大大简化的对象创建。在这种情况下,javascript的对象其实就是一个关联数组。那么javascript的数组又是什么呢?在javascript中,数组又可以认为是索引数组,即可以用整数来进行索引。数组和对象在这种情况下非常接近,那到底他们的区别在哪里呢?其实,javascript的对象和数组之间的区别并不是那么的明显和必要,因为在javascript中**,数组也是一种对象**,只不过他有比较特殊的方法,比如push,pop等,当使用typeof判断数组类型时其会返回object便可看出。有一个比较直观的方法可以说明对象和数组之间的关系:var a=[1,2,3,4];a[“pro”]=“hello”;alert(a.length)。在这种情况下,数组a的长度不变,pro是a这个对象的属性而不是其元素,由于在javascript中,对象的属性可以用点号和中括号来引用,而数组的元素使用中括号来引用,因此会造成误解。所以,在javascript中,数组是一种特殊的对象,其除了具有一般对象的一些属性和方法外,又具有一些专属于数组的属性和方法。
在来说说函数与对象之间的联系
Object、Function和其它对象的关系可以归纳为下面四点:
一切对象都最终继承自Object对象,Object对象直接继承自根源对象null
一切函数对象(包括Object对象)都直接继承自Function对象
Object对象直接继承自Function对象
Function对象直接继承自己,最终继承自Object对象
是不是感觉有点绕,下面我会逐点解释(下面的"一切对象"指除null的其它一切对象):
- 一切对象都最终继承自Object对象,Object对象直接继承自根源对象null
下面两点可以佐证:
1)一切对象的原型链最终都是… → Object.prototype → null。例如定义一个num变量var num = 1,则num的原型链为x → Number.prototype → Object.prototype → null; 定义一个函数对象fnfunction fn() {},则fn的原型链为fn → Function.prototype → Object.prototype → null;等等…
2)一切对象都包含有Object的原型方法,Object的原型方法包括了toString、valueOf、hasOwnProperty等等,在js中不管是普通对象,还是函数对象都拥有这些方法,下面列出了几个例子,大家可以自行去举例验证:
- 一切函数对象(包括Object对象)都直接继承自Function对象
函数对象包括了Function、Object、Array、String、Number,还有正则对象RegExp、Date对象等等,它们在js中的构造源码都是function xxx() {[native code]);,Function其实不仅让我们用于构造函数,它也充当了函数对象的构造器,甚至它也是自己的构造器。
从原型链可以佐证:
js中 对象.proto === 构造器.prototype,由此可以见得它们之间的关系。
疑:Object对象都继承自Function对象了,而一切对象又都继承自Object对象,这边是不是有矛盾,Object对象和Function对象的关系是不是有点♂复♀杂?
答:其实疑问的内容就是上面结论的三四点,它们没有矛盾,关系也不复杂。
一切对象都继承自Object对象是因为一切对象的原型链最终都是… → Object.prototype → null,包括Function对象,只是Function的原型链稍微绕了一点,Function的原型链为Function → Function.prototype → Object.prototype → null,它与其它对象的特别之处就在于它的构造器为自己,即直接继承了自己,最终继承于Object,上面的原型链可以在浏览器验证:
2. Object继承自Function,Object的原型链为 Object → Function.prototype → Object.prototype → null,原型链又绕回来了,并且跟第一点没有冲突。可以说Object和Function是互相继承的关系。
3、4点的解答在第2点中
疑问
1)一切对象继承自Object,Object又继承自Function,那一切对象是不是都有Function的原型方法?
答:不对,普通对象都没有Function的原型方法。从我们所写原型链中可以看出,Object是继承自Function,而Object也有Function的原型方法(比如bind),但Object继承得到的方法储存于__proto__属性中,普通对象从Object继承到的原型方法却在于prototype属性中,因而不对。
2)Function对象怎么那么怪,自己继承自己?
答:就是 就是。
总结
Object对象直接继承自Function对象,一切对象(包括Function对象)直接继承或最终继承自Object对象。