深入理解JS—对象和原型

来源:互联网 发布:java数组的调用 编辑:程序博客网 时间:2024/05/29 04:02

“一切都是对象”这句话的重点在于如何去理解“对象”这个概念。

——当然,也不是所有的都是对象,值类型就不是对象。

在谈对象之前,首先咱们还是先看看javascript中一个常用的函数——typeof()。typeof应该算是咱们的老朋友,还有谁没用过它?

typeof函数输出的一共有几种类型,在此列出:

function show(x) {            console.log(typeof(x));    // undefined            console.log(typeof(10));   // number            console.log(typeof('abc')); // string            console.log(typeof(true));  // boolean            console.log(typeof(function () { }));  //function            console.log(typeof([1, 'a', true]));  //object            console.log(typeof ({ a: 10, b: 20 }));  //object            console.log(typeof (null));  //object            console.log(typeof (new Number(10)));  //object        }        show();

以上代码列出了typeof输出的集中类型标识,其中上面的四种(undefined, number, string, boolean)属于简单的值类型,不是对象。剩下的几种情况——函数、数组、对象、null、new Number(10)都是对象。他们都是引用类型。

*判断一个变量是不是对象非常简单。值类型的类型判断用typeof,引用类型的类型判断用instanceof。

var fn = function () { };console.log(fn instanceof Object);  // true

对象——若干属性的集合

对象是什么?在java或者C#中的对象都是new 实例化出的,而且里面有字段、属性、方法,规定的非常严格。但是javascript就比较随意了——数组是对象,函数是对象,对象还是对象。对象里面的一切都是属性,只有属性,没有方法。那么这样方法如何表示呢?——方法也是一种属性。因为它的属性表示为键值对的形式。

而且,更加好玩的事,javascript中的对象可以任意的扩展属性,没有class的约束。这个大家应该都知道,就不再强调了。

那么函数和数组也可以这样定义属性吗?——当然不行,但是它可以用另一种形式,总之函数/数组之流,只要是对象,它就是属性的集合。

例如:

var fn = function () {            alert(100);        };        fn.a = 10;        fn.b = function () {            alert(123);        };        fn.c = {            name: "芷若初荨",            year: 1994        };

上段代码中,函数就作为对象被赋值了a、b、c三个属性——很明显,这就是属性的集合。

有些朋友或者会问,看这些有什么用呢?其实大家如果学到了JQuery,想要看懂JQuery源码,那么这个就会起到很大的作用。在jQuery源码中,“jQuery”或者“$”,这个变量其实是一个函数。

所以一切(引用类型)都是对象,对象是属性的集合。

函数和对象之间的关系

函数就是对象的一种,因为通过instanceof函数可以判断,但是函数与对象之间,却不仅仅是一种包含和被包含的关系,函数和对象之间的关系比较复杂。

但有一点是可以肯定的,对象都是通过函数来创建的,可是这是为什么呢?大家看下面一个实例就知道了。如:

        //var obj = { a: 10, b: 20 };        //var arr = [5, 'x', true];        //上面两行代码的本质是:        var obj = new Object();        obj.a = 10;        obj.b = 20;        var arr = new Array();        arr[0] = 5;        arr[1] = 'x';        arr[2] = true;

输出结果:

console.log(typeof (Object));  // functionconsole.log(typeof (Array));  // function

原型Prototype

既typeof之后的另一位老朋友!

prototype也是我们的老朋友,即使不了解的人,也应该都听过它的大名。

刚刚谈到函数是一种对象,也是属性的集合,我们可以对函数进行自定义属性,JS默认就给函数提供了一个属性——Prototype,这个prototype的属性值是一个对象,这个prototype的属性值是一个对象(属性的集合,再次强调!),默认的只有一个叫做constructor的属性,指向这个函数本身

每个对象都有一个*__proto__属性,指向创建该对象的函数的prototype。

在说明“Object prototype”之前,先说一下自定义函数的prototype。自定义函数的prototype本质上就是和 var obj = {} 是一样的,都是被Object创建,所以它的proto指向的就是Object.prototype。

这里写图片描述

但是Object.prototype确实一个特例——它的proto指向的是null,切记切记!

对象的proto指向的是创建它的函数的prototype,就会出现:Object.proto === Function.prototype。用一个图来表示。

这里写图片描述

上图中,很明显的标出了:自定义函数Foo.proto指向Function.prototype,Object.proto指向Function.prototype,形成一个循环引用。其实稍微想一下就明白了。Function也是一个函数,函数是一种对象,也有proto属性。既然是函数,那么它一定是被Function创建。所以——Function是被自身创建的。所以它的proto指向了自身的Prototype。

那么Function.prototype指向的对象,它的proto是不是也指向Object.prototype?

这里写图片描述

答案是肯定的。因为Function.prototype指向的对象也是一个普通的被Object创建的对象,所以也遵循基本的规则。

以上纯属个人在查询相关资料和看视频后的理解,如有错误,请指正,谢谢!

0 0
原创粉丝点击