原型链

81 阅读2分钟

原型链

原型链的概念最早由 JavaScript 的创造者 Brendan Eich 发明,

在 JavaScript 中,每个对象都有一个内部链接到另一个对象的属性,该对象被称为原型。如果我们访问一个对象的属性或方法,但该对象本身没有定义这个属性或方法,JavaScript 引擎会沿着原型链向上查找,直到找到该属性或方法或者到达原型链的顶端(通常是 Object.prototype)。

每个对象都有proto属性,但是只有函数对象才有 prototype 属性

// 函数对象
function Person(name) {
  this.name = name;
}

Person.prototype.sayHello = function () {
  console.log("Hello, my name is " + this.name);
};

// 普通对象
var obj = {
  prop: "value",
};

console.log(typeof Person); // 输出:function
console.log(typeof obj); // 输出:object

console.log(obj.__proto__); // 输出:Object.prototype
console.log(Person.prototype); // 输出:Person.prototype
console.log(obj.hasOwnProperty("prop")); // 输出:true

var person = new Person("Alice");
person.sayHello(); // 输出:Hello, my name is Alice

"new"关键字用于创建一个对象实例,同时将该对象的原型链连接到构造函数的原型对象上。

  • 创建一个空对象。
  • 将该空对象的原型指向构造函数的原型对象(即构造函数.prototype)。
  • 将构造函数内部的 this 指向该空对象。
  • 执行构造函数内部的代码,为该空对象添加属性和方法。
  • 返回该空对象作为"new"操作符的结果。

ES6 类语法

ES2015(也称为 ES6)引入了类语法,使得定义和使用对象更加简洁和易读。 使用 class 关键字定义的类实际上也是一种函数对象。虽然我们通常称其为类对象,但在语言层面上,它仍然是一个特殊的函数对象。

class Person {
  constructor(name) {
    this.name = name;
  }
  sayHello() {
    console.log("Hello, my name is " + this.name);
  }
}

console.log(typeof Person); // 输出:function

var person = new Person("Alice");
person.sayHello(); // 输出:Hello, my name is Alice

函数对象和类对象在 JavaScript 中有一些相似之处:都是对象、都可以拥有属性和方法、都可以被函数调用、都可以通过原型链继承属性和方法 。

但也有一些关键的区别:

差异点函数对象类对象
语法函数声明或函数表达式class 关键字
内部方法 constructor用于创建实例对象和初始化属性
继承方式通过原型链extends 关键字(本质也是原型链)
方法枚举性可枚举默认不可枚举
静态方法定义无法直接定义静态方法使用 static 关键字定义静态方法