Classes on mdn web docs开始:

公共字段声明

class Rectangle {
  height = 0;
  width;
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}

constructor之外的heightwidth不是毫无意义吗,因为它们总是在constructor中被覆盖?

What's the significance of the height and width declaration/initialization outside of constructor in this case?
Are they used/reachable by any means?

推荐答案

属性只有declared个一次(在构造函数之外);如果没有这些声明,就不会有这些属性的声明(而是通过赋值创建).公共属性声明(也称为"公共类字段")是可选的,但可以帮助避免对象中的形状更改(这可以提高效率)和/或减少JavaScript引擎为避免形状更改而需要对创建的对象进行的分析.基本上,它们提供了一种declarative(而不是命令式[逐步])的方式来表示(在本例中)Rectangle个对象始终具有heightwidth属性.虽然JavaScript引擎可以通过分析构造函数代码来解决这个问题,但声明意味着它不必担心(对于那些属性).

构造函数之外的高度和宽度不是没有意义吗,因为它们总是在构造函数中被覆盖?

height属性上的初始值设定项(= 0)毫无意义,是的,因为它会被构造函数中的代码明确地覆盖,这样做的赋值是构造函数中的第一条语句.如果它不是第一条语句,那么构造函数中的代码将能够在赋值之前观察height中的0.

[the height and width declaration/initialization outside of constructor]是否已使用/可通过任何方式访问?

它们可以由后续的类字段初始值设定项使用.例如,这是有效的:

class Example {
    a = 2;
    b = this.a * 3;
}
console.log(new Example().b); // 6

可能还值得指出的是,如果类是一个子类,则有一点不同:当您使用声明语法时,属性是通过"define"语义创建的(就像您使用Object.defineProperty函数一样),而如果您只对其赋值,则使用赋值语义.如果超类还定义了属性,那么这很重要:

class Super {
    #example = 42;

    get example() {
        console.log("Getting example");
        return this.#example;
    }
    set example(value) {
        console.log("Setting example");
        this.#example = value;
    }
}

class Sub extends Super {
    example = 67;
}

const super1 = new Super();
console.log(`What kind of property is super1.example?`);
console.log(propertyKind(super1, "example"));

const sub1 = new Sub();
console.log(`What kind of property is sub1.example?`);
console.log(propertyKind(sub1, "example"));

function propertyKind(obj, name) {
    let descr;
    do {
        descr = Object.getOwnPropertyDescriptor(obj, name);
        if (descr) {
            break;
        }
        obj = Object.getPrototypeOf(obj);
        if (!obj) {
            break;
        }
    } while (!descr);

    return descr
        ? "value" in descr
            ? "data"
            : "accessor" // presumably
        : "none";
}

请注意,examplesuper1上的访问器属性(通过从其原型继承),但它是sub1上的data属性,因为它是redeclaredSub.如果Sub刚刚分配给它,它将只使用创建的属性Super:

class Super {
    #example = 42;

    get example() {
        console.log("Getting example");
        return this.#example;
    }
    set example(value) {
        console.log("Setting example");
        this.#example = value;
    }
}

class Sub extends Super {
    constructor() {
        super();
        this.example = 67;
    }
}

const super1 = new Super();
console.log(`What kind of property is super1.example?`);
console.log(propertyKind(super1, "example"));

const sub1 = new Sub();
console.log(`What kind of property is sub1.example?`);
console.log(propertyKind(sub1, "example"));

function propertyKind(obj, name) {
    let descr;
    do {
        descr = Object.getOwnPropertyDescriptor(obj, name);
        if (descr) {
            break;
        }
        obj = Object.getPrototypeOf(obj);
        if (!obj) {
            break;
        }
    } while (!descr);

    return descr
        ? "value" in descr
            ? "data"
            : "accessor" // presumably
        : "none";
}

请注意,现在,它是sub1super1上的访问器属性(当Sub进行赋值时,Super.example中的setter代码运行).


TL;DR-我会保留声明以保持清晰和潜在的效率,但删除height上的= 0初始值设定项,因为该值显然永远不会被使用.

Javascript相关问答推荐

如何修复循环HTML元素附加函数中的问题?

我在这个黑暗模式按钮上做错了什么?

使用axios.获取实时服务器时的404响应

IMDB使用 puppeteer 加载更多按钮(nodejs)

react/redux中的formData在expressjs中返回未定义的req.params.id

InDesign—创建一个独立的窗口,在文档中进行更正时保持打开状态

CheckBox作为Vue3中的一个组件

JS—删除对象数组中对象的子对象

为什么我的导航条打开状态没有在窗口addeventlistener(Reaction Js)中更新?

以Angular 实现ng-Circle-Progress时出错:模块没有导出的成员

将Node.js包发布到GitHub包-错误ENEEDAUTH

Vaadin定制组件-保持对javascrip变量的访问

Google脚本数组映射函数横向输出

React:防止useContext重新渲染整个应用程序或在组件之间共享数据而不重新渲染所有组件

如何修复错误&语法错误:不能在纯react 项目中JEST引发的模块&之外使用导入语句?

使用createBrowserRoutVS BrowserRouter的Reaction路由

JSON Web令牌(JWT)错误:RSA密钥对的签名无效

MAT-TREE更多文本边框对齐问题

如何动态呈现适合未知屏幕大小的最大数量的表行?苗条的

将promise列表拆分到组.按组并行和顺序执行所有promise