天天看点

javascript之原型和原型链

原型的好处可以让所有对象实例共享它所包含的属性和方法。为了理解原型,需要先理解对象的概念

1. js中有两种对象,分别是函数对象和普通对象。

var fun1    = function(){}
console.log(typeof fun1);   #function
var fun2    = new Function('myfunc','console.log(test);');
console.log(typeof fun2);  #function
console.log(typeof Object); #function
console.log(typeof Function); #function

function f1(){}
 var obj1 = new f1();
 console.log(typeof obj1);   #$object
 var obj2 =new Object();
 console.log(typeof obj2);   #$object
 var obj3 = new f1();
 console.log(typeof obj3);   #$object
           

在上面的例子中 obj1 obj2 obj3 为普通对象,func1 func2 为函数对象。怎么区分,其实很简单,凡是通过new Function()创建的对象都是函数对象,其他的都是普通对象。func1归根结底是通过 new Function()的方式进行创建的。Function Object 也都是通过 New Function()创建的。

2. 所有的函数对象都有prototype属性和

__proto__

属性,所有的普通对象都没有prototype属性,prototype属性指向的对象称为原型对象,

__proto__

用于指向创建它的函数对象的原型对象。在原型对象中有一个constructor属性,用来指向它的函数对象

var car = function(){
    this.name   = "i'm a car";
}
car.prototype.say = function()
{
    return this.name;
}
var carObject   = new car();
console.log(carObject.say());
           

上例中,car是一个函数对象,car的prototype属性指向它的原型对象,car的原型对象中有一个constructor属性指向car这个函数对象。carObject是car的一个实例,他有一个

__proto__

属性,此属性指向car的原型对象,同样的car的原型对象也有

__proto__

属性,指向创建它的函数对象Object的prototype,Object.prototype对象也有

__proto__

属性,但它比较特殊,为null,至此由car到null即构成了原型链

一般的原型对象是普通对象,但是Function的原型对象是函数对象,这是一个特例,虽然它是函数对象,但他没有prototype属性,

function f1(){};
 console.log(f1.prototype) //f1{}
 console.log(typeof f1. prototype) //Object
 console.log(typeof Function.prototype) // Function,这个特殊
 console.log(typeof Object.prototype) // Object
 console.log(typeof Function.prototype.prototype) //undefined
           

从这句console.log(f1.prototype) //f1 {} 的输出就结果可以看出,f1.prototype就是f1的一个实例对象。就是在f1创建的时候,创建了一个它的实例对象并赋值给它的prototype,基本过程如下:

var temp = new f1();
 f1. prototype = temp;
           

所以,Function.prototype为什么是函数对象就迎刃而解了,上文提到凡是new Function ()产生的对象都是函数对象,所以temp1是函数对象。

var temp1 = new Function ();
     Function.prototype = temp1;
           

4.js中常用的继承方式:组合继承

function Box(name) {
this.name = name;
this.arr = ['哥哥','妹妹','父母'];
}
Box.prototype.run = function () {
return this.name;
};
function Desk(name, age) {
Box.call(this, name); //第二次调用Box
this.age = age;
}
Desk.prototype = new Box(); //第一次调用Box
           

继续阅读