JavaScript 对象原型

JavaScript 是一种基于原型的面向对象语言,每个对象都有其原型对象,原型可以说是对象的模板,对象从原型继承属性和方法。

JavaScript 是一种基于原型的面向对象语言,每个对象都有其原型对象,原型可以说是对象的模板,对象从原型继承属性和方法。

在上一章中,我们学习了如何使用对象构造函数

function Person(first, last, age, eyecolor) {
  this.firstName = first;
  this.lastName = last;
  this.age = age;
  this.eyeColor = eyecolor;
}

const myFather = new Person("John", "Doe", 50, "blue");
const myMother = new Person("Sally", "Rally", 48, "green");

我们还了解到您不能向现有对象构造函数添加新属性:

Person.nationality = "English";

要将新属性添加到构造函数,您必须将其添加到构造函数:

function Person(first, last, age, eyecolor) {
  this.firstName = first;
  this.lastName = last;
  this.age = age;
  this.eyeColor = eyecolor;
  this.nationality = "English";
}

原型继承

所有 JavaScript 对象都从原型继承属性和方法:

  • Date 对象继承自 Date.prototype
  • Array 对象继承自 Array.prototype
  • Person 对象继承自 Person.prototype

Object.prototype 是对原型继承链的顶端。

Date 对象、 Array 对象和 Person 对象都继承自 Object.prototype

向对象添加属性和方法

有时您希望向给定类型的所有现有对象添加新属性(或方法)。

有时您想向对象构造函数添加新的属性(或方法)。

使用 prototype 属性

构造函数的 prototype 返回原型对象。我们可以通过添加属性或者方法来扩展原型对象。当在原型对象上添加了新的属性和方法后,基于此构造函数的所有对象都拥有了新的属性和方法。

向 Person 原型添加新的属性:

function Person(first, last, age, eyecolor) {
  this.firstName = first;
  this.lastName = last;
  this.age = age;
  this.eyeColor = eyecolor;
}

Person.prototype.nationality = "English";

const myFather = new Person("John", "Doe", 50, "blue");
myFather.nationality;

向 Person 原型添加新的方法:

function Person(first, last, age, eyecolor) {
  this.firstName = first;
  this.lastName = last;
  this.age = age;
  this.eyeColor = eyecolor;
}

Person.prototype.name = function () {
  return this.firstName + " " + this.lastName;
};

const myFather = new Person("John", "Doe", 50, "blue");
myFather.name();

通过原型扩展 String

有时候我们需要给 String 添加一些通用的功能,就可以通过扩展 String.prototype 来达到此目的。

以下展示了通过扩展 String.prototype 实现一个需求的过程。

需求:

给 String 添加一个 format 方法,要求能够按照方法参数的值格式化字符串。比如,我传入 "{0} {1}".format("Hello", "World") 应该返回 "Hello World"

  • 参数动态的,可以多个参数
  • 第 1 个参数替换模板字符串中的 {0},第 2 个参数替换 {1},依次类推

实现:

// 修改原型之前先检测一下是否已经有同名的方法或者属性
if (!String.prototype.format) {
  String.prototype.format = function () {
    var args = arguments;
    return this.replace(/{(\d+)}/g, function (match, number) {
      return typeof args[number] != "undefined" ? args[number] : match;
    });
  };
} else {
  console.log("String.prototype.format 已存在");
}

测试:

先打开浏览器的开发者工具中的控制台,然后拷贝上面的代码后回车,再拷贝下面的代码到控制台后,回车,看一下输出是否和预期一致。

console.log("{0} {1}".format("Hello", "World"));
console.log("我最喜欢的动物是: {0}".format("狗"));