JavaScript---原型和原型链

目录

一、引用类型皆为对象

二、原型和原型链是什么

三、__proto__与prototype

总结

四、原型链顶层

五、constructor

六、函数对象的原型链


一、引用类型皆为对象

原型原型链 都是来源于对象 而服务于对象

  • JavaScript中一切引用类型都是对象,对象就是属性的集合
  • Array、Function、Object、Date、RegExp都是引用类型
  • 数组是对象、函数是对象、正则是对象、对象还是对象
javascript 复制代码
const arr = []
const fn = function() {}
const obj = {}

console.log(typeof arr) // "object"
console.log(fn instanceof Object) // true
console.log(typeof obj) // "object"

二、原型和原型链是什么

每一个对象从被创建开始就和另一个对象关联,从另一个对象上继承其属性,这个"另一个对象"就是"原型"

当访问一个对象的属性时,先在对象的本身查找,找不到就去对象的原型上找,如果还找不到,就去对象的原型的原型上去找,如此重复,直到找到为止,或者查找到最顶层的原型对象中也没有找到,就结束查找,返回undefined

而在对象的原型上,依次查找时,所遍历的所有原型,叫作"原型链"

javascript 复制代码
const obj = {}
obj.sayHello = () => {console.log('Hello')}
console.log(obj.hasOwnProperty('sayHello')) // true
  • 上面代码中,我们访问obj.hasOwnProperty()时,发现该对象并没有这个方法,但是我们仍然可以使用,这是因为在obj对象的原型上,存在该方法,所以我们可以调用
  • 到现在,我们可以理解数组可以使用push、slice等方法,函数可以使用call、bind方法了,因为在它们的原型链上找到了对应的方法

三、__proto__与prototype

每个对象都有原型,我们怎么获取到一个对象的原型呢?可以使用对象的"proto"属性,指向对象的原型

  • 所有引用类型都有__proto__属性
  • proto 属性在ES6中不推荐被使用,现在更推荐使用Obejct.getPrototypeOf(),该方法也可以获取到对象的属性
javascript 复制代码
console.log(Object.getPrototypeOf(obj) === obj.__proto__) // true

构造函数 是为了创建特定类型的对象,那如果我想让"Person"这个构造函数创建的对象都共享一个方法,不能像下面这样:

错误示范:

javascript 复制代码
function Person(name){
    this.name = name;
}
// 调用构造函数Person创建一个新对象PersonA
const personA = new Person();
// 给PersonA的原型添加一个方法,以供之后Person创建的对象共享
personA.__proto__.sayHello = function(){
    console.log(`Hello, my name is ${this.name}`);
}
// 创建一个新的Person对象PersonB
const personB = new Person('Bob');
// 调用PersonB的sayHello方法
personB.sayHello(); // Hello, my name is Bob
  • 当我们不想修改构造函数创建的对象,并且还不想修改构造函数时,如果先通过构造函数创建一个对象,再通过对象的原型修改,这样确实可以,但实在太过啰嗦

为此,我们可以通过"prototype"来直接修改原型,每个函数多拥有prototype属性,指向使用new操作符和该函数创建的对象的实例的原型对象

javascript 复制代码
console.log(personA.__proto__ === Person.prototype); // true
console.log(personB.__proto__ === Person.prototype); // true

正确示范:

javascript 复制代码
function Person(name){
    this.name = name;
}
Person.prototype.sayHello = function(){
    console.log(`Hello, my name is ${this.name}`);
}
const personA = new Person('Bob');
personA.sayHello(); // Hello, my name is Bob

总结

  • 对象有**proto属性(Object.create(null)除外 ),函数有proto属性,数组也有proto属性,只要是引用类型** ,就有**proto属性,指向其原型**
  • 只有函数有prototype属性,指向new操作符加调用该函数创建的对象实例的原型对象

四、原型链顶层

原型链 之所以叫原型链 ,不叫原型环 ,说明它是有始有终的,那么原型链的顶层是什么呢?

personA对象的原型对象,很简单:

javascript 复制代码
console.log(personA.__proto__ === Person.prototype); 

接着往上找,Person.prototype 也是一个普通对象,可以理解为Object构造函数创建的,所以得出下面结论:

javascript 复制代码
console.log(Person.prototype.__proto__ === Object.prototype); // true
console.log(Person.prototype.__proto__)
  • 上图红框内的**proto** 就是Person.prototype.proto,也就是下图:

Object.protype 也是一个对象,那么它的原型呢?是空值null

javascript 复制代码
Object.prototype.__proto__ === null

五、constructor

构造函数都有一个prototype属性,指向使用这个构造函数创建的对象实例的原型对象

这个原型对象中默认有一个constructor属性,指回该构造函数

javascript 复制代码
Person.prototype.constructor === Person // true

六、函数对象的原型链

函数也是对象,故函数也有**proto**属性,这里比较容易混淆

因为函数既有prototype 也有**proto**,很容易搞晕

我们只需要记住:

  • 函数的prototype 使用的前提是:"函数被作为构造函数使用,此时prototype指向构造函数创建的对象实例的__proto__原型对象"
  • 函数的**proto** 指的是:"函数被当做一个普通对象使用,此时它的__proto__指向Function.prototype,因为Function是所有函数的构造函数"
  • 一个特例,Fyunction.__prototype === Function.prototype,记住就好
javascript 复制代码
console.log(Person.__proto__ === Function.prototype) // true
console.log(Person.__proto__.constructor === Function) // true
console.log(Person.__proto__.__proto__ === Object.prototype) // true

有点绕,但是理解这三个代码,相信**proto** 和prototype你永远不会弄混了

相关推荐
1104.北光c°25 分钟前
滑动窗口HotKey探测机制:让你的缓存TTL更智能
java·开发语言·笔记·程序人生·算法·滑动窗口·hotkey
wuhen_n1 小时前
网络请求在Vite层的代理与Mock:告别跨域和后端依赖
前端·javascript·vue.js
for_ever_love__1 小时前
Objective-C学习 NSSet 和 NSMutableSet 功能详解
开发语言·学习·ios·objective-c
用户69371750013846 小时前
Google 正在“收紧侧加载”:陌生 APK 安装或需等待 24 小时
android·前端
蓝帆傲亦6 小时前
Web 前端搜索文字高亮实现方法汇总
前端
用户69371750013846 小时前
Room 3.0:这次不是升级,是重来
android·前端·google
似水明俊德7 小时前
02-C#.Net-反射-面试题
开发语言·面试·职场和发展·c#·.net
漫随流水8 小时前
旅游推荐系统(view.py)
前端·数据库·python·旅游
Thera7778 小时前
C++ 高性能时间轮定时器:从单例设计到 Linux timerfd 深度优化
linux·开发语言·c++
踩着两条虫9 小时前
VTJ.PRO 核心架构全公开!从设计稿到代码,揭秘AI智能体如何“听懂人话”
前端·vue.js·ai编程