JavaScript自定义对象

源码下载

  本节课讲解如何自定义一个具有属性和方法的对象。本节课创建的自定义对象,从数据类型的角度看,称为对象object类型。万物皆对象,虽然数字类型数据、字符串类型数据、数组类型数据都属于对象,拥有方法和属性,但是一般 不称呼这些类型的数据为对象类型数据,主要是因为他们都有自己的独特特性。比如数字赋值的变量都是存储在栈内存,而数组赋值的变量,数组元素存储在对内存中,数组数据的索引存放在栈内存中,访问数组数据时,通过栈内存访问堆内存。

9        //使用大括号{ }符号创建对象
10       let area = {
11           PI:3.14,
12           rectangle:  function (a,b) {
13               let s = a*b;
14               return s;
15           }
16       };
17       //先使用大括号{ }符号创建一个空对象,在利用符号点.给函数添加属性和方法。
18   //    let area = {};
19   //    area.PI = 3.14;
20   //    area.rectangle = function (a,b) {
21   //            let s = a*b;
22   //            return s;
23   //        };
24       //使用构造函数创建对象
25   //      function fun() {
26   //          this.PI = 3.14;
27   //          this.rectangle = function (a,b) {
28   //            let s = a*b;
29   //            return s;
30   //        }
31   //      }
32   //      let area = new fun();
33   
34       let S1 = area.rectangle(10,20);
35       let S2 = area.PI*10*10;
36       document.write(S1);
37       document.write("<br>");
38       document.write(S2);

代码解析

  对象的定义可以参考数组,数组使用方括号[...]定义,对象使用大括号{...}定义,数组定义好之后会把数据的地址赋值给所声明的变量,查看代码第10到第16行{...}定义的对象通过let声明把对象的地址赋值给变量area,{...}定义的 对象数据和[...]定义的数组数据一样,在初始化的时候都会存入堆内存,把堆内存数据存储地址赋值给声明的变量。正是因为如此,数组和对象(指自定义的对象,非广义上的所有对象)成为引用数据,对应的数字类型的数据存储在栈内存。 不同的管理方式,主要是为了提高效率,这里不再展开讲,继续回到自定义对象的方法上。

  第11行代码定义了一个area的属性PI,属性PI的属性值是3.14,也就是圆周率的值,这里的PI就和前面讲到的属性length一样可以通过符号点.调用area.PI返回数值3.14。定义属性的格式,属性和属性值之间用冒号连接,定义完成一个属性以后用逗号隔开, 和数组一样元素之间用逗号隔开。第12行定义的属性和第11行定义的属性略有不同,不同之处主要体现在属性值上面,rectangle的属性值是一个匿名函数,函数里面有13、14行两行语句。这种情况下不在把属性称之为属性,称为方法,可以对照 前面代码提到过的数组对象的内置方法push,可以通过点.符号调用。

  第18到23行注释掉的代码,也是定义对象的一种方式。这一点可以对比数组,数组可以先定义一个空数组,然后往数组里面写入数据,数组访问和写入数据都可以通过[]和下标i完成,对象添加访问属性一样可以通过点.符号和属性名来写入或访问属性。 第19行代码写入的是PI属性,属性值通过 = 运算符赋值,第20行到第23行代码把匿名函数的存储地址赋值给rectangle方法名,该方法有两个参数a和b,用a、b的乘积表示矩形面积。

  第34行调用rectangle方法,同时带入参数10和20,返回面积200,赋值给S1变量。第34行调用PI属性值求解一个半径为10 的圆面积。其实Javascript脚本语言有内置对象Math,该内置对象具有圆周率的属性PI,编程时可以直接调用, 本次案例知识简单演示了自定义圆周率属性,一般Javascript内置包含的属性和方法,尽量使用,不需要自己再去定义。后面的教程会把Javascript脚本语言内置对象支持的数百个方法和属性全部列举出来,这里不再详述。

构造函数方式定义对象

  具体代码就是第25到第32行,定义的效果和使用大括号{...}一样。Javascript语言的ES5版本里面没有类似C++、java中的class类关键字,ES6版本里面有,本节课先不讲解class。 上面的代码分为两大部分,第25到第31行是一个具名函数fun,可以理解为类,一个模板,第32行使用关键字new进行实例化。什么是类?什么是对象?什么是实例化?如果不懂就先别管,任何抽象的编程思想都是对具象代码的抽象,任何抽象的编程符号 都是对具象的CPU指令、内存操作的抽象。任何抽象的CPU指令都是对实际存在的晶体数字电路的抽象。你掌握底层的具象知识,就容易理解封装的外层抽象知识。

  现在回到具体的代码,先来理解函数里面的this,你可以用第32行的代码的变量名area 替换掉this,你会发现形式上和前面添加方法的方式一样,如果暂时搞不懂this对内存的操作细节,你就暂时理解为this关键字的使用可以保证,这个函数可以多次使用new用来创建不同对象,this的作用就是把属性指向当前定义的对象。 new操作符的意思是首先开辟一片内存,把构造函数fun里面的语句全部复制初始化到这个内存区域(注意获得的是整个函数对象的数据,而不是对象数据的索引地址),把该内存区域的地址赋值给变量area。

  可以把构造函数当做模板使用,多次用new创建多个对象,每一个对象创建好之后,可以分别再单独添加各自的私有属性和私有方法。 通过关键字new操作构造函数创建的对象存放在堆内存中的,描述对象的变量名存储在栈内存中,直接定义的数字类型变量一般放在栈内存中,

this

  this关键字在很多编程语言中都有,在不同的语言中,有相同也有差异。this本身在Javascript语言中也比较复杂,本节课也不会详细总结介绍,如果没有案例作为支撑,抽象的概念罗列只会迷惑大家。 首先看第26行的代码this.PI = 3.14;,this之后使用的是符号点,这也就是说this相对于PI来说是一个对象,通过这个语句是为了给this对象添加PI属性。第27行代码的是给this对象添加了一个方法rectangle。 this对象有什么用?在本次案例中,当使用new操作构造函数fun的时候,你这时候可以把this当作一个指针,PI属性、rectangle方法通过this关联到新的area对象,具体来说this的属性和方法都会被拷贝(复制) 到通过new创建area指向的新对象。简单说,哪个对象通过new操作this所在的构造函数。this的属性和方法就会被复制给那个对象。