原型链负责方法查找与共享,apply负责临时改变this并调用函数;二者角色分明:原型链通过__proto__自动向上查找,apply用于构造函数继承或临时借用方法,不可相互替代。

JavaScript 中原型链和 apply 并不直接“配合”来借用父类方法——这是两个不同层面的机制,容易混淆。需要先理清:原型链负责方法查找与共享,apply(或 call)负责临时改变函数执行时的 this 指向并立即调用。它们可以共存于一个继承方案中,但角色分明、各司其职。
原型链本身不依赖 apply,它靠 __proto__ 和 prototype 链式查找
- 当你写
obj.say(),JS 引擎会:- 先在
obj自身找say - 找不到,就查
obj.__proto__(即构造函数的prototype) - 再找不到,继续向上查,直到
null
- 先在
- 这个过程完全自动,不涉及
apply。
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(`${this.name} makes a sound`);
};
const cat = new Animal('Mittens');
cat.speak(); // ✅ 正常走原型链,输出 "Mittens makes a sound"这里没用 apply,也完全可行。
apply 的作用:在非原型调用场景下,“强行借用”父类方法
apply 不是为继承而生,而是为「函数复用」服务。当你想让某个对象临时使用另一个构造函数里的逻辑(比如初始化属性),或者让一个普通对象调用本不属于它的方法时,才用 apply。
常见两类用法:
立即学习“Java免费学习笔记(深入)”;
- 在子类构造函数中初始化实例属性(构造函数继承)
- 临时调用父类原型上的方法(较少见,但合法)
✅ 场景一:子类构造中用 apply 初始化父类属性(组合继承的一部分)
function Animal(name, age) {
this.name = name;
this.age = age;
}
Animal.prototype.eat = function(food) {
console.log(`${this.name} eats ${food}`);
};
function Dog(name, age, breed) {
// ? 这里用 apply 借用 Animal 构造逻辑,给 this(新 Dog 实例)赋值 name/age
Animal.apply(this, [name, age]);
this.breed = breed;
}
const myDog = new Dog('Max', 3, 'Husky');
console.log(myDog.name); // Max ✅
console.log(myDog.breed); // Husky ✅
myDog.eat('meat'); // ❌ TypeError: myDog.eat is not a function —— eat 在 Animal.prototype 上,但 Dog.prototype 没连上去!⚠️ 注意:仅靠 apply,Dog 实例无法访问 Animal.prototype.eat —— 因为原型链没建立。要补上这一步,得手动设置:
在调试 Java 后端 API 故障时使用此技能,尤其适用于以下任务:分析日志、跨 Controller、Service 和 Mapper 层追踪请求、定位异常根因、检查 SQL 执行或参数流转,以及生成简洁的诊断结论与修复方案。
Dog.prototype = Object.create(Animal.prototype); Dog.prototype.constructor = Dog; // 修复 constructor
这样 myDog.eat() 才能成功,此时:
- 属性靠
apply继承(每个实例独有) - 方法靠原型链继承(共享、复用)
这就是「组合继承」的核心逻辑。
✅ 场景二:临时借用父类原型方法(调试或特殊调用)
const bird = { name: 'Tweety', wings: 2 };
Animal.prototype.speak.apply(bird); // ✅ 输出 "Tweety makes a sound"这里 bird 不是 Animal 实例,也没有原型链关系,但通过 apply 把 speak 的 this 指向 bird,就能运行。这不是继承,只是“方法借用”。
为什么不用 apply 实现原型方法继承?
因为:
-
apply是一次性调用,不能建立持久的查找链 - 原型链是动态查找机制,支持后续新增方法自动生效(如后加
Animal.prototype.run = ...,所有实例立刻可用) -
apply调用的是函数副本,每次都要手动传参、手动绑定,无法替代原型的自然委托
总结关键点
- 原型链解决「方法在哪里找、怎么共享」的问题
-
apply解决「这个函数能不能用在当前对象上、参数怎么传」的问题 - 真正实用的继承方案(如组合继承)是二者分工合作:
-
apply处理实例属性初始化 - 原型链(
Child.prototype = Object.create(Parent.prototype))处理方法继承与复用
-
不复杂但容易忽略。

















