Java Script作为一门弱类型语言,它对象的概念相对于Java语言有些不清晰,但它又有一些特性区别于Java,以下便叙述一下我学习过程中对JavaScript对象的理解。
一、对象即为键值对集合。
1 var number = new Number(10); //Map map = new HashMap(); 2 number.one = "Hello, "; //<=>map.put(one, "Hello, "); 3 number.tow = "world!"; //<=>map.put(one, "world!"); 4 console.log(number);
由该段代码的执行结果可以清晰的得到,js的对象本质就是HashMap,即键值对的集合。通过 "对象名.成员名" 的方式增加成员。
二、关于类与对象的区别。
1 var obj = new Object; 2 console.log("obj:", obj); 3 console.log("Object:", Object); 4 var number = new Number(10); 5 console.log("number:", number); 6 console.log("Number:", Number);
由该段代码的执行结果可以看到,对象只有一个属性:__proto__,而类都存在有两个共同的属性:prototype和__proto__(类其他的只是简单的属性和方法,重点论述前两者)。
对于prototype和__proto__是什么?有什么用?可以简述为以下。
1.prototype是类特有的属性,是对象不具备的,所以判断一个对象是否为“类”类型可以通过观察是否有prototype属性。而且prototype代表类的new生成对象的类型。
2.__proto__代表着对象的类型,且与其类的prototype属性内容一致,如图所示。读者也可以通过 "对象名.__proto__ === 类名称.prototype”的方式确认,其结果为true。
3.类的prototype与其对象的__proto__都是指针且指向同一空间,证明如下。
1 var number = new Number(10); 2 Number.prototype.addOne = "addOne"; 3 console.log("number:", number); 4 console.log("Number:", Number);
1 var number = new Number(10); 2 Number.prototype.addOne = "addOne"; 3 console.log("number:", number); 4 console.log("Number:", Number); 5 number.__proto__.addOne = "hadModify"; 6 console.log("number:", number); 7 console.log("Number:", Number);
通过以上两段代码和结果可以清晰的看到,不管是通过Number.prototype.addOne来增加成员,还是通过number.__proto__.addOne来更改成员的值都是成功的,证明了以上的结论。
注:同时可以得到一个额外的结论,prototype和__proto__都是对象,都是键值对集合,可以增加成员。而且通过更改对象的__proto__的指向空间可以更改对象的类型,在此不再赘述,毕竟已下划线开头的变量不应当是程序员能轻易修改的内容。
4.通过类名.成员名添加prototype成员可以等效为静态成员。
通过类名.成员名添加protype成员,其类生成的对象都拥有该成员,且可以获得其值,但无法直接更改,与Java语言类似,java在类中添加静态成员,是所有其类的对象共同拥有的,且只能通过类名.静态成员名获取和赋值,例子如下。
1 var number = new Number(10); 2 Number.prototype.addOne = "addOne"; //增加prototype的成员 3 console.log("number:", number); 4 console.log("Number:", Number); 5 console.log("number.addOne:", number.addOne); //获取该成员的值
注:在此多叙述一些js中左值赋值和表达式获得属性值的内部机理:
(1)左值方式:首先查询该左值成员在本对象中的键值对是否存在,若存在,则更改该成员值即可,若不存在,则创造该键值对。
(2)表达式方式:首先查询成员在本对象中的键值对是否存在,若存在,则更改该成员值即可,若不存在,则沿着__proto__(原型链)查找,在__proto__的键值对集合 中查找,直到找到Object的prototype中的键值对,若有任何一次找到,则输出,若依然找不到则输出undefined。
三、function的本质
1 var klass = function () { 2 }; 3 console.log("Function:",Function); 4 console.log("function:", klass); 5 console.log("klass instanceof Function:", klass instanceof Function);
由以上代码和结果可以得出:function为Function的对象,所以function为对象。function又拥有prototype属性,所以function为“类”类型。我们平常熟知function为方法,所以function为方法的定义。综上function有三重身份!
四、Object、Function、function和用户自定义类之间的关系
在此我用一个图来表示之间的关系,具体描述如下:
(1)Object 是所有类的祖先类,它的prototype属性(之前讲述过prototype实际为一个对象)中不存在__proto__表示它的所属类,即Object为所有类的“根”。
(2)所有的类都是function类型,所有function都是类。由图可以清晰看到,所有类的__proto__ 指向Function的prototype属性指向的空间。function为用户自定义类。
(3)所有类的prtotype属性(prototype实际为一个对象)都是Object的对象。
注:具体证明不再赘述,只列出之间关系,读者可以通过观察prototypt和__proto__两个属性的内容探究。
五、继承关系
本文尚未完结,后续补充。