对象、函数、原型之间的关系

在 JavaScript 中,对象 、函数 和 原型 是三者紧密联系的核心概念。它们共同构成了 JavaScript 中面向对象编程的基石,并通过原型链实现了继承与代码复用。本文将从对象、函数、原型的基础概念到它们之间的关系进行详细的讲解,帮助你理解 JavaScript 的底层机制。

1. 什么是对象?

在 JavaScript 中,一切皆对象。对象是包含属性和方法的容器。属性可以是基本数据类型,如字符串、数字等;方法则是一个可以执行的函数。

javascript 复制代码
var person = {
    name: "浮游",
    age: 20,
    greet: function() {
        console.log("Hello, I am " + this.name);
    }
};

console.log(person.name);  // 浮游
person.greet();  // Hello, I am 浮游

上面的 person 是一个对象,它包含了两个属性 name 和 age,以及一个方法 greet。

2. 什么是函数?

JavaScript 中的函数实际上也是对象。与其他对象不同的是,函数对象可以被调用。此外,每个函数在创建时都会自动拥有两个属性:prototype 和 __proto__。

javascript 复制代码
function Foo() {}
console.log(typeof Foo); // function
console.log(Foo instanceof Object); // true

可以看出,函数本质上是对象,具有对象的一些特性。同时,它们也有特殊的属性,方便实现继承与原型链机制。

函数的两大属性:
  • prototype:每个函数都有的属性,指向函数的原型对象,用于继承。
  • __proto__:指向创建该对象的构造函数的原型。

3. 什么是原型?

原型 是实现继承的核心概念。每个 JavaScript 对象都有一个隐藏的属性 [[Prototype]],可以通过 __proto__ 来访问。原型是一个对象,它用于实现对象之间的属性和方法的共享。

3.1 原型对象 (prototype)

每个函数对象在创建时都会有一个 prototype 属性,该属性指向原型对象,而这个原型对象中包含了通过该函数创建的实例所共享的属性和方法。

javascript 复制代码
function Person(name, age) {
    this.name = name;
    this.age = age;
}

// 向原型对象中添加方法
Person.prototype.greet = function() {
    console.log("Hello, I am " + this.name);
};

var person1 = new Person("浮游", 20);
var person2 = new Person("熠星", 24);

person1.greet();  // Hello, I am 浮游
person2.greet();  // Hello, I am 熠星

在上面的例子中,Person 函数有一个 prototype 属性,所有通过 Person 创建的对象 (person1 和 person2) 都共享 prototype 中的 greet 方法。

3.2 隐式原型 (__proto__)

每个 JavaScript 对象都有一个 __proto__ 属性,指向其构造函数的原型。通过这个属性,对象可以继承构造函数原型上的属性和方法。__proto__ 是对象与原型之间的链接,形成了原型链。

javascript 复制代码
console.log(person1.__proto__ === Person.prototype); // true
console.log(Person.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__); // null, 原型链的顶端

person1 通过 __proto__ 链接到 Person.prototype,Person.prototype 又通过 __proto__ 链接到 Object.prototype,这就是 JavaScript 原型链的基础。

4. 对象、函数与原型的关系

JavaScript 是基于原型的语言,这意味着每个对象都从一个"原型"对象继承属性和方法。

  • 函数是对象 :函数本身是一个对象,有 __proto__ 属性,它指向 Function.prototype。
  • 对象有原型 :每个对象都有一个 __proto__ 属性,它指向它的构造函数的 prototype。
  • 原型链 :通过 __proto__ 属性,对象可以访问其原型对象上的属性和方法。如果在自身对象中找不到某个属性,它会沿着原型链向上查找。
4.1 构造函数与实例对象的关系
javascript 复制代码
function Car(model) {
    this.model = model;
}

Car.prototype.drive = function() {
    console.log(this.model + " is driving");
};

var car1 = new Car("Toyota");
var car2 = new Car("Honda");

car1.drive();  // Toyota is driving
car2.drive();  // Honda is driving

console.log(car1.__proto__ === Car.prototype);  // true
console.log(Car.prototype.constructor === Car);  // true
  • car1 和 car2 是由构造函数 Car 创建的实例对象。
  • 它们的 __proto__ 属性都指向 Car.prototype。
  • Car.prototype.constructor 指向 Car 构造函数本身。
4.2 原型链的查找机制

当你访问一个对象的属性时,JavaScript 引擎首先会在对象本身的属性中查找。如果找不到,它会沿着原型链在其原型对象上查找。这个过程会持续到原型链的顶端------Object.prototype。

javascript 复制代码
console.log(car1.toString()); // [object Object]

car1 并没有 toString 方法,但是它沿着原型链找到了 Object.prototype.toString,因此可以调用它。

5. 原型链

原型链 是指对象通过 __proto__ 一直向上查找,直到找到 Object.prototype 为止。如果在整个原型链中没有找到该属性,则返回 undefined。

javascript 复制代码
console.log(car1.__proto__); // Car.prototype
console.log(car1.__proto__.__proto__); // Object.prototype
console.log(car1.__proto__.__proto__.__proto__); // null, 原型链的顶端

6. 总结

  • 对象:JavaScript 中的任何实体都是对象,它们可以有属性和方法。
  • 函数 :JavaScript 中的函数也是对象,它们有额外的 prototype 属性,用于支持原型链和继承。
  • 原型 :原型是对象的共享属性和方法的容器,通过原型链实现继承。每个对象都有一个 __proto__ 属性,指向它的构造函数的 prototype。
对象、函数与原型的关系:
text 复制代码
对象 --通过 __proto__ --> 构造函数的 prototype --通过 constructor--> 构造函数

通过这个关系,JavaScript 实现了灵活的继承机制,使得我们能够通过原型链实现对象的扩展和代码的复用。

7. 关键要点

  • 原型链是 JavaScript 继承机制的核心,通过它可以实现属性和方法的查找。
  • 每个函数都有一个 prototype 属性,指向它的原型对象,原型对象上的属性和方法可以被该构造函数的实例对象共享。
  • 每个对象都有一个 __proto__ 属性,指向它的构造函数的原型对象。
  • 原型链的终点是 Object.prototype,它是所有对象的最终原型。
相关推荐
qq_406981036 小时前
c++的decltype是什么
开发语言·c++
坤坤子吖6 小时前
算法学习——单调队列
开发语言·c++·笔记·学习·算法
我就是全世界6 小时前
OpenCode Go 套餐划算吗:先看你用哪个模型
开发语言·后端·golang
螺丝钉tina6 小时前
[Playwright] [02]常用命令与调试:Debug UI、Mode和 Trace Viewer
开发语言·javascript·测试工具·ui·自动化
杜 硕6 小时前
从零开始的C++生活——第六讲——01
开发语言·c++·生活
淡漠的蓝精灵7 小时前
web.py:一个简单到极致的 Python Web 框架
开发语言·前端·python·其他
乌暮7 小时前
请求进门先安检:Spring 拦截器与统一功能实战指南
java·开发语言·后端·学习·spring
开开心心就好7 小时前
竖式除法出题工具,整除余数混合模式
运维·服务器·前端·javascript·ocr·perl·1024程序员节
এ慕ོ冬℘゜7 小时前
JS 事件循环、宏任务微任务:单线程底层原理 + 执行顺序
开发语言·javascript·ecmascript
其实防守也摸鱼7 小时前
Chrome 扩展安全攻防实录:从攻击面到防御实践
开发语言·前端·网络·chrome·安全·web安全·php