JS构造函数与原型

来源:互联网 发布:淘宝页尾怎么装修 编辑:程序博客网 时间:2024/05/18 16:37

JavaScript中定义"类"的时候可以通过构造函数和原型的方式来实现,它们之间有何区别和利弊呢?

首先来看一个通过构造函数实现类定义的例子:

[javascript] view plaincopy
  1. function Car(color,model,drivers){  
  2.     this.color=color;  
  3.     this.model=model;  
  4.     this.drivers=drivers;  
  5.       
  6.     this.blar = function(){  
  7.         alert("I am a car: " + model + " in " + color + ". " + drivers + " can drive me" );  
  8.     }  
  9. }  
  10.   
  11. var car1 = new Car('red','BMW',['Mike','Kevin']);  
  12. car1.blar();  
  13.   
  14. var car2 = new Car('red','BMW',['Mike','Kevin']);  
  15. car2.blar();  
在上面的例子中,每一个实例中,函数blar都会拷贝到实例中,弊端就是浪费内存。
在来看一个通过利用prototype来定义类的例子:
[javascript] view plaincopy
  1. function Drivers(){  
  2.     var names="";  
  3.     this.addDriver= function(name){  
  4.         names = names +" " + name;  
  5.     }  
  6.     this.toString = function(){  
  7.         return  names;  
  8.     }  
  9. }  
  10.   
  11.   
  12. function Car(){  
  13. }  
  14.   
  15. Car.prototype.color = "red";  
  16. Car.prototype.model = "BMW";  
  17.   
  18. //Car.prototype.drivers = ['Mike','Kevin'];  
  19.   
  20. Car.prototype.drivers =new Drivers();  
  21.   
  22. Car.prototype.blar = function(){  
  23.         alert("I am a car: " + this.model + " in " + this.color + ". " + this.drivers + " can drive me" );  
  24.     };  
  25.   
  26. var car1 = new Car();  
  27. car1.color='Blue';  
  28. //car1.drivers.push('Luios');  
  29. car1.drivers.addDriver('Mike');  
  30. car1.drivers.addDriver('Kevin');  
  31. car1.drivers.addDriver('Luios');  
  32.   
  33. car1.blar();//outputs I am a car: BMW in Blue. Mike,Kevin,Luios can drive me  
  34. var car2 = new Car();  
  35. car2.blar(); //outputs I am a car: BMW in red. Mike,Kevin,Luios can drive me  
prototype方式定义的方式,函数不会拷贝到每一个实例中,所有的实例共享prototype中的定义,节省了内存。但是属性如果是对象的话,所有实例也是共享同一个对象,
如上例中的drivers使用自定义对象或者数组的时候,如果其中某一个实例改变了其中的值,所有的实例的值都被改变。因为所有实例的属性指向的是同一个对象的引用,如果上面的例子中car2.drivers=['Ivy','Lili'];来改变实例car2的属性内容,相对于car2.drivers指向了另一个对象(这时候car2有一个实例属性,有一个prototype属性都是drivers)。
Javascript是一种动态语言,实例创建之后可以动态添加属性和方法,在“构造函数”的定义之外也可以添加属性和方法。其实,下面例子中sayHi本身也是一个全局的类型为Function的实例。
[javascript] view plaincopy
  1. var obj = {};  
  2. obj.prop="value";  
  3. obj.test = function(){  
  4.     alert("test function: " + this.prop);  
  5. }  
  6. obj.test();  
  7.   
  8. function sayHi() {  
  9.     alert("hi");  
  10. }  
  11.   
  12. sayHi.sayHello = function() {  
  13.     alert("hello");  
  14. };  
  15. sayHi.sayHello();//outputs hello  
注意如果想让添加的属性或者方法能够被实例使用,要使用prototype添加,下面的例子说明了这一点
[javascript] view plaincopy
  1. function sayHi() {  
  2.     alert("hi");  
  3. }  
  4.   
  5. sayHi.sayHello = function() {  
  6.     alert("hello");  
  7. };  
  8.   
  9. sayHi.sayHello();//outputs hello  
  10.   
  11. var osayHi = new sayHi();//outputs hi  
  12. osayHi.sayHello(); // TypeError: osayHi.sayHello is not a function  
因为不是通过在prototype中以这样的方式添加的(sayHi.prototype.sayHello),实例是不能访问sayHello方法的,只能通过sayHi.sayHello(类似如静态方法)的方式访问。同样如果添加的时候是通过prototype方式,则不能用静态方式访问。
[javascript] view plaincopy
  1. function sayHi() {  
  2.     alert("hi");  
  3. }  
  4.   
  5. sayHi.prototype.sayHello = function() {  
  6.     alert("hello");  
  7. };  
  8.   
  9. var osayHi = new sayHi();// outputs hi  
  10. osayHi.sayHello(); // outputs hello  
  11.   
  12. sayHi.sayHello(); //TypeError: sayHi.sayHello is not a function  
0 0
原创粉丝点击