原型
定义
原型:是对象(prototype
),它提供了一套属性和方法可供后代继承。
- 原型是 function 对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法
- 利用原型的特点和概念,可以提取共有属性
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 的原型对象
- 对象如何查看原型 :隐式属性
_proto_
- 对象如何查看对象的构造函数:构造器
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
new 关键字做了什么
- 一个继承自
Play.prototype
的新对象 p1/p2 被创建 p1.__proto__ === Player.prototype
,也就是说p1.__proto__
指向Player.prototype
- 将
this
指向新创建的对象 p1/p2 - 返回新对象
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 函数
- 用new Object() 的方式新建了一个对象 obj
- 取出第一个参数,就是我们要传入的构造函数。此外因为 shift 会修改原数组,所以 arguments 会被去除第一个参数
- 将 obj 的原型指向构造函数,这样 obj 就可以访问到构造函数原型中的属性
- 使用 apply,改变构造函数 this 的指向到新建的对象,这样 obj 就可以访问到构造函数中的属性
- 返回 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