函数的方法
约 580 字大约 2 分钟
2026-03-31
下面的代码执行结果是什么?
JS code example
console
Click the run button to execute the code ...
1. 执行前的内存状态
function Foo() {
// 修改静态方法(当Foo被调用时才执行)
Foo.a = function () {
console.log(1);
};
// 创建实例方法
this.a = function () {
console.log(2);
};
}
// 在原型上添加方法
Foo.prototype.a = function () {
console.log(3);
};
// 定义静态方法(立即执行)
Foo.a = function () {
console.log(4);
};此时:
Foo.a指向function() { console.log(4); }(静态方法)Foo.prototype.a指向function() { console.log(3); }(原型方法)
2. 第一次调用 Foo.a()
Foo.a(); // 输出 4直接调用构造函数上的静态方法 Foo.a。
3. 执行 new Foo()
let obj = new Foo();new 操作执行构造函数 Foo():
- 执行
Foo.a = function() { console.log(1); }- 修改了静态方法
Foo.a的指向 - 现在
Foo.a指向function() { console.log(1); }
- 修改了静态方法
- 执行
this.a = function() { console.log(2) }- 为实例
obj添加实例方法a
- 为实例
此时内存状态:
// 静态方法(已被修改)
Foo.a = function () {
console.log(1);
};
// 实例方法
obj = {
a: function () {
console.log(2);
},
// __proto__ 指向 Foo.prototype
};
// 原型方法(保持不变)
Foo.prototype.a = function () {
console.log(3);
};4. 调用 obj.a()
obj.a(); // 输出 2查找顺序(原型链):
- 先查找
obj自身的属性:找到实例方法a()→ 执行输出2 - 不会查找到原型上的
a(),因为自身已有该方法
5. 第二次调用 Foo.a()
Foo.a(); // 输出 1调用的是已被构造函数修改后的静态方法。
验证原型链
// 验证原型链方法
console.log(obj.__proto__.a()); // 3(原型方法仍然存在)
// 删除实例方法后
delete obj.a;
console.log(obj.a()); // 3(现在使用原型方法)
console.log(obj.a === Foo.prototype.a); // true
// 验证静态方法只能通过构造函数访问
console.log(obj.a === Foo.a); // false(一个是实例/原型方法,一个是静态方法)
console.log(Foo.a()); // 1关键点
- 静态方法 vs 实例方法 vs 原型方法 是三个不同的东西
- 构造函数内部的
Foo.a = ...修改的是静态方法(函数执行时修改) this.a = ...创建的是实例方法(覆盖同名原型方法)- 实例方法查找优先级:实例属性 > 原型属性