浅谈JavaScript原型链
在javascript中是支持面向对象编程的,讲到面向对象(Object Oriented简称为OO)一般很容易想到继承和多态,而在javascript中呢,继承主要是靠原型链作为主要方法去实现的。其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。
来看一段代码:
function Animal(name,color){ this.name = name; this.color = color; } Animal.prototype.type = "动物"; Animal.prototype.msg = function(){ alert( "I am "+this.name+" my color is "+this.color); } var cat = new Animal("cat","black"); alert(cat.name); //cat alert(cat.color); //black
alert(cat.type); //动物
cat.msg(); //I am cat my color is black
函数Animal就是一个构造函数,对象cat是通过new Animal()产生的一个实例对象,这个cat实例对象就继承了构造函数Animal的name、color属性了,这种叫做构造函数模式
在背后是如何实现继承的呢?
这里有三个概念:构造函数(函数Animal)、原型对象(Animal.prototype)、实例对象(对象cat)
·创建的每一个函数都有一个prototype属性,这个属性是一个指针,指向了一个原型对象,原型对象就是用来包含所有实例对象共享的属性和方法
·在默认的情况下呢,原型对象会自动获得一个constructor(构造函数)属性,这个属性包含了一个指向构造函数的指针
·而通过调用构造函数产生的实例对象,它们都包含了一个指向原型对象的内部指针,叫做__proto__
简单地画了一个图方便理解:
我们去浏览器打印出来看一看,是不是如图所说那样
console.log(animal.prototype);
constructor是指向了原来的构造函数Animal,并且是包含了type属性和msg方法的
console.log(cat);
实例对象cat的__proto__是指向了原型对象的,也正是靠它实现了继承原型对象包含的属性和方法的
在这个过程中会发现一个有意思的事情,会看到原型对象里面也有个__proto__内部指针,指向的是Object对象,所有的对象最终都会通过__proto__指针指向到Object的,再回头去理解原型“链”这个概念,还是挺形象的
几种继承方式:
·组合式继承
function SuperType(){
this.friends = ['tom','jason','pual']; } function SubType(age){ SuperType.call(this); //使用call,借用sup构造函数 this.age = age; } SubType.prototype = new SuperType(); //修改sub原型对象等于super的实例
SubType.prototype.constructor = SubType; //让sub的原型对象constructor指针指向构造函数
sub var x = new SubType('20');
x.friends.push('jack');
alert(x.friends); //tom,jason,pual,jack
·原型式继承
var person = { name : 'x', age : 20, friend : ['tom','jason','pual'] } var anotherPerson = Object(person); anotherPerson.friend.push('jack'); alert(anotherPerson.friend); //tom,jason,pual,jack
·寄生组合继承
function SuperType(name){ this.name = name; } SuperType.prototype.sayName = function(){ alert('my name is ' + this.name); } function SubType(name,age){ SuperType.call(this,name); this.age = age; } function inheritPrototype(subType,superType){ var prototype = Object(superType.prototype); //新建prototype对象指向super的原型对象 prototype.constructor = subType; //修改constructor指向构造函数sub subType.prototype = prototype; //修改sub的原型对象指向prototype } inheritPrototype(SubType,SuperType); var x = new SubType('x'); alert(x.name); //x x.sayName(); //my name is x
原型链细分点展开来讲还是有许多地方可以去探讨的,这篇就先写到这吧
以上,是我对原型链的个人理解,文中如有错误,欢迎大家指正:)