JavaScript 函数、原型和原型链详解

原型和原型链详解

一、JS函数的四种含义:

首先执行一段代码:

function Fun() {};

var fun1= new Fun(); console.log(fun1 instanceof Fun);

//其执行结果为true;说明JavaScript里面确实存在着类与对象(fun1为对象,Fun为类)。

fun1.prototype  //undefined;

Fun.prototype  //Object{...};

我们可以得到一些结论:

结论一:函数的两个身份一个是函数一个是类,可以利用函数来创建这个函数所对应这个类的对象。

结论二:可以通过看是否拥有prototype属性判断是类还是对象;

再去执行这段代码:我们知道new 的过程有三件事:1.申请空间,2.初始化(js不存在,仅仅申请空间),3.构造方法

function Fun () {
    this.mem = 10;
    console.log(this);
}
var fun1 = new Fun;

执行结果如下:

扫描二维码关注公众号,回复: 11349032 查看本文章

可以看到this的内容已经被输出了,则可以的到一下结论:

结论三:任何一个函数,作为类new一下,该函数该类的构造方法就是该函数本身;

结论四:函数其本身就是一个对象(可以从图中看出是Object{...};

还有一个额外的结论:

console.log("Fun.prototype.constructor === Fun", Fun.prototype.constructor === Fun);//结果为true

console.log("fun1.__proto__.constructor === Fun", fun1.__proto__.constructor === Fun);

结论:实例对象有隐含的属性__proto__中的constructor,指向它构造函数(Fun)即函数本身。

最后函数四种含义概括为:函数、对象、类、构造。

二、原型和原型链

(小编在里面说的原型即代码里的prototype,原型链即<prototype>或者__proto__);

执行这段代码:

function Point (row, col) {
	this.setRow = function (row) {
		this.row =  row ? row : 1; 
	}
	this.setCol = function (col) {
		this.col =  col ? col : 1; 
	}
	this.getRow = function () {
		return this.row;
	}
	this.getCol = function () {
		return this.col;
	}
	this.toString = function () {
		return this.row + "," + this.col;
	}

	this.setRow(row);
	this.setCol(col);
}

var point1 = new Point(2, 3);
console.log("point1 : ", point1);
console.log("Point : ", Point);
console.log("point1 instanceof Point : ", point1 instanceof Point);
console.log("point1.__proto__ : ", point1.__proto__);
console.log("Point.prototype : ", Point.prototype);
console.log("point1.__proto__ === Point.prototype : ", point1.__proto__ === Point.prototype);

结果如下:

point1是Point的一个实例对象:其包含一个<protoType>属性,从黑框可以看出,其就是其隐藏的__proto__属性。我们把这个属性称为原型链,而仅仅只有类才拥有绿色框所显示的prototype属性:我们称之为原型。而从图黑框中我们可以看出,原型链应该指向原型而非类本身。原型链说明的是它的类型身份,即例如:A instanceof B 与否。

总结这张图我们可以知道如下结论:

  1. 对象拥有原型链而类(函数,对象)拥有原型链<prototype>和原型prototype;
  2. 原型链说明的是这个对象的类型身份(通俗来讲就是它的爸爸是哪个);
  3. 原型链应该指向的是原型对象而非类本身。

至此,我们可以得到这样一个图:


console.log("Function:", Function);
console.log("Function.prototype === Point.__proto__:", Function.prototype === Point.__proto__);
console.log("Point instanceof Function:", Point instanceof Function);

console.log("Function.prototype === Function.__proto__:", Function.prototype === Function.__proto__);
console.log("Function instanceof Function:", Function instanceof Function);

再去执行这段代码:执行结果为:

  1.  Function是系统给的一个类,我们从上面蓝色框看到Point类的原型链指向的是Function的原型对象,也就是说,Function是Point的父类。
  2. 从绿色框看出,Function的原型链指向的是Function自己的原型对象,也就是说Function的父类就是自己。
  3. 我们可以看到每个类都有一个原型,我们常说的原型对象应该是它的一个实例级原型实例(原型对象)。它们都有原型链(<property>),应该指向的是统一类型即,此时均指向Object类的原型对象。即但我们看到红色框就是Function的原型对象,黑色框就是它们应该都有的原型对象的原型链。

此时我们得到的关系图如下

接下来,就让我们去探究一下这个<prototype> : Object{...};

console.log("Object:", Object);
console.log("Object.__proto__ === Function.prototype:", Object.__proto__ === Function.prototype);
console.log("Object.prototype.__proto__ === Object.prototype:", Object.prototype.__proto__ === Object.prototype);
console.log("Object.prototype.__proto__:", Object.prototype.__proto__);

console.log("Object instanceof Function:", Object instanceof Function);
console.log("Object instanceof Object:", Object instanceof Object);
console.log("Function instanceof Object:", Function instanceof Object);

从紫色框可以看出Object类的原型链指向Function的原型对象,但是此时我们的Object类的原型对象的原型链指向哪里呢,是否指向自己的原型对象呢? 从蓝色框的可以看出它的原型对象的原型链并不指向自己的的原型。

此时我们才真正知道它并没有指向了,是尽头。

此时我们得到如图:

此时我们终于看清了他们之间的关系,是不是有一些些的神奇呢,当时小编感受是:当我们追溯到根源时,要么什么都没有(Null)要么就是一个圈,进得去出不来。(Function 和Object)。 

下面,发现画的太丑了,找了一张更为清晰的图:

猜你喜欢

转载自blog.csdn.net/baidu_41922630/article/details/102638071