JS-原型和原型链以及继承和instaceof实现

每一个构造函数都有一个内置属性prototype,叫做显式原型属性,简称为显式原型

构造函数的prototype默认指向一个空的Object对象,而构造函数创建的对象的__proto__指向其构造函数的prototype

function Person(){}

const p = new Person()

p.proto === Person.prototype

Person.prototype instanceof Object

当【对象.属性】或【对象.方法】时,会先在对象自身查找,如果自身找不到,则会去自身的__proto__指向的原型对象上找

所以我们在定义类(构造函数)时,通常将实例方法定义在类(构造函数)的prototype属性上,即原型对象上。因为这样,创建对象就可以自动沿着__proto__找到原型对象上的方法。

原型链

===

原型链又叫做隐式原型链,因为原型对象本身也是一个对象,所以原型对象也有__proto__这个隐式原型属性,而原型对象默认是一个空的Object对象,所以原型对象的构造函数就是Object函数,所以原型对象的__proto__指向的是Object.prototype

而根据【对象.属性】,【对象.方法】的查找规则,如果对象在自身找不到某个属性或方法,则会沿着__proto__去原型对象上找,如果原型对象上也没有,则继续验证原型对象的__proto__去上一级原型对象的身上找,…,尽头就是Object.prototype这个原型对象,它的__proto__指向null。

这就解释了为什么所有对象都默认toString方法,因为所有对象能可以根据隐式原型链找到Object.prototype原型对象,而toString方法就是定义在Object.prototype上的。

这也解释了为什么对象访问一个不存在属性时会报错undefined,因为原型链的尽头是null,而null上没有任何属性,所以返回unedfined。

Function构造函数在原型链中的位置

====================

我们需要知道,在JS中函数也是一种对象,这里的函数包括构造函数,即构造函数也是一种对象,而函数对象的构造函数是谁呢?

它就是Function构造函数。我们可以人为function Array(){} ,function String(){} 这些对象,都是Function构造函数的实例。

const Person = new Function(‘name’,‘this.name = name’)

const p = new Person(‘张三’)

console.log§

所以Function可以理解为是所有函数对象的构造函数,函数对象的隐式原型属性指向了Function构造函数的显式原型

这也解释了为什么每个函数都可以调用call,apply,bind方法,因为这三个方法都是定义在Function.prototype上的

验证Object.__proto__ === Function.prototype

那么Function构造函数也是一个函数,即Function构造函数也是一个对象,那么Function.__proto__指向谁呢

其实也是指向它的构造函数的显式原型。

那么Function构造函数是谁构造的呢? 是它自己。

Function.__proto__ === Function.prototype

总结

==

任意对象的__proto__都指向自己构造函数的prototype

原型对象的__proto__也指向自己构造函数的prototype

构造函数的原型对象默认是空的Object对象

构造函数对象(包括Object()和Function())的构造函数都是Function,比较有代表性的是:

Object.__proto__ === Function.prototype

Function.__proto__ === Function.prototype

那么Function.prototype.__proto__指向谁呢,答案是Obejct.prototype

原型链在类继承中的应用

===========

假设现在有一个学生类,想继承人类。

则1、继承人类的属性 2、继承人类的方法

ES5中实现继承

function Person(name, age) {

this.name = name

this.age = age

}

Person.prototype.sayHi = function() {

console.log(‘你好,我叫’ + this.name + ‘,今年’ + this.age + ‘岁了。’)

}

function Student(level, name, age) {

this.level = level

Person.call(this, name, age) // 实例属性继承

}

Student.prototype.sayLevel = function() {

console.log(‘我已经’ + this.level + ‘年级了。’)

}

Student.prototype.proto = Person.prototype // 实例方法继承

const stu = new Student(1, ‘张三’, 6)

stu.sayLevel()

stu.sayHi()

console.log(stu);

对应的原型链如下,原本Student.prototype.__proto__是指向Object.prototype

现在将Student.prototype.__proto__指向Person.prototype

这样stu实例依旧可以访问Object原型上方法,也可以访问Person原型上方法

另一种原型链继承方案是Student.prototype = new Person()

function Person(name, age) {

this.name = name

this.age = age

}

Person.prototype.sayHi = function() {

console.log(‘你好,我叫’ + this.name + ‘,今年’ + this.age + ‘岁了。’)

}

function Student(level, name, age) {

this.level = level

Person.call(this, name, age) // 实例属性继承

}

Student.prototype = new Person() // 必须要先写,早于Student.protptype.xxx = function

Student.prototype.sayLevel = function() {

console.log(‘我已经’ + this.level + ‘年级了。’)

}

const stu = new Student(1, ‘张三’, 6)

stu.sayLevel()

stu.sayHi()

console.log(stu);

这种继承方案stu对象可以顺着隐式原型链访问到Person.prototype上的方法,完成方法继承,但是存在一个缺点,stu.__proto__原型对象是一个new Person()对象,那么new Person()对象的属性就会影响到所有的Student实例

我觉得:原型链继承单纯的用作方法继承,使用Vue的继承思路 vc.prototype.__proto__ === vm.prototype

就挺好的。

但是好像听说:ES6之前,程序员无法直接操作对象的隐式原型属性,现在ES6可以了

JS的四大继承方案

=========

1、原型继承:方法继承,Child.prototype === new Father() 或者 Child.prototype.__proto__ === Father.prototype

2、call继承: 属性继承

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
(img-c0EdvGOY-1715540752159)]

[外链图片转存中…(img-HyP9L3kb-1715540752160)]

[外链图片转存中…(img-O05KG4fx-1715540752160)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值