资讯专栏INFORMATION COLUMN

即将到来 Javascript 三个改变, 你会很喜欢它们的,因为确实是方便了很多!

tinysun1234 / 667人阅读

摘要:你将看到它们的语法时时关注它们的进展与更新。标准有个版本,个发布第个版本被放弃了。此建议的目的只是避免在起草建议被放弃或发生重大带来的麻烦。如果使用过度,将导致性能下降。在这个场景中,数字和空字符串都被认为是假的。

想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你!

让我们看看JavaScript中一些有用的即将出现的特性。你将看到它们的语法、时时关注它们的进展与更新。在此,我们将编写一个小测试案例来展示如何从今天开始使用这些特性!

如果您已经熟悉Ecma TC39委员会如何决定和处理JavaScript语言的更改,请跳过这一部分。

JavaScript是 ECMAScript 的语言标准的实现,ECMAScript 是在web浏览器的早期发展过程中为规范标准化语言的实现而诞生的。

ECMAScript标准有8个版本,7个发布(第4个版本被放弃了)。

JavaScript引擎在每次发布后开始实行指定的特性升级。这个图表说明并不是每个引擎都能实现了新出的每个特性,而且一些引擎实现这些特性的时间要比其他引擎长。这似乎不是最理想的,但我相信这总比没有标准要好。

起草

每个ECMAScript版本都要经过一个审核起稿的过程。如果一个起草建议被认为是有用的和向后兼容的,它将被包含在下一版中。

这个地址 概述了提案的五个阶段。每一个提案都是从一个“strawman”或最初提出的 stage-0 开始的。在这一级,它们要么尚未提交给技术委员会,要么尚未被拒绝,但仍未达到进入下一阶段的标准。

下面所示的草建议没有一项处于stage-0。

作为个人推荐,我建议读者在生产应用程序中避免使用stage-0建议,直到它们处于稳定的阶段。此建议的目的只是避免在起草建议被放弃或发生重大带来的麻烦。

好了,背景就啰嗦到这里了,需要使用这些新出来的特性,还需要如下步骤:

始化项目、安装依赖(前提需要安装node.js,nmp)
npm init -f && 
npm i ava@1.0.0-beta.3 
@babel/preset-env@7.0.0-beta.42 
@babel/preset-stage-0@7.0.0-beta.42 
@babel/register@7.0.0-beta.42 
@babel/polyfill@7.0.0-beta.46 
@babel/plugin-proposal-pipeline-operator
@babel/plugin-transform-runtime@7.0.0-beta.42 
@babel/runtime@7.0.0-beta.42 --save-dev

在 package.json 文件中添加以下代码:

"scripts": {
  "test": "ava"
},
"ava": {    
  "require": [      
    "@babel/register",
    "@babel/polyfill"   
  ]  
}

在根目录新建 .babelrc 文件,内容如下:

 {
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "node": "current"
        }
      }
    ],
    [
      "@babel/preset-stage-0",
      {
        "decoratorsLegacy": true,
        "pipelineProposal": "minimal"
      }
    ]
  ],
  "plugins": [
    "@babel/plugin-transform-runtime",
      [
        "@babel/plugin-proposal-optional-chaining",
        {
          "loose": false
        }
      ],
      [
        "@babel/plugin-proposal-decorators",
        {
          "decoratorsBeforeExport": false
        }
      ],
      [
        "@babel/plugin-proposal-class-properties"
      ],
      [
        "@babel/plugin-proposal-pipeline-operator",
        {
          "proposal": "minimal"
        }
      ]
  ]
}

接下,我们写个粟子把即将出来 JavaSrcipt 特性用起来吧!

自判断链接(Optional Chaining)

Optional Chaining 能检查一个对象上面是否存在某属性,我们项目中,如果有一个用户对象有如下结构:

const data = {
  user: {
    name: "小智",
    address: {
      street: "小智测试地址",
    }, 
  },
};

但实际项目中,我们 user 里面数据是请求获取,然后我们在赋值给 user,所以实际项目中我们一般会这么写:

const data = {
  user: {},
};

假设我们在程序要读取 user中的 street, 我们会这样写 data.user.address.street,恩,这时我们在控制台就会收到来自谷歌的红色问候:

console.log(data.user.address.street); // Uncaught TypeError: Cannot read     property "street" of undefined

为了避免出错,我们会这样写:

const street = data && data.user && data.user.address && data.user.address.street;
console.log(street); // undefined
我的感受,这种写法:

1)丑陋
2)繁琐冗长
3)狗屎

即将出现的特性中,我们可以这样写:

console.log(data.user?.address?.street); // undefined

这样是不是更加简洁方便呢?既然我们看到了这个特性的有用性,我们就可以继续深入研究了!

