导航


HTML

CSS

JavaScript

浏览器 & 网络

版本管理

框架

构建工具

TypeScript

性能优化

软实力

算法

UI、组件库

Node

冷门技能

原型 prototype

⭐️ prototype 是函数的属性,其值是个对象

function Handphone() {}
console.log(Handphone.prototype);

Untitled

prototype 是构造函数中的,构造出的每个实例对象的公共祖先

所有被该构造函数构造出来的对象,都可以继承原型上的属性和方法

function Handphone(color, brand) {
	this.color = color;
  this.brand = brand;
}
Handphone.prototype.rom = '64G';
Handphone.prototype.ram = '6G';

var hp1 = new Handphone('red', '小米');
var hp2 = new Handphone('black', 'huawei');

console.log(hp1.rom);
console.log(hp2.ram);

Untitled

⭐️ constructor 指向构造函数本身

function Handphone(color, brand) {
	this.color = color;
  this.brand = brand;
}
console.dir(Handphone);
console.dir(Handphone.prototype.constructor);

Untitled

constructor 可以被修改

function Telephone() {}
function Handphone(color, brand) {
	this.color = color;
  this.brand = brand;
}
Handphone.prototype = {
	constructor: Telephone
}
console.log(Handphone.prototype)

Untitled

⭐️ proto 是实例化以后的结果

function Car() {
	var this = {
  	__proto__: Car.prototype
  }
}
Car.prototype.name = 'Benz';
var car = new Car();
console.log(car);

Untitled

function Person() {}
Person.prototype.name = '张三';

var p1 = {
	name: 'lance'
}

var person = new Person();
console.log(person.name);
person.__proto__ = p1;
console.log(person.name);

Untitled

⭐️ 实例化对象以后再来修改构造函数的 prototype,不影响该对象的原型属性 ,因为修改后的 prototype 指向了新的对象,不影响原来的 prototype,但影响原来 prototype 下的 constructor

Car.prototype.name = 'Benz';
function Car() {}
var car = new Car();
Car.prototype = { // 实例化之后赋值,car还是原来的
	name: 'Mazda'
}
console.log(car.name); //答案:																										 Benz

console.dir(Car);
console.dir(car);
console.log(car.__proto__.constructor === Car); //答案:               true
console.log(Car.prototype.constructor === Object.prototype.constructor); //                 true

Untitled

Car.prototype.name = 'Benz';
function Car() {}
var car = new Car();
Car.prototype.name = 'hhhh';
console.log(car.name); // 																													hhhh

Untitled

↑注意是直接替换 Car.prototype 还是改 Car.prototype 对象下边的属性↑

Car.prototype.name = 'GC';
function Car() {}
var car = new Car();
Car.prototype = { // 																									实例化之后赋值,car还是原来的
	name: 'Lance'
}
console.log(car.name); //																										 GC
var car2 = new Car();

console.log(Car);
console.log(car);
console.log(car2);
console.log(car.__proto__.constructor === Car); //																			 true

Untitled

原型结构图

Untitled

原型链

沿着原型__proto__往上不断找属性的这条链条叫做原型链

Professor.prototype.tSkill = 'Java';
function Professor() {}
var professor = new Professor();

Teacher.prototype = professor;
function Teacher() {
	this.mSkill = 'JS/JQ';
}
var teacher = new Teacher();

Student.prototype = teacher;
function Student() {
	this.pSkill = 'HTML/CSS';
}
var student = new Student();

console.log(student);

// student: {
//   pSkill: 'HTML/CSS',
//   __proto__: { // teacher
//   	mSkill: 'JS/JQ',
//     __proto__: { // professor
//       __proto__: { // Professor.prototype
//         tSkill: 'Java',
//       	constructor: Professor,
//         __proto__: Object.prototype
//       }
//     }
//   }
// }

student.__proto__.__proto__.__proto__ === Professor.prototype; // true
student.__proto__.__proto__.__proto__.__proto__ === Object.prototype; // true

Untitled

⭐️ 原型链的顶端是 Object.prototype

Professor.prototype.tSkill = 'Java';
function Professor() {}
var professor = new Professor();

Teacher.prototype = professor;
function Teacher() {
	this.mSkill = 'JS/JQ';
}
var teacher = new Teacher();

Student.prototype = teacher;
function Student() {
	this.pSkill = 'HTML/CSS';
}
var student = new Student();

console.log(professor, Object.prototype);

Untitled

原型链结构图

Untitled

⭐️ Object 与 Function 之间的关系

// Object.prototype 是原型链的顶端
console.log(Object.prototype.__proto__ === null) // true

// Function可以理解为制造一切函数的机器,且自身也是由自己制造的,所以
console.log(Function.__proto__ === Function.prototype); // true

