JavaScript类constructor返回对象是否合法?可用于实现公私方法控制吗?
constructor返回自定义对象的运行效果
JS中使用new关键字实例化类时,默认的执行逻辑是:
- 创建一个继承自类原型的空对象,将构造函数内的
this指向该对象 - 执行构造函数内的逻辑
- 如果构造函数没有主动返回非原始类型的值,默认返回这个
this指向的类实例
如果构造函数主动返回一个对象(如你示例中的return { getp1: this.getp1 }),那么new操作的返回结果就会是这个自定义的对象,原本的类实例会被丢弃。
你给出的示例代码运行逻辑也符合这个规则:
class X { y = '' x = 0 constructor(p1, p2) { this.p1 = p1 this.p2 = p2 return { getp1: this.getp1 } } getp1 = () => this.p1 } let x = new X("fo", "bar") console.log(x.p1) // undefined console.log(x.getp1() ) // "fo"
这里的变量x是你手动返回的普通对象,不是X类的实例,所以直接访问x.p1、x.y都拿不到值,这些属性都挂载在被丢弃的原类实例上。只有getp1作为箭头函数绑定了原类实例的this,所以可以通过闭包访问到原实例的p1属性。
该方式是否可实现私有/公有权限控制?
可以实现简单的属性访问拦截效果,但属于非标准的hack用法,非常不推荐在生产环境使用,存在多个明显缺陷:
- 破坏类的原型链关联:返回的普通对象和原类没有继承关系,执行
x instanceof X会返回false,类原型上定义的方法、父类继承的属性都无法访问,完全丢失了类的核心特性。 - 额外性能开销:每次实例化都会额外创建一个新的返回对象,同时原类实例因为被返回的方法闭包引用无法被GC回收,实例数量较多时会产生不必要的内存占用。
- 可维护性差:不符合JS生态的通用编码规范,后续维护代码的开发者很容易忽略构造函数的返回逻辑,引发预期外的问题。
目前JS已经有原生标准的私有属性/方法实现,使用#作为前缀声明的属性就是类私有属性,外部无法直接访问,是官方推荐的权限控制方案,示例如下:
class X { #p1 #p2 y = '' x = 0 constructor(p1, p2) { this.#p1 = p1 this.#p2 = p2 } getp1() { return this.#p1 } } let x = new X("fo", "bar") console.log(x.p1) // undefined console.log(x.getp1()) // "fo" console.log(x instanceof X) // true
内容的提问来源于stack exchange,提问作者MHS
相关产品推荐
相关产品推荐

