目录
一、对象的原型
1.1 概念
JavaScript当中每个对象都有一个特殊的内置属性 [[prototype]] ,这个特殊的对象可以指向另外一个对象。
1.2 作用
- 当通过引用对象的属性key来获取一个value时,它会触发[[Get]]的操作
- 这个操作会首先检查该对象是否有对应的属性,如果有的话就使用它
- 如果对象中没有该属性,那么会访问对象[[prototype]] 内置属性指向的对象上的属性
💠只要是对象都会有这样的一个内置属性!
1.3 获取方式
🔹方式一:(不常用)
通过对象的__proto__属性可以获取到 (早期浏览器自己添加的,存在一定的兼容性问题)
🔹方式二:(常用)
通过Object.getPrototypeOf方法可以获取到
二、函数的原型 prototype
2.1 概念
所以的函数都有一个prototype的属性(注意:不是__proto__)
(🏷️箭头函数没有原型)
💠虽然函数也是一个对象,但是对象上面没有prototype的属性;
💠因为是函数,所以才有这个特殊的属性;
💠(隐式全都要,显式只有函数有)
2.2 作用
用来构建对象时,给对象设置隐式原型的
2.2.1 new操作符
步骤:1. 在内存中创建一个新的对象(空对象)
2. 这个对象内部的[ [ prototype ] ] 属性会被赋值为该构造函数的prototype属性
因此,也就意味着通过Person构造函数创建出来的所有对象的[ [ prototype ] ] 属性都指向Person.prototype
function Person() {
}
//函数的显式原型
console.log(Person.prototype)
//new操作
var p1 = new Person()
var p2 = new Person()
var p3 = new Person()
//实例的隐式原型 指向 函数的显式原型
console.log(p1.__proto__)
console.log(p1.__proto__ === Person.prototype) // true
//实例的隐式原型都共同指向构造函数的显式原型
console.log(p1.__proto__ === p3.__proto__) //true
2.3 constructor属性
函数的显式原型上都会存在一个属性叫做constructor,这个constructor指向当前的函数对象
function Person() {
}
console.log(Person.prototype.constructor) // [Function: Person]
console.log(p1.__proto__.constructor) // [Function: Person]
console.log(p1.__proto__.constructor.name) // Person
三、面向对象的特征—继承
3.1 面向对象三大特性
封装、继承、多态
- 封装:我们前面将属性和方法封装到一个类中,可以称之为封装的过程
- 继承:继承是面向对象中非常重要的,不仅仅可以减少重复代码的数量,也是多态的前提(纯面向对象中)
- 多态:不同的对象在执行时表现出不同的形态
3.2 继承是做什么的?
继承可以帮助我们将重复的代码和逻辑抽取到父类中,子类只需要直接继承过来使用即可。
继承也是多态的前提。
3.3 JavaScript中如何实现继承
使用JavaScript原型链的机制
四、JavaScript原型链
从一个对象上获取属性,如果在当前对象中没有获取到就会去它的原型上面获取
五、Object
5.1 Object的原型
那么什么地方是原型链的尽头:Object的原型对象
console.log(obj.__proto__.__proto__.__proto__) //[Object: null prototype] {}
这时会发现打印出来的结果