广州北大青鸟计算机职业培训学校
互联网技术培训、软件技术培训、大数据培训、云计算培训、数据分析培训信息网
当前位置:网站首页 > 软件专业 > 前端开发专业 > 正文

JavaScript的新特性是什么?_惠州前端培训学校

作者:alu发布时间:2022-03-18分类:前端开发专业浏览:594


导读:JavaScript的新特性是什么?下面惠州北大青鸟老师给大家分享一下,希望对大家有帮助。

JavaScript的新特性是什么?下面惠州北大青鸟老师给大家分享一下,希望对大家有帮助。

创建测试项目

新建一个目录并运行运行以下命令:

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.42 @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"

],

"plugins": [

"@babel/plugin-transform-runtime"

]

}

现在可以开始写一些测试用例了!

1、可选运算符

在JavaScript中,我们一直在使用对象,但有时候对象里并不是我们期望的数据结构。假设下面是我们期望得到的数据,可能是通过调用API查询数据库得到的。


const data = {

user: {

address: {

street: "Pennsylvania Avenue"

}

}

}

如果该用户没有完成注册,可能得到下面的数据:


const data = {

user: {}

};

当尝试按下面的方式访问street时,会得到报错:

console.log(data.user.address.street);

// Uncaught TypeError: Cannot read property 'street' of undefined

为避免这种情况,需要按如下方式访问“street”属性:

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

这样看起来更简单了,现在我们已经看到了这个功能的用处,现在来写一个测试!


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');

});

我们看到了可选符号的正常使用,接下来是一些不规范数据的测试用例:


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',

eighbors: [

'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);

});

有时我们不知道某个函数是否在对象中实现,一个常见的场景是,某些旧版浏览器可能没有某些功能,我们可以使用可选运算符接来检测函数是否已实现。看如下代码:


const data = {

user: {

address: {

street: 'main street',

eighbors: [

'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);

});

如果调用链不完整,函数将不会执行,它背后的逻辑应该是这样的:

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

如果在可选链操作符之后是 undefined 或者 null则什么都不会执行,我们可以在以下测试中看到该规则的实际应用:


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等库以及&&进行链式调用的使用。

2、空值合并

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

1. 检查 null 或 undefined

2. 给变量设置默认值

3. 确保0,false和''不设置默认值

像这样:

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

或者这样:

value || 'default value'

问题是,对于第二个实现,在值为0、false和''时都被视为false,所以我们必须明确检查null和undefined。

value != null

和上面相同:

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

这就是新提案的用武之地,现在我们可以这样做:

value ?? 'default value';

这可以保护我们不会为0、false和''设置默认值,在不使用三元运算符和!= null检查的情况下捕获null和undefined。

接下来编写一个简单的测试来验证它是如何工作的:


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设置了默认值,没有为0,''和false设置默认值。

3、管道运算符

在函数式编程中,我们有一个概念叫compose,它多个函数调用合并在一起,调用时从右到左执行每个函数,函数接收前一个函数的输出作为其输入,以下是我们在纯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);

});

需要注意,一旦将async函数添加到管道,必须await该返回值,因为此时返回值是promise。有一提案开始支持|> await asyncFunction,但尚未实现。

最后,既然你已经看到了这些提案的实际应用,我希望你能够尝试一下这些提案!

想学前端,可以来惠州北大青鸟新方舟校区详细了解。

标签:惠州前端培训学校惠州前端基础惠州前端培训北大青鸟IT计算机学校北大青鸟IT软件学校前端北大青鸟IT学校惠州北大青鸟北大青鸟


前端开发专业排行
标签列表
网站分类
文章归档
最近发表