写个粟子(test.js):

// test.js
import test from "ava";

const valid = {
  user: {
    address: {
      street: "main street",
    },
  },
};

function getAddress(data) {
  return data?.user?.address?.street;
}

test("Optional Chaining returns real values", (t) => {
  const result = getAddress(valid);
  t.is(result, "main street");
});

测试:
npm test

现在我们看到自判断链接维护了点标记的先前功能。接下测试一下,一连串的 .属性 操作:

test("Optional chaining returns undefined for nullish properties.", (t) => {
  t.is(getAddress(), undefined);
  t.is(getAddress(null), undefined);
  t.is(getAddress({}), undefined);
});

下面是自判断链接如何用于数组属性访问:

const valid = {
  user: {
    address: {
      street: "main street",
      neighbors: [
        "john doe",
        "jane doe",
      ],
    },
  },
};

function getNeighbor(data, number) {
  return data?.user?.address?.neighbors?.[number];
}

test("Optional chaining works for array properties", (t) => {
  t.is(getNeighbor(valid, 0), "john doe");
});

test("Optional chaining returns undefined for invalid array properties", (t) => {
  t.is(getNeighbor({}, 0), undefined);
});

有时我们不知道函数是否在对象中实现,一个常见的例子是在使用web浏览器时。一些较老的浏览器可能没有某些功能。幸运的是,我们可以使用自判断链接来检测函数是否实现了!

const data = {
  user: {
    address: {
      street: "main street",
      neighbors: [
        "john doe",
        "jane doe",
      ],
    },
    getNeighbors() {
      return data.user.address.neighbors;
    }
  },
};

function getNeighbors(data) {
  return data?.user?.getNeighbors?.();
}
  
test("Optional chaining also works with functions", (t) => {
  const neighbors = getNeighbors(data);
  t.is(neighbors.length, 2);
  t.is(neighbors[0], "john doe");
});

test("Optional chaining returns undefined if a function does not exist", (t) => {
  const neighbors = getNeighbors({});
  t.is(neighbors, undefined);
});

如果链不完整,表达式将不执行。在JavaScript引擎下,表达式粗略地转换成这个:

value == null ? value[some expression here]: undefined;

在“自判断链接” ?之后,如果值未定义或为空,则执行。我们可以在下面的测试中看到该规则的作用:

let neighborCount = 0;

function getNextNeighbor(neighbors) {
  return neighbors?.[++neighborCount];
}

test("It short circuits expressions", (t) => {
  const neighbors = getNeighbors(data);
  t.is(getNextNeighbor(neighbors), "jane doe");
  t.is(getNextNeighbor(undefined), undefined);
  t.is(neighborCount, 1);
});

所以“自判断链接”减少了对if语句、导入库(如lodash)和&&操作符号的需要。

您可能会注意到,使用这个“自判断链接”具有最小的开销。你检查的每一级”?“必须隐藏在某种条件逻辑中。如果使用过度,将导致性能下降。

下面是我们在JavaScript中看到的一些常见操作:

检查null或者undefined的值

设置默认值

判断值是否为 0,null, ""

你可能见过这样做的:

value != null ? value : "default value";

或者你可能见过这种不恰当的做法:

value || "default value"

问题是对于这两个实现,我们的三目运算符条件没有满足。在这个场景中,数字0、false和空字符串都被认为是假的。这就是为什么我们必须检查null和 undefined。

value != null

与之相同的是:

value !== null && value !== undefined

这个就是 Nullish 合并出现原因,我们可以这样做:

value ?? "default value";

这就可以防止默认那些不可靠的值(null,undefined),代替三目运算和 !=null 的操作;

写个测试粟子:
import test from "ava";

test("Nullish coalescing defaults null", (t) => {
  t.is(null ?? "default", "default");
});

test("Nullish coalescing defaults undefined", (t) => {
  t.is(undefined ?? "default", "default");
});

test("Nullish coalescing defaults void 0", (t) => {
  t.is(void 0 ?? "default", "default");
});

test("Nullish coalescing does not default 0", (t) => {
  t.is(0 ?? "default", 0);
});

test("Nullish coalescing does not default empty strings", (t) => {
  t.is("" ?? "default", "");
});

test("Nullish coalescing does not default false", (t) => {
  t.is(false ?? "default", false);
});

您可以在测试中看到,默认值为null、undefined和void 0,结果为undefined。它不会默认false值,如0、"和false.

管道操作符

在函数式编程中,我们有一个术语“组合”,它是将多个函数调用链接在一起的行为。每个函数接收前一个函数的输出作为输入。下面是我们用普通JavaScript讨论的一个例子:

