为什么用继承,而不用原型链?原型链的话,比较好理解,而“继承”是面向对象中经常见到的一个概念,但是为什么用继承,主要就是为了区分它们之间的不同。
javascript中的继承是通过原型链来体现的,例如下面的代码:
function Foo(){
this.name = "oyakuki";
this.age = 20;
}
var fn = new Foo();
fn.name = "jim";
console.log(fn.name); //jim
console.log(fn.age); //20
以上代码中,fn是Foo函数new出来的对象,fn.name是fn对象的基本属性,fn.age是怎么来的呢?——从Foo.prototype得来,因为fn.proto指向的是Foo.prototype。
访问一个对象的属性时,先在基本属性中查找,如果没有,再沿着proto这条链向上找,这就是原型链。
如下图演示的那样:
上图中,访问f1.b时,f1的基本属性中没有b,于是沿着proto找到了Foo.prototype.b。
那么在实际工作中我们怎样能区分出到底是本身的属性还是继承而来的属性呢?
可以用hasOwnProperty()这个方法;
function Foo(){};
var fn = new Foo();
fn.name = "jim";
Foo.prototype.name = "oyakuki";
Foo.prototype.age = "20";
var item;
for(item in fn){
if(fn.hasOwnProperty(item)){
console.log(item); //name
}
}
fn的这个hasOwnProperty方法是从哪里来的? fn本身没有,Foo.prototype中也没有,哪儿来的?
它是从Object.prototype中来的,请看图:
对象的原型链是沿着proto这条线走的,因此在查找fn.hasOwnProperty属性时,就会顺着原型链一直查找到Object.prototype。
由于所有的对象的原型链都会找到Object.prototype,因此所有的对象都会有Object.prototype的方法。这就是所谓的“继承”。
说一个函数的例子吧。
我们都知道每个函数都有call,apply方法,都有length,arguments,caller等属性。为什么每个函数都有?这肯定是“继承”的。函数由Function函数创建,因此继承的Function.prototype中的方法。不信可以请微软的Visual Studio老师给我们验证一下:
看到了吧,有call、length等这些属性。
那怎么还有hasOwnProperty呢?——那是Function.prototype继承自Object.prototype的方法。