constructor属性、__proto__属性、prototype属性、原型链
1、明确js的规则
(1)在js中,万物皆对象(变量、自定义函数、系统函数等等);
(2)__proto__
和constructor
是对象一定具有的属性;
(3)而prototype
是函数独有的属性,普通对象是没有的(这里将函数认为成一种特殊的对象);
为什么以上三点是这样定义的,我也不知道为什么,这就是js中的基本规则,就像数学中的1+1=2,没有为什么,1+1就是等于2,甲鱼的臀部- - -龟腚(规定)。
2、普通对象、函数
在这里,我将用户自己声明的变量称之为普通对象;
将用户自定义的函数和js原生提供的Array、Number等函数称之为函数(本身人家也叫函数);
请注意,无论是普通对象还是函数,它都是对象
3、constructor属性
它是对象必有的属性,因此普通对象和函数都具有constructor
属性
该属性指向(等于)构造此对象的函数。
记住这里,这个属性指向一个函数!!!!也可以说,这个属性就是一个函数
这里要说明的一点是,函数的构造函数都是系统函数中的Function
函数,注意这里的F是大写,可不是小写的
4、__proto__属性
它是对象必有的属性,因此普通对象和函数都具有__proto__
属性
本篇文章的最重要的一句话
一个对象的__proto__
属性总是指向其构造函数的prototype
。怎么去寻找一个对象的构造函数呢?该对象的构造函数就是第3点中constructor
属性所指的函数!所以要理解这句话,首先你得弄清楚constructor
5、prototype属性
它是函数必有的属性,普通对象没有;在第3点中我们提到,constructor
属性永远指向一个函数,那么它也有prototype
属性
prototype
属性也是一个对象,那么它也具有__proto__
属性和constructor
属性;
特别的,Object函数的prototype
属性的__proto__
属性指向(等于)null
;(这是为了原型链不闭合,即给原型链一个终点)
6、原型链
通过上面的介绍我们知道:每个对象都__proto__
属性,该属性永远指向(等于)其构造函数的prototype
属性,而prototype
属性也是对象,那它也有__proto__
属性,然后__proto__
属性又永远指向(等于)其构造函数的prototype
属性…,由此,就形成了一个链条,我们称之为原型链。
原型链有啥用呢:请看示例
function Person(name) {
this.name = name;
}
Person.prototype.sex = "男";
var b = new Person("小明");
console.log(b);
console.log(b.sex);
//结果
//Person { name: '小明' }
//男
首先我把b打印出来了,它是Person { name: '小明' }
,很明显,它没有sex
这个属性,那为什么我打印b.sex
它还会显示出来呢,js在寻找对象身上的属性时,首先会在其本身上寻找,找到了则直接返回其值;如果找不到,则沿着原型链一级一级的寻找,在某一级找到时,则直接返回,不继续寻找;一直找到原型链的终点null。
原型链是js能够实现面向对象的关键!
7、图解
仔细看看然后想一想,这里面一共有多少条原型链?
答案揭晓:一共四条:
上图原型链终点位置标错了!不是故意的,但是也不打算改了,留下一个错误也是给自己提醒
提供一下没有划线的图,大家可以自己download然后画一画,多画几遍就明白了。(最后下面这个图也自己画,这个应该没啥难度)