javascript 之原型理解

最近一直在了解javascript原型的问题,也算是理解了一点,但愿把我所理解的,用简单的例子和说明,让更多人清除的去理解javascript原型javascript

1,原型 prototype 是一个什么东西

咱们建立的每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象。简单的说 prototype就是一个对象java

理解原型对象:浏览器

不管何时只要建立了一个新函数,就会根据一组特定的规则为该函数建立一个prototype属性,这个属性指向函数的原型对象。
建立自定义的构造函数后,原型对象默认只会取得constructor属性,至于其余方法,则都是从Object继承而来的,
当用构造函数建立一个实例后,该实例内部将包含一个指针(内部属性)__proto__,指向构造函数的原型。
经过访问对象的 __proto__ 属性,这个属性在脚本中是彻底不可见的,这个连接存在于实例与构造函数的原型对象之间,而不是存在于实例与构造函数之间。
上面的话看不懂么,不要怕,咱们一句话一句话来验证。

下面开始跟着我来清除的看到原型prototype 这个东西,在浏览器的控制台,输入下面的代码(若是你连控制台都不知道,就别玩了)函数

function A(){
		this.name = "xiami";
	}

来看看咱们的prototype属性, 在控制台输入下面的代码 (图片是返回的结果表示)this

A.prototype

看看这个原型对象有什么spa

默认的它有一个constructor属性,指向咱们的构造函数prototype

如今咱们看看这个函数实例化以后,它的原型还在不在?设计

a = new A();

 如今 a 是A函数的实例,若是咱们给我如今给A函数原型中添加name属性为1,那么我在 a对象中能看到么?3d

A.prototype.name = 1;

而后输入a.name ,发现结果是1,怎么这么神奇,在实例化以后,给构造函数的原型添加属性,还能被对象访问到。这种方法不推介使用,w3c的说法是不容易被跟踪,具体的状况我也没遇到过,那么它是怎么实现的呢?咱们再来看看上面的这句话指针

当用构造函数建立一个实例后,该实例内部将包含一个指针(内部属性)__proto__,指向构造函数的原型。这个属性不必定是 __proto__ ,可是这个指针必定是存在的,我在火狐浏览器发现 是用 __proto__ 属性,这个时候咱们能够使用 a.__proto__  查看咱们A的原型对象了,是真的么?

点击箭头指向的地方,以下图

是否是和咱们以前 看到的原型对象如出一辙,是否是理解了上面的那句话,这也是在实例化后,添加原型属性,在对象中也能访问的缘由么?

上面的name 是刚才 给构造函数A的原型对象添加的name属性,这也说明了它们指向的是同一个原型

下面是最初始化的一个状态,只要函数存在、对象存在,这个属性或指针就是存在的(下面的constructor 属性值为 A()指向构造函数 ,画图的时候忘记写了)

给原型对象添加 name属性后(下面的constructor 属性值为 A() 指向构造函数,画图的时候忘记写了)

原本觉得有好多要写的,这个文章写了好几回了,可能理解不是很深,忽然发现没有什么要写的了,准备准备再接着写

2,原型链和继承

原型链的基本思想是利用原型让一个引用类型继承另外一个引用类型的属性和方法。

回顾上面说的,构造函数、原型 和 实例(对象) 的关系,每一个构造函数都有一个原型对象,原型对象包含一个指向构造函数的指针(constructor 你还记得么),而实例都包含一个指向原型对象的内部指针(上面说的__proto__属性)。

若是咱们让原型对象等于另外一个类型的实例,此时的原型对象将包含一个指向另外一个原型的指针(__proto__属性),相应的,另外一个原型中也包含着一个指向另外一个构造函数的指针。假如另外一个原型又是另外一个类型的实例,那么上述关系依然成立,这样层层递进,就构成了实例与原型的链条,这就是所谓原型链的基本概念。

上面这句话是否是很绕,那么下面就让咱们来用例子理解它:

     function SuperType(){
		this.property = true;
	}
	// 给 SuperType 原型添加方法
	SuperType.prototype.getSuperValue = function(){
		return this.property;
	}

	function SubType(){
		this.subproperty = false;
	}

	// 重写SubType原型
	SubType.prototype = new SuperType();
	// 给Subtype 原型添加方法
	SubType.prototype.getSubValue = function(){
		return this.subproperty;
	}

	// 实例化 SubType
	var instance = new SubType();
	console.log(instance.getSuperValue());	// 结果是 true

 首先咱们建立SuperType函数,函数内有一个属性,给SuperType原型添加方法

分析:默认建立函数,就会为该函数建立一个 prototype对象,prototype对象中有一个constructor 属性 指向构造函数 SuperType()

而后,咱们建立SubType函数,函数内有一个属性,重写SubType原型对象,将SuperType 的实例 赋给 SubType的原型对象

分析:建立SubType函数也会为它建立一个 prototype对象,可是这里用SuperType的实例 给重写了,那么重写后变成什么了呢?

既然被重写了,那它里面的constructor属性 确定没有了,被代替的是 SuperType实例的属性值(包括方法),那么这些属性值是什么呢?

还记得前面说过的当函数建立一个实例后,该实例会包含一个内部指针,指向构造函数的原型

最后得知SubType的原型对象的值包括:SuperType实例的属性值,SuperType的原型值,SuperType的原型

 

参考:

javascript高级程序设计第三版,第6章,面向对象的程序设计

相关文章
相关标签/搜索