中科医院 http://m.39.net/pf/a_5154126.html随着现代互联网IT发展趋势,其中,作为前端最重要的编程语言JavaScript,每年都在不断发展,让该语言都会通过新功能变得更强大,让开发人员编写更具表现力和简洁的代码。
接下来,让我们探索ECMAScript(ES13)中添加的最新功能,并查看它们的使用示例以便我们更好地理解它们。
1、类字段声明
在ES13之前,类字段只能在构造函数中声明,与许多其他语言不同,我们不能在类的最外层范围内声明或定义它们。
classCar{
constructor(){
this.color=blue;
this.age=2;
}
}
constcar=newCar();
console.log(car.color);//blue
console.log(car.age);//2
ES13消除了这个限制,现在我们可以编写如下代码:
classCar{
color=blue;
age=2;
}
constcar=newCar();
console.log(car.color);//blue
console.log(car.age);//2
2、私有方法和字段
以前,不能在类中声明私有成员,成员通常以下划线(_)为前缀,表示它是私有的,但仍然可以从类外部访问和修改。
classPerson{
_firstName=Joseph;
_lastName=Stevens;
getname(){
return`{this._firstName}{this._lastName}`;
}
}
constperson=newPerson();
console.log(person.name);//JosephStevens
//Membersintendedtobeprivatecanstillbeaccessed
//fromoutsidetheclass
console.log(person._firstName);//Joseph
console.log(person._lastName);//Stevens
//Theycanalsobemodified
person._firstName=Robert;
person._lastName=Becker;
console.log(person.name);//RobertBecker
使用ES13,我们现在可以将私有字段和成员添加到类中,方法是在其前面加上井号(#),试图从类外部访问它们会导致错误:
classPerson{
#firstName=Joseph;
#lastName=Stevens;
getname(){
return`{this.#firstName}{this.#lastName}`;
}
}
constperson=newPerson();
console.log(person.name);
//SyntaxErrorrivatefield#firstNamemustbe
//declaredinanenclosingclass
console.log(person.#firstName);
console.log(person.#lastName);
请注意,这里抛出的错误是语法错误,发生在编译时,因此没有部分代码运行,编译器甚至不希望您尝试从类外部访问私有字段,因此,它假定您正在尝试声明一个。
3、await运算符
在JavaScript中,await运算符用于暂停执行,直到Promise被解决(履行或拒绝)。
以前,我们只能在async函数中使用此运算符-使用async关键字声明的函数。我们无法在全球范围内这样做。
functionsetTimeoutAsync(timeout){
returnnewPromise((resolve)={
setTimeout(()={
resolve();
},timeout);
});
}
//SyntaxError:awaitisonlyvalidinasyncfunctions
awaitsetTimeoutAsync();
使用ES13,现在我们可以:
functionsetTimeoutAsync(timeout){
returnnewPromise((resolve)={
setTimeout(()={
resolve();
},timeout);
});
}
//Waitsfortimeout-noerrorthrown
awaitsetTimeoutAsync();
4、静态类字段和静态私有方法
我们现在可以在ES13中为类声明静态字段和静态私有方法,静态方法可以使用this关键字访问类中的其他私有/公共静态成员,实例方法可以使用this.constructor访问它们。
classPerson{
static#count=0;
staticgetCount(){
returnthis.#count;
}
constructor(){
this.constructor.#incrementCount();
}
static#incrementCount(){
this.#count++;
}
}
constperson1=newPerson();
constperson2=newPerson();
console.log(Person.getCount());//2
5、类静态块
ES13允许在创建类时定义只执行一次的静态块,这类似于其他支持面向对象编程的语言(如C#和Java)中的静态构造函数。
一个类的类主体中可以有任意数量的静态{}初始化块,它们将与任何交错的静态字段初始值设定项一起按照声明的顺序执行,我们可以在静态块中使用超属性来访问超类的属性。
classVehicle{
staticdefaultColor=blue;
}
classCarextendsVehicle{
staticcolors=[];
static{
this.colors.push(super.defaultColor,red);
}
static{
this.colors.push(green);
}
}
console.log(Car.colors);//[blue,red,green]
6、私人领域的人体工程学品牌检查
我们可以使用这个新特性来检查一个对象中是否有一个特定的私有字段,使用in运算符。
classCar{
#color;
hasColor(){
return#colorinthis;
}
}
constcar=newCar();
console.log(car.hasColor());//true;
in运算符可以正确区分不同类的同名私有字段:
classCar{
#color;
hasColor(){
return#colorinthis;
}
}
classHouse{
#color;
hasColor(){
return#colorinthis;
}
}
constcar=newCar();
consthouse=newHouse();
console.log(car.hasColor());//true;
console.log(car.hasColor.call(house));//false
console.log(house.hasColor());//true
console.log(house.hasColor.call(car));//false
7、at()方法进行索引
我们通常在JavaScript中使用方括号([])来访问数组的第N个元素,这通常是一个简单的过程,我们只访问数组的N-1属性。
constarr=[a,b,c,d];
console.log(arr[1]);//b
但是,如果我们想使用方括号访问数组末尾的第N个项目,我们必须使用arr.length-N的索引。
constarr=[a,b,c,d];
//1stelementfromtheend
console.log(arr[arr.length-1]);//d
//2ndelementfromtheend
console.log(arr[arr.length-2]);//c
新的at()方法让我们可以更简洁、更有表现力地做到这一点,要访问数组末尾的第N个元素,我们只需将负值-N传递给at()。
constarr=[a,b,c,d];
//1stelementfromtheend
console.log(arr.at(-1));//d
//2ndelementfromtheend
console.log(arr.at(-2));//c
除了数组,字符串和TypedArray对象现在也有at()方法。
conststr=CodingBeauty;
console.log(str.at(-1));//y
console.log(str.at(-2));//t
consttypedArray=newUint8Array([16,32,48,64]);
console.log(typedArray.at(-1));//64
console.log(typedArray.at(-2));//48
8、RegExp匹配索引
这个新功能允许我们指定我们想要获取给定字符串中RegExp对象匹配的开始和结束索引。
以前,我们只能在字符串中获取正则表达式匹配的起始索引。
conststr=sunandmoon;
constregex=/and/;
constmatchObj=regex.exec(str);
//[and,index:4,input:sunandmoon,groups:undefined]
console.log(matchObj);
我们现在可以指定一个d正则表达式标志来获取匹配开始和结束的两个索引。
conststr=sunandmoon;
constregex=/and/d;
constmatchObj=regex.exec(str);
/**
[
and,
index:4,
input:sunandmoon,
groups:undefined,
indices:[[4,7],groups:undefined]
]
*/
console.log(matchObj);
设置d标志后,返回的对象将具有包含开始和结束索引的indices属性。
9、Object.hasOwn()方法
在JavaScript中,我们可以使用Object.prototype.hasOwnProperty()方法来检查对象是否具有给定的属性。
classCar{
color=green;
age=2;
}
constcar=newCar();
console.log(car.hasOwnProperty(age));//true
console.log(car.hasOwnProperty(name));//false
但是,这种方法存在一定的问题,一方面,Object.prototype.hasOwnProperty()方法不受保护-它可以通过为类定义自定义hasOwnProperty()方法来覆盖,该方法可能具有与Object.prototype.hasOwnProperty()完全不同的行为。
classCar{
color=green;
age=2;
//Thismethoddoesnottelluswhetheranobjectof
//thisclasshasagivenproperty.
hasOwnProperty(){
returnfalse;
}
}
constcar=newCar();
console.log(car.hasOwnProperty(age));//false
console.log(car.hasOwnProperty(name));//false
另一个问题是,对于使用null原型创建的对象(使用Object.create(null)),尝试对其调用此方法会导致错误。
constobj=Object.create(null);
obj.color=green;
obj.age=2;
//TypeErrorbj.hasOwnPropertyisnotafunction
console.log(obj.hasOwnProperty(color));
解决这些问题的一种方法是使用调用Object.prototype.hasOwnPropertyFunction属性上的call()方法,如下所示:
constobj=Object.create(null);
obj.color=green;
obj.age=2;
obj.hasOwnProperty=()=false;
console.log(Object.prototype.hasOwnProperty.call(obj,color));//true
console.log(Object.prototype.hasOwnProperty.call(obj,name));//false
这不是很方便,我们可以编写一个可重用的函数来避免重复自己:
functionobjHasOwnProp(obj,propertyKey){
returnObject.prototype.hasOwnProperty.call(obj,propertyKey);
}
constobj=Object.create(null);
obj.color=green;
obj.age=2;
obj.hasOwnProperty=()=false;
console.log(objHasOwnProp(obj,color));//true
console.log(objHasOwnProp(obj,name));//false
不过没有必要,因为我们可以使用新的内置Object.hasOwn()方法。与我们的可重用函数一样,它接受对象和属性作为参数,如果指定的属性是对象的直接属性,则返回true。否则,它返回false。
constobj=Object.create(null);
obj.color=green;
obj.age=2;
obj.hasOwnProperty=()=false;
console.log(Object.hasOwn(obj,color));//true
console.log(Object.hasOwn(obj,name));//false
10、错误原因
错误对象现在有一个cause属性,用于指定导致即将抛出的错误的原始错误。这有助于为错误添加额外的上下文信息并帮助诊断意外行为,我们可以通过在作为第二个参数传递给Error()构造函数的对象上设置cause属性来指定错误的原因。
functionuserAction(){
try{
apiCallThatCanThrow();
}catch(err){
thrownewError(Newerrormessage,{cause:err});
}
}
try{
userAction();
}catch(err){
console.log(err);
console.log(`Causeby:{err.cause}`);
}
11、从最后一个数组查找
在JavaScript中,我们已经可以使用Arrayfind()方法在数组中查找通过指定测试条件的元素,同样,我们可以使用findIndex()来查找此类元素的索引。
虽然find()和findIndex()都从数组的第一个元素开始搜索,但在某些情况下,最好从最后一个元素开始搜索。
在某些情况下,我们知道从最后一个元素中查找可能会获得更好的性能。例如,这里我们试图在数组中获取值prop等于y的项目。使用find()和findIndex():
constletters=[
{value:v},
{value:w},
{value},
{value:y},
{value:z},
];
constfound=letters.find((item)=item.value===y);
constfoundIndex=letters.findIndex((item)=item.value===y);
console.log(found);//{value:y}
console.log(foundIndex);//3
这行得通,但是由于目标对象更靠近数组的尾部,如果我们使用findLast()和findLastIndex()方法从末尾搜索数组,我们可以让这个程序运行得更快。
constletters=[
{value:v},
{value:w},
{value},
{value:y},
{value:z},
];
constfound=letters.findLast((item)=item.value===y);
constfoundIndex=letters.findLastIndex((item)=item.value===y);
console.log(found);//{value:y}
console.log(foundIndex);//3
另一个用例可能要求我们专门从末尾搜索数组以获取正确的项目。例如,如果我们想在数字列表中查找最后一个偶数,find()和findIndex()会产生错误的结果:
constnums=[7,14,3,8,10,9];
//gives14,insteadof10
constlastEven=nums.find((value)=value%2===0);
//gives1,insteadof4
constlastEvenIndex=nums.findIndex((value)=value%2===0);
console.log(lastEven);//14
console.log(lastEvenIndex);//1
我们可以在调用find()和findIndex()之前调用数组的reverse()方法来反转元素的顺序。
但是这种方法会导致数组发生不必要的突变,因为reverse()会反转数组的元素。避免这种突变的唯一方法是制作整个数组的新副本,这可能会导致大型数组出现性能问题。
此外,findIndex()仍然无法在反转数组上工作,因为反转元素也意味着更改它们在原始数组中的索引。要获得原始索引,我们需要执行额外的计算,这意味着编写更多代码。
constnums=[7,14,3,8,10,9];
//Copyingtheentirearraywiththespreadsyntaxbefore
//callingreverse()
constreversed=[...nums].reverse();
//correctlygives10
constlastEven=reversed.find((value)=value%2===0);
//gives1,insteadof4
constreversedIndex=reversed.findIndex((value)=value%2===0);
//Needtore-calculatetogetoriginalindex
constlastEvenIndex=reversed.length-1-reversedIndex;
console.log(lastEven);//10
console.log(reversedIndex);//1
console.log(lastEvenIndex);//4
在findLast()和findLastIndex()方法派上用场的情况下。
constnums=[7,14,3,8,10,9];
constlastEven=nums.findLast((num)=num%2===0);
constlastEvenIndex=nums.findLastIndex((num)=num%2===0);
console.log(lastEven);//10
console.log(lastEvenIndex);//4
这段代码更短,更易读。最重要的是,它会产生正确的结果。
结论
通过上面的使用,所以我们已经看到了ES13为JavaScript带来的最新特性,使用它们来提高我们作为开发人员的工作效率,并以更简洁和清晰的方式编写更简洁的代码。
通过以上文章对JavaScript新特性的介绍,如果想要了解更多前端开发技术,可以