javascript学习笔记(五)原型和原型链详解(2)

使用原型的好处是可以让对象实例共享它所包含的属性和方法。也就是说,不必在构造函数中添加定义对象信息,而是可以直接将这些信息添加到原型中。使用构造函数的主要问题就是每个方法都要在每个实例中创建一遍。

在JavaScript中,一共有两种类型的值,原始值和对象值。每个对象都有一个内部属性 prototype ,我们通常称之为原型。原型的值可以是一个对象,也可以是null。如果它的值是一个对象,则这个对象也一定有自己的原型。这样就形成了一条线性的链,我们称之为原型链。

含义

函数可以用来作为构造函数来使用。另外只有函数才有prototype属性并且可以访问到,但是对象实例不具有该属性,只有一个内部的不可访问的__proto__属性。__proto__是对象中一个指向相关原型的神秘链接。按照标准,__proto__是不对外公开的,也就是说是个私有属性,但是Firefox的引擎将他暴露了出来成为了一个共有的属性,我们可以对外访问和设置。

复制代码 代码如下:


<script type="text/javascript">
    var Browser = function(){};
    Browser.prototype.run = function(){
        alert("I'm Gecko,a kernel of firefox");
    }

var Bro = new Browser();
    Bro.run();
</script>

当我们调用Bro.run()方法时,由于Bro中没有这个方法,所以,他就会去他的__proto__中去找,也就是Browser.prototype,所以最终执行了该run()方法。(在这里,函数首字母大写的都代表构造函数,以用来区分普通函数)

当调用构造函数创建一个实例的时候,实例内部将包含一个内部指针(__proto__)指向构造函数的prototype,这个连接存在于实例和构造函数的prototype之间,而不是实例与构造函数之间。

复制代码 代码如下:


<script type="text/javascript">
function Person(name){
                this.name=name;
            }

Person.prototype.printName=function(){
                alert(this.name);
            }

var person1=new Person('Byron');
            var person2=new Person('Frank');
</script>

Person的实例person1中包含了name属性,同时自动生成一个__proto__属性,该属性指向Person的prototype,可以访问到prototype内定义的printName方法,大概就是这个样子的:

javascript学习笔记(五)原型和原型链详解

再举个栗子:

复制代码 代码如下:


<script type="text/javascript">
    function Animal(name)   //积累构造函数
    {
        this.name = name;//设置对象属性
    }

Animal.prototype.behavior = function() //给基类构造函数的prototype添加behavior方法
    { 
        alert("this is a "+this.name);
    }

var Dog = new Animal("dog");//创建Dog对象
    var Cat = new Animal("cat");//创建Cat对象

Dog.behavior();//通过Dog对象直接调用behavior方法
    Cat.behavior();//output "this is a cat"

alert(Dog.behavior==Cat.behavior);//output true;
</script>

可以从程序运行结果看出,构造函数的prototype上定义的方法确实可以通过对象直接调用到,而且代码是共享的。(可以试一下将Animal.prototype.behavior 中的prototype属性去掉,看看还能不能运行。)在这里,prototype属性指向Animal对象。

数组对象实例

再看个数组对象的实例。当我们创建出array1这个对象的时候,array1实际在Javascript引擎中的对象模型如下:

复制代码 代码如下:


var array1 = [1,2,3];

javascript学习笔记(五)原型和原型链详解

array1对象具有一个length属性值为3,但是我们可以通过如下的方法来为array1增加元素:

array1.push(4);
push这个方法来自于array1的__proto__成员指向对象的一个方法(Array.prototye.push())。正是因为所有的数组对象(通过[]来创建的)都包含有一个指向同一个具有push,reverse等方法对象(Array.prototype)的__proto__成员,才使得这些数组对象可以使用push,reverse等方法。

函数对象实例

复制代码 代码如下:


function Base() { 
    this.id = "base"
}  

javascript学习笔记(五)原型和原型链详解

复制代码 代码如下:


var obj = new Base();

这样代码的结果是什么,我们在Javascript引擎中看到的对象模型是:

javascript学习笔记(五)原型和原型链详解

new操作符具体干了什么呢?其实很简单,就干了三件事情。

复制代码 代码如下:


var obj  = {}; 
obj.__proto__ = Base.prototype; 
Base.call(obj);

原型链

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wgsjdf.html