原型和原型链


原文链接:https://blog.csdn.net/qq_34645412/article/details/105997336
原文链接:https://blog.csdn.net/yucihent/article/details/79424506

一、原型

什么是原型?

原型:每一个javascript对象(除null外)创建的时候,都会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型中“继承”属性。

var obj = new Object();

创建一个对象obj的同时,会关联一个对象。它所关联的对象就是新建对象obj的原型。
在这里插入图片描述

二、prototype

在JavaScript中,每个函数都有一个prototype属性,这个属性指向函数的原型对象。

prototype其实就是对象与对象的原型关联的属性。

例如:

var obj = new Object();

在这里插入图片描述
再例如:

 function Animal(weight) {
   this.weight = weight
 }

在这里插入图片描述
函数本身也是一个对象,所以并不冲突。

每一个对象都会从原型中“继承”属性。

举个例子:

function Animal(weight) {
      this.weight = weight;
      // console.log(this); //Animal
    }
Animal.prototype.height = 10
var cat1 = new Animal(20);
var cat2 = new Animal();
console.log(cat1);
console.log(cat2);
console.log('cat1', cat1.height)//10
console.log('cat2', cat2.height)//10

在这里插入图片描述
cat1和cat2都是实例化的Animal,它们的区别在于参数weight,一个20,一个undefined,但是cat1和cat2本身都是没有hieght属性的,但是却都能打印出height值均为10,产生这种结果的原因是cat1和cat2继承了原型Animal.prototype中的height属性。

三、proto

每个对象(除null外)都会有的属性,__proto__,这个属性会指向该对象所在的构造函数的原型对象。

console.log(cat1);
console.log(cat2);
console.log(cat1.__proto__);
console.log('cat1.__proto__ === Animal.prototype', cat1.__proto__ === Animal.prototype) //true
console.log('cat2.__proto__ === Animal.prototype', cat2.__proto__ === Animal.prototype) //true

在这里插入图片描述

__proto__是实例指向原型的属性

prototype是对象或者构造函数指向原型的属性
在这里插入图片描述

四、constructor

每个原型都有一个constructor属性,指向该关联的构造函数。

console.log('Animal===Animal.prototype.constructor', Animal === Animal.prototype.constructor) //true  Animal就是上面的构造函数
// 获取原型对象
console.log('Object.getPrototypeOf(cat1) === Animal.prototype', Object.getPrototypeOf(cat1) === Animal.prototype)  //true
console.log('cat1.constructor === Animal',cat1.constructor === Animal) //true

在这里插入图片描述

更新图解:
在这里插入图片描述
为什么cat1.constructor === Animal为true ?

cat1中并没有属性constructor ,但是它的原型cat1.__proto__指向的是Animal.prototype,每一个对象都会从原型中“继承”属性,而Animal.prototype原型中是有属性constructor的,于是cat1的constructor属性继承自原型中的constructor属性。这里便能看出一点点原型链的影子 !!

五、实例与原型

当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性。

function Animal(weight){
      this.weight=weight;
}
Animal.prototype.name='animal';
var cat1=new Animal();
cat1.name='littleCat';
console.log('cat1.name',cat1.name);
delete cat1.name;
console.log('cat1.name',cat1.name);

在这里插入图片描述
删除属性前,是littleCat,删除属性后,该实例没有了name属性,找不到name属性的时候,它就会去 它的对象原型中去找也就是去cat1.__proto__中也就是Animal.prototype中去寻找,而Animal.prototype中的name属性的值是animal,所以删除name属性后的值变成了原型中属性name的值animal。

如果cat1的原型中也没有name属性呢?会怎么办?去原型的原型中找?那么原型的原型是什么?

我们说原型是对象创建的时候关联的另一个对象,那么既然原型也是一个对象,那它也应该关联一个对象是原型的原型。
在这里插入图片描述

//原型链的终点
var obj=new Object();
console.log('Object.prototype.__proto__===null',Object.prototype.__proto__===null);  //true

六、原型链

将原型的实例赋值给另一个对象,另一个对象再赋值给其他的对象,就会形成一条原型链。

