You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript构造函数与prototype定义方法的正确性及实例访问疑问

构造函数内部定义方法 vs 挂载到prototype的区别与解惑

嘿,这问题问得特别好,很多刚接触JS构造函数的开发者都会有这个困惑,我来给你掰扯清楚~

两种写法都合法,只是适用场景不同

首先明确:构造函数内部定义方法和挂载到.prototype上都是正确的写法,但它们的工作机制和适用场景有很大区别:

1. 构造函数内部定义方法

就像你示例里的写法:

function Person(first, last, age, gender, interests) {
  this.name = { first, last };
  this.bio = function() {
    alert(this.name.first + ' ' + this.name.last + ' is ' + this.age + ' years old.'+ ' He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
  };
}
  • 每次用new Person()创建实例时,这些方法都会重新生成一份副本——每个实例都拥有属于自己的独立方法。
  • 优势:方法内部可以直接访问构造函数里的局部变量(如果有的话),而且单个实例的方法可以被独立修改,不会影响其他实例。
  • 劣势:如果创建大量实例,会浪费内存,因为每个实例都重复持有逻辑完全相同的方法。

2. 挂载到.prototype上定义方法

这也是MDN更推荐的写法:

function Person(first, last, age, gender, interests) {
  this.name = { first, last };
  this.age = age;
  this.gender = gender;
  this.interests = interests;
}
Person.prototype.bio = function() {
  alert(this.name.first + ' ' + this.name.last + ' is ' + this.age + ' years old.'+ ' He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
};
Person.prototype.greeting = function() {
  alert('Hi! I\'m ' + this.name.first + '.');
};
  • 所有通过new Person()创建的实例,都会共享prototype上的方法——方法只在内存中存在一份,所有实例都指向同一个方法引用。
  • 优势:极大节省内存,而且修改prototype上的方法后,所有已存在的实例都会立刻获取到更新后的方法。
  • 劣势:方法无法直接访问构造函数内部的局部变量(只能通过this访问实例的属性),如果某个实例重写了该方法,会覆盖prototype上的版本,但不会影响其他实例。

为什么你的示例没用到prototype,实例却能访问方法?

你对MDN教程的描述可能产生了小误解——其实构造函数内部通过this.xxx = function(){}定义的方法,是直接挂载到每个实例对象上的“自有属性”,不属于prototype链的继承范畴,但实例本身确实能直接访问这些成员。

MDN所说的“只有prototype上的属性和方法对实例可用”,准确表述应该是:实例会继承prototype上的属性和方法,但实例自己的自有属性(包括构造函数里通过this定义的)优先级更高,会覆盖prototype上的同名成员。

举个例子帮你理解优先级:

function Person(first) {
  this.name = first;
  // 实例的自有方法
  this.greeting = function() {
    alert('Hi from instance!');
  };
}
// prototype上的继承方法
Person.prototype.greeting = function() {
  alert('Hi from prototype!');
};

const p1 = new Person('Bob');
p1.greeting(); // 弹出"Hi from instance!",因为自有属性优先级更高

简单总结:

  • 构造函数里用this定义的属性/方法:每个实例独有的自有属性
  • prototype上定义的属性/方法:所有实例共享的继承属性
  • 实例访问成员时,先找自有属性,找不到再去prototype链上依次查找

内容的提问来源于stack exchange,提问作者JMay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:09:02