MST

星途 面试题库

面试题:TypeScript类的访问修饰符在模块间调用的应用

假设你正在开发一个大型前端项目,项目结构采用模块化设计。有一个模块定义了一个包含私有(private)、受保护(protected)和公共(public)访问修饰符的类。请描述如何在其他模块中正确地访问和使用这个类的不同成员,并给出简单示例代码。
34.1万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

在JavaScript中,并没有像Java、C# 等语言那样原生的 privateprotected 访问修饰符。不过,可以通过一些约定和闭包等技术来模拟类似的效果。

模拟私有成员

通常在JavaScript中,我们用下划线 _ 作为约定,表示该属性或方法是私有的,不应该在外部直接访问。

// module1.js
const MyClass = (function() {
    // 私有变量
    let _privateVariable = 'This is a private variable';

    function _privateMethod() {
        console.log('This is a private method');
    }

    return class {
        constructor() {
            // 公共属性
            this.publicProperty = 'This is a public property';
        }

        // 公共方法
        publicMethod() {
            _privateMethod();
            console.log(_privateVariable);
            return 'This is a public method';
        }
    };
})();

export default MyClass;

访问模块中的类及成员

在其他模块中,我们可以导入这个类,并访问其公共成员。

// module2.js
import MyClass from './module1.js';

const myObject = new MyClass();
console.log(myObject.publicProperty);
console.log(myObject.publicMethod());
// 虽然没有严格限制,但不应该直接访问 _privateVariable 和 _privateMethod
// console.log(myObject._privateVariable); // 不推荐这样做
// myObject._privateMethod(); // 不推荐这样做

关于模拟 protected 成员

在ES6 类中,同样没有原生的 protected 修饰符。但可以通过在子类中访问父类的内部状态来模拟 protected 的效果。

// module3.js
const ParentClass = (function() {
    let _protectedVariable = 'This is a protected variable';

    function _protectedMethod() {
        console.log('This is a protected method');
    }

    return class {
        constructor() {
            this.publicProperty = 'This is a public property';
        }

        publicMethod() {
            _protectedMethod();
            console.log(_protectedVariable);
            return 'This is a public method';
        }
    };
})();

export class ChildClass extends ParentClass {
    constructor() {
        super();
    }

    childPublicMethod() {
        // 这里可以访问 _protectedVariable 和 _protectedMethod
        _protectedMethod();
        console.log(_protectedVariable);
        return 'This is a method in child class';
    }
}
// module4.js
import { ChildClass } from './module3.js';

const childObject = new ChildClass();
console.log(childObject.publicProperty);
console.log(childObject.publicMethod());
console.log(childObject.childPublicMethod());

在实际的TypeScript项目中,可以使用 privateprotected 关键字,TypeScript 编译器会在编译时进行类型检查,以确保访问控制的正确性。

// module5.ts
class MyClass {
    private _privateVariable: string = 'This is a private variable';
    protected _protectedVariable: string = 'This is a protected variable';
    public publicProperty: string = 'This is a public property';

    private _privateMethod() {
        console.log('This is a private method');
    }

    protected _protectedMethod() {
        console.log('This is a protected method');
    }

    public publicMethod() {
        this._privateMethod();
        console.log(this._privateVariable);
        this._protectedMethod();
        console.log(this._protectedVariable);
        return 'This is a public method';
    }
}

export default MyClass;
// module6.ts
import MyClass from './module5.ts';

class ChildClass extends MyClass {
    constructor() {
        super();
    }

    childPublicMethod() {
        // 可以访问 protected 成员
        this._protectedMethod();
        console.log(this._protectedVariable);
        return 'This is a method in child class';
    }
}

const myObject = new MyClass();
console.log(myObject.publicProperty);
console.log(myObject.publicMethod());
// 以下访问会报错,因为是 private 成员
// console.log(myObject._privateVariable); 
// myObject._privateMethod(); 

const childObject = new ChildClass();
console.log(childObject.publicProperty);
console.log(childObject.publicMethod());
console.log(childObject.childPublicMethod());
// 以下访问会报错,因为是 private 成员
// console.log(childObject._privateVariable); 
// childObject._privateMethod();