function Animal(weight) {
      this.weight = weight
}
Animal.prototype.name = 'animal'
var cat1 = new Animal();
console.log('cat1',cat1);
var pinkCat = cat1;
console.log('pinkCat',pinkCat)
console.log('pinkCat.name', pinkCat.name)
console.log('pinkCat.__proto__ === cat1.__proto__ === Animal.prototype', pinkCat.__proto__ === cat1.__proto__ === Animal.prototype)
console.log('pinkCat.__proto__ === cat1.__proto__',pinkCat.__proto__ === cat1.__proto__);
console.log('cat1.__proto__ === Animal.prototype',cat1.__proto__ === Animal.prototype);
console.log('pinkCat.__proto__ === Animal.prototype',pinkCat.__proto__ === Animal.prototype);

var samllPinkCat = pinkCat;
console.log('samllPinkCat',samllPinkCat);
console.log('samllPinkCat.name', samllPinkCat.name)
console.log('samllPinkCat.__proto__ === pinkCat.__proto__ === cat1.__proto__ === Animal.prototype',samllPinkCat.__proto__ === pinkCat.__proto__ === cat1.__proto__ === Animal.prototype)
console.log('samllPinkCat.__proto__ === pinkCat.__proto__',samllPinkCat.__proto__ === pinkCat.__proto__)
console.log('pinkCat.__proto__ === cat1.__proto__',pinkCat.__proto__ === cat1.__proto__);
console.log('cat1.__proto__ === Animal.prototype',cat1.__proto__ === Animal.prototype);
console.log('samllPinkCat.__proto__ === Animal.prototype',samllPinkCat.__proto__ === Animal.prototype);

在这里插入图片描述
在这里插入图片描述
原型链一层一层链接上去形成一条链条就是所谓的原型链。以上cat1实例化了Animal,cat1赋值给了pinkCat,pinkCat又赋值给了samllPinkCat,就形成看原型链,从samllPinkCat,pinkCat到cat1最后到Animal。

七、练习

//小练习1
Function.prototype.a = "a";
Object.prototype.b = "b";
function Person() {}
console.log(Person);    //function Person()
let p = new Person();
console.log(p);         //Person {} 对象
console.log(p.a);       //undefined
console.log(p.b);       //b

在这里插入图片描述
在这里插入图片描述

在这里,主要说一下p.__proto__.__proto__

p是Person()的一个实例,是一个Person对象,它拥有一个属性值__proto__。并且__proto__也是一个对象,它包含两个属性值constructor和__proto__。

console.log(p.__proto__.constructor);   //function Person(){}  构造函数本身
console.log(p.__proto__.__proto__);     //对象 Object{},拥有很多属性值

Person.prototype的隐式原型的constructor指向Object(),即Person.prototype.__proto__.constructor == Object()
得到一个拥有多个参数的Object()函数。

所以虽然p没有b属性,会一直通过__proto__向上查找,最后当查找到Object.prototype时找到,最后打印出b,向上查找过程中,得到的是Object.prototype,而不是Function.prototype,找不到a属性,所以结果为undefined,这就是原型链,通过__proto__向上进行查找,最终到null结束。

总结:

1.p.__proto__.constructor == function Person(){}
2.p.___proto__.__proto__== Object.prototype
3.p.___proto__.__proto__.__proto__== Object.prototype.__proto__ == null
4.通过__proto__形成原型链而非protrotype

//小练习2
//Function
function Function() { }
console.log(Function);  // f Function(){}
console.log(Function.prototype.constructor);    // f Function(){}
console.log(Function.prototype.__proto__);      //Object.prototype
console.log(Function.prototype.__proto__.__proto__);    //NULL
console.log(Function.prototype.__proto__.constructor);  // f Object()
console.log(Function.prototype.__proto__ === Object.prototype); //true

在这里插入图片描述

八、原型的作用

1.数据共享 节约内存内存空间
2.实现继承

当方法写在构造函数Person内时,每次使用构造函数Person()实例化出对象的时候,就会给每个实例对象的方法开辟空间。可是当实例化许多对象的时候,就会浪费大量的空间,因为每个实例对象的方法功能是一样的,所以没有必要,我们将方法添加到了Person()构造函数的原型(prototype)上了,因此就只有一份方法。当实例对象需要使用这些方法的时候就在自己的__proto__属性中找到并调用这些方法实现相应的功能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值