JS - 原型、原型链

186 阅读2分钟

前置知识

对初学者来说一般很难理解原型和原型链的概念,但是原型和原型链又是 JS 中组中非常重要的知识点之一

  • 想要弄清楚原型和原型链,需要清楚:__ proto__ 、prototype、constructor
  • JS 中对象和函数之间的关系:函数是对象的一种
  • 函数、构造函数之间的区别:任何函数都可以作为构造函数,只有通过 new 关键字调用才可以把函数称为构造函数。
// 定义一个普通函数 Person 
function Person() {
	this.name = name
	
}
// 通过 new 关键字调用 Person 函数 创造了 p 实例
// 此时 Person 是一个构造函数 
var p = new Person()

原型、原型链

原型 —— prototype

  • 原型 prortotype 是构造函数的属性
  • prototype 本身是一个对象
  • prototype 是一个存储空间,存储的信息其后代都可以使用
  • 最终指向 空

原型链 __ proto__

  • 实例化构造函数的结果,属于实例对象(函数)独有的属性
  • 是一个容器,存储构造函数的 prototype
  • 是一个隐式属性,系统隐式添加到实例对象上

构造函数 —— constructor

  • 对象才有的属性
  • 一定是一个函数

以上三张关系图,反复多看几次、理解一下可以清楚明白其三者之间的关系

原型、原型链案例分析

原型

  • 原型上的属性,其后代都可以访问
function Car() {
  this.color = "red";
  this.brand = "奔驰";
}
Car.prototype.source= 'Europe' // 设置 Car 函数对象的原型
var car1 = new Car();

console.log(Car) // {source: 'Europe', constructor: f Car()}
console.log(car1); // {brand: "奔驰",  color: "red"}
console.log(car1.source) // Europe,原型上的属性,其后代都可以访问并使用

原型链

  • __ proto__ 是可以修改的,修改后的值直接覆盖之前的值
function Car(){
	this.__proto__ = Car.prototype //实例化之后 隐式的给this 添加一个 __proto__属性
}
Car.prototype.name = 'Bena'
var car = new Car()
console.log(car)


function Car() {}
Car.prototype.name = "";
var car1 = new Car();

Car.prototype.name = 'Benz' // 修改 prototype.name 属性
Car.prototype = { // 重写 prototype 属性
	name: "Mazda" 
}
// 重写 prototype 属性 修改了实例化对象中 this.__proto__ 容器中包含的prototype 的值

console.log(car1.name); // Benz
// 以 Car.prototype.name = 'xxx' 的方式会直接修改 Car.prototype.name 的属性值
// car1 实例化于重写 Car.prototype 属性之前 ,因此他当前的 name 指向 Benz
// car1.__proto__ --> Car.prototype ,因此访问的是修改前的 Car.prototype.name

console.log(Car.prototype.name); // Mazda
// 重写 Car.prototype.name 修改之后 就会去覆盖之前的属性值

原型、原型链 是一个比较抽象的知识点,在工作中也不常用,因此需要反复的巩固,个人也会出现长时间不看,混乱的情况。