Skip to content

Latest commit

 

History

History
226 lines (184 loc) · 5.94 KB

29最新提案.md

File metadata and controls

226 lines (184 loc) · 5.94 KB

最新提案

1.do 表达式

获取块级作用域的值:在块级作用域之前加上do,返回内部最后执行的表达式的值。

let x = do {
  if (foo()) { f() }
  else if (bar()) { g() }
  else { h() }
};

2.throw 表达式

抛出错误

  • 行首:throw语句
  • 不是行首:throw表达式
// 报错
console.log(throw new Error());

3.链判断运算符

读取对象内部的某个属性。判断是否为null或undefined。如果是的,就不再往下运算,而是返回undefined

  • 短路机制
  • delete 运算符
  • 括号不改变运算顺序
  • 报错场合
  • 右侧不得为十进制数值
const firstName = (message
  && message.body
  && message.body.user
  && message.body.user.firstName) || 'default';

const firstName = message?.body?.user?.firstName || 'default';
const fooValue = myForm.querySelector('input[name=foo]')?.value

// 以下写法是禁止的,会报错。
// 1.构造函数
new a?.()
new a?.b()

// 2.链判断运算符的右侧有模板字符串
a?.`{b}`
a?.b`{c}`

// 3.链判断运算符的左侧是 super
super?.()
super?.foo

// 4.链运算符用于赋值运算符左侧
a?.b = c

4.Null 判断运算符

只有运算符左侧的值为null或undefined时,才会返回右侧的值

  • ||运算符null 、undefined、 '' 、 false、0
  • ??运算符null 、undefined
const headerText = response.settings.headerText ?? 'Hello, world!';
const animationDuration = response.settings.animationDuration ?? 300;
const showSplashScreen = response.settings.showSplashScreen ?? true;

5.函数的部分执行

  • ?占位符 :单个参数的占位符
  • ...占位符:多个参数的占位符

注意点:

  • 函数的部分执行是基于原函数的,如果原函数发生变化,部分执行生成的新函数也会立即反映这种变化
  • 如果预先提供的那个值是一个表达式,那么这个表达式并不会在定义时求值,而是在每次调用时求值
  • 如果新函数的参数多于占位符的数量,那么多余的参数将被忽略
  • ...只会被采集一次,如果函数的部分执行使用了多个...,那么每个...的值都将相同
let obj = {
  f(x, y) { return x + y; },
};

const g = obj.f(?, 3);
g(1) // 4

函数的部分执行是基于原函数的,如果原函数发生变化,部分执行生成的新函数也会立即反映这种变化

let f = (x, y) => x + y;

const g = f(?, 3);
g(1); // 4

// 替换函数 f
f = (x, y) => x * y;

g(1); // 3

如果预先提供的那个值是一个表达式,那么这个表达式并不会在定义时求值,而是在每次调用时求值。

let a = 3;
const f = (x, y) => x + y;

const g = f(?, a);
g(1); // 4

// 改变 a 的值
a = 10;
g(1); // 11

如果新函数的参数多于占位符的数量,那么多余的参数将被忽略。

const f = (x, ...y) => [x, ...y];
const g = f(?, 1);
g(2, 3, 4); // [2, 1]

...只会被采集一次,如果函数的部分执行使用了多个...,那么每个...的值都将相同

const f = (...x) => x;
const g = f(..., 9, ...);
g(1, 2, 3); // [1, 2, 3, 9, 1, 2, 3]

6.管道运算符

可以把前一个操作的值传给后一个操作

  • 只能传递一个值:函数必须是一个单参数函数,如果是多参数函数,就必须进行柯里化,改成单参数的版本
function doubleSay (str) {
  return str + ", " + str;
}

function capitalize (str) {
  return str[0].toUpperCase() + str.substring(1);
}

function exclaim (str) {
  return str + '!';
}

// 传统的写法
exclaim(capitalize(doubleSay('hello')))
// "Hello, hello!"

// 管道的写法
'hello'
  |> doubleSay
  |> capitalize
  |> exclaim
// "Hello, hello!"

7.数值分隔符

较长的数值允许每三位添加一个分隔符(通常是一个逗号),增加数值的可读性

  • 不能在数值的最前面(leading)或最后面(trailing)。
  • 不能两个或两个以上的分隔符连在一起。
  • 小数点的前后不能有分隔符。
  • 科学计数法里面,表示指数的e或E前后不能有分隔符。
let budget = 1_000_000_000_000;
budget === 10 ** 12 // true

// 二进制
0b1010_0001_1000_0101
// 十六进制
0xA0_B0_C0

8.BigInt 数据类型

JavaScript 所有数字都保存成 64 位浮点数

  1. 数值的精度只能到 53 个二进制位(相当于 16 个十进制位),大于这个范围的整数,JavaScript 是无法精确表示的
  2. 二是大于或等于2的1024次方的数值,JavaScript 无法表示,会返回Infinity

BigInt 只用来表示整数,没有位数的限制,任何位数的整数都可以精确表示

// 超过 53 个二进制位的数值,无法保持精度
Math.pow(2, 53) === Math.pow(2, 53) + 1 // true

// 超过 2 的 1024 次方的数值,无法表示
Math.pow(2, 1024) // Infinity
const a = 2172141653n;
const b = 15346349309n;

// BigInt 可以保持精度
a * b // 33334444555566667777n

// 普通整数无法保持精度
Number(a) * Number(b) // 33334444555566670000

0b1101n // 二进制
0o777n // 八进制
0xFFn // 十六进制

42n === 42 // false,因为BigInt 与普通整数是两种值,它们之间并不相等。  

typeof 123n // 'bigint'

9.Math.signbit()

Math.sign()用来判断一个值的正负,但是如果参数是-0,它会返回-0。

  • 如果参数是NaN,返回false
  • 如果参数是-0,返回true
  • 如果参数是负值,返回true
  • 其他情况返回false
Math.signbit(2) //false
Math.signbit(-2) //true
Math.signbit(0) //false
Math.signbit(-0) //true

10.双冒号运算符

“函数绑定”(function bind)运算符,用来取代call、apply、bind调用 函数绑定运算符是并排的两个冒号(::),双冒号左边是一个对象,右边是一个函数

foo::bar;
// 等同于
bar.bind(foo);

foo::bar(...arguments);
// 等同于
bar.apply(foo, arguments);