快速了解 js中原型和原型链

133 阅读3分钟
  • 前言

    突然间被办公室的一个java小哥哥问到:小前哥,js中的原型链是啥,你能给我描述一下嘛?脑子好像突然失灵,不知道从哪个方便要给小哥哥讲这个问题,最后找了一个自认为不错的文章发给他看(哈哈,此处有小哥哥的大白眼)。小哥哥的大白眼让我觉得自己是时候要自救一波基础知识了,决定从基础开始我的前端自救之路了。。

    要明白js中原型和原型链,我们首先必须要知道几个概念

  • 正文

  • 构造函数:在 JavaScript中,用new关键字来调用的函数,称为构造函数。构造函数首字母一般大写。

function Animal(){ }
//这就是一个最简单的构造函数
  • prototype : 每个 函数 都有一个prototype属性,这里是函数,它是构造函数的原型对象 ;
  • constructor 原型对象上的一个指向构造函数的属性
  • 实例对象:实例对象通过构造函数进行创建。
var pig = new Animal()
//通过new关键字,我们就创建了一个实例对象
  • __proto__ : 每个对象都有这个私有属性,这里是对象,JavaScript中,一切皆是对象,函数也是对象,所以函数也有这个属性。它指向构造函数的原型对象
  • 原型与实例
    function Animal() {}
    Animal.prototype.name = 'Peiqi';
    var pig = new Animal();
        console.log(pig.name) //Peiqi
        console.log(pig.age) // undefined
    pig.name = 'Jony';
    pig.age = 18
        console.log(pig.name) // Jony
    delete pig.name;
        console.log(pig.name) // Peiqi
        console.log(pig.age) // 18

这里我们可以看出,pig.name先开始从pig对象中查找,找到的时候返回了Jony,找不就从pig的原型_proto_即Animal.prototype中找。

  • 原型链

    JavaScript 对象有一个指向一个原型对象的链。当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。换句话说:每个实例对象( object )都有一个私有属性(称之为 __ proto __ )指向它的构造函数的原型对象(prototype )。该原型对象也有一个自己的原型对象( __ proto __ ) ,层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。

在这里
function Animal(){}
var pig = new Animal();
console.log(pig.__proto__ == Animal.prototype)
pig.__proto__ == Animal.prototype
Animal.prototype.constructor == Animal
pig.__proto__.__proto__.constructor == Object
Object.prototype.constructor == Object
pig.__proto__ .__proto__ == Object.prototype
原型链最终指向null
pig.__proto__·__proto__.__proto__ == null
下面看另外一个例子
var o = {a: 1};
// o 这个对象继承了 Object.prototype 上面的所有属性
// o 自身没有名为 hasOwnProperty 的属性, hasOwnProperty 是 Object.prototype 的属性
// 因此 o 继承了 Object.prototype 的 hasOwnProperty
// Object.prototype 的原型为 null
// 原型链如下:
// o ---> Object.prototype ---> null

var a = ["yo", "whadup", "?"];
// 数组都继承于 Array.prototype 
// (Array.prototype 中包含 indexOf, forEach 等方法)
// 原型链如下:
// a ---> Array.prototype ---> Object.prototype ---> null

function f(){
  return 2;
}
// 函数都继承于 Function.prototype
// 原型链如下:
// f ---> Function.prototype ---> Object.prototype ---> null

最后我们可以看出:

1. 原型存在的意义就是组成原型链:引用类型皆对象,每个对象都有原型,原型也是对象,也有它自己的原型,一层一层,组成原型链。

2. 原型链存在的意义就是继承:访问对象属性时,在对象本身找不到,就在原型链上一层一层找。说白了就是一个对象可以访问其他对象的属性。

3. 继承存在的意义就是属性共享:好处有二:一是代码重用,字面意思;二是可扩展,不同对象可能继承相同的属性,也可以定义只属于自己的属性。