原型与原型链
# 原型与原型链关系
prototype
:原型;
__proto__
:原型链(内置对象),实际上是原型的链接点;
从属关系:
prototype
:从属于函数,函数的一个属性;平时说的函数的原型,实际上就是函数的prototype属性,它本身是一个对象;
__proto__
: 从属于对象,对象Object的一个属性,本身也是一个对象。
对象的__proto__保存着该对象的构造函数的prototype。
# 实例证明两者关系
声明一个函数,来验证函数是否有prototype属性:
function Test() {}
console.log(Test.prototype)
2
打印结果:
{constructor: ƒ}
constructor: ƒ Test()
__proto__: Object
2
3
说明函数只要构造出来,便存在prototype属性;同时prototype也是一个对象,因此存在__proto__属性;
现在利用函数和关键字new 构造出一个对象实例,判断是否存在__proto__属性:
const test = new Test()
console.log(test.__proto__)
2
打印结果:
{constructor: ƒ}
constructor: ƒ Test()
__proto__: Object
2
3
说明对象创建时便存在__proto__属性;
console.log(test.__proto__ === Test.prototype) //true
验证了对象的__proto__属性保存了该对象的构造函数的prototype。
由于函数的prototype属性本身也是对象,因此也存在__proto__属性,在上面已经验证过,继续研究该__proto__属性是否有保存prototype,以及是谁的:
console.log(Test.prototype.__proto__);
打印结果:
{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
constructor: ƒ Object()
hasOwnProperty: ƒ hasOwnProperty()
...
2
3
4
根据打印的结果可以看出,对于的是构造函数Object的prototype,通过如下打印结果验证:
console.log(Test.prototype.__proto__ === Object.prototype); // true
但是通过__proto__走到Obejct后,实际上已经走到了最顶层,Object.prototype是最顶层了,该原型上不存在__proto__属性了:
console.log(Object.prototype.__proto__) //null
# 原型与原型链继承
function Test() {
this.a = 1;
}
Test.prototype.b = 2;
Object.prototype.c = 3
const test = new Test();
console.log(test);
2
3
4
5
6
7
8
9
10
11
打印结果:
Test {a: 1}
a: 1
__proto__:
b: 2
constructor: ƒ Test()
__proto__:
c: 3
...
2
3
4
5
6
7
8
原型链本质上是:以一个对象为基准,以__proto__为链接,一直到Object.prototype为止这个链,称为原型链。
继承的体现:能打印出b、c,他们不在构造函数里面,如果在构造函数中没有,就去原型链__proto__上去继承,直到Object.prototype,这就是原型链继承。
console.log(test.a); //1
console.log(test.b); //2
console.log(test.c); //3
2
3
# Function 和 Object 的特殊性
FUnction 和 Object 是函数也是对象。
之前将Test()看做函数来考虑的,但它同时也是对象,因此也存在__proto__属性:
console.log(Test.__proto__); //ƒ () { [native code] }
console.log(Test.__proto__ === Function.prototype); //true
2
打印结果显示该属性为函数,并且与等同于Function.prototype,即表示Test()是由Function构造出来的。(const Test = new Function())
同时Function也是函数,因此也有__proto__ 和 prototype,这里需要注意,在底层规定两者是相等的:
console.log(Function.prototype === Function.__proto__); //true
同时对于Object除了是对象外,也是函数,故存在__proto__属性; 当创建对象时,相对于new Object:
const obj = {} // =>等同于
const obj = new Object(); //function
2
console.log(typeof Object); //function
console.log(Object.__proto__ === Function.prototype); //true
2
可以得知Object也是由Function构造而来的;在new Object时候底层就是由Function构造而来的。
结合可以得出:Object.__proto__ === Function.__proto__
;
# 判断对象的属性是否存在
判断对象本身是否存在属性使用hasOwnProperty
方法;
console.log(test.hasOwnProperty('a')); //true
console.log(test.hasOwnProperty('b')); //true
console.log(test.hasOwnProperty('c')); //false
2
3
判断对象的整个原型链上是否存在,使用in
方法:
console.log('a' in test); //true
console.log('b' in test); //true
console.log('c' in test); //true
2
3