1、名称对应
prototype
:原型
__proto__
:原型链(链接点)
2、从属关系
prototype
:是函数的一个属性,它的类型是对象{}
。
__proto__
:是对象Object的一个属性,它的类型也是对象{}
。
对象的__proto__
保存着该对象的构造函数的prototype
。
一个函数的原型的__proto__
全等于Object.prototype
。
原型链的最顶层是Object.prototype
。
3、实例验证从属关系
3.1、有一个函数Test()
function Test(){}
由于函数都有prototype
属性:
console.log(Test.prototype);//构造函数Test()有prototype属性
得到输出结果:

3.2、实例化Test()
函数的对象
let test = new Test();
实例化test
对象,由于对象都有__proto__
属性:
console.log(test.__proto__);//由构造函数Test()构造出来的对象有__proto__属性
得到输出结果如下:

由于对象的__proto__
保存着该对象的构造函数的prototype
,那么构造方法的prototype
应该完全等于对象的__proto__
:
console.log(Test.prototype === test.__proto__);//true
得到如下输出结果:

由于一个函数的原型的__proto__
全等于Object.prototype
:
console.log(Test.prototype.__proto__ === Object.prototype);//true
得到输出结果:

由于原型链的最顶层是Object.prototype
,所以Object.prototype
不会再有__proto__
:
console.log(Object.prototype.__proto__);//null
得到输出结果:

4、原型链继承
在Test()
构造函数中新增属性"a:1"、在Test()方法的原型上新增"b:2"、在Object的原型上新增"c:3":
function Test(){
this.a = 1;//构造方法中新增属性a
}
Test.prototype.b = 2;//构造方法的原型上新增属性b
Object.prototype.c = 3;//在Object的原型上新增属性c
let test = new Test();
console.log(test);
输出结果:

输出这三个新增的属性:
console.log(test.a);
console.log(test.b);
console.log(test.c);
结果:

这个原型链的结构如下:
test:{
a:1,
__proto__:Test.prototype = {
b:2
__proto__:Object.prototype = {
c:3
}
}
}
以一个对象为基准,以
__proto__
为链接,一直到Object.prototype
为止的这个链叫做原型链。
如上面的例子:在自己的这个对象test中没有找到属性b就会沿着原型链继续向上找,直到在Test.prototype
上找到属性b;c属性也是一样,在对象自身和Test.prototype
都没有找到,继续向上找最终在Object.prototype
中找到属性c;这就是原型继承;也就是为什么test.b
和test.c
能够输出正确的值的原因。

在任意一层找到了目标属性,都不会再继续向上一层查找,例如:在test对象本身有属性b,
Test.prototype
上也有属性b。此时访问test.b
返回的是test对象本身的属性b,而不是Test.prototype
上的属性b。
5、Object和Function的特殊性
Object和Function既是函数又是对象。
5.1、Function
以下的Test方法其底层的构造方法是Function
即:const Test = new Function();
function Test(){
this.a = 1;
}
Test
既是对象又是函数,那么Test
就有__proto__
属性;Function
是它的构造函数,因此Function
就有原型prototype
,并且Test.__proto__
保存的就是Function.prototype
。
因此:
console.log(Test.__proto__=== Function.prototype);
输出:true
。
Function既是函数又是对象,那么Function
也有__proto__
和prototype
。
输出:
console.log(Function.__proto__);
console.log(Function.prototype);
结果:

验证它们是否相等:
console.log(Function.__proto__=== Function.prototype);
输出:true
,说明它们完全相等。
结论:Function的
__proto__
本身就指向它自己的prototype
。
5.2、Object
Object既是对象又是函数。说明Object本质上也是由Function构造的。
因此:
console.log(Object.__proto__ === Function.prototype);//true
又因为Function的__proto__
指向它自己的prototype
,所以:
console.log(Object.__proto__ === Function.__proto__);//true
6、判断对象中某个属性是否存在的方法
6.1、判断对象中是否存在某个属性
obj.hasOwnProperty('属性名')
方法用来判断对象中是否存在某个属性,该方法返回一个布尔值,属性存在返回true,不存在返回false。
console.log(test.hasOwnProperty('a'));//true
console.log(test.hasOwnProperty('b'));//false,因为b属性在Test.prototype上
console.log(test.hasOwnProperty('c'));//false,因为c属性在Object.prototype上
6.2、判断对象原型链上是否存在某个属性
console.log('a' in test);//true
console.log('b' in test);//true 自Test.prototype上继承而来
console.log('c' in test);//true 自Object.prototype上继承而来
7、constructor与实例直接的关系和特性
7.1、constructor属性
输出constructor
:
console.log(test.constructor);
结果:

说明contrustor
就是实例化对象的构造函数。
console.log(test.constructor === Test)//true
7.2、对象的constructor可以被修改
function Test2(){
this.a = 222;
}
test.constructor = Test2;//原本为Test()改成Test2()
console.log(test);