function doubleSay (str) {
  return str + ", " + str;
}
function capitalize (str) {
  return str[0].toUpperCase() + str.substring(1);
}
function exclaim (str) {
  return str + "!";
}
let result = exclaim(capitalize(doubleSay("hello")));
result //=> "Hello, hello!"

这种串接非常常见,以至于组合函数出现在大多数函数库中,比如lodash和ramda。

使用新的管道操作符,您可以跳过第三方库,像这样编写上面的代码:

let result = "hello"
  |> doubleSay
  |> capitalize
  |> exclaim;

result //=> "Hello, hello!"

这样做的目的是为了提高链的可读性。它也将在未来与部分应用程序很好地工作,或目前它可以实现如下:

let result = 1
  |> (_ => Math.max(0, _));

result //=> 1
let result = -5
  |> (_ => Math.max(0, _));

result //=> 0

现在我们看到了语法,可以开始编写测试了!

import test from "ava";

function doubleSay (str) {
  return str + ", " + str;
}

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

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

test("Simple pipeline usage", (t) => {
  let result = "hello"
    |> doubleSay
    |> capitalize
    |> exclaim;

  t.is(result, "Hello, hello!");
});

test("Partial application pipeline", (t) => {
  let result = -5
    |> (_ => Math.max(0, _));

  t.is(result, 0);
});

test("Async pipeline", async (t) => {
  const asyncAdd = (number) => Promise.resolve(number + 5);
  const subtractOne = (num1) => num1 - 1;
  const result = 10
    |> asyncAdd
    |> (async (num) => subtractOne(await num));
  
  t.is(await result, 14);
});

好了,现在您已经看到了这些新特性的实际应用,希望不久的你可以熟练的尝试它!

你的点赞,是我持续分享好东西的动力,欢迎点赞!

欢迎加入前端大家庭,里面会经常分享一些技术资源。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/99357.html

相关文章

  • 人工智能革命:遥远未来...即将到来

    摘要:为了让一个人被传送到未来并从他们所经历的震惊程度中死去,他们必须向前走足够长的时间才能达到死亡水平或死亡进展单位。电影回到未来于年上映,而过去则发生在年。 showImg(http://upload-images.jianshu.io/upload_images/13825820-35b9513286a761f1.jpg?imageMogr2/auto-orient/strip%7Ci...

    xiaokai 评论0 收藏0
  • 2019 年值得学习顶级 JavaScript 框架与主题

    摘要:我们的目标是找出最有职业投资回报率的主题和技术。比特币在几年内增长了若干个量级。比特币倍拐点在这个图表中,每个箭头始于倍点,指向价格修正后的最低点。 showImg(https://segmentfault.com/img/remote/1460000017919159); 图:Jon Glittenberg Happy New Year 2019 (CC BY 2.0) 又到了一年的...

    legendaryedu 评论0 收藏0
  • “别更新,学不动” 之:全栈开发者 2019 应该学些什么?

    摘要:但是,有一件事是肯定的年对全栈开发者的需求量很大。有一些方法可以解决这个问题,例如模式,或者你可以这么想,其实谷歌机器人在抓取单页应用程序时没有那么糟糕。谷歌正在这方面努力推进,但不要指望在年会看到任何突破。 对于什么是全栈开发者并没有一个明确的定义。但是,有一件事是肯定的:2019 年对全栈开发者的需求量很大。在本文中,我将向你概述一些趋势,你可以尝试根据这些趋势来确定你可能要投入的...

    NervosNetwork 评论0 收藏0
  • “别更新,学不动” 之:全栈开发者 2019 应该学些什么?

    摘要:但是,有一件事是肯定的年对全栈开发者的需求量很大。有一些方法可以解决这个问题,例如模式,或者你可以这么想,其实谷歌机器人在抓取单页应用程序时没有那么糟糕。谷歌正在这方面努力推进,但不要指望在年会看到任何突破。 对于什么是全栈开发者并没有一个明确的定义。但是,有一件事是肯定的:2019 年对全栈开发者的需求量很大。在本文中,我将向你概述一些趋势,你可以尝试根据这些趋势来确定你可能要投入的...

    sutaking 评论0 收藏0
  • “别更新,学不动” 之:全栈开发者 2019 应该学些什么?

    摘要:但是,有一件事是肯定的年对全栈开发者的需求量很大。有一些方法可以解决这个问题,例如模式,或者你可以这么想,其实谷歌机器人在抓取单页应用程序时没有那么糟糕。谷歌正在这方面努力推进,但不要指望在年会看到任何突破。 对于什么是全栈开发者并没有一个明确的定义。但是,有一件事是肯定的:2019 年对全栈开发者的需求量很大。在本文中,我将向你概述一些趋势,你可以尝试根据这些趋势来确定你可能要投入的...

    ormsf 评论0 收藏0

发表评论

0条评论

tinysun1234

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<