JS-关于原型与原型链这件事

原型与原型链是JS中逃避不过的知识点,那么到底什么是原型与原型链呢?不急,且听我慢慢道来:

一、为什么会出现原型与原型链

关键字:实现继承,共享属性

众所周知,JS最初的想法只是想设计一门简单脚本语言,可是JS里毕竟都是对象,总需要有一个东西将其全部联系起来,于是Brendan Eich(JS语言设计的负责人)想到了通过new来构造实例对象,可是new有一个缺点-----无法共享属性和方法,构造出来的对象都是相互独立的,这可万万不行,太消耗资源了。如下,万一有一天我的宠物种类就全变成“猫猫”了呢,但是把pet1的种类修改过后,pet2的种类仍是“狗狗”,这怎么行呢?

function MyPet(name){
     this.name = name;
     this.species = "狗狗";
}
var pet1 = new MyPet("小白");
var pet2 = new MyPet("花花");

pet1.species = "猫猫";
pet2.species ===> "狗狗"

于是Brendan Eich便决定在构造函数上再设置一个prototype属性,将构造共有的属性与方法都写在这上面,那些不需要共享的就放在构造函数里面,这样不就大大的节约资源了吗?如下:

function MyPet(name){
     this.name = name;
}
MyPet.prototype = {species:"狗狗"};

var pet1 = new MyPet("小白");
var pet2 = new MyPet("花花");

pet1.species = "狗狗";
pet1.species = "狗狗";

这样,当需要改变我的宠物种类时,只需要将prototype的species属性值改成“猫猫“就可以了

//修改过后
MyPet.prototype.species = "猫猫"
pet1.species ===》 "猫猫";
pet1.species ===》 "猫猫";

总结:这样一来,所有的实例对象就可以共享prototype的属性,而prototype就是我们所说的原型。

好了,前菜上完了,下面进入我们今天的主体部分。

二、详解

2.1 prototyep(原型)

根据上面的描述可以知道,prototype里会存放所有共享的属性和方法,所以在JS内部,prototype是作为一个对象的方式存在的

function fn(){}
console.log(typeof fn.prototype) ==> Object

所以,对于构造函数来说,拥有了prototype就可以将一些属性和方法传递给所有的实例对象了,如下:

function Student(name,age){
    this.name = name;
    this.age = age;
  }
Student.prototype.grade = "大学";
var s1 = new Student("小红",24);
var s2 = new Student("小明",25);
console.log(s1.grade); //大学
console.log(s2.grade); //大学

在这里,s1,s2的原型(__proto__)指向的就是Student的prototype

虽然说s1,s2这两个实例身上并没有特意去写grade这一属性,但是由于在构造函数Student的prototype上添加了grade属性,所以s1,s2自然而然就可以顺着原型,去Student的prototype上得到,也就是说当某个实例本身没有该属性或方法时,就会去其原型上找到

所以,只要通过更改Student上prototype的属性值,s1,s2的grade也就会跟着改变了,如下:

Student.prototype.grade = "初中";
console.log(s1.grade); //初中
console.log(s2.grade); //初中

当然了,如果某个实例对象本身就有该属性,则会直接访问自身的,如下:

Student.prototype.grade = "大学"
s1.grade = "小学"
console.log(s1.grade); //小学
console.log(s2.grade); //大学

2.2 原型链

根据JS的规定,所有对象都有自己的原型对象。一方面,任何一个对象都可以充当其他人的原型,两一方面,由于原型对象也是对象,所以也有自己的原型。因此,就会形成一个原型链,就像上面说的,如果某一个实例对象没有该属性或方法,就会去其原型对象上找,直到找到为止,话不多说,先看代码,然后写一个完整的链条:

function Student(name,age){
     this.name = name;
     this.age = age;
}
Student.prototype.grade = "大学";
var s1 = new Student("小红",24);
var s2 = new Student("小明",25);
s1.grade = "初中";
console.log(s1.grade); //初中
console.log(s2.grade); //大学

s2.__proto__ == Student.prototype //true

 当然了,如果连Student都没有我们要的属性的话那就只能再往上找了,在JS中,所有原型都可以追朔到Object.prototype上,这就是所有对象都有valueof和toString的原因,因为这两个方法就在Object.prototype上,但值得注意的是JS中Object.prototype.__proto__为null,因此原型链的尽头是null。

初次写博客,不足之处,还请见谅,欢迎随时补充!

最后,以上部分思想来自阮一峰老师的”Javascript继承机制的设计思想“,网址:http://www.ruanyifeng.com/blog/2011/06/designing_ideas_of_inheritance_mechanism_in_javascript.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值