一道简单的题目区分函数对象实例对象

189 阅读3分钟

前言

最近在通过面试题对自己的基础进行一些查漏补缺,顺便记录一下📝 不想用题目的形式一题题写面试题的题解,这些已经有很多大佬整理得很好了,多看一看再梳理一下就能记住 我更希望以文章的形式去加深对某个知识点的理解,开锤

一道简单的题目:

function Person(name) {
    this.name = name
}

// 函数对象上的方法
Person.say = function () {
    console.log('----');
}

// 原型对象上的方法
Person.prototype.say = function () {
    console.log('===');
}

const p = new Person('Tom')

// 函数对象执行的是函数对象的上方法 clg(---)
Person.say()
// 实例对象p执行的是原型对象上的方法 clg(===)
p.say()

当涉及到JavaScript中的对象、构造函数和原型时,有一些重要的概念需要理解。

在JavaScript中,构造函数是用于创建对象在例子中,Person 函数充当了构造函数的角色。当你使用 new 关键字来调用构造函数时,它会创建一个新的对象,并将属性和方法分配给这个对象。

function Person(name) {
    this.name = name;
}

函数对象上的方法

一个有趣的特性是,JavaScript中的函数本身也是对象。这意味着你可以在函数对象上定义方法,这些方法可以被函数本身调用。在你的例子中,你定义了一个在 Person 函数对象上的 say 方法:

Person.say = function () {
    console.log('----');
}

当你调用 Person.say() 时,它会在函数对象上执行这个方法,输出 ----

原型对象上的方法

除了函数对象上的方法,JavaScript还提供了一种更为高效的方法共享机制,即原型。原型也是一个对象,每个构造函数都有一个关联的原型对象,你可以在原型对象上定义方法和属性,这些方法和属性会被由构造函数创建的对象共享。 (也就是会被new出来的实例对象共享)

在我们的例子中,定义了一个在 Person.prototype 上的 say 方法:

Person.prototype.say = function () {
    console.log('===');
}

当你通过构造函数创建一个实例(例如 const p = new Person('Tom')),这个实例将继承原型上的方法。因此,p.say() 会输出 ===

回过头来,让我们再看会这一段代码:

// 构造函数
function Person(name) {
    this.name = name
}

// 函数对象上的方法
Person.say = function () {
    console.log('----');
}

// 原型对象上的方法
Person.prototype.say = function () {
    console.log('===');
}

const p = new Person('Tom')

// 函数对象执行的是函数对象的上方法 clg(---)
Person.say()
// 实例对象p执行的是原型对象上的方法 clg(===)
p.say()

我们就能够很好的理解为什么两种say方法执行输出的结果不同了,因为一个是函数对象,一个是实例对象,正因为函数的特殊性——JavaScript中的函数本身也是对象。所以才会有2种绑定say方法的方式。

理解这个概念对我们看api文档也很有帮助:

在翻阅Promise的Mdn文档的时候,我们可以看到有些方法是定义在Promise.prototype上的,而有的是直接定义在Promise

定义在prototype上的方法,我们都是通过实例对象去调用,例如

const p = new Promise((resolve,reject)=>{
  // ...
})

p.then() //用的是实例p去调用

而定义在Promise函数对象上的,例如reject的语法糖,我们是这么调用的

const rejectedPromise = Promise.reject('Something wrong.');

希望通过这个示例,能加深你对函数对象和实例对象的理解。

封面.jpg