javascript中的原型探索
本文讲的是javascript中的原型,比较初级的一些理解,有写的不对的地方,欢迎指出。
原型,什么是原型
原型是一个对象,就这么简单,
每个对象都有一个属性prototype,这个prototype的属性值是一个对象,默认的,这个对象只有一个constructor的属性,这个属性指向这个对象本身。
如下图所示:
可以看到上图的关系还是很明朗的,首先,咱们有一个SuperType的对象,然后这个prototype属性指向一个对象,这个对象指向的是SuperType.Prototype,SuperType.Prototype也有一个叫constructor的属性,这个属性指向了SuperType本身。
原型是做什么用的
原型可以用来继承(待会会讲),还可以用来定义公共属性和方法,如下:
function Person(age){
this.age = age;
}
Person.prototype = {
name:'jackwen',
sayName: function(){
alert('this is sayName function');
},
sayAge: function(){
alert('my age is ' + this.age);
}
}
var p1 = new Person(12);
var p2 = new Person(23);
p1.sayName();
p2.sayName();
p1.sayAge();
p2.sayAge();
运行上面的代码,会弹出四个框,内容分别为:
this is sayName function
this is sayName function
my age is 12
my age is 23
ok,很简单,不做多余的解释,没接触过原型的,就不要说是玩js的,因为你肯定是个js的入门者。
原型链是什么
当从一个对象那里调取属性或方法时,如果该对象自身不存在这样的属性或方法,就会去自己关联的prototype对象那里寻找,如果prototype没有,就会去prototype关联的前辈prototype那里寻找,如果再没有则继续查找Prototype.Prototype引用的对象,依次类推,直到Prototype.….Prototype为undefined(Object的Prototype就是undefined)从而形成了所谓的“原型链”。
用原型链来实现继承
1、基本继承。咱们看下面的代码:
function Person(){
this.name = 'jackwen';
}
Person.prototype = {
sayName: function(){
console.log('my name is ' + this.name);
}
}
function Student(){
this.age = 23;
}
Student.prototype = new Person();
var stu = new Student();
stu.sayName();
stu.sayAge();
大家应该可以想到,输出为:my name is jackwen
那么,咱们也就看到了Student原来是没有sayName这个函数的,那么,就会到Student.prototype去找,在Person中找,还是没有找到,就去到Person.prototype中找,找到了就输出了,但是,在查找sayAge的过程中,在Person.prototype中都没有找到,所以就报了错咯。
2、借用构造函数继承
看下面代码:
var Person = function(name){
this.name = name || 'person' ;
} ;
Person.prototype.getName = function(){
return this.name ;
} ;
var Student = function(name){
Person.apply(this,arguments) ;
} ;
Student.prototype = Person.prototype ;
var person = new Person('person') ;
var student = new Student('student') ;
console.log(person.getName()) ;
console.log(student.getName()) ;
上面的方法,是在子类创建的时候,运行一下父类,这样就可以调用父类的构造函数来进行子类的初始化工作,然后把父类原型中的所有东西都给了子类的原型,ok,继承搞定。
3、临时构造函数模式
看下面代码:
var Person = function(name){
this.name = name || 'Person' ;
} ;
Person.prototype.getName = function(){
return this.name ;
} ;
Person.prototype.obj = {a : 1} ;
var Student = function(name){
Person.apply(this,arguments) ;
} ;
var F = new Function();
F.prototype = Person.prototype ;
Student.prototype = new F() ;
var person = new Person('Person') ;
var student = new Student('Student') ;
console.log(student.obj.a) ; //1
console.log(person.obj.a) ; //1
student.obj.a = 2 ;
console.log(student.obj.a) ; //2
console.log(person.obj.a) ; //2
ok,看到上面的代码,其实咱们已经实现了继承,但是有一个问题需要注意的是,在原型对象中,如果有属性不是函数的话,子类对属性的改变会影响父类的改变,但是如果原型对象中的属性全部都是函数的话,就是没有问题的咯。