首页 > 代码库 > Javascript中的原型链

Javascript中的原型链

说到原型链,首先得说一下对象。

在javascript中我们经常说“一切皆为对象”,而对象又是属性的集合,但并不是所有的类型都是对象,undefined, number, string, boolean都属于简单的值类型,不是对象。我们所说的可以作为对象的有:数组、函数、对象、Null、New Number()。

所以函数是一种对象,但是一切对象又是函数创建的,有人可能会说不对啊,例如下面这种的,obj是对象,但是并没有函数啊。

var obj = { a: 10, b: 20 }; 

其实上面的对象创建是一种简写,其代码本质是

var obj = new Object();
obj.a = 10;
obj.b = 20;

Object()就是一个函数。

所以对象和函数到底是一个什么关系呢?要想弄清楚这两个的关系,就必须搞懂prototype原型

prototype是每个函数中都有的属性,是js默认给函数的一个属性,而且他的属性值也是一个对象,有一个默认的属性叫constructor,指向函数本身。既然原型是一个对象,我们就可以自定义原型属性

function F(){ }; //创建一个F的函数
F.prototype.name = "Ann";//给F函数创建一个原型属性
F.prototype.year = function(){
              return 18;    
}
var f = new F();//利用函数F()new一个对象f
console.log(f.name);
console.log(f.year());

其实f对象有一个隐藏的属性——“__proto__”,这个属性引用了创建这个对象的函数F的prototype。即:f.__proto__ === F.prototype

那下面就来说一说__proto__是个什么玩意

上文说到每个函数都有prototype即原型,而__proto__是每个对象都有的,称为隐式原型。

每个对象的__proto__指向创建该对象的函数的prototype,可以用下图表示。

技术分享

但是上图中的Object.prototype也是对象,它的prototype却很特殊,指向的是null。

另外我们说函数也是对象,函数的__proto__指向谁呢?从下图可以看出f1和f2是Foo创建出来的两个对象,他们的__proto__指向创建该对象的函数的原型Foo.prototype,而Foo.prototype也是对象,因此Foo.prototype的__proto__指向创建它的Object函数的原型。另外Foo的作为函数时,原型指向Foo.prototype,原型中的属性constructor指向函数本身。当funtion Foo()作为对象时,该对象的__proto__指向创建Foo的函数的原型,而函数都是由Function创建的,因此,自定义函数Foo()的__proto__指向Function的原型,而Function原型的属性constructor又指向函数Function。感觉被绕晕了。。。

技术分享

 

理解了prototype和__proto__之后就要引出javascript中的继承了。。。。

javascript中的继承是通过原型链来完成的。先看个例子

function F(){};
F.a = 1;
F.prototype.a = 2;
F.prototype.b = 3;
var f = new F();
console.log(f.a);//1
console.log(f.b);//3

f是函数F创建的对象,访问属性时先访问基本属性,这里的F.a=1就是基本属性,如果没有基本属性,就顺着__proto__找,f.b没有基本属性,因此沿着找到了F,prototype,中的

F.prototype.b = 3;这就是所谓的原型链。

Javascript中的原型链