欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

javascript中类的定义和继承

程序员文章站 2022-04-04 16:04:46
...

类的定义

类定义有三种基本方法,

创建并能返回特定类型的对象的函数(工厂函数),例如:function Co(){ var o = new Object; o.a = 1 return o}; 用这种方式创建对象: var o = Co()
创建构造函数,用new 实例化,例如 function Co(){this.a = 1} 用这种方式创建对象:var o = new Co()
原型方式,利用对象的prototype属性,例如 function Co(){}; Co.prototype.a = 1; 用这种方式创建对象: var o = new Co()
可灵活运用这三种方式进行组合

类的继承

类的继承有两种基本方法

对象冒充 基本原理: 构造函数使用this关键字给所有属性和方法赋值(构造函数实际上仅仅是赋值函数),所以可以利用一种方式,在类内部直接运行赋值函数,把其this关键字传递给新类。例如:


var a = function(){
	this.a = 1;
	this.b = 2;
	alert(this);
}

var b = function(){
	this.aa = a;//对a中的this进行转换,同样的方式还有
	this.aa();
	delete this.aa;  //要把这个中间方法删除掉,否则可能会在以后的操作中覆盖原来类的方法

	//或者
	a.call(this,arg1,arg2);
	//或者
	a.apply(this,[args]);
}

var ob = new b();	


原型链

基本原理:关于原型链,详见(http://www.iteye.com/topic/53537)把超类的一个实例付给子类的prototype对象,即可把超类的固定属性和方法传递给子类,要注意一点,这种方法无法在实例化时传递参数,所以一般采用混合方式进行类的继承。

prototype.js中的类定义和继承

1.6.0以前:

/** obsolete syntax **/ 
var Person = Class.create();    //通过Class.create方法创建空类
Person.prototype = {               //把方法定义到prototype中,注意,是通过initalize方法初始化类的属性
  initialize: function(name) { 
    this.name = name; 
  }, 
  say: function(message) { 
    return this.name + ': ' + message; 
  } 
}; 

var guy = new Person('Miro'); 
guy.say('hi'); 
// -> "Miro: hi" 
                                            //prototype中的继承方式:
var Pirate = Class.create();    //建立空类;
// inherit from Person class: 
Pirate.prototype = Object.extend(new Person(), {    //先实例化超类,再把超类中的方法复制到子类中去,
  // redefine the speak method                               //注意,实际上prototype类定义机制中并没有直接定义
say: function(message) {                                       //类的属性而是通过intilize方法,而且所有的方法都
    return this.name + ': ' + message + ', yarr!';      //之直接定义在prototype中,所以直接用原型链方式
  }                                                                        //继承超类的所有方法不会产生问题。
}); 

var john = new Pirate('Long John'); 
john.say('ahoy matey'); 
// -> "Long John: ahoy matey, yarr!"



来看一下Class.create方法的实现代码


var Class = {
  create: function() {
    return function() {                                          //实际上把所有的属性定义到intiliaze方法(实际上是一个类)中,
      this.initialize.apply(this, arguments);              //然后通过对象冒充方式继承该类
    }
  }
}			


可以从prototype的例子充分体会到通过对象冒充和原型链类继承的差别,一般来说属性需用对象冒充方式继承,方法需用原型链方式继承。

prototype-1.6.0以后版本:

1.6.0以后,对prototype的类进行了更多的扩展,举例:	

/** new, preferred syntax **/ 
// properties are directly passed to `create` method 
var Person = Class.create({ 
  initialize: function(name) {                       //不必定义一个空类,and定义方法的位置改变
    this.name = name; 
  }, 
  say: function(message) { 
    return this.name + ': ' + message; 
  } 
}); 

// when subclassing, specify the class you want to inherit from 
var Pirate = Class.create(Person, {            //第一个参数是class,作为超类在定义类时直接继承
  // redefine the speak method 
say: function($super, message) { 
    return $super(message) + ', yarr!'; 
  } 
}); 

var john = new Pirate('Long John'); 
john.say('ahoy matey'); 
// -> "Long John: ahoy matey, yarr!"



//声明子类时对子类的initialize进行重写

1.60以前

var Animal = Class.create(); 
Animal.prototype = { 
  initialize: function(name, sound) {                                 //超类,顶一个两个参数
    this.name = name; 
    this.sound = sound; 
  }, 	          

speak: function() { 
alert(name + " says: " + sound + "!"); 
} 
}; 

var snake = new Animal("Ringneck", "hissssssssss"); 
snake.speak(); 
// -> alerts "Ringneck says: hissssssssss!" 

var Dog = Class.create(); 

Dog.prototype = Object.extend(new Animal(), { 
initialize: function(name) { //子类,定义一个参数
this.name = name; 
this.sound = "woof"; 
} 
}); 

var fido = new Dog("Fido"); 
fido.speak(); 
// -> alerts "Fido says: woof!"	

1.60以后

var Animal = Class.create({ 
  initialize: function(name, sound) { 
    this.name = name; 
    this.sound = sound; 
  }, 
	      

speak: function() { 
alert(this.name + " says: " + this.sound + "!"); 
} 
}); 
// subclassing Animal 
var Snake = Class.create(Animal, { 
initialize: function($super, name) { //通过$super的方式调用超类的initliaze, 
$super(name, 'hissssssssss'); 
} 
}); 
var ringneck = new Snake("Ringneck"); 
ringneck.speak(); 
//-> alerts "Ringneck says: hissssssssss!" 

var rattlesnake = new Snake("Rattler"); 
rattlesnake.speak(); 
//-> alerts "Rattler says: hissssssssss!" 

// mixing-in Enumerable 
var AnimalPen = Class.create(Enumerable, { 
initialize: function() { 
var args = $A(arguments); 
if (!args.all( function(arg) { return arg instanceof Animal })) 
throw "Only animals in here!"
this.animals = args; 
}, 

// implement _each to use Enumerable methods 
_each: function(iterator) { 
return this.animals._each(iterator); 
} 
});
var snakePen = new AnimalPen(ringneck, rattlesnake); 
snakePen.invoke('speak'); 
//-> alerts "Ringneck says: hissssssssss!" 
//-> alerts "Rattler says: hissssssssss!"