跳转到主要内容

主页内容

JavaScript原型prototype和原型链__proto__

由 webadmin 发布于 阅读 48 次
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上找到属性bc属性也是一样,在对象自身和Test.prototype都没有找到,继续向上找最终在Object.prototype中找到属性c;这就是原型继承;也就是为什么test.btest.c能够输出正确的值的原因。

在任意一层找到了目标属性,都不会再继续向上一层查找,例如:在test对象本身有属性bTest.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);