原型和原型链

146 阅读2分钟

原型

定义

原型:是对象(prototype),它提供了一套属性和方法可供后代继承。

  1. 原型是 function 对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法
  2. 利用原型的特点和概念,可以提取共有属性
function Player() {
    this.color = 'red';
}

Player.prototype.start = function () {
    console.log(111111);
}

const whitePlayer = new Player();
const blackPlayer = new Player();

原型上添加属性或者方法的好处

优点:只在内存中创建一次,实例化的对象都会指向这个 prototype 对象。
如果不通过原型的方式,每生成一个新对象,都会在内存中新开辟一块存储空间,当对象变多之后,性能会变得很差。
如何添加:

// 这样写,显得非常麻烦
Player.prototype.xx1 = function () {};
Player.prototype.xx2 = function () {};
Player.prototype.xx3 = function () {};
// 这样写,又有可能覆盖原先原型中的属性或者方法
Player.prototype = {
  xx1: function(){},
  xx2: function(){},
  ...
};
// 解构,对象合并
{ 
    ...player,{ xx1: function(){} } 
}

如何找到 Player 的原型对象

  1. 对象如何查看原型 :隐式属性 _proto_
  2. 对象如何查看对象的构造函数:构造器 constructor
function Player(color) {
  this.color = color;
}

Player.prototype.start = function () {
  console.log(color + "下棋");
};

const whitePlayer = new Player("white");
const blackPlayer = new Player("black");

console.log(blackPlayer.__proto__); // Player {}
// 可以通过 Object.getPrototypeOf 来获取 __proto__
console.log(Object.getPrototypeOf(blackPlayer)); // Player {}
console.log(Player.prototype); // Player {}
console.log(Player.__proto__); // [Function]

blackPlayer.__proto__ === Player.prototype // true

prototype.png

new 关键字做了什么

  1. 一个继承自 Play.prototype 的新对象 p1/p2 被创建
  2. p1.__proto__ === Player.prototype,也就是说p1.__proto__指向Player.prototype
  3. this 指向新创建的对象 p1/p2
  4. 返回新对象

4.1 如果构造函数没有显式的返回值,那么返回 this
4.2 如果构造函数有显式的返回值,是基本类型(number string boolean)那么返回 this
4.3 如果构造函数有显式的返回值,是引用类型,比如{a: 1},那么返回{a: 1}

function Player(color) {
    this.color = color; // this 
    // return 1; // this
    // return {name: 'fj'}; // {name: 'fj'}
}
const white = new Player('white');
console.log(white);

手写 new 函数

  1. 用new Object() 的方式新建了一个对象 obj
  2. 取出第一个参数,就是我们要传入的构造函数。此外因为 shift 会修改原数组,所以 arguments 会被去除第一个参数
  3. 将 obj 的原型指向构造函数,这样 obj 就可以访问到构造函数原型中的属性
  4. 使用 apply,改变构造函数 this 的指向到新建的对象,这样 obj 就可以访问到构造函数中的属性
  5. 返回 obj
function objectFactory() {
  let obj = new Object();
  let Constructor = [].shift.call(arguments);
  obj.__proto__ = Constructor.prototype;
  let ret = Constructor.apply(obj, arguments);
  return typeof ret === "object" ? ret : obj;
}

原型链

定义

原型链:由 __proto__prototype 链接的链条
当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层为止。最顶层也没有时返回 undefined

Object.prototype.name = 'Object';

function Player(){};
Player.prototype.name = 'prototype';

const p1 = new Player();
p1.name = 'p1';

console.log(p1.name); // p1
delete p1.name;
console.log(p1.name); // prototype
delete Player.prototype.name;
console.log(p1.name); // Object
delete Object.prototype.name;
console.log(p1.name); // undefined