犀牛书学习笔记(8):理解原型和对象

前面讲到,javascript是基于原型的面向对象语言,本篇将对javascript中原型的理解,从而理解javascript如何构建对象体系。举个例子,基于类的对象和基于原型的对象构建方式区别在于:创建“人”这对象的时候,及鱼类的方式是定义人的模型,然后按照人的模型创建一个人。基于原型的方式是通过人的基因(原型)来创建一个人。

原型的由来

所有函数都有一个原型属性,当函数被定义的时候,原型自动创建和初始化,原型的初始化值是一个对象,该对象只有一个属性:constructor,该属性指向原型相关联的的构造函数。添加给原型对象的任何属性,都会被被构造函数初始化的对象的属性。对象从类实例化而来,类定义从构造函数开始,参见类定义章节的说明。

在执行操作符new的时候,构造函数的原型就被设置为构造函数的原型的值。就这样所有的对象在默认的情况下都有一个原型属性,因为原型本身也是对象,所以每个原型自身又有一个原型(只有一种例外,默认的对象原型在原型链的顶端)。一个对象的真正原型是被对象内部的[[Prototype]]属性(property)所持有。原型属性被初始化为一个对象,ECMA引入了标准对象原型访问器Object.getPrototype(object),到目前为止只有Firefox和chrome实现了此访问器。

下面的代码展示了获取对象原型的方法

var a = {}; 
Object.getPrototypeOf(a); //获取对象a的原型   
a.__proto__; //获取对象a原型的非标准方法,原型是对象的属性
a.constructor.prototype; //通过构造函数获得对象a的原型

 

如果想获取基本数据类型如int、false的原型,会自动转换为其封装对象,只有对象才具有原型。

到这里,就可以很好地理解为什么通过构造函数可以创建对象,构造函数也是函数,有一个原型属性,new一个构造函数的时候,基于构造函数的原型创建了对象实例。构造函数初始化

的对象从原型哪里继承了所有的属性和方法,因此原型是放置方法和不变属性的理想的地方。

通过下面的代码来说明原理

function A() {                           //定义构造函数a
    this.width = 10;
    this.data = [1,2,3];
    this.key = "this is A";
}

A._objectNum = 0;                        //定义A的私有属性
A.prototype.say = function(){
    alert("hello");
}                                        //给A的原型对象添加属性

var a = new A();                         //创建一个对象实例
a.say();                                 //调用方法 

 

原型链 

因为每个对象和原型都有一个原型(注:原型也是一个对象),对象的原型指向对象的父,而父的原型又指向父的父,我们把这种通过原型层层连接起来的关系撑为原型链。这条链的末端一般总是默认的对象原型。和基于类的面向对象的继承一样,原型的继承实现了基于原型的对象的继承。

对象在查找某个属性的时候,会首先遍历自身的属性,如果没有则会继续查找[[Prototype]]引用的对象,如果再没有则继续查找[[Prototype]].[[Prototype]]引用的对象,依次类推,直到[[Prototype]].….[[Prototype]]undefinedObject[[Prototype]]就是undefined)。

posted @ 2013-11-14 21:28  LaoHoo  阅读(249)  评论(0编辑  收藏  举报