一、普通函数 VS 静态函数,本质区别是什么?
我们从一个代码段开始:
js
class User {
hello() { console.log('hello'); } // 普通方法(实例方法)
static bye() { console.log('bye'); } // 静态方法
}
区别:
类型 | 定义方式 | 调用方式 | this指向 |
---|---|---|---|
普通方法 | 不加static | 实例对象.方法() | 实例对象 |
静态方法 | static修饰 | 类名.方法() | 类本身 |
演示:
js
const u = new User();
u.hello(); // hello
User.bye(); // bye
User.hello(); // 报错
u.bye(); // 报错
二、面试官会怎么考你?
面试官:如何用代码判断某个方法是静态方法还是普通方法?
很多人的答案是:
看有没有
static
关键字!
错!
正如你拿到三方库的源码或通过反射获取类属性时,根本不会出现 static
这个字眼。你拿的只是一个函数,你怎么判断它的类型?
三、绝招:用方法"挂载的位置"一秒区分
静态方法和普通方法的本质区别是什么?
答:它们的挂载位置不同!
- 静态方法挂载在 类本身("构造函数"对象)上
- 普通方法 挂载在 类的原型(
prototype
)上
代码验证
js
console.log(User.bye); // Function: bye
console.log(User.prototype.hello); // Function: hello
console.log(User.hello); // undefined
console.log(User.prototype.bye); // undefined
四、实用函数,一键判断方法类型!
人生苦短,直接上代码:
js
function isStaticMethod(cls, methodName) {
return typeof cls[methodName] === 'function' &&
typeof cls.prototype[methodName] !== 'function';
}
function isInstanceMethod(cls, methodName) {
return typeof cls.prototype[methodName] === 'function' &&
typeof cls[methodName] !== 'function';
}
测试一下:
js
class Hero {
fight() {} // 普通方法
static revive() {} // 静态方法
}
console.log(isStaticMethod(Hero, 'fight')); // false
console.log(isStaticMethod(Hero, 'revive')); // true
console.log(isInstanceMethod(Hero, 'fight')); // true
console.log(isInstanceMethod(Hero, 'revive')); // false
是不是超级丝滑!
五、进阶:属性描述符一眼就分辨
利用 Object.getOwnPropertyDescriptor
也能一秒区分:
js
console.log(Object.getOwnPropertyDescriptor(Hero, 'revive')); // 有值
console.log(Object.getOwnPropertyDescriptor(Hero.prototype, 'revive'));// undefined
哪些方法只有对象本身有?静态!
只能通过 prototype 访问到?普通方法!
六、面试亮点加分(原理深入)
1. 静态方法不被继承给实例
js
const h = new Hero();
console.log(h.revive); // undefined
2. prototype 只持有普通方法
js
console.log(Hero.prototype); // 只包含 fight
3. 对象字面量没有"静态方法"这种说法
js
const obj = {
foo() {}
}
只有类(class
)里的 static 才有静态方法!
七、彩蛋:ES5、ES6差异知多少?
ES5没有static
关键字,但你可以这样模拟静态方法:
js
function Car() {}
Car.run = function() { console.log('run!'); }; // 静态方法
Car.prototype.drive = function() { console.log('drive'); }; // 实例方法
同理,这两种方法的区分还是靠"挂载位置"!
最后
如果你觉得有用,记得点赞、收藏、转发给更多小伙伴哦!