ES13 新增特性

1、类字段声明

 ES13之前,类字段只能在构造函数中声明,与许多其他语言不同,我们不能在类的最外层范围内声明或定义它们

<script>
class Car {
		constructor(){
			this.color = 'pink';
			this.age = 18;
		}
	}
const car = new Car();
console.log(car.color); //pink
console.log(car.age);   // 18
</script>

ES13消除了这个限制,现在我们可以编写如下代码:

<script>
class Cars {
		color = 'black';
		age = 16;
	}
const car1 = new Cars();
console.log(car1.color); //black
console.log(car1.age);   // 16
</script>

2、私有方法和字段

以前不能在类中声明私有成员,成员通常以下划线(_)为前缀,表示它是私有的,但仍然可以从类外部访问和修改

<script>
	class Person {
		_firstName = '小白';
		_lastName = '小黑';
		get name() {
			return `${this._firstName} ${this._lastName}`;
		}
	}
	const person = new Person();
	console.log(person.name); //小白 小黑
	console.log(person._firstName); // 小白
	console.log(person._lastName); // 小黑
	person._firstName = '小王';
	person._lastName = '小明';
	console.log(person.name); //小王 小明
</script>

 使用ES13 我们现在可以将私有字段和成员添加到类中,方法是在其前面加上#号,试图从类外部访问它们会导致错误:

<script>
class Persons {
		#firstName = "小刘";
		#lastName = "小李";
		get name() {
			return `${this.#firstName} ${this.#lastName}`;
		}
	} 
	const persons = new Persons();
	console.log(persons.name);
