深挖原型、原型链

关于原型和原型链,之前也有写过一篇文章,地址:https://blog.csdn.net/fish_skyyyy/article/details/113960342

现根据自己所学到的新知识,再来深挖一下原型和原型链。

典型的面向对象编程语言(C++、Java),都有”类(class)“的概念。类就是对象的模板,对象就是类的实例。但是JS的语言体系不是基于类的,而是基于构造函数和原型链的。


一、原型

关于原型,实际上就是prototype、proto、constructor的三角关系。

想要了解原型,就要了解三个最基础的概念:构造函数、原型对象、实例对象。

1、构造函数

首先什么是构造函数?想要搞懂什么是构造函数,就要先搞懂什么是函数?函数有哪几种创建形式?

函数是这样的一段JS代码,它只定义一次,但可能被执行或调用任意次。

函数的创建形式:

① 声明式:function myfun(){}

这种定义的方式,无论在哪定义,别的地方都可以调用。

② 函数的字面量/直接量/表达式:var myfun=function(){}

此时函数作为表达式存在,只能调用在定义的后面

表达式:凡是将数据和运算符等联系起来有值的式子被称作表达式。

③ new Function:var myfun=new Function(arg1,arg2,...,argn,body)

Function构造函数所有的参数都是字符串类型,前面的参数都作为生成函数的参数,即形参,可以没有形参;最后一个参数表示的是要创建函数的函数体。

JS中任意函数都是Function的实例。


那么什么是构造函数呢?

构造函数:是一个函数,并且任何的函数都可以作为构造函数来存在,它的本质是初始化对象。

构造函数都是和new一起使用的,new就是在创建对象,从无到有,构造函数就是在为初始化的对象添加属性和方法。

说白了,构造函数就是专门用来生成对象实例的函数。

举个构造函数的例子:

function Person(first, last, age, eyecolor) {
    this.firstName = first;
    this.lastName = last;
    this.age = age;
    this.eyeColor = eyecolor;
}

构造函数的特点:
① 函数体内部使用了this关键字,代表了所要生成的对象实例。
② 生成对象的时候,必须使用new命令。

为了与普通函数区别,构造函数名字的首字母通常大写。

那么想要构造对象:
① new申请内存,创建对象
② 调用构造函数,构造函数有一个隐式参数this
③ 刚创建出来的对象的引用赋值给this
④ 利用”this.成员 = 值“ 来给对象添加成员


2、原型对象

首先,我们先来了解一下什么是对象?

对象是单个实物的抽象。
例如:一辆汽车、一个人都可以是对象。

对象是一个容器,封装了属性和方法。
属性是兑现好的状态,方法是对象的行为。
例如:”属性“记录动物的状态(名称、年龄、性别等),”方法“记录动物的行为(奔跑、捕猎等等)。

prototype(原型):每个对象都会在其内部初始化一个属性,就是prototype(原型),所有 JavaScript 对象都从原型继承属性和方法,这个属性指向函数的原型对象。

原型对象的用途:是为每个实例对象存储共享的方法和属性。

日期对象继承自 Date.prototype。
数组对象继承自 Array.prototype。
Person 对象继承自 Person.prototype。

Object.prototype 位于原型继承链的顶端:
日期对象、数组对象和 Person 对象都继承自 Object.prototype。

构造函数和实例原型之间的关系:原型对象=构造函数名.prototype


3、实例对象

在面向对象的编程中,通常把创建对象的过程称为实例化。

实例对象:通过构造函数的new操作创建的对象是实例对象。可以用一个构造函数创建多个实例对象。

了解实例对象之后,我们来搞懂new的基本用法:

new命令的作用就是执行构造函数,返回一个实例对象。通过new命令,可以让构造函数生成一个实例对象,保存在一个变量中,这个新生成的实例对象,能从构造函数中得到属性。

new命令执行时,构造函数内部的this就代表了新生成的实例对象。

如果在继承属性的过程中缺失了new命令:

var Person = function() {
	this.name = 'zhangsan';
}
var person = Person();
console.log(person)//undefined
console.log(name)//zhangsan

此时,构造函数变成了普通函数,并不会生成实例对象,this此时代表全局对象,name属性变成了全局变量,将造成意想不到的结果。

4、三者关系图

在这里插入图片描述

5、关于prototype、proto、constructor

① 【prototype】:每一个函数都有一个prototype对象属性,prototype的所有属性和方法都会被构造函数的实例继承。
② 【constructor】:原型对象有一个constructor属性,指向该原型对象对应的构造函数。
③ 【proto】:每个实例对象除prototype属性外,还存在一个__proto__的属性,这其实是浏览器自定义的属性,成为隐式原型,在创建对象时自动添加,默认值是构造函数的prototype。

原型对象=构造函数名.prototype

function Person(first, last, age, eyecolor) {
    this.firstName = first;
    this.lastName = last;
    this.age = age;
    this.eyeColor = eyecolor;
}
var person = new Person();

console.log(person.__proto__ === Person.prototype); // true
console.log(Person===Person.prototype.constructor)  //true
console.log(person.constructor === Person); // true

在这里插入图片描述

二、原型链

实例对象与原型之间的连接,叫做原型链。

proto(隐式连接),每个对象都有一个proto属性,原型链上的对象正是依靠这个属性连接在一起。

当你访问一个属性或方法时,如果这个对象中没有这个属性或方法,那么将会访问这个对象的proto属性所指向上一个对象,并在这个对象中查找指定的方法或属性;如果还是找不到,就会继续通过那个对象的proto属性执行的对象再向上进行查找,直到null。

如果原型对象是另一个类型的实例,那么这个原型对象将会有一个指向另一个类型的原型对象的内部指针( __ proto __ ),而这个另一个类型的原型对象(Object.prototype)中又包含了一个指向其构造函数的指针(constructor)。

假如另一个原型又是另一个类型的实例,那么上述关系依然成立。如此层层递进,就构成了实例与原型的链条。这就是所谓的原型链的基本概念。

console.log(Object.prototype.__proto__ === null) // true

函数也是对象,是一种具有特殊功能的对象,任何函数都可以看作是Fucntion()构造函数new操作实例化的结果。
所以有:

console.log(person.constructor === Person); // true
console.log(Person.constructor === Function); // true

所有的原型链最后都将沿着obj.prototype指向null,所有的constructor最后指向Function。

先放一张简单的图,便于理解:
在这里插入图片描述
重点来了!!!!

在这里插入图片描述

最后再来理解一句话:函数是对象构造的,对象也是函数构造的,两者既是函数也是对象。

console.log(Function instanceof Object);//true
console.log(Object instanceof Function);//true

其中,instanceof 的用法:A instanceof B,判断B的原型是否在A的原型链上。

Object 的原型 Object.prototype 在 Function 的原型链上,Function 的原型对象 Function.prototype 也在 Object 原型链上。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值