JavaScript中Function原型及其prototype属性的简单应用
大家都知道在JavaScript中是没有类的概念的,但是却是有对象的概念的。有的人可能理解对象和类有些迷糊,这里简单的概括一下他们之间的区别:
类:抽象的概念,例如人,动物,汽车等都可以抽象成一个类
对象:是指这种概念中的实体,例如“一个带着红帽子的小男孩”、“一辆红色的奔驰汽车”,“一只白色的小猫”都是实体也就是对象
实例化:就是指以类为基础构建一个实体。类所拥有的特征,其实例化对象,也一定拥有这些特征,而且实例化后可能拥有更多特征。
用Java代码表示:
1 /* 2 人 3 属性: 身高 height 4 行为: 说话 speak 5 */ 6 class Person 7 { 8 private int age; 9 public void setAge(int a) 10 { 11 age = a; 12 } 13 Person() //构造函数,而且是空参数 14 { 15 this.name = name; 16 this.age = age; 17 System.out.println("name="+name+" age="+age); 18 } 19 public int getAge() 20 { 21 return age; 22 } 23 void speak() 24 { 25 System.out.println("age="+age); 26 } 27 } 28 class PersonDemo 29 { 30 public static void main(String[] args) 31 { 32 Person p = new Person("张三",25); 33 } 34 } 35 //运行结果 ==> name=张三 age=25
我们在JavaScript中用到对象时是没有类的概念的,但是程序的世界里千变万化,博大精深,这里提供一种方法,可以用function构造出一种假象类,从而实现类的构造
1 /* 2 * 这里同样使用人来构造一个类 3 */ 4 function Person(name,age) 5 { 6 this.name = name; 7 this.age = age; 8 } 9 var people = new Person("张三",25);
下面就来介绍一下Function:
Function是由function关键字定义的函数对象的原型
在javascript中,多出了一个原型的概念。所谓原型,其实就是一个对象的本质,但复杂就复杂在,原型本身也是对象,因此,任何一个对象又可以作为其他对象的原型。Function就相当于一个系统原型,可以把它理解为一种“基本对象类型”,是“对象”这个概念范畴类的基本数据类型。除了Function之外,其实还有很多类似的首字母大写的对象原型,例如Object, Array, Image等等。有一种说法是:javascript中所有的一切都是对象(除了基本数据类型,其他的一切全是对象),所有的对象都是Object衍生出来的。(按照这种说法,我们应该返回去再思考,上面说的类的假设是否成立。)
极其重要的prototype概念
prototype的概念在javascript中极其重要,它是javascript中完成上面说的“一切皆对象”的关键。有了prototype,才有了原型,有了原型,才有了javascript五彩缤纷的世界(当然,也有人说是杂乱的)。我们可以这样去理解prototype:世界上本没有javascript,上帝说要有Object,于是有了Object,可是要有Function怎么办?只需要对Object进行扩展,可是如何扩展?只需要用prototype……当然,这是乱扯的,不过在javascript中,只要是function,就一定会有一个prototype属性。实际上确实是这样
1 Function.prototype.show = function() {...}
在原型的基础上通过prototype新增属性或方法,则以该对象为原型的实例化对象中,必然存在新增的属性或方法,而且它的内容是静态不可重载的。原型之所以被称为原型,可能正是因为这种不可重载的特质。
比如上面的这段代码,会导致每一个实例化的function,都会具备一个show方法。
注意上面橙色加粗的文字,每一个实例化的function,都会具备一个show方法那我们该如何使用这个方法呢?
1 Function.prototype.show = function() 2 { 3 return "我是一个函数的新方法"; //函数需要有返回值! 4 } 5 Function.show(); //输出=>我是一个函数的新方法 6 Function; //Function的原型为 =>function Function() { [native code] } 7 var f = new Function(); 8 f.show(); //输出=>我是一个函数的新方法
而如果我们自己创建了一个类,则可以通过prototype将之转化为原型:
1 function Cat() {...} 2 Cat.prototype.run = function() {}; 3 var cat1 = new Cat();
这时,对于cat1而言,Cat就是原型,而该原型拥有一个run的原始方法,所以无论实例化多少个Cat,每一个实例化对象都有run方法,而且该方法是不能被重载的,通过cat1.run = function(){}是无效的。
为了和其他语言的类的定义方法统一,我们可以将这种原型属性在定义类的时候,写在类的构造里面:
1 function Cat() { 2 .... 3 Cat.prototype.run = function() {}; 4 }
new Function()是函数原型的一个实例化
在理解了Function原型的概念之后,再来看new Function()就显得很容易了。
1 var message = new Function('msg','alert(msg)'); 2 // 等价于: 3 function message(msg) { 4 alert(msg); 5 }
new Function(参数1,参数2,…,参数n,函数体),它的本意其实是通过实例化一个Function原型,得到一个数据类型为function的对象,也就是一个函数,而该变量就是函数名。
小结:
本文参考了 http://www.techug.com/post/utm_javascript.html 这篇文章,在笔者看到原文中说在原型的基础上通过prototype新增属性或方法,则以该对象为原型的实例化对象中,必然存在新增的属性或方法,而且它的内容是静态不可重载的这句话但是一时却不知道如何去调用新添加的方法,后来发现prototype新增方法方法里必须要有返回值,并且需要通过Function来进行调用,而且在添加show()方法后输入Function输出的结果为
1 function Function() { [native code] }