什么是原型?
🟢 每一个函数都有一个原型(是一个空间,或者是一个对象,内部能存储一些东西),原型内部都有一个constructor,这个属性表明当前这个原型具体是哪个函数的
函数访问原型的方法 : 函数.prototype
🟢 每一个对象都有一个__proto__ (注意:proto两边分别是两个下划线),可以去访问到自己构造函数的原型
🟢 实例化对象,本质上也是一个函数,所以它也可以访问到自己的构造函数对象访问原型的方法
对象访问原型的方法 : 对象.__proto__
🟢对象的访问规则,先在当前作用域(就是对象内部)查找,找到就使用;如果没有找到,则会顺着__proto__向上查找
<script>
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.a = '我是后续通过 JS 代码添加到函数的原型内部的属性'
Person.prototype.sayHi = () => {
console.log('你好')
}
console.log(Person.prototype) // 打印函数 Person 的原型
const p1 = new Person('AA001', 18)
const p2 = new Person('AA002', 28)
p1.sayHi()
console.log(p1.a)
console.log(p1.__proto__) // 打印对象的构造函数的原型
console.log(p1.sayHi)
console.log(p2.sayHi)
console.log(p1.sayHi == p2.sayHi)
</script>
❗❗❗ 注意点 : 构造函数的函数体内,通常写属性;构造函数的原型内, 通常写方法(函数)
构造函数的原型内部添加方法, 并不是为了给构造函数使用,通常是为了给实例化对象使用
<script>
function Person(name) {
this.name = name
}
Person.prototype.sayHi = () => {
console.log(111)
}
const p = new Person('AA666')
p.sayHi()
const arr = new Array() //数组构造函数
const obj = new Object() //对象构造函数
const reg = new RegExp() //正则构造函数
const date = new Date() //时间构造函数
console.log(arr)
console.log(obj)
console.log(reg)
console.log(date)
</script>
🍀上诉打印结果为:
❗❗❗ 记住,任何一个数组的构造函数都是Array;任何一个对象的构造函数都是Object;任何一个函数的构造函数都是Function
案例分析
🍀举一个小例子:
需求: 给数组扩展一个求最大值的方法
<script>
Array.prototype.getMax = function () {
let max = this[0]
for (let i = 1; i < this.length; i++) {
if (max < this[i]) {
max = this[i]
}
}
return max
}
const arr1 = new Array(1, 2, 100, 5, 3, 4)
const max = arr1.getMax()
console.log(max)
const arr2 = new Array(1, 2, 100, 5, 3, 4, 999)
const max2 = arr2.getMax()
console.log(max2)
</script>
🍀打印结果:
原型链
含义:查找对象的某一个属性:
🍀先在对象内部开始查找, 找到直接使用, 然后停止查找
🍀如果没有找到, 会去对象的__proto__查找, 如果找到直接使用, 然后停止查找
🍀如果这里没找到, 会继续去对象的 __proto__ 查找, 找到直接使用, 然后停止查找
🍀如果还是没找到, 会继续向上查找
🍀...
🍀直到找到顶层作用对象 Object.prototype, 找到就用, 找不到就返回一个 undefined
案例分析
🍀举一个小例子:
✏️ 问题1: p 的 __proto__ 指向谁?
✏️ 问题2: Person 的 __proto__ 指向谁?
✏️ 问题3: Person.prototype 的 __proto__ 指向谁?
✏️ 问题4: Function 的 __proto__ 指向谁?
✏️ 问题5: Function.prototype 的 __proto__ 指向了谁?
✏️ 问题6: Object 的 __proto__ 指向了谁?
✏️ 问题7: Object.prototype 的 __proto__ 指向了谁?
<script>
function Person (name) {
this.name = name
}
Person.prototype.sayHi = function () {
console.log(100)
}
const p = new Person('QF001')
console.log(p.__proto__ === Person.prototype)
console.log(Person.__proto__ === Function.prototype)
console.log(Person.prototype.__proto__ === Object.prototype)
console.log(Function.__proto__ === Function.prototype)
console.log(Function.prototype.__proto__ === Object.prototype)
console.log(Object.__proto__ === Function.prototype)
console.log(Object.prototype.__proto__)
</script>
<script>
* 问题1: p 的 __proto__ 指向谁?
* + p 是 Person 的实例化对象
* + __proto__ 指向自身构造函数的原型
* + p.__proto === Person.prototype
* 问题2: Person 的 __proto__ 指向谁?
* + Person 是构造函数, 本质上函数
* + 只要是一个函数, 他就是 Function 的实例
* + Person.__proto__ 指向了 他的构造函数的原型, 构造函数是 Function, 那么构造函数的 原型 Function.prototype
* + Person.__proto__ === Function.prototype
* 问题3: Person.prototype 的 __proto__ 指向谁?
* + Person.prototype 其实就是 构造函数 Person 的原型对象, 本质上就是对象
* + 只要是一个 对象, 他就是 Object 的实例
* + Person.prototype.__proto__ 指向了 他的构造函数的原型, 构造函数 Object, 那么构造函数的原型 Object.prototype
* 问题4: Function 的 __proto__ 指向谁?
* + Function 是构造函数, 本质上就是一个函数
* + 只要是一个函数, 他就是 Function 的实例
* + Function.__proto__ 指向了 他的构造函数的原型, 构造函数 Function, 那么 构造函数的原型 Function.prototype
* + Function.__proto__ === Function.prototype
* 问题5: Function.prototype 的 __proto__ 指向了谁?
* + Function.prototype 其实就是 构造函数 Function 的原型对象, 本质上是对象
* + 只要是一个对象, 他就是 Object 的实例
* + Function.prototype.__proto__ 指向了 他的构造函数的原型, 构造函数 Object, 那么构造函数的原型 Object.prototype
* + Function.prototype.__proto__ === Object.prototype
* 问题6: Object 的 __proto__ 指向了谁?
* + Object 是一个构造函数, 本质上还是一个函数
* + 只要是一个函数, 那么他的构造函数 就是 Function
* + Object.__proto__ 指向了他的构造函数的原型, 他的构造函数是 Function, 那么构造函数的原型 Function.prototype
* + Object.__proto__ === Function.prototype
* 问题7: Object.prototype 的 __proto__ 指向了谁?
* + Object.prototype 是构造函数 Object 的原型对象, 本质上就是一个对象
* + 但是重点: Object.prototype 是 JS 顶层的对象
* + Object.prototype.__proto__ === null
</script>