开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天,点击查看活动详情
原型
在 JavaScript 中是使用构造函数来新建一个对象的,每一个构造函数的内部都有一个 prototype 属性,它的属性值是一个对象,这个对象包含了可以由该构造函数的所有实例共享的属性和方法。
当使用构造函数新建一个对象后,在这个对象的内部将包含一个指针,这个指针指向构造函数的 prototype 属性对应的值,在 ES5 中这个指针被称为对象的原型。一般来说不应该获取到这个值的,但是现在浏览器中都实现了 __proto__ 属性来访问这个属性。
但是最好不要使用这个属性,因为它不是规范中规定的。可以通过 Object.getPrototypeOf() 这个方法来获取对象的原型。
原型链
当访问一个对象的属性时,如果这个对象内部不存在这个属性,那么它就会去它的原型对象里找这个属性,这个原型对象又会有自己的原型,于是就这样一直找下去,也就是原型链的概念。
放一张经典大图
有点乱,不要紧
我们自己手画一遍
打开 excalidraw
根据刚刚的定义,构造函数都有一个 prototype 属性
使用构造函数创建的实例对象,通过 __proto__ 指向构造函数的 prototype
构造函数也是函数,它的上一级是 Function
原型对象也是对象,对象的上一级是 Object
大致可以总结出:可以通过
__proto__来寻找自己的上一级
把图合起来看
虽然有一些是经典图里面没有的,但是至少看起来比较简洁了。
原型链的终点
原型链的终点是 null,即 Object.prototype.__proto__=== null。
原型修改、重写
function Person(name) {
this.name = name
}
// 修改原型
Person.prototype.getName = function() {}
var p = new Person('hello')
// 实例对象通过 __proto__ 指向构造函数的 prototype
console.log(p.__proto__ === Person.prototype) // true
console.log(p.__proto__ === p.constructor.prototype) // true
// 重写原型
Person.prototype = {
getName: function() {}
}
let p = new Person('hello')
console.log(p.__proto__ === Person.prototype) // true
// p.constructor ===> Object
console.log(p.__proto__ === p.constructor.prototype) // false
如果希望可以成立,就要用constructor指回来
Person.prototype = {
getName: function() {}
}
let p = new Person('hello')
p.constructor = Person
console.log(p.__proto__ === Person.prototype) // true
console.log(p.__proto__ === p.constructor.prototype) // true
小练习🙋:
实例对象通过 proto 指向构造函数的 prototype
p.__proto__ // Person.prototype
原型对象也是对象,对象的上一级是 Object
Person.prototype.__proto__ // Object.prototype
原型对象也是对象,对象的上一级是 Object
p.__proto__.__proto__ // Object.prototype
p.
__proto__.constructor ===> Person。Person.prototype:原型对象也是对象,对象的上一级是 Object
p.__proto__.constructor.prototype.__proto__ // Object.prototype
原型对象也是对象,对象的上一级是 Object
Person.prototype.constructor.prototype.__proto__ // Object.prototype
p.__proto__.constructor // Person
Person.prototype.constructor // Person
更多练习题可以查看:juejin.cn/post/694303…