几分钟带你理解原型链

​目录

1 对象

2 原型

3 原型链

对象

​​ 讲到原型链,那么我们要先认识javascript里面的对象,那么什么是对象?
所谓万物皆对象,这句话是不是很抽象,抽象就对了,这是一个很广的概念;对象指的是一类具体的事物;里面封装了属性(property)和方法(method);
例如:

张三是一个对象,

那么张三的属性就有:身高、体重、肤色等等;

而对应的方法(或者是行为)就有:吃饭、睡觉、打豆豆等等

在程序员的世界里,万事万物我们都可以封装成为对象;了解到了对象,那么我们如何在代码中创建一个对象呢?

1 创建对象的三种方式

1.1 字面量形式创建

var hero = { 

	name: '德玛西亚', 

	attack: function(){}

}

1.2 new空构造形式创建

var hero = new Object();

hero.name = '德玛西亚';

hero.attack = function(){};

1.3 自定义构造函数

function Hero(name,attack){

	this.name = name;

	this.attack = attack;

}
var hero = new Hero('德玛西亚',function(){});

1.4 使用构造函数与实例对象的关系

使用构造函数的好处不仅仅在于代码的简洁性,更重要的是我们可以识别对象的具体类型。
在每一个实例对象中同时有一个 constructor属性,该属性指向创建该实例的构造函数:

在这里插入图片描述

var hero1 = new Hero('德玛西亚', function () { });
var hero2 = new Hero('德莱文', function () { });
console.log(hero1.constructor === Hero);//true
console.log(hero2.constructor === Hero);//true
console.log(hero1.constructor === hero2.constructor);//true
  • 构造函数是根据具体的事物抽象出来的抽象模板
  • 实例对象是根据抽象的构造函数模板得到的具体实例对象
  • 每一个实例对象都具有一个 constructor 属性,指向创建该实例的构造函数
  • 可以通过实例的 constructor属性判断实例和构造函数之间的关系

了解到了构造函数与实例对象的关系后,下面我们来看原型

原型

1 为什么会有原型?

我们在使用构造函数的时候,一般都会声明方法,那么就会存在每次实例化一个对象的时候,都会为这些相同的方法创建一块内存区域去存储,这样就会导致内存的浪费;为了解决这个问题,就有了原型 prototype

2 原型与构造函数和示例对象的关系

在这里插入图片描述

  • 任何函数都具有一个 prototype 属性,该属性是一个对象

  • 构造函数的 prototype 对象默认都有一个 constructor 属性,指向 prototype 对象所在函数

  • 通过构造函数得到的实例对象内部会包含一个指向构造函数的 prototype 对象的指针 __proto__

  • 所有实例都直接或间接继承了原型对象的成员

    function Hero() {
      //定义空的构造函数
    }
    Hero.prototype.sayHi = function() {
         console.log('你好');
    }
    var hero = new Hero();
    hero.sayHi();
    

    上面代码在Hero里面没有定义sayHi()的方法,而是在Hero构造函数的prototype属性(得到的是原型对象)里定义的sayHi(),在调用的时候让实例对象进行的调用,那么输出结果如下:
    在这里插入图片描述

原型链

1 什么是原型链?

方法和属性的搜索原则,用白话来讲,就是我们实例化对象在使用属性,或者调用方法的时候,系统是如何帮我们去查找的

2 如何去搜索的

  • 搜索首先从对象实例本身开始,例如hero实例对象
  • 如果在hero实例中找到了具有给定名字的属性,则返回该属性的值
  • 如果没有找到,则继续搜索hero指针hero.__proto__指向的原型对象,在原型对象中查找具有给定名字的属性
  • 如果在原型对象中找到了这个属性,则返回该属性的值,如果还没有找到,那么会从hero的原型对象里面的指针hero原型对象.__proto__上继续寻找
  • 依次类推,一直向上找,当向上找到Object的原型的时候,这条原型链就算到头了

在这里插入图片描述

实例

function Hero() {
//定义空的构造函数
}
//给原型对象定义方法
Hero.prototype.sayHi = function() {
     console.log('你好');
}
//在原型对象上定义属性
Hero.prototype.name = '我是一个英雄';
var hero = new Hero();
hero.sayHi();
console.log(hero.name);

输出结果如下:

在这里插入图片描述

3 注意事项

接着上面例子,不管创建多少个实例对象,如果构造函数里面没有定义属性和方法,是享有的原型对象的,那么它们获取的属性和方法都是同一个

function Hero() {
//定义空的构造函数
}
//给原型对象定义方法
Hero.prototype.sayHi = function() {
     console.log('你好');
}
//在原型对象上定义属性
Hero.prototype.name = '我是一个英雄';
//第一个对象
var hero = new Hero();
console.log('我是第一个创建的:' + hero.name);
hero.sayHi();
//第二个对象
var hero1 = new Hero();
console.log('我是第二个创建的:' + hero1.name);
hero1.sayHi();

输出结果

在这里插入图片描述

如果获取的属性或者是方法,通过原型链的寻找都没有找到,那么就会出现以下问题

实例代码

function Hero() {
//定义空的构造函数
}
var hero = new Hero();
console.log(hero.name);
hero.sayHi();

输出结果

在这里插入图片描述

出现这个结果很好理解,name属性是我们自己定义的,通过原型链向上搜寻原则,找到Object的原型对象,里面还没有,那么就是undefined未定义的;而方法不一样,当我们找到Object的原型对象,里面没有sayHi()方法,那么就会抛出异常,sayHi()不是一个函数;

希望这篇帖子让大家对于原型和原型链的理解有一些帮助;有兴趣小伙伴可以来关注一下我们长沙校区黑马程序员,下面是微信二维码,请加上备注-CSDN
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值