JavaScript is constantly being upgraded and iterated, and there are more and more new features to make our code simple and interesting to write, this article will introduce 5 new features, let’s study them together.

1. Use “Object.hasOwn” instead of the “in” operator

Sometimes, we want to know if a property exists on an object, we usually use the “in” operator or “obj.hasOwnProperty”, but they both have their own drawbacks.

in

The “in” operator will return true if the specified property is located in the object or its prototype chain.

1
2
3
4
5
6
7
8
const Person = function (age) {
  this.age = age
}
Person.prototype.name = 'fatfish'

const p1 = new Person(24)
console.log('age' in p1) // true 
console.log('name' in p1) // true  注意这里

obj.hasOwnProperty

The hasOwnProperty method returns a boolean value indicating whether the object ownProperty has a corresponding value in it (properties in the prototype chain are not read).

1
2
3
4
5
6
7
8
const Person = function (age) {
  this.age = age
}
Person.prototype.name = 'fatfish'

const p1 = new Person(24)
console.log(p1.hasOwnProperty('age')) // true 
console.log(p1.hasOwnProperty('name')) // fasle  注意这里

obj.hasOwnProperty can already filter out properties in the prototype chain, but in some cases it is still not safe.

1
2
Object.create(null).hasOwnProperty('name')
// Uncaught TypeError: Object.create(...).hasOwnProperty is not a function

Object.hasOwn

Don’t worry, we can use Object.hasOwn to avoid these two problems, which is more convenient and safer than the “obj.hasOwnProperty” method.

1
2
3
4
5
6
let object = { age: 24 }
Object.hasOwn(object, 'age') // true
let object2 = Object.create({ age: 24 })
Object.hasOwn(object2, 'age') // false  
let object3 = Object.create(null)
Object.hasOwn(object3, 'age') // false 

2. Declaring Private Attributes with #

Previously, we usually use _ to denote private properties, but it is not reliable and can still be modified externally.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Person {
  constructor (name) {
    this._money = 1
    this.name = name
  }
  get money () {
    return this._money
  }
  set money (money) {
    this._money = money
  }
  showMoney () {
    console.log(this._money)
  }
}
const p1 = new Person('fatfish')
console.log(p1.money) // 1
console.log(p1._money) // 1
p1._money = 2 // 依旧可以从外部修改_money属性,所以这种做法并不安全
console.log(p1.money) // 2
console.log(p1._money) // 2

Use “#” for truly private attributes

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Person {
  #money=1
  constructor (name) {
    this.name = name
  }
  get money () {
    return this.#money
  }
  set money (money) {
    this.#money = money
  }
  showMoney () {
    console.log(this.#money)
  }
}
const p1 = new Person('fatfish')
console.log(p1.money) // 1
// p1.#money = 2 // 没法从外部直接修改
p1.money = 2
console.log(p1.money) // 2
console.log(p1.#money) // Uncaught SyntaxError: Private field '#money' must be declared in an enclosing class

3. very useful “number separator”

See the example directly.

1
2
3
4
5
const sixBillion = 6000000000
// ❌ 难以阅读
const sixBillion2 = 6000_000_000
// ✅ 更加易于阅读
console.log(sixBillion2) // 6000000000

Of course it can also be used in computational expressions.

1
const sum = 1000 + 6000_000_000 // 6000001000

4. Use “?.” Simplifying “&&” and ternary operators

These examples must be very familiar to you, is there a way to simplify them?

1
2
3
4
const obj = null
console.log(obj && obj.name)
const $title = document.querySelector('.title')
const title = $title ? title.innerText : undefined

“?.”

1
2
3
4
const obj = null
console.log(obj?.name)
const $title = document.querySelector('.title')
const title = $title?.innerText

Tips

?. The general usage of.

  1. obj?.prop object property
  2. obj?. [expr] object property
  3. func?. (… .args) Execute function

5. Using “BigInt” for large numbers

It is not safe to calculate numbers in JS that exceed Number.MAX_SAFE_INTEGER.

Example:

1
2
3
Math.pow(2, 53) === Math.pow(2, 53) + 1 // true
// Math.pow(2, 53) => 9007199254740992
// Math.pow(2, 53) + 1 => 9007199254740992

This problem can be completely avoided by using “BigInt”.

1
BigInt(Math.pow(2, 53)) === BigInt(Math.pow(2, 53)) + BigInt(1) // false