关于JavaScript继承和prototype的一点体会(一)

JavaScript中的prototype很容易使初学者迷惑不解,我也刚开始学习这门语言,写了一小段代码帮助理解。(千言万语,尽在注释中:)

  1、首先是一个简单的函数来判断是否是JavaScript中的对象。JavaScript中的数据类型分为原始类型和对象类型(包括函数)

 1 function isObject(object) {
 2 
 3     //注意,undefined == null,过滤掉null和undefined
 4     if(object == null) throw TypeError();
 5 
 6     //object的类型,过滤掉原始类型如数字,字符串和布尔值
 7     var type = typeof object;
 8 
 9     if(type !== "object" && type !== "function") throw TypeError();
10 
11     //object是一个对象
12     return true;
13 }

 

  2、实现一个继承方法,返回一个子对象。

 1 function inherit(Base) {
 2 
 3     //Base是一个对象
 4     if(isObject(Base)) {
 5 
 6         //Object.create是ES5提出的一种新的对象创建方式,如果存在此方法,则直接返回结果。
 7         if(Object.create)
 8             return Object.create(Base);
 9 
10         //一个空构造函数,用于构造Sub对象
11         function Sub() {}
12 
13         //将Sub的prototype属性设置为Base,每一个JavaScript的都有这个属性
14         //Sub便"拥有"Base中的属性和方法,如果Sub还有它的自对象,那属于Sub以
15         //及Sub父对象的属性和方法也被继承下来,这就是原型链(prototype chain)
16         Sub.prototype = Base;
17 
18         //返回一个Base的子对象,即Sub
19         return new Sub();
20     }
21
22 }

  3,Eva继承自Person,其中我们通过Eva.name="Eva"给她重新取了个名字,此时程序将打印"Hello, Eva"。(Person.greeting = ...此时写在Person对象里面和外面并无区别,一会在讨论对象的大小时会谈到。)

 1 /**
 2  * Person是一个对象字面量,定义了属性name和方法greeting;
 3  * @type {{name: string, greeting}}
 4  */
 5 var Person = {name:"cnblogs"};
 6 
 7 Person.greeting = function() {
 8     console.log("Hello, " + this.name);
 9 };
10 
11 //Eva继承自Person对象,它将Person的属性和方法都继承过来
12 var Eva = inherit(Person);
13 
14 //name继承自Person,将Eva的名字重写为"Eva"
15 Eva.name = "Eva";
16 
17 //greeting继承自Person
18 Eva.greeting();

  4、更常用和高效的一种方式,此时程序将打印"Hello, John"。

 1 /**
 2  * 通过定义构造器来创建Person2类对象,定义了属性name和原型方法greeting;
 3  * 
 4  * @param name
 5  * @constructor
 6  */
 7 var Person2 = function(name) {
 8     this.name = name;
 9 };
10 
11 //"动态"给Person2添加一个greeting方法,此方法并不真正属于Person2,而
12 //属于Person2.prototype,这样就实现了给Person2及其子类对象添加方法,但
13 //并不占用多的内存空间。
14 Person2.prototype.greeting = function() {
15     console.log("Hello, " + this.name);
16 };
17 
18 var John = inherit(new Person2("John"));
19 
20 John.greeting();

  5、此时,如果我们有一个返回对象大小的函数,我们就更能明白prototype在实现继承时是怎么一回事了。

 1 /**
 2  * 返回一个对象的大小(在这里是一个对象真正占有的属性和方法的个数)
 3  * @param object
 4  * @returns {number}
 5  */
 6 function objectSize(object) {
 7 
 8     var size = 0;
 9 
10     //这里直接使用了Object的hasOwnProperty方法(注意Object是大写)
11     //Object.prototype.hasOwnProperty = function(propertyName) {};
12     var hasOwnProperty = Object.prototype.hasOwnProperty;
13 
14     //循环遍历object中的所有能"访问"的属性和方法
15     //注意能"访问"并不等于拥有
16     for(var key in object) {
17 
18         //将hasOwnProperty函数绑定到object(this)上进行调用
19         //Function.prototype.call = function(thisArg,args) {};
20         if(hasOwnProperty.call(object, key)) {
21 
22             size++;
23 
24         }
25     }
26     //返回真正属于object的属性和方法个数
27     return size;
28 }

  6、所以在实际编程中,往往只将属性写在对象内部,而使用prototype添加各种方法给本对象和子对象使用,但是这些方法在内存中只有一份!(是不是联想到静态成员函数?)

 1 //继承(通过prototype添加)来的不属于我!!
 2 
 3 //程序将打印"2",Person真正拥有name和greeting
 4 console.log("Person size: " + objectSize(Person));
 5 
 6 //程序将打印"1",Eva真正拥有的是重写name属性,如果不重写,将打印"0"
 7 console.log("Eva size: " + objectSize(Eva));
 8 
 9 //程序将打印"1",Person2真正拥有的只是name属性
10 console.log("Person2 size: " + objectSize(new Person2("John")));
11 
12 //程序将打印"0",John啥都没有,都是从"别人"借过来的
13 console.log("John size: " + objectSize(John));

 

 未完待续...

 

posted @ 2016-03-22 21:52  cdefgab1011  阅读(245)  评论(0编辑  收藏  举报