// Object从「对象」角度来讲,是由构造函数 Function 生产的
console.log(Object.__proto__ === Function.prototype) // true

// Function虽然由自身生产,但生产“机器”总要一个模板吧,这个模板对象(Function.prototype.__proto__)就是 Object.prototype
console.log(Function.prototype.__proto__ === Object.prototype) // true

// Object作为一个机器可以看做是有由Function制造出来的
// 而Function作为一个对象可以看做是由Object制造出来的。
console.log(Object instanceof Function) // true
console.log(Function instanceof Object) // true

// String 作为「对象」,是由构造函数 Function 生产的
console.log(String.__proto__ === Function.prototype) // true
// String.prototype 是个对象,是有 Object 生产的
console.log(String.prototype.__proto__ === Object.prototype) // true

function Person() {}
// 自定义构造函数作为「对象」,也是 Function 生产的
console.log(Person.__proto__ === Function.prototype) // true
console.log(Person.prototype.__proto__ === Object.prototype) // true
// Person 和 Object 一样,都是构造函数,都是有 Function 生产出来的对象
console.log(Person.__proto__ === Object.__proto__);

function Student() {
  Person.call(this)
}
Student.prototype = Object.create(Person.prototype)
Student.prototype.constructor === Student
console.log(Student.__proto__ === Function.prototype) // true
console.log(Student.prototype.__proto__ === Person.prototype) // true

修改原型上的值

⭐️ 原型的引用值的属性可以修改

Professor.prototype.tSkill = 'Java';
function Professor() {}
var professor = new Professor();

Teacher.prototype = professor;
function Teacher() {
	this.mSkill = 'JS/JQ';
  this.success = {
  	alibaba: '28',
    tencent: '20'
  }
}
var teacher = new Teacher();

Student.prototype = teacher;
function Student() {
	this.pSkill = 'HTML/CSS';
}

var student = new Student();
console.log({ "修改student引用值之前的success": student.success });

// 🌰 此处chrome控制台先打印,再执行下边语句
// 修改引用值
student.success.baidu = '100';
console.log({ "修改student引用值之后的student": student });

Untitled

⭐️ 修改基本值,不影响原型属性

Professor.prototype.tSkill = 'Java';
function Professor() {}
var professor = new Professor();

Teacher.prototype = professor;
function Teacher() {
	this.mSkill = 'JS/JQ';
  this.success = {
  	alibaba: '28',
    tencent: '20'
  }
}
var teacher = new Teacher();

Student.prototype = teacher;
function Student() {
	this.pSkill = 'HTML/CSS';
}

var student = new Student();

// 修改基本类型
console.log({ "修改student基本类型之前的success": student.success });
student.success = 666;
console.log({ "修改student基本类型之后的student": student });

Untitled

修改一个原型上不存在的引用值,报错

Professor.prototype.tSkill = 'Java';
function Professor() {}
var professor = new Professor();

Teacher.prototype = professor;
function Teacher() {
	this.mSkill = 'JS/JQ';
  this.success = {
  	alibaba: '28',
    tencent: '20'
  }
}
var teacher = new Teacher();

Student.prototype = teacher;
function Student() {
	this.pSkill = 'HTML/CSS';
}

var student = new Student();

// 修改不存在的引用类型
student.profile.name = 'lance';
// 报错: Cannot set property 'name' of undefined

⭐️ 原始值自增

Professor.prototype.tSkill = 'Java';
function Professor() {}
var professor = new Professor();

Teacher.prototype = professor;
function Teacher() {
	this.mSkill = 'JS/JQ';
  this.students = 500;
}
var teacher = new Teacher();

Student.prototype = teacher;
function Student() {
	this.pSkill = 'HTML/CSS';
}
var student = new Student();
console.log(student.students);
student.students++;
console.log(teacher);
console.log(student);

Untitled

分析:学生的 students 值变了,professor 的 students 值没变。过程是:

  1. student.students++; => student.students = student.students + 1
  2. =赋值右边 student 自身没有 students,在原型上读取 students 值,再 + 1 计算
  3. =赋值左边 student.students 是个原始值,则在自身上添加 students 属性
  4. 最后赋值

谁调用,this 指向谁

function Car() {
	this.brand = 'Benz';
}
Car.prototype = {
	brand: 'Mazda',
  intro: function() {
  	console.log('我是' + this.brand + '车');
  }
}
var car = new Car();
car.intro();
console.log(car);
Car.prototype.intro();

Untitled

function Person() {
	this.smoke = function() {
  	this.weight--;
  }
}
Person.prototype = {
	weight: 130
}
var person = new Person();
person.smoke();
person.weight;
console.log(person);
console.log(Person.prototype);

Untitled