我正在阅读有关JavaScript类的内容,偶然发现了“ 公共类字段语法”这个术语。在深入研究它时,我遇到了这个Babel's documentation on class properties。
有人可以解释一下吗-实施方面,这种新语法的用例是什么? (到目前为止,它为JavaScript提供了哪些解决方案/优点?)
下面是(在Google Chrome浏览器中没有错误)下面的示例:
class Person {
firstName = "Mike";
lastName = "Patel";
// this is a public class field syntax
getName = () => {
return this.firstName + " " + this.lastName;
};
}
var p = new Person();
console.log(p.firstName); // Mike
console.log(p.lastName); // Patel
console.log(p.getName); // () => { return this.firstName + " " + this.lastName; }
console.log(typeof p.getName); // function
console.log(p.getName()); // Mike Patel
答案 0 :(得分:2)
简而言之,使用此代码的原因是易于理解代码。没有类字段声明,您将执行
class Person {
constructor() {
this.firstName = "Mike";
this.lastName = "Patel";
this.getName = () => {
return this.firstName + " " + this.lastName;
};
}
}
var p = new Person();
console.log(p.firstName); // Mike
console.log(p.lastName); // Patel
console.log(p.getName); // () => { return this.firstName + " " + this.lastName; }
console.log(typeof p.getName); // function
console.log(p.getName()); // Mike Patel
这可行,但是现在您同时具有方法声明和 instance属性都收集在构造函数中。但是,您可以有更多的方法,这意味着您的类定义总体上看起来毫无意义:
class MyClass() {
constructor(someArg) {
this.prop1 = 1;
this.prop2 = 2;
this.prop3 = 3;
this.prop4 = someArg;
this.method1 = () => {}
this.method2 = () => {}
this.method3 = () => {}
this.method4 = () => {}
}
}
,依此类推。同样,一切都在构造函数中。如果您有很多代码,那么很难读懂什么是什么。而且,如果构造函数接受任何参数,那么您就有额外的开销来跟踪这些参数。简而言之,它很难阅读,很难维护,没有真正的好处。您将所有东西都塞在同一位置。
使用类字段声明,您将它们分开并得到
class MyClass() {
/* properties - don't depend on the constructor*/
prop1 = 1;
prop2 = 2;
prop3 = 3;
prop4; /* this is a property that this class will have -
I don't need to look at the constructor to know about it */
/* easy to see what the constructor does that is only about *constructing* the object */
constructor(someArg) {
this.prop4 = someArg;
}
/* methods are separated from the rest of the properties and construction logic */
method1 = () => {}
method2 = () => {}
method3 = () => {}
method4 = () => {}
}
总而言之,它不是革命性的,但它的语法稍微好一点,可以更轻松地表达类的内容。
答案 1 :(得分:1)
通过预先声明字段,类定义变得更加自我记录;实例始终经历较少的状态转换,因为声明的字段始终存在。
引入类字段还允许使用私有类字段,这也带来了一些好处:
通过定义在类外部不可见的内容,ESnext提供了更强的封装,确保您的类用户不会因内部而意外绊倒,因为内部可能会改变版本。
答案 2 :(得分:0)
它源自this proposal,其中正在解决“问题”。
假设您要拥有一个包含默认属性的类Foo
,那么您可以编写以下内容
class Foo {
defaultAttribute = 'default';
getDefault() { return this.defaultAttribute; }
}
请记住,上面的建议没有在atm实施。设置类对象(编译时)将忽略defaultAttribute = '...'
。它甚至不是(功能对象的)原型或现场成员的一部分。
这是因为编译器未选择defaultAttribute
。因此,您无法执行foo.defaultAttribute
。
调用getDefault()
会在此处引发错误,因为当时未定义。如果您在构造函数中为defaultAttribute
提供了一个值,则该函数将起作用;
class Foo {
defaultAttribute = 'default';
constructor() {
this.defaultAttribute = 'hello';
}
getDefault() { return this.defaultAttribute; }
}
在这种情况下,defaultAttribute
设置为'Hello',但它没有没有用'default'
覆盖原始变量。
有了该建议,就解决了“忽略”问题,您可以按照刚才的描述进行操作:
class Foo {
defaultAttribute = 'default';
getDefault() { return this.defaultAttribute; }
}
通过此操作,您可以跳过constructor()
class Foo1 {
defaultAttribute = 'default';
getDefault() { return this.defaultAttribute; }
}
class Foo2 {
defaultAttribute = 'default';
constructor() {this.defaultAttribute = 'hello';}
getDefault() { return this.defaultAttribute; }
}
const foo1 = new Foo1();
const foo2 = new Foo2();
console.log(foo1.getDefault());
console.log(foo2.getDefault());