//这里抛出的错误是语法错误,发送在编译时,因此没有部分代码运行,编译器甚至不希望您尝试从类外部访问私有字段,因此,它假定您正在尝试声明一个
    console.log(persons.#firstName);
	console.log(persons.#lastName);
</script>

3、 await 运算符

在js中,await 运算符用于暂停执行,直到Promise 被解决(履行或拒绝)以前只能在async函数中使用此运算符 使用async关键字声明的函数

<script>	
function setTimeoutAsync(timeout){
		return new Promise((resolve) => {
			setTimeout(()=> {
				resolve();
			},timeout)
		})
	}
	// await is only valid in async functions and the top level bodies
	// await setTimeoutAsync(3000);
</script>	

使用ES13可以

<script>	
function setTimeoutAsync(timeout){
		return new Promise((resolve) => {
			setTimeout(()=> {
				resolve();
			},timeout)
		})
	}
	//  waits for timeout - no error thrown
	// await setTimeoutAsync(3000);
</script>	

4、静态类字段和静态私有方法

在ES13中为类声明静态字段和静态私有方法,静态方法可以使用this关键字访问类中的其它私有/公共静态成员,实列方法可以使用this.constructor访问它们

<script>
	class Personn {
		static #count = 0;
		static getCount(){
			return this.#count
		}
		constructor(){
			this.constructor.#inc()
		}
		static #inc(){
			this.#count++;
		}
	}
	const person1 = new Personn();
	const person2 = new Personn();
	console.log(Personn.getCount()); //2
</script>

5、类静态块

ES13允许在创建类定义只执行一次的静态块,这类似于其他面向对象编程的语言中的静态构造函数一个类的类主体中可以有任意数量的静态{} 初始化块,它们将于任何交错的静态字段初始值设定一起按照声明的顺序执行,可以在静态块中使用超属性来访问超类的属性

<script>
    class Vehicle {
		static defautColors = 'black';
	}
	class Card extends Vehicle {
		static colors = [];
		static {
			this.colors.push(super.defautColors,'red')
		}
		static {
			this.colors.push('green');
		}
	}
	console.log(Card.colors); //["black" "red" "green"]
</script>

 6、at( ) 方法进行索引

通常在js中使用方括号([])来访问数组的第N个元素,这通常是一个简单的过程,只访问数组的N-1 属性

<script>
    let arr = ['a','b','c']
    console.log(arr[1]); //b
</script>

但是如果想使用方括号访问数组末尾的第N个元素,我们必须使用arr.length-N 的索引

<script>
    const arr1 = [1,2,3,]
	console.log(arr1[arr1.length-1]); //3
	console.log(arr1[arr1.length-2]); //2
</script>

 新的at()方法更简洁,要访问数组末尾的第N个元素,只需要将负值-N 传递给 at()

<script>
    let num = [3,4,5,6]
	console.log(num.at(-1)); //6
	console.log(num.at(-2)); //5
</script>

 除了数组,字符串和TypedArray 对象现在也有 at()方法

<script>
    const str = 'coding';
	console.log(str.at(-1)); //g
	console.log(str.at(-2)); //n
	let typedArray = new Uint8Array([9,8,7,6]);
	console.log(typedArray.at(-1)); //6
	console.log(typedArray.at(-2)); //7
</script>

7、RegExp 匹配索引

新功能允许指定想要获取给定字符串中 RegExp对象匹配的开始和结束索引。以前只能在字符串中获取正则表达式匹配的起始索引

<script>
    let strs = 'sun and moon';
	let regex = /and/;
	let matchObj = regex.exec(strs);
	//['and',index:4,input:'sun and moon', groups:undefined]
	console.log('matchObj',matchObj);
</script>

现在可以指定一个 d 正则表达式标志来获取匹配开始和结束的两个索引

<script>
    const str1 = "sun and moon";
	const regex1 = /and/d;
	const matchObj1 = regex1.exec(str1)
	// ['and',index:4,input:'sun and moon', groups:undefined, indices:[ groups:undefined, [4,7]]]
	console.log('matchObj1',matchObj1);
</script>

8、Object.hasOwn( ) 方法

在js中,可以使用Object.prototype.hasOwnProperty()方法来检查对象是否具有给定的属性

<script>
    class Car2 {
		color = "white";
		age = 14;
	}
	const car2 = new Car2();
	console.log(car2.hasOwnProperty('age')); // true
	console.log(car2.hasOwnProperty('name')); // false
</script>

但是这种方法存在一定问题,一方面Object.prototype.hasOwnProperty()方法不受保护,它可以通过为类定义自定义 hasOwnProperty()方法覆盖,该方法可能具有Object.prototype.hasOwnProperty()完全不同的行为

<script>
    class Car3 {
		color = "hotpink";
		age = 11;
		hasOwnProperty() {
			return  false
		}
	}
	const car3 = new Car3();
	console.log(car3.hasOwnProperty('age')); // false
	console.log(car3.hasOwnProperty('name')); //false

    //另一个问题是,对于使用Null 原型创建的对象(使用 Object.create(null)) 尝试对其调用此方法会导致错误
    const obj = Object.create(null);
	obj.color ="blue";
	obj.age = 2;
	//  obj.hasOwnProperty is not a function
	// console.log(obj.hasOwnProperty('color'));
</script>

解决上面问题的一种方法是使用调用 Object.prototype.hasOwnProperty Function 属性上的call()方法,如下:

	const obj1= Object.create(null);
	obj1.color ="blue";
	obj1.age = 2;
	obj1.hasOwnProperty =  () => false;
	console.log(Object.prototype.hasOwnProperty.call(obj1,'color')); // true
	console.log(Object.prototype.hasOwnProperty.call(obj1,'name'));	// false

 这不是很方便,我们可以编写一个可重用的函数来避免重复自己

function objHasOwnProp(obj,propertyKey) {
		return Object.prototype.hasOwnProperty.call(obj,propertyKey);
	}
	const obj2 = Object.create(null);
	obj2.color = 'red';
	obj2.age = 3;
	obj2.hasOwnProperty = () => false;
	console.log(objHasOwnProp(obj2,'color')); // true
	console.log(objHasOwnProp(obj2,'name')); //fasle

不过没有必要,因为可以使用新的内置 Object.hasOwn()方法,与我们的可重用函数一样,它接受对象和属性作为参数 如果指定的属性是对象的直接属性,则返回 true 否则 返回false

	const obj3 = Object.create(null);
	obj3.color = 'orange';
	obj3.age = 6;
	obj3.hasOwnProperty = () => false;
	console.log(Object.hasOwn(obj3,'color'),'obj3'); //true
	console.log(Object.hasOwn(obj3,'name')); // false

9、错误原因

错误对象现在有一个 cause 属性,用于指定导致即将抛出的原始错误,这有助于为错误加额外的上下文信息并帮助诊断意外行为, 我们可以通过在作为第二个参数传递给 Error()构造函数的对象上设置 cause 属性来指定错误的原因

<script>
    function userAction(){
		try{
			apiCallThatCanThrow();
		}catch(err) {
			throw new Error('New error message', { cause: err});
		}
	}
	try{
		userAction();
	}catch(err) {
		console.log('err',err);
		console.log(`Cause by: ${err.cause}`);
	}
</script>

10、从最后一个数组查找

在js中可以使用 Array find()方法在数组中查找通过指定测试条件的元素,同样也可以使用findIndex()方法来查找此类元素的索引

虽然 find()方法和findIndex() 都从数组的第一个元素开始搜索,但在某些情况下,最好从最后一个元素开始搜索.

在某些情况下,我们知道从最后一个元素中查找可能会获得更好的性能,列如,试图在数组中获取值prop等于 y 的项目.使用find()和findIndex();

<script>
    const letters = [
		{value:'v'},
		{value:'w'},
		{value:'x'},
		{value:'y'},
		{value:'z'},
	]
	const found = letters.find(item => item.value === 'y');
	const foundIndex = letters.findIndex(v => v.value === 'y')
	console.log('found',found); //{value: 'y'}
	console.log('foundIndex',foundIndex); //3
</script>

但是由于目标对象更靠近数组的尾部,如果我们使用findLast()和findLastIndex()方法从末尾搜索数组,则可以让程序运行得更快

<script>
    const letter = [
		{value:'v'},
		{value:'w'},
		{value:'x'},
		{value:'y'},
		{value:'z'},
	]
	const founds = letter.findLast(item => item.value === 'y');
	const foundsIndex = letter.findLastIndex(item => item.value === 'y');
	console.log('founds',founds); //{value: 'y'}
	console.log('foundsIndex',foundsIndex); //3
</script>

另一个用例可能要求我们专门从末尾搜索数组以获取正确的项目.例如,如果想在数字列表中查找最后一个偶数   find() 和 findIndex() 会产生错误的结果

<script>
    let nums = [5,6,7,8,9,10];
	let lastEven = nums.find(v => v % 2 === 0);
	let lastEvenIndex = nums.findIndex(item => item % 2 === 0);
	console.log('lastEven',lastEven);  //6
	console.log('lastEvenIndex',lastEvenIndex);  //1
</script>

可以在调用find() 和findIndex()之前调用数组的reverse() 方法来反转元素的顺序.

但是这种方法会导致数组发生不必要的突变,因为reverse()会反转数组的元素,避免这种突变的唯一方法是

制作整个数组的新副本,这可能会导致大型数组出现性能问题.此外,findIndex()仍然无法在反转数组上工作,

因为反转元素也意味着更改他们在原始数组中的索引,要获得原始索引,需要执行额外的计算,意味编写更多的代码

<script>
    let nums1 = [5,6,7,8,9,10];
	let reversed = [...nums1.reverse()];
	let lastEven1 = reversed.find(v  => v % 2 === 0);
	let reversedIndex = reversed.findIndex(v => v % 2 === 0);
	let lastEvenIndex1 = reversed.length - 1 - reversedIndex;
	console.log('lastEven1',lastEven1); //10
	console.log('reversedIndex',reversedIndex); //0
	console.log('lastEvenIndex1',lastEvenIndex1); // 5

	
	let lastEven2 = nums1.findLast(v => v % 2 === 0);
	let lastEvenIndex2 = nums1.findLastIndex(v => v % 2 === 0);

	console.log('lastEven2',lastEven2); //6
	console.log('lastEvenIndex2',lastEvenIndex2); //4
</script>

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 作为 CSDN 开发的 AI 语言模型,我可以告诉您,ES2023 新增特性包括:1. Promise.any() 方法;2. WeakRefs 弱引用;3. 数字分隔符;4. String.prototype.replaceAll() 方法;5. Logical Assignment Operators 逻辑赋值运算符;6. Numeric Separators 数字分隔符。以上是我对您问题的回答,希望能够帮到您。 ### 回答2: ES2023是指ECMAScript的下一版标准,它的新增特性有以下几个方面: 1. 数值分隔符(Numeric Separators):ES2023将新增一个下划线(_)作为数值分隔符,以提高数字的可读性和编写代码时的易读性。例如,可以使用数字分隔符将一个大数字分隔成更易读的部分。 2. Promise.any()方法:ES2023将引入Promise.any()方法,该方法返回一个Promise,一旦其中任何一个传入的Promise变为resolve状态,该方法就会立即resolve。这个特性可以用于处理多个异步操作,只要有一个成功即可,无需等待其他。 3. 数值类型千分位分隔符(Intl.NumberFormat):ES2023将提供Intl.NumberFormat构造函数的新特性,使得开发者能够使用千位分隔符来格式化和解析数字。这在国际化开发中特别有用。 4. 字符串用于限制属性名称(Symbol-based Property Restrictions):ES2023将引入Symbol-based Property Restrictions来限制属性名称的值必须为Symbol类型。这样可以避免在使用对象属性时不小心使用了字符串。 5. SharedArrayBuffer 和 Atomics增强:ES2023将对SharedArrayBuffer和Atomics进行一些增强,以提高多线程和并发操作的性能和安全性。 以上就是ES2023新增的一些特性,通过这些特性的引入,可以提高JavaScript开发的效率和代码质量,同时也为多线程和国际化开发提供了更好的支持。 ### 回答3: ES2023是JavaScript的下一个版本,虽然它尚未正式发布,但已经可以预测一些可能的新增特性。以下是可能包含在ES2023中的一些特性: 1. Shared memory and atomics: ES2023可能会引入共享内存和原子操作,这将允许多个线程之间共享数据,并能够以原子方式访问和修改共享数据。 2. Optional chaining: 该特性已经在ES2020中引入。它允许开发者使用?.语法来简化对对象属性或方法的安全访问,避免了因为遇到空值或未定义的情况而导致的错误。 3. Pipeline operator: 管道运算符是一种用于简化函数式编程的语法。它允许通过简洁流畅的方式将函数应用于一系列数据。这个特性在ES2022被正式接受,并且可能进一步改进和扩展。 4. Record and Tuple types: 这两种类型已经被TC39委员会接受为Stage 2特性,并有望在ES2023中正式成为一部分。Record类型允许定义具有固定属性集的对象,而Tuple类型允许定义具有固定长度的数组。 5. Ergonomic brand checks: 这个特性的目标是为了提高类型安全性,同时保持语法的简洁和易读。它将提供一种在编译时对对象进行类型判断的方法,以便在运行时避免错误。 请注意,以上列出的特性只是一些可能会出现在ES2023中的特性,具体实施和变化还有待官方发布和确认。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值