chore(learn): Applied MDX format to Chinese curriculum files (#40462)

This commit is contained in:
Randell Dawson
2020-12-16 00:37:30 -07:00
committed by GitHub
parent 873fce02a2
commit 9ce4a02a41
1665 changed files with 58741 additions and 88042 deletions

View File

@ -1,87 +1,65 @@
---
id: 5a661e0f1068aca922b3ef17
title: 使用方括号访问数组的内容
challengeType: 1
forumTopicId: 301149
title: 使用方括号访问数组的内容
---
## Description
<section id='description'>
# --description--
所有数据结构的基本特性是,它们不仅能够存储数据,我们还能够按照需求来访问存放在其中的数据。我们已经学习了如何创建一个数组结构,现在让我们开始学习如何访问这个数组结构中的数据。
我们先定义一个包含 3 个元素的数组:
```js
let ourArray = ["a", "b", "c"];
```
在一个数组结构中,其内部的每个元素都有一个与之对应的<dfn>索引</dfn><dfn>index</dfn>。索引是该元素在数组中的位置可被用于引用该元素。但需要注意的是JavaScript 数组的索引是从0开始的<dfn>zero-indexed</dfn>),即一个数组的第一个元素是在数组中的<em><strong>第 0 个</strong></em>位置,而不是第 1 个位置。
要从一个数组中获取一个元素,我们可以在一个数组变量名的后面加一个使用“方括号”括起来的索引。这叫做<dfn>方括号符号</dfn><dfn>bracket notation</dfn>)。
例如我们要从<code>ourArray</code>数组变量中获取数据元素<code>"a"</code>并将其赋值给一个变量,我们可以编写如下所示的代码:
在一个数组结构中,其内部的每个元素都有一个与之对应的<dfn>索引</dfn><dfn>index</dfn>。索引是该元素在数组中的位置可被用于引用该元素。但需要注意的是JavaScript 数组的索引是从0开始的<dfn>zero-indexed</dfn>),即一个数组的第一个元素是在数组中的***第 0 个***位置,而不是第 1 个位置。 要从一个数组中获取一个元素,我们可以在一个数组变量名的后面加一个使用“方括号”括起来的索引。这叫做<dfn>方括号符号</dfn><dfn>bracket notation</dfn>)。 例如我们要从`ourArray`数组变量中获取数据元素`"a"`并将其赋值给一个变量,我们可以编写如下所示的代码:
```js
let ourVariable = ourArray[0];
// ourVariable 的值为 "a"
```
除了使用 “索引” 来获取某个元素值以外,你还可以通过类似的方法来<em>设置</em>一个索引位置所对应的元素值:
除了使用 “索引” 来获取某个元素值以外,你还可以通过类似的方法来*设置*一个索引位置所对应的元素值:
```js
ourArray[1] = "not b anymore";
// ourArray 现在的值为 ["a", "not b anymore", "c"];
```
我们现在已经利用方括号将索引为 1 的元素从<code>"b"</code>设置为了<code>"not b anymore"</code>
</section>
我们现在已经利用方括号将索引为 1 的元素从`"b"`设置为了`"not b anymore"`
## Instructions
<section id='instructions'>
在本挑战中,请你将<code>myArray</code>中第二个元素(索引<code>1</code>)设置为除了<code>"b"</code>以外的任意值。
</section>
# --instructions--
## Tests
<section id='tests'>
在本挑战中,请你将`myArray`中第二个元素(索引`1`)设置为除了`"b"`以外的任意值。
```yml
tests:
- text: '<code>myArray[0]</code>等于<code>&quot;a&quot;</code>'
testString: assert.strictEqual(myArray[0], "a");
- text: '<code>myArray[1]</code>不再设置为<code>&quot;b&quot;</code>'
testString: assert.notStrictEqual(myArray[1], "b");
- text: '<code>myArray[2]</code>等于<code>&quot;c&quot;</code>'
testString: assert.strictEqual(myArray[2], "c");
- text: '<code>myArray[3]</code>等于<code>&quot;d&quot;</code>'
testString: assert.strictEqual(myArray[3], "d");
# --hints--
```
</section>
## Challenge Seed
<section id='challengeSeed'>
<div id='js-seed'>
`myArray[0]`等于`"a"`
```js
let myArray = ["a", "b", "c", "d"];
// change code below this line
//change code above this line
console.log(myArray);
assert.strictEqual(myArray[0], 'a');
```
</div>
</section>
## Solution
<section id='solution'>
`myArray[1]`不再设置为`"b"`
```js
// solution required
let myArray = ["a", "b", "c", "d"];
myArray[1] = "e";
assert.notStrictEqual(myArray[1], 'b');
```
</section>
`myArray[2]`等于`"c"`
```js
assert.strictEqual(myArray[2], 'c');
```
`myArray[3]`等于`"d"`
```js
assert.strictEqual(myArray[3], 'd');
```
# --solutions--

View File

@ -1,95 +1,63 @@
---
id: 587d7b7c367417b2b2512b1a
title: 使用方括号访问属性名称
challengeType: 1
forumTopicId: 301150
title: 使用方括号访问属性名称
---
## Description
<section id='description'>
在关于对象的第一个挑战中,我们提到可以在方括号符号中用一个变量作为属性名来访问属性值。假设一个超市的收银台的程序中使用了一个<code>foods</code>对象,并且有一些程序逻辑会设置<code>selectedFood</code>,我们需要查询<code>foods</code>对象来检查某种食物是否存在,我们可以这样写检查逻辑:
# --description--
在关于对象的第一个挑战中,我们提到可以在方括号符号中用一个变量作为属性名来访问属性值。假设一个超市的收银台的程序中使用了一个`foods`对象,并且有一些程序逻辑会设置`selectedFood`,我们需要查询`foods`对象来检查某种食物是否存在,我们可以这样写检查逻辑:
```js
let selectedFood = getCurrentFood(scannedItem);
let inventory = foods[selectedFood];
```
上述代码会先计算<code>selectedFood</code>变量的值,并返回<code>foods</code>对象中以该值命名的属性对应的值,若没有以该值命名的属性则会返回<code>undefined</code>。有时候对象的属性名在运行之前是不确定的,或者我们需要动态地访问对象的属性,这时方括号符号就会很有用。
</section>
上述代码会先计算`selectedFood`变量的值,并返回`foods`对象中以该值命名的属性对应的值,若没有以该值命名的属性则会返回`undefined`。有时候对象的属性名在运行之前是不确定的,或者我们需要动态地访问对象的属性,这时方括号符号就会很有用。
## Instructions
<section id='instructions'>
我们已经定义了一个<code>checkInventory</code>函数,它接受一个被扫描到的商品名作为输入参数。它要返回<code>foods</code>对象中以<code>scannedItem</code>的值命名的属性的值。只有有效的属性名会作为参数传入<code>checkInventory</code>,你在完成挑战时不需处理参数无效的情况。
</section>
# --instructions--
## Tests
<section id='tests'>
我们已经定义了一个`checkInventory`函数,它接受一个被扫描到的商品名作为输入参数。它要返回`foods`对象中以`scannedItem`的值命名的属性的值。只有有效的属性名会作为参数传入`checkInventory`,你在完成挑战时不需处理参数无效的情况。
```yml
tests:
- text: <code>checkInventory</code>是一个函数
testString: assert.strictEqual(typeof checkInventory, 'function');
- text: '<code>foods</code>对象应该只有以下键值对: <code>apples: 25</code> <code>oranges: 32</code> <code>plums: 28</code> <code>bananas: 13</code> <code>grapes: 35</code> <code>strawberries: 27</code>'
testString: 'assert.deepEqual(foods, {apples: 25, oranges: 32, plums: 28, bananas: 13, grapes: 35, strawberries: 27});'
- text: <code>checkInventory(&quot;apples&quot;)</code>应该返回<code>25</code>
testString: assert.strictEqual(checkInventory('apples'), 25);
- text: <code>checkInventory(&quot;bananas&quot;)</code>应该返回<code>13</code>
testString: assert.strictEqual(checkInventory('bananas'), 13);
- text: <code>checkInventory(&quot;strawberries&quot;)</code>应该返回<code>27</code>
testString: assert.strictEqual(checkInventory('strawberries'), 27);
# --hints--
```
</section>
## Challenge Seed
<section id='challengeSeed'>
<div id='js-seed'>
`checkInventory`是一个函数
```js
let foods = {
assert.strictEqual(typeof checkInventory, 'function');
```
`foods`对象应该只有以下键值对: `apples: 25` `oranges: 32` `plums: 28` `bananas: 13` `grapes: 35` `strawberries: 27`
```js
assert.deepEqual(foods, {
apples: 25,
oranges: 32,
plums: 28,
bananas: 13,
grapes: 35,
strawberries: 27
};
// do not change code above this line
function checkInventory(scannedItem) {
// change code below this line
}
// change code below this line to test different cases:
console.log(checkInventory("apples"));
});
```
</div>
</section>
## Solution
<section id='solution'>
`checkInventory("apples")`应该返回`25`
```js
// solution required
let foods = {
apples: 25,
oranges: 32,
plums: 28,
bananas: 13,
grapes: 35,
strawberries: 27
};
function checkInventory(scannedItem) {
return foods[scannedItem];
}
assert.strictEqual(checkInventory('apples'), 25);
```
</section>
`checkInventory("bananas")`应该返回`13`
```js
assert.strictEqual(checkInventory('bananas'), 13);
```
`checkInventory("strawberries")`应该返回`27`
```js
assert.strictEqual(checkInventory('strawberries'), 27);
```
# --solutions--

View File

@ -1,14 +1,15 @@
---
id: 587d78b2367417b2b2512b0e
title: 使用 push() 和 unshift() 添加项目到数组中
challengeType: 1
forumTopicId: 301151
title: 使用 push() 和 unshift() 添加项目到数组中
---
## Description
<section id='description'>
一个数组的长度与其包含的数据类型一样,是不固定的。数组可以包含任意数量的元素,可以不限次数地往数组中添加元素或者从中移除元素,或者说数组是<dfn>可变的</dfn><dfn>mutable</dfn>)。在本挑战中,我们要学习两个以编程方式修改数组的方法:<code>Array.push()</code><code>Array.unshift()</code>
这两个方法都接收一个或多个元素作为参数;对一个数组调用这两个方法都可以将输入的元素插入到该数组中;<code>push()</code>方法将元素插入到一个数组的末尾,而<code>unshift()</code>方法将元素插入到一个数组的开头。请看以下例子:
# --description--
一个数组的长度与其包含的数据类型一样,是不固定的。数组可以包含任意数量的元素,可以不限次数地往数组中添加元素或者从中移除元素,或者说数组是<dfn>可变的</dfn><dfn>mutable</dfn>)。在本挑战中,我们要学习两个以编程方式修改数组的方法:`Array.push()``Array.unshift()`
这两个方法都接收一个或多个元素作为参数;对一个数组调用这两个方法都可以将输入的元素插入到该数组中;`push()`方法将元素插入到一个数组的末尾,而`unshift()`方法将元素插入到一个数组的开头。请看以下例子:
```js
let twentyThree = 'XXIII';
@ -22,63 +23,40 @@ romanNumerals.push(twentyThree);
```
注意,我们还可以输入变量,这允许我们很灵活地动态改变我们数组中的数据。
</section>
## Instructions
<section id='instructions'>
我们已经定义了一个<code>mixedNumbers</code>函数,它会接受一个数组作为参数。请你修改这个函数,使用<code>push()</code><code>unshift()</code>来将<code>'I', 2, 'three'</code>插入到数组的开头,将<code>7, 'VIII', 9</code>插入到数组的末尾,使得这个函数返回一个依次包含 1-9 的数组。
</section>
# --instructions--
## Tests
<section id='tests'>
我们已经定义了一个`mixedNumbers`函数,它会接受一个数组作为参数。请你修改这个函数,使用`push()``unshift()`来将`'I', 2, 'three'`插入到数组的开头,将`7, 'VIII', 9`插入到数组的末尾,使得这个函数返回一个依次包含 1-9 的数组。
```yml
tests:
- text: '<code>mixedNumbers([&quot;IV&quot;, 5, &quot;six&quot;])</code>现在应该返回<code>[&quot;I&quot;, 2, &quot;three&quot;, &quot;IV&quot;, 5, &quot;six&quot;, 7, &quot;VIII&quot;, 9]</code>'
testString: assert.deepEqual(mixedNumbers(['IV', 5, 'six']), ['I', 2, 'three', 'IV', 5, 'six', 7, 'VIII', 9]);
- text: <code>mixedNumbers</code>函数应该使用<code>push()</code>方法
testString: assert(mixedNumbers.toString().match(/\.push/));
- text: <code>mixedNumbers</code>函数应该使用<code>unshift()</code>方法
testString: assert(mixedNumbers.toString().match(/\.unshift/));
# --hints--
```
</section>
## Challenge Seed
<section id='challengeSeed'>
<div id='js-seed'>
`mixedNumbers(["IV", 5, "six"])`现在应该返回`["I", 2, "three", "IV", 5, "six", 7, "VIII", 9]`
```js
function mixedNumbers(arr) {
// change code below this line
// change code above this line
return arr;
}
// do not change code below this line
console.log(mixedNumbers(['IV', 5, 'six']));
assert.deepEqual(mixedNumbers(['IV', 5, 'six']), [
'I',
2,
'three',
'IV',
5,
'six',
7,
'VIII',
9
]);
```
</div>
</section>
## Solution
<section id='solution'>
`mixedNumbers`函数应该使用`push()`方法
```js
function mixedNumbers(arr) {
// change code below this line
arr.push(7,'VIII',9);
arr.unshift('I',2,'three');
// change code above this line
return arr;
}
assert(mixedNumbers.toString().match(/\.push/));
```
</section>
`mixedNumbers`函数应该使用`unshift()`方法
```js
assert(mixedNumbers.toString().match(/\.unshift/));
```
# --solutions--

View File

@ -1,13 +1,13 @@
---
id: 587d78b3367417b2b2512b11
title: 使用 splice() 增加项目
challengeType: 1
forumTopicId: 301152
title: 使用 splice() 增加项目
---
## Description
<section id='description'>
你还记得在上个挑战中我们提到<code>splice()</code>方法可以接受最多 3 个参数吗?我们现在可以进一步了解<code>splice()</code>。除了移除元素,我们还可以利用它的第三个参数来向数组中<em>添加</em>元素。第三个参数可以是一个或多个元素,这些元素会被添加到数组中。这使我们能够便捷地将数组中的一个或一系列元素换成其他的元素。例如:
# --description--
你还记得在上个挑战中我们提到`splice()`方法可以接受最多 3 个参数吗?我们现在可以进一步了解`splice()`。除了移除元素,我们还可以利用它的第三个参数来向数组中*添加*元素。第三个参数可以是一个或多个元素,这些元素会被添加到数组中。这使我们能够便捷地将数组中的一个或一系列元素换成其他的元素。例如:
```js
const numbers = [10, 11, 12, 12, 15];
@ -20,63 +20,52 @@ console.log(numbers);
// 返回 [ 10, 11, 12, 13, 14, 15 ]
```
以一个数字数组开始。接着调用 <code>splice()</code> 方法,在 (3) 的索引位置开始删除元素,删除的元素数量是 (1)(13, 14) 是在删除位置插入的元素,可以在 <code>amountToDelete</code> 后面插入任意数量的元素(以逗号分隔),每个都会被插入。
</section>
以一个数字数组开始。接着调用 `splice()` 方法,在 (3) 的索引位置开始删除元素,删除的元素数量是 (1)(13, 14) 是在删除位置插入的元素,可以在 `amountToDelete` 后面插入任意数量的元素(以逗号分隔),每个都会被插入。
## Instructions
<section id='instructions'>
我们已经定义了一个<code>htmlColorNames</code>函数,它以一个 HTML 颜色的数组作为输入参数。请修改这个函数,利用<code>splice()</code>来移除数组中的前两个元素,并在对应的位置上添加<code>'DarkSalmon'</code><code>'BlanchedAlmond'</code>
</section>
# --instructions--
## Tests
<section id='tests'>
我们已经定义了一个`htmlColorNames`函数,它以一个 HTML 颜色的数组作为输入参数。请修改这个函数,利用`splice()`来移除数组中的前两个元素,并在对应的位置上添加`'DarkSalmon'``'BlanchedAlmond'`
```yml
tests:
- text: '<code>htmlColorNames</code>应该返回<code>[&quot;DarkSalmon&quot;, &quot;BlanchedAlmond&quot;, &quot;LavenderBlush&quot;, &quot;PaleTurqoise&quot;, &quot;FireBrick&quot;]</code>'
testString: assert.deepEqual(htmlColorNames(['DarkGoldenRod', 'WhiteSmoke', 'LavenderBlush', 'PaleTurquoise', 'FireBrick']), ['DarkSalmon', 'BlanchedAlmond', 'LavenderBlush', 'PaleTurquoise', 'FireBrick']);
- text: <code>htmlColorNames</code>函数应该使用<code>splice()</code>方法
testString: assert(/.splice/.test(code));
- text: 你不应该使用<code>shift()</code>或<code>unshift()</code> 。
testString: assert(!/shift|unshift/.test(code));
- text: 您不应该使用数组括号表示法。
testString: assert(!/\[\d\]\s*=/.test(code));
# --hints--
```
</section>
## Challenge Seed
<section id='challengeSeed'>
<div id='js-seed'>
`htmlColorNames`应该返回`["DarkSalmon", "BlanchedAlmond", "LavenderBlush", "PaleTurqoise", "FireBrick"]`
```js
function htmlColorNames(arr) {
// change code below this line
// change code above this line
return arr;
}
// do not change code below this line
console.log(htmlColorNames(['DarkGoldenRod', 'WhiteSmoke', 'LavenderBlush', 'PaleTurqoise', 'FireBrick']));
assert.deepEqual(
htmlColorNames([
'DarkGoldenRod',
'WhiteSmoke',
'LavenderBlush',
'PaleTurquoise',
'FireBrick'
]),
[
'DarkSalmon',
'BlanchedAlmond',
'LavenderBlush',
'PaleTurquoise',
'FireBrick'
]
);
```
</div>
</section>
## Solution
<section id='solution'>
`htmlColorNames`函数应该使用`splice()`方法
```js
function htmlColorNames(arr) {
arr.splice(0,2,'DarkSalmon', 'BlanchedAlmond');
return arr;
}
assert(/.splice/.test(code));
```
</section>
你不应该使用`shift()``unshift()`
```js
assert(!/shift|unshift/.test(code));
```
您不应该使用数组括号表示法。
```js
assert(!/\[\d\]\s*=/.test(code));
```
# --solutions--

View File

@ -1,12 +1,12 @@
---
id: 587d7b7c367417b2b2512b18
title: 将键值对添加到对象中
challengeType: 1
forumTopicId: 301153
title: 将键值对添加到对象中
---
## Description
<section id='description'>
# --description--
对象object本质上是<dfn>键值对key-value pair</dfn>的集合,或者说,一系列被映射到唯一标识符(叫做<dfn>属性property</dfn>或者<dfn>key</dfn>)的数据。让我们来看一个很简单的例子:
```js
@ -18,7 +18,7 @@ let FCC_User = {
};
```
上面的代码定义了一个叫做<code>FCC_User</code>的对象,它有 4 个<dfn>属性</dfn>,每个属性映射一个特定的值。如果我们想知道<code>FCC_User</code>有多少<code>followers</code>,我们可以这样访问其<code>followers</code>属性:
上面的代码定义了一个叫做`FCC_User`的对象,它有 4 个<dfn>属性</dfn>,每个属性映射一个特定的值。如果我们想知道`FCC_User`有多少`followers`,我们可以这样访问其`followers`属性:
```js
let userData = FCC_User.followers;
@ -32,74 +32,47 @@ let userData = FCC_User['followers'];
// userData 等于 572
```
注意,在用<dfn>方括号符号</dfn>时,我们在括号里写的是字符串<code>followers</code>(用引号括起)。方括号符号让我们能用一个变量作为属性名来访问对象的属性(请记住)。若我们在方括号中不写引号而直接写<code>followers</code>JavaScript 引擎会将其看作一个变量,并抛出一个<code>ReferenceError: followers is not defined</code>的错误。
</section>
注意,在用<dfn>方括号符号</dfn>时,我们在括号里写的是字符串`followers`(用引号括起)。方括号符号让我们能用一个变量作为属性名来访问对象的属性(请记住)。若我们在方括号中不写引号而直接写`followers`JavaScript 引擎会将其看作一个变量,并抛出一个`ReferenceError: followers is not defined`的错误。
## Instructions
<section id='instructions'>
用这样的语法,我们还可以向对象中<em><strong>新增</strong></em>键值对。我们已经创建了一个有 3 个属性的<code>foods</code>对象,请为其新增 3 项:值为<code>13</code><code>bananas</code>属性、值为<code>35</code><code>grapes</code>属性和值为<code>27</code><code>strawberries</code>属性。
</section>
# --instructions--
## Tests
<section id='tests'>
用这样的语法,我们还可以向对象中***新增***键值对。我们已经创建了一个有 3 个属性的`foods`对象,请为其新增 3 项:值为`13``bananas`属性、值为`35``grapes`属性和值为`27``strawberries`属性。
```yml
tests:
- text: <code>foods</code>应该是一个对象。
testString: assert(typeof foods === 'object');
- text: <code>foods</code>应该有一个值为<code>13</code>的<code>&quot;bananas&quot;</code>属性。
testString: assert(foods.bananas === 13);
- text: <code>foods</code>应该有一个值为<code>35</code>的<code>&quot;grapes&quot;</code>属性。
testString: assert(foods.grapes === 35);
- text: <code>foods</code>应该有一个值为<code>27</code>的<code>&quot;strawberries&quot;</code>属性。
testString: assert(foods.strawberries === 27);
- text: 你应该用点符号或者方括号符号来设置对象的属性。
testString: assert(code.search(/bananas:/) === -1 && code.search(/grapes:/) === -1 && code.search(/strawberries:/) === -1);
# --hints--
```
</section>
## Challenge Seed
<section id='challengeSeed'>
<div id='js-seed'>
`foods`应该是一个对象。
```js
let foods = {
apples: 25,
oranges: 32,
plums: 28
};
// change code below this line
// change code above this line
console.log(foods);
assert(typeof foods === 'object');
```
</div>
</section>
## Solution
<section id='solution'>
`foods`应该有一个值为`13``"bananas"`属性。
```js
let foods = {
apples: 25,
oranges: 32,
plums: 28
};
// change code below this line
foods['bananas'] = 13;
foods['grapes'] = 35;
foods['strawberries'] = 27;
// change code above this line
assert(foods.bananas === 13);
```
</section>
`foods`应该有一个值为`35``"grapes"`属性。
```js
assert(foods.grapes === 35);
```
`foods`应该有一个值为`27``"strawberries"`属性。
```js
assert(foods.strawberries === 27);
```
你应该用点符号或者方括号符号来设置对象的属性。
```js
assert(
code.search(/bananas:/) === -1 &&
code.search(/grapes:/) === -1 &&
code.search(/strawberries:/) === -1
);
```
# --solutions--

View File

@ -1,13 +1,14 @@
---
id: 587d7b7b367417b2b2512b14
title: 使用 indexOf() 检查元素是否存在
challengeType: 1
forumTopicId: 301154
title: 使用 indexOf() 检查元素是否存在
---
## Description
<section id='description'>
由于数组可以在任意时间被修改或者说<em>被改变mutated</em>我们不能保证某个数据在一个给定数组中的位置甚至不能保证该元素还存在于该数组中。幸运的是JavaScript 给我们提供了另一个内置方法<code>indexOf()</code>。这个方法让我们可以便捷地检查某个元素是否存在于一个数组中。<code>indexOf()</code>方法接受一个元素作为输入参数,并返回该元素在数组中的位置(索引);若该元素不存在于数组中则返回<code>-1</code>
# --description--
由于数组可以在任意时间被修改或者说*被改变mutated*我们不能保证某个数据在一个给定数组中的位置甚至不能保证该元素还存在于该数组中。幸运的是JavaScript 给我们提供了另一个内置方法`indexOf()`。这个方法让我们可以便捷地检查某个元素是否存在于一个数组中。`indexOf()`方法接受一个元素作为输入参数,并返回该元素在数组中的位置(索引);若该元素不存在于数组中则返回`-1`
例如:
```js
@ -18,64 +19,47 @@ fruits.indexOf('oranges'); // 返回 2
fruits.indexOf('pears'); // 返回 1即第一个出现的 'pears' 元素在数组中的索引为 1
```
</section>
# --instructions--
## Instructions
<section id='instructions'>
<code>indexOf()</code>在快速检查一个数组中是否存在某个元素时非常有用。我们已经定义了一个<code>quickCheck</code>函数,它接受一个数组和一个元素作为输入参数。请修改这个函数,利用<code>indexOf()</code>方法,使得当输入的数组中含有输入的元素时,函数返回<code>true</code>;不含有输入的元素时,函数返回<code>false</code>
</section>
`indexOf()`在快速检查一个数组中是否存在某个元素时非常有用。我们已经定义了一个`quickCheck`函数,它接受一个数组和一个元素作为输入参数。请修改这个函数,利用`indexOf()`方法,使得当输入的数组中含有输入的元素时,函数返回`true`;不含有输入的元素时,函数返回`false`
## Tests
<section id='tests'>
# --hints--
```yml
tests:
- text: '<code>quickCheck([&quot;squash&quot;, &quot;onions&quot;, &quot;shallots&quot;], &quot;mushrooms&quot;)</code>应该返回<code>false</code>'
testString: assert.strictEqual(quickCheck(['squash', 'onions', 'shallots'], 'mushrooms'), false);
- text: '<code>quickCheck([&quot;squash&quot;, &quot;onions&quot;, &quot;shallots&quot;], &quot;onions&quot;)</code>应该返回<code>true</code>'
testString: assert.strictEqual(quickCheck(['onions', 'squash', 'shallots'], 'onions'), true);
- text: '<code>quickCheck([3, 5, 9, 125, 45, 2], 125)</code>应该返回<code>true</code>'
testString: assert.strictEqual(quickCheck([3, 5, 9, 125, 45, 2], 125), true);
- text: '<code>quickCheck([true, false, false], undefined)</code>应返回<code>false</code>'
testString: assert.strictEqual(quickCheck([true, false, false], undefined), false);
- text: <code>quickCheck</code>函数应该使用<code>indexOf()</code>方法
testString: assert.notStrictEqual(quickCheck.toString().search(/\.indexOf\(/), -1);
```
</section>
## Challenge Seed
<section id='challengeSeed'>
<div id='js-seed'>
`quickCheck(["squash", "onions", "shallots"], "mushrooms")`应该返回`false`
```js
function quickCheck(arr, elem) {
// change code below this line
// change code above this line
}
// change code here to test different cases:
console.log(quickCheck(['squash', 'onions', 'shallots'], 'mushrooms'));
assert.strictEqual(
quickCheck(['squash', 'onions', 'shallots'], 'mushrooms'),
false
);
```
</div>
</section>
## Solution
<section id='solution'>
`quickCheck(["squash", "onions", "shallots"], "onions")`应该返回`true`
```js
function quickCheck(arr, elem) {
// change code below this line
return arr.indexOf(elem) >= 0;
// change code above this line
}
assert.strictEqual(
quickCheck(['onions', 'squash', 'shallots'], 'onions'),
true
);
```
</section>
`quickCheck([3, 5, 9, 125, 45, 2], 125)`应该返回`true`
```js
assert.strictEqual(quickCheck([3, 5, 9, 125, 45, 2], 125), true);
```
`quickCheck([true, false, false], undefined)`应返回`false`
```js
assert.strictEqual(quickCheck([true, false, false], undefined), false);
```
`quickCheck`函数应该使用`indexOf()`方法
```js
assert.notStrictEqual(quickCheck.toString().search(/\.indexOf\(/), -1);
```
# --solutions--

View File

@ -1,13 +1,13 @@
---
id: 587d7b7d367417b2b2512b1c
title: 检查对象是否具有某个属性
challengeType: 1
forumTopicId: 301155
title: 检查对象是否具有某个属性
---
## Description
<section id='description'>
现在我们可以新增、修改和移除对象中的属性。但如果我们想知道一个对象中是否含有某个属性呢JavaScript 为我们提供了两种不同的方式来实现这个功能,一个是<code>hasOwnProperty()</code>方法,另一个是<code>in</code>关键字。如果我们有一个<code>users</code>对象,它有一个<code>Alan</code>属性,我们可以用以下两种方式之一来检查该属性在对象中是否存在:
# --description--
现在我们可以新增、修改和移除对象中的属性。但如果我们想知道一个对象中是否含有某个属性呢JavaScript 为我们提供了两种不同的方式来实现这个功能,一个是`hasOwnProperty()`方法,另一个是`in`关键字。如果我们有一个`users`对象,它有一个`Alan`属性,我们可以用以下两种方式之一来检查该属性在对象中是否存在:
```js
users.hasOwnProperty('Alan');
@ -15,107 +15,73 @@ users.hasOwnProperty('Alan');
// 都返回 true
```
</section>
# --instructions--
## Instructions
<section id='instructions'>
我们已经创建了一个含有一些用户的<code>users</code>对象和一个<code>isEveryoneHere</code>函数,该函数接受<code>users</code>对象作为参数。请完成该函数使其在<code>users</code>对象中包含以下 4 个键<code>Alan</code><code>Jeff</code><code>Sarah</code><code>Ryan</code>时才返回<code>true</code>,否则返回<code>false</code>
</section>
我们已经创建了一个含有一些用户的`users`对象和一个`isEveryoneHere`函数,该函数接受`users`对象作为参数。请完成该函数使其在`users`对象中包含以下 4 个键`Alan``Jeff``Sarah``Ryan`时才返回`true`,否则返回`false`
## Tests
<section id='tests'>
# --hints--
```yml
tests:
- text: <code>users</code>对象应该只含有<code>Alan</code>、<code>Jeff</code>、<code>Sarah</code>和<code>Ryan</code>4 个键。
testString: assert("Alan" in users && "Jeff" in users && "Sarah" in users && "Ryan" in users && Object.keys(users).length === 4);
- text: <code>isEveryoneHere</code>函数在<code>users</code>对象包含<code>Alan</code>、<code>Jeff</code>、<code>Sarah</code>和<code>Ryan</code>4 个键时应该返回<code>true</code>。
testString: assert(isEveryoneHere(users) === true);
- text: <code>isEveryoneHere</code>函数在<code>users</code>对象不包含<code>Alan</code>、<code>Jeff</code>、<code>Sarah</code>或<code>Ryan</code>4 个键时应该返回<code>false</code>。
testString: assert((function() { delete users.Alan; return isEveryoneHere(users) })() === false);
- text: 如果 <code>Jeff</code> 不是 <code>users</code> 对象的属性,函数 <code>isEveryoneHere</code> 应该返回 <code>false</code>。
testString: assert((function() { delete users.Jeff; return isEveryoneHere(users) })() === false);
- text: 如果 <code>Sarah</code> 不是 <code>users</code> 对象的属性,函数 <code>isEveryoneHere</code> 应该返回 <code>false</code>。
testString: assert((function() { delete users.Sarah; return isEveryoneHere(users) })() === false);
- text: 如果 <code>Ryan</code> 不是 <code>users</code> 对象的属性,函数 <code>isEveryoneHere</code> 应该返回 <code>false</code>。
testString: assert((function() { delete users.Ryan; return isEveryoneHere(users) })() === false);
```
</section>
## Challenge Seed
<section id='challengeSeed'>
<div id='js-seed'>
`users`对象应该只含有`Alan``Jeff``Sarah``Ryan`4 个键。
```js
let users = {
Alan: {
age: 27,
online: true
},
Jeff: {
age: 32,
online: true
},
Sarah: {
age: 48,
online: true
},
Ryan: {
age: 19,
online: true
}
};
function isEveryoneHere(obj) {
// change code below this line
// change code above this line
}
console.log(isEveryoneHere(users));
assert(
'Alan' in users &&
'Jeff' in users &&
'Sarah' in users &&
'Ryan' in users &&
Object.keys(users).length === 4
);
```
</div>
</section>
## Solution
<section id='solution'>
`isEveryoneHere`函数在`users`对象包含`Alan``Jeff``Sarah``Ryan`4 个键时应该返回`true`
```js
let users = {
Alan: {
age: 27,
online: true
},
Jeff: {
age: 32,
online: true
},
Sarah: {
age: 48,
online: true
},
Ryan: {
age: 19,
online: true
}
};
function isEveryoneHere(obj) {
return [
'Alan',
'Jeff',
'Sarah',
'Ryan'
].every(i => obj.hasOwnProperty(i));
}
console.log(isEveryoneHere(users));
assert(isEveryoneHere(users) === true);
```
</section>
`isEveryoneHere`函数在`users`对象不包含`Alan``Jeff``Sarah``Ryan`4 个键时应该返回`false`
```js
assert(
(function () {
delete users.Alan;
return isEveryoneHere(users);
})() === false
);
```
如果 `Jeff` 不是 `users` 对象的属性,函数 `isEveryoneHere` 应该返回 `false`
```js
assert(
(function () {
delete users.Jeff;
return isEveryoneHere(users);
})() === false
);
```
如果 `Sarah` 不是 `users` 对象的属性,函数 `isEveryoneHere` 应该返回 `false`
```js
assert(
(function () {
delete users.Sarah;
return isEveryoneHere(users);
})() === false
);
```
如果 `Ryan` 不是 `users` 对象的属性,函数 `isEveryoneHere` 应该返回 `false`
```js
assert(
(function () {
delete users.Ryan;
return isEveryoneHere(users);
})() === false
);
```
# --solutions--

View File

@ -1,12 +1,12 @@
---
id: 587d7b7b367417b2b2512b17
title: 组合使用数组和扩展运算符
challengeType: 1
forumTopicId: 301156
title: 组合使用数组和扩展运算符
---
## Description
<section id='description'>
# --description--
<dfn>展开运算符</dfn>的另一个大用处是合并数组,或者将某个数组的所有元素插入到另一个数组的任意位置。用传统的语法我们也可以连接两个数组,但只能两个数组首尾相接。而展开语法能使下面的操作变得极其简单:
```js
@ -17,61 +17,24 @@ let thatArray = ['basil', 'cilantro', ...thisArray, 'coriander'];
```
使用展开语法,我们这样就实现了一个用传统方法要写得很复杂冗长的操作。
</section>
## Instructions
<section id='instructions'>
我们已经定义了一个返回<code>sentence</code>变量的<code>spreadOut</code>函数,请修改该函数,利用<dfn>展开运算符</dfn>使该函数返回数组<code>['learning', 'to', 'code', 'is', 'fun']</code>
</section>
# --instructions--
## Tests
<section id='tests'>
我们已经定义了一个返回`sentence`变量的`spreadOut`函数,请修改该函数,利用<dfn>展开运算符</dfn>使该函数返回数组`['learning', 'to', 'code', 'is', 'fun']`
```yml
tests:
- text: '<code>spreadOut</code>应该返回<code>[&quot;learning&quot;, &quot;to&quot;, &quot;code&quot;, &quot;is&quot;, &quot;fun&quot;]</code>'
testString: assert.deepEqual(spreadOut(), ['learning', 'to', 'code', 'is', 'fun']);
- text: <code>spreadOut</code>函数里应该用到展开语法
testString: assert.notStrictEqual(spreadOut.toString().search(/[...]/), -1);
# --hints--
```
</section>
## Challenge Seed
<section id='challengeSeed'>
<div id='js-seed'>
`spreadOut`应该返回`["learning", "to", "code", "is", "fun"]`
```js
function spreadOut() {
let fragment = ['to', 'code'];
let sentence; // change this line
return sentence;
}
// do not change code below this line
console.log(spreadOut());
assert.deepEqual(spreadOut(), ['learning', 'to', 'code', 'is', 'fun']);
```
</div>
</section>
## Solution
<section id='solution'>
`spreadOut`函数里应该用到展开语法
```js
// solution required
function spreadOut() {
let fragment = ['to', 'code'];
let sentence = ['learning', ...fragment, 'is', 'fun'];
return sentence;
}
assert.notStrictEqual(spreadOut.toString().search(/[...]/), -1);
```
</section>
# --solutions--

View File

@ -1,13 +1,14 @@
---
id: 587d7b7b367417b2b2512b13
title: 使用扩展运算符复制数组
challengeType: 1
forumTopicId: 301157
title: 使用扩展运算符复制数组
---
## Description
<section id='description'>
<code>slice()</code>已经能让我们从一个数组中选择一些元素来复制到新数组中了,而 ES6 中又新引入了一个简洁且可读性强的语法<dfn>展开运算符spread operator</dfn>,它能让我们方便地复制数组中的<em>所有</em>元素。展开语法是这样的:<code>...</code>
# --description--
`slice()`已经能让我们从一个数组中选择一些元素来复制到新数组中了,而 ES6 中又新引入了一个简洁且可读性强的语法<dfn>展开运算符spread operator</dfn>,它能让我们方便地复制数组中的*所有*元素。展开语法是这样的:`...`
在实践中,我们可以这样用展开运算符来复制一个数组:
```js
@ -17,82 +18,54 @@ let thatArray = [...thisArray];
// thisArray 保持不变,等于 thatArray
```
</section>
# --instructions--
## Instructions
<section id='instructions'>
我们已经定义了一个<code>copyMachine</code>函数,它接受<code>arr</code>(一个数组)和<code>num</code>(一个数字)作为输入参数。该函数应该返回一个由<code>num</code><code>arr</code>组成的新数组。我们已经为你写好了大部分的代码,但它还不能正确地工作。请修改这个函数,使用展开语法,使该函数正确工作(提示:我们已经学到过的一个方法很适合用在这里!)
</section>
我们已经定义了一个`copyMachine`函数,它接受`arr`(一个数组)和`num`(一个数字)作为输入参数。该函数应该返回一个由`num``arr`组成的新数组。我们已经为你写好了大部分的代码,但它还不能正确地工作。请修改这个函数,使用展开语法,使该函数正确工作(提示:我们已经学到过的一个方法很适合用在这里!)
## Tests
<section id='tests'>
# --hints--
```yml
tests:
- text: '<code>copyMachine([true, false, true], 2)</code>应该返回<code>[[true, false, true], [true, false, true]]</code>'
testString: assert.deepEqual(copyMachine([true, false, true], 2), [[true, false, true], [true, false, true]]);
- text: '<code>copyMachine([1, 2, 3], 5)</code>应该返回<code>[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]</code>'
testString: assert.deepEqual(copyMachine([1, 2, 3], 5), [[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]);
- text: '<code>copyMachine([true, true, null], 1)</code>应该返回<code>[[true, true, null]]</code>'
testString: assert.deepEqual(copyMachine([true, true, null], 1), [[true, true, null]]);
- text: '<code>copyMachine([&quot;it works&quot;], 3)</code>应该返回<code>[[&quot;it works&quot;], [&quot;it works&quot;], [&quot;it works&quot;]]</code>'
testString: assert.deepEqual(copyMachine(['it works'], 3), [['it works'], ['it works'], ['it works']]);
- text: <code>copyMachine</code>函数中应该对数组<code>arr</code>使用<code>spread operator</code>。
testString: assert(removeJSComments(code).match(/\.\.\.arr/));
```
</section>
## Challenge Seed
<section id='challengeSeed'>
<div id='js-seed'>
`copyMachine([true, false, true], 2)`应该返回`[[true, false, true], [true, false, true]]`
```js
function copyMachine(arr, num) {
let newArr = [];
while (num >= 1) {
// change code below this line
// change code above this line
num--;
}
return newArr;
}
// change code here to test different cases:
console.log(copyMachine([true, false, true], 2));
assert.deepEqual(copyMachine([true, false, true], 2), [
[true, false, true],
[true, false, true]
]);
```
</div>
### After Test
<div id='js-teardown'>
`copyMachine([1, 2, 3], 5)`应该返回`[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]`
```js
const removeJSComments = str => str.replace(/\/\*[\s\S]*?\*\/|\/\/.*$/gm, '');
assert.deepEqual(copyMachine([1, 2, 3], 5), [
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[1, 2, 3]
]);
```
</div>
</section>
## Solution
<section id='solution'>
`copyMachine([true, true, null], 1)`应该返回`[[true, true, null]]`
```js
function copyMachine(arr,num){
let newArr=[];
while(num >=1){
// change code below this line
newArr.push([...arr]);
//change code above this line
num--;
}
return newArr;
}
console.log(copyMachine([true, false, true], 2));
assert.deepEqual(copyMachine([true, true, null], 1), [[true, true, null]]);
```
</section>
`copyMachine(["it works"], 3)`应该返回`[["it works"], ["it works"], ["it works"]]`
```js
assert.deepEqual(copyMachine(['it works'], 3), [
['it works'],
['it works'],
['it works']
]);
```
`copyMachine`函数中应该对数组`arr`使用`spread operator`
```js
assert(removeJSComments(code).match(/\.\.\.arr/));
```
# --solutions--

View File

@ -1,13 +1,13 @@
---
id: 587d7b7a367417b2b2512b12
title: 使用 slice() 拷贝数组项目
challengeType: 1
forumTopicId: 301158
title: 使用 slice() 拷贝数组项目
---
## Description
<section id='description'>
接下来我们要介绍<code>slice()</code>方法。<code>slice()</code>并不修改数组,而是复制或者说<em>提取extract</em>给定数量的元素到一个新数组里,而调用方法的数组则保持不变。<code>slice()</code>只接受 2 个输入参数&mdash;第一个是开始提取元素的位置索引第二个是结束提取元素的位置索引。slice 方法会提取直到截止索引的元素,但被提取的元素不包括截止索引对应的元素。请看以下例子:
# --description--
接下来我们要介绍`slice()`方法。`slice()`并不修改数组,而是复制或者说*提取extract*给定数量的元素到一个新数组里,而调用方法的数组则保持不变。`slice()`只接受 2 个输入参数第一个是开始提取元素的位置索引第二个是结束提取元素的位置索引。slice 方法会提取直到截止索引的元素,但被提取的元素不包括截止索引对应的元素。请看以下例子:
```js
let weatherConditions = ['rain', 'snow', 'sleet', 'hail', 'clear'];
@ -18,56 +18,27 @@ let todaysWeather = weatherConditions.slice(1, 3);
```
现在我们从一个已有的数组中提取了一些元素,并用这些元素创建了一个新数组。
</section>
## Instructions
<section id='instructions'>
我们已经定义了一个<code>forecast</code>函数,它接受一个数组作为参数。请修改这个函数,利用<code>slice()</code>来从输入的数组中提取信息,并返回一个包含元素<code>'warm'</code><code>'sunny'</code> 的新数组。
</section>
# --instructions--
## Tests
<section id='tests'>
我们已经定义了一个`forecast`函数,它接受一个数组作为参数。请修改这个函数,利用`slice()`来从输入的数组中提取信息,并返回一个包含元素`'warm'``'sunny'` 的新数组。
```yml
tests:
- text: '<code>forecast</code>应该返回<code>[&quot;warm&quot;, &quot;sunny&quot;]</code>'
testString: assert.deepEqual(forecast(['cold', 'rainy', 'warm', 'sunny', 'cool', 'thunderstorms']), ['warm', 'sunny']);
- text: <code>forecast</code>函数应该使用<code>slice()</code>方法
testString: assert(/\.slice\(/.test(code));
# --hints--
```
</section>
## Challenge Seed
<section id='challengeSeed'>
<div id='js-seed'>
`forecast`应该返回`["warm", "sunny"]`
```js
function forecast(arr) {
// change code below this line
return arr;
}
// do not change code below this line
console.log(forecast(['cold', 'rainy', 'warm', 'sunny', 'cool', 'thunderstorms']));
assert.deepEqual(
forecast(['cold', 'rainy', 'warm', 'sunny', 'cool', 'thunderstorms']),
['warm', 'sunny']
);
```
</div>
</section>
## Solution
<section id='solution'>
`forecast`函数应该使用`slice()`方法
```js
function forecast(arr) {
return arr.slice(2,4);
}
assert(/\.slice\(/.test(code));
```
</section>
# --solutions--

View File

@ -1,13 +1,14 @@
---
id: 587d7b7b367417b2b2512b16
title: 创建复杂的多维数组
challengeType: 1
forumTopicId: 301159
title: 创建复杂的多维数组
---
## Description
<section id='description'>
# --description--
很好!你已经学到很多关于数组的知识了!但这些只是一个开始,你将在接下来的小节中学习到与数组相关的更多知识。但在继续去学习<dfn>对象</dfn><dfn>Objects</dfn>)之前,让我们再花一点时间看一看,数组怎样能够变得比之前的挑战中更复杂一点。
数组的一个强大的特性是,它可以包含其他数组,甚至完全由其他数组组成。我们已经在上一个挑战中看到了包含数组的数组,但它还算是比较简单的。数组中的数组还可以在包含其他数组,数组中是可以嵌套任意层的数组的。数组从而可以被用来实现非常复杂的叫做<dfn>多维multi-dimensional</dfn>或嵌套nested数组的数据结构。请看如下例子
```js
@ -29,8 +30,7 @@ let nestedArray = [ // 顶层,或第 1 层——最外层的数组
];
```
虽然这个例子看起来错综复杂,但这样复杂的数组并不算罕见,尤其是在处理大量数据的时候。
但我们仍能简单地用方括号符号来访问到嵌套得最深的数组:
虽然这个例子看起来错综复杂,但这样复杂的数组并不算罕见,尤其是在处理大量数据的时候。 但我们仍能简单地用方括号符号来访问到嵌套得最深的数组:
```js
console.log(nestedArray[2][1][0][0][0]);
@ -46,69 +46,145 @@ console.log(nestedArray[2][1][0][0][0]);
// now logs: deeper still
```
</section>
# --instructions--
## Instructions
<section id='instructions'>
我们已经定义了一个<code>myNestedArray</code>数组变量。请修改<code>myNestedArray</code>,用<dfn>字符串string</dfn><dfn>数字number</dfn>或者<dfn>布尔值boolean</dfn>作为数组的数据元素,使得<code>myNestedArray</code>刚好有 5 层数组嵌套(记住,最外层的数组是第 1 层)。请在第 3 层的数组中包含字符串<code>'deep'</code>,在第 4 层的数组中包含字符串<code>'deeper'</code>,在第 5 层的数组中包含字符串<code>'deepest'</code>
</section>
我们已经定义了一个`myNestedArray`数组变量。请修改`myNestedArray`,用<dfn>字符串string</dfn><dfn>数字number</dfn>或者<dfn>布尔值boolean</dfn>作为数组的数据元素,使得`myNestedArray`刚好有 5 层数组嵌套(记住,最外层的数组是第 1 层)。请在第 3 层的数组中包含字符串`'deep'`,在第 4 层的数组中包含字符串`'deeper'`,在第 5 层的数组中包含字符串`'deepest'`
## Tests
<section id='tests'>
# --hints--
```yml
tests:
- text: <code>myNestedArray</code>中的数据元素应当只能是字符串、数字或者布尔值。
testString: 'assert.strictEqual((function(arr) { let flattened = (function flatten(arr) { const flat = [].concat(...arr); return flat.some (Array.isArray) ? flatten(flat) : flat; })(arr); for (let i = 0; i < flattened.length; i++) { if ( typeof flattened[i] !== ''number'' && typeof flattened[i] !== ''string'' && typeof flattened[i] !== ''boolean'') { return false } } return true })(myNestedArray), true);'
- text: <code>myNestedArray</code>应该刚好有 5 层数组嵌套。
testString: 'assert.strictEqual((function(arr) {let depth = 0;function arrayDepth(array, i, d) { if (Array.isArray(array[i])) { arrayDepth(array[i], 0, d + 1);} else { depth = (d > depth) ? d : depth;}if (i < array.length) { arrayDepth(array, i + 1, d);} }arrayDepth(arr, 0, 0);return depth;})(myNestedArray), 4);'
- text: <code>myNestedArray</code>里应该有且只有一个字符串<code>&quot;deep&quot;</code>,并且应该出现在第 3 层数组中。
testString: assert((function howDeep(array, target, depth = 0) {return array.reduce((combined, current) => {if (Array.isArray(current)) { return combined.concat(howDeep(current, target, depth + 1));} else if (current === target) { return combined.concat(depth);} else { return combined;}}, []);})(myNestedArray, 'deep').length === 1 && (function howDeep(array, target, depth = 0) {return array.reduce((combined, current) => {if (Array.isArray(current)) { return combined.concat(howDeep(current, target, depth + 1));} else if (current === target) { return combined.concat(depth);} else { return combined;}}, []);})(myNestedArray, 'deep')[0] === 2);
- text: <code>myNestedArray</code>里应该有且只有一个字符串<code>&quot;deeper&quot;</code>,并且应该出现在第 4 层数组中。
testString: assert((function howDeep(array, target, depth = 0) {return array.reduce((combined, current) => {if (Array.isArray(current)) { return combined.concat(howDeep(current, target, depth + 1));} else if (current === target) { return combined.concat(depth);} else { return combined;}}, []);})(myNestedArray, 'deeper').length === 1 && (function howDeep(array, target, depth = 0) {return array.reduce((combined, current) => {if (Array.isArray(current)) { return combined.concat(howDeep(current, target, depth + 1));} else if (current === target) { return combined.concat(depth);} else { return combined;}}, []);})(myNestedArray, 'deeper')[0] === 3);
- text: <code>myNestedArray</code>里应该有且只有一个字符串<code>&quot;deepest&quot;</code>,并且应该出现在第 5 层数组中。
testString: assert((function howDeep(array, target, depth = 0) {return array.reduce((combined, current) => {if (Array.isArray(current)) { return combined.concat(howDeep(current, target, depth + 1));} else if (current === target) { return combined.concat(depth);} else { return combined;}}, []);})(myNestedArray, 'deepest').length === 1 && (function howDeep(array, target, depth = 0) {return array.reduce((combined, current) => {if (Array.isArray(current)) { return combined.concat(howDeep(current, target, depth + 1));} else if (current === target) { return combined.concat(depth);} else { return combined;}}, []);})(myNestedArray, 'deepest')[0] === 4);
```
</section>
## Challenge Seed
<section id='challengeSeed'>
<div id='js-seed'>
`myNestedArray`中的数据元素应当只能是字符串、数字或者布尔值。
```js
let myNestedArray = [
// change code below this line
['unshift', false, 1, 2, 3, 'complex', 'nested'],
['loop', 'shift', 6, 7, 1000, 'method'],
['concat', false, true, 'spread', 'array'],
['mutate', 1327.98, 'splice', 'slice', 'push'],
['iterate', 1.3849, 7, '8.4876', 'arbitrary', 'depth']
// change code above this line
];
assert.strictEqual(
(function (arr) {
let flattened = (function flatten(arr) {
const flat = [].concat(...arr);
return flat.some(Array.isArray) ? flatten(flat) : flat;
})(arr);
for (let i = 0; i < flattened.length; i++) {
if (
typeof flattened[i] !== 'number' &&
typeof flattened[i] !== 'string' &&
typeof flattened[i] !== 'boolean'
) {
return false;
}
}
return true;
})(myNestedArray),
true
);
```
</div>
</section>
## Solution
<section id='solution'>
`myNestedArray`应该刚好有 5 层数组嵌套。
```js
let myNestedArray = [
// change code below this line
['unshift', ['deep', ['deeper', ['deepest']]],false, 1, 2, 3, 'complex', 'nested'],
['loop', 'shift', 6, 7, 1000, 'method'],
['concat', false, true, 'spread', 'array'],
['mutate', 1327.98, 'splice', 'slice', 'push'],
['iterate', 1.3849, 7, '8.4876', 'arbitrary', 'depth']
// change code above this line
];
assert.strictEqual(
(function (arr) {
let depth = 0;
function arrayDepth(array, i, d) {
if (Array.isArray(array[i])) {
arrayDepth(array[i], 0, d + 1);
} else {
depth = d > depth ? d : depth;
}
if (i < array.length) {
arrayDepth(array, i + 1, d);
}
}
arrayDepth(arr, 0, 0);
return depth;
})(myNestedArray),
4
);
```
</section>
`myNestedArray`里应该有且只有一个字符串`"deep"`,并且应该出现在第 3 层数组中。
```js
assert(
(function howDeep(array, target, depth = 0) {
return array.reduce((combined, current) => {
if (Array.isArray(current)) {
return combined.concat(howDeep(current, target, depth + 1));
} else if (current === target) {
return combined.concat(depth);
} else {
return combined;
}
}, []);
})(myNestedArray, 'deep').length === 1 &&
(function howDeep(array, target, depth = 0) {
return array.reduce((combined, current) => {
if (Array.isArray(current)) {
return combined.concat(howDeep(current, target, depth + 1));
} else if (current === target) {
return combined.concat(depth);
} else {
return combined;
}
}, []);
})(myNestedArray, 'deep')[0] === 2
);
```
`myNestedArray`里应该有且只有一个字符串`"deeper"`,并且应该出现在第 4 层数组中。
```js
assert(
(function howDeep(array, target, depth = 0) {
return array.reduce((combined, current) => {
if (Array.isArray(current)) {
return combined.concat(howDeep(current, target, depth + 1));
} else if (current === target) {
return combined.concat(depth);
} else {
return combined;
}
}, []);
})(myNestedArray, 'deeper').length === 1 &&
(function howDeep(array, target, depth = 0) {
return array.reduce((combined, current) => {
if (Array.isArray(current)) {
return combined.concat(howDeep(current, target, depth + 1));
} else if (current === target) {
return combined.concat(depth);
} else {
return combined;
}
}, []);
})(myNestedArray, 'deeper')[0] === 3
);
```
`myNestedArray`里应该有且只有一个字符串`"deepest"`,并且应该出现在第 5 层数组中。
```js
assert(
(function howDeep(array, target, depth = 0) {
return array.reduce((combined, current) => {
if (Array.isArray(current)) {
return combined.concat(howDeep(current, target, depth + 1));
} else if (current === target) {
return combined.concat(depth);
} else {
return combined;
}
}, []);
})(myNestedArray, 'deepest').length === 1 &&
(function howDeep(array, target, depth = 0) {
return array.reduce((combined, current) => {
if (Array.isArray(current)) {
return combined.concat(howDeep(current, target, depth + 1));
} else if (current === target) {
return combined.concat(depth);
} else {
return combined;
}
}, []);
})(myNestedArray, 'deepest')[0] === 4
);
```
# --solutions--

View File

@ -1,102 +1,51 @@
---
id: 587d7b7d367417b2b2512b1e
title: 使用 Object.Keys() 生成对象所有键组成的数组
challengeType: 1
forumTopicId: 301160
title: 使用 Object.Keys() 生成对象所有键组成的数组
---
## Description
<section id='description'>
我们还可以输入一个对象作为参数来调用<code>Object.keys()</code>方法,使其生成一个包含对象中所有键的数组。这会返回一个由对象中所有键的名称(字符串)组成的数组。再次说明,这个数组中的项的顺序是不确定的。
</section>
# --description--
## Instructions
<section id='instructions'>
请你完成<code>getArrayOfUsers</code>函数,使其返回一个包含输入的对象的所有属性的数组。
</section>
我们还可以输入一个对象作为参数来调用`Object.keys()`方法,使其生成一个包含对象中所有键的数组。这会返回一个由对象中所有键的名称(字符串)组成的数组。再次说明,这个数组中的项的顺序是不确定的。
## Tests
<section id='tests'>
# --instructions--
```yml
tests:
- text: <code>users</code>对象应该只包含<code>Alan</code>、<code>Jeff</code>、<code>Sarah</code>和<code>Ryan</code>这 4 个键
testString: assert('Alan' in users && 'Jeff' in users && 'Sarah' in users && 'Ryan' in users && Object.keys(users).length === 4);
- text: <code>getArrayOfUsers</code>函数应该返回一个包含<code>users</code>对象中所有键的数组
testString: assert((function() { users.Sam = {}; users.Lewis = {}; let R = getArrayOfUsers(users); return (R.indexOf('Alan') !== -1 && R.indexOf('Jeff') !== -1 && R.indexOf('Sarah') !== -1 && R.indexOf('Ryan') !== -1 && R.indexOf('Sam') !== -1 && R.indexOf('Lewis') !== -1); })() === true);
请你完成`getArrayOfUsers`函数,使其返回一个包含输入的对象的所有属性的数组。
```
# --hints--
</section>
## Challenge Seed
<section id='challengeSeed'>
<div id='js-seed'>
`users`对象应该只包含`Alan``Jeff``Sarah``Ryan`这 4 个键
```js
let users = {
Alan: {
age: 27,
online: false
},
Jeff: {
age: 32,
online: true
},
Sarah: {
age: 48,
online: false
},
Ryan: {
age: 19,
online: true
}
};
function getArrayOfUsers(obj) {
// change code below this line
// change code above this line
}
console.log(getArrayOfUsers(users));
assert(
'Alan' in users &&
'Jeff' in users &&
'Sarah' in users &&
'Ryan' in users &&
Object.keys(users).length === 4
);
```
</div>
</section>
## Solution
<section id='solution'>
`getArrayOfUsers`函数应该返回一个包含`users`对象中所有键的数组
```js
let users = {
Alan: {
age: 27,
online: false
},
Jeff: {
age: 32,
online: true
},
Sarah: {
age: 48,
online: false
},
Ryan: {
age: 19,
online: true
}
};
function getArrayOfUsers(obj) {
return Object.keys(obj);
}
console.log(getArrayOfUsers(users));
assert(
(function () {
users.Sam = {};
users.Lewis = {};
let R = getArrayOfUsers(users);
return (
R.indexOf('Alan') !== -1 &&
R.indexOf('Jeff') !== -1 &&
R.indexOf('Sarah') !== -1 &&
R.indexOf('Ryan') !== -1 &&
R.indexOf('Sam') !== -1 &&
R.indexOf('Lewis') !== -1
);
})() === true
);
```
</section>
# --solutions--

View File

@ -1,13 +1,14 @@
---
id: 587d7b7b367417b2b2512b15
title: 使用 For 循环迭代数组的所有项
challengeType: 1
forumTopicId: 301161
title: 使用 For 循环迭代数组的所有项
---
## Description
<section id='description'>
在进行与数组有关的编程时我们有时需要遍历数组的所有元素来找出我们需要的元素或者对数组执行特定的操作。JavaScript 提供了几个内置的方法,它们以不同的方式遍历数组来获得不同的结果(如<code>every()</code><code>forEach()</code><code>map()</code>等等)。而简单的<code>for</code>循环不仅能实现这些功能,而且相比之下也更灵活。
# --description--
在进行与数组有关的编程时我们有时需要遍历数组的所有元素来找出我们需要的元素或者对数组执行特定的操作。JavaScript 提供了几个内置的方法,它们以不同的方式遍历数组来获得不同的结果(如`every()``forEach()``map()`等等)。而简单的`for`循环不仅能实现这些功能,而且相比之下也更灵活。
请看以下例子:
```js
@ -25,73 +26,86 @@ greaterThanTen([2, 12, 8, 14, 80, 0, 1]);
// 返回 [12, 14, 80]
```
这个函数使用一个<code>for</code>循环来遍历一个数组,逐一对其中的元素进行测试。我们用这个方法简单地以编程的方式找出了数组中大于<code>10</code>的元素,并返回了一个包含这些元素的数组。
</section>
这个函数使用一个`for`循环来遍历一个数组,逐一对其中的元素进行测试。我们用这个方法简单地以编程的方式找出了数组中大于`10`的元素,并返回了一个包含这些元素的数组。
## Instructions
<section id='instructions'>
我们已经定义了一个<code>filteredArray</code>函数,它接受一个嵌套的数组参数<code>arr</code>以及一个<code>elem</code>参数,并要返回一个新数组。<code>arr</code>数组中的数组可能包含<code>elem</code>元素,也可能不包含。请修改该函数,用一个<code>for</code>循环来做筛选,使函数返回一个由<code>arr</code>中不包含<code>elem</code>的数组组成的新数组。
</section>
# --instructions--
## Tests
<section id='tests'>
我们已经定义了一个`filteredArray`函数,它接受一个嵌套的数组参数`arr`以及一个`elem`参数,并要返回一个新数组。`arr`数组中的数组可能包含`elem`元素,也可能不包含。请修改该函数,用一个`for`循环来做筛选,使函数返回一个由`arr`中不包含`elem`的数组组成的新数组。
```yml
tests:
- text: '<code>filteredArray([[10, 8, 3], [14, 6, 23], [3, 18, 6]], 18)</code>应该返回<code>[ [10, 8, 3], [14, 6, 23] ]</code>'
testString: assert.deepEqual(filteredArray([ [10, 8, 3], [14, 6, 23], [3, 18, 6] ], 18), [[10, 8, 3], [14, 6, 23]]);
- text: '<code>filteredArray([ [&quot;trumpets&quot;, 2], [&quot;flutes&quot;, 4], [&quot;saxophones&quot;, 2] ], 2)</code>应返回<code>[ [&quot;flutes&quot;, 4] ]</code>'
testString: assert.deepEqual(filteredArray([ ['trumpets', 2], ['flutes', 4], ['saxophones', 2] ], 2), [['flutes', 4]]);
- text: '<code>filteredArray([ [&quot;amy&quot;, &quot;beth&quot;, &quot;sam&quot;], [&quot;dave&quot;, &quot;sean&quot;, &quot;peter&quot;] ], &quot;peter&quot;)</code>应该返回<code>[ [&quot;amy&quot;, &quot;beth&quot;, &quot;sam&quot;] ]</code>'
testString: assert.deepEqual(filteredArray([['amy', 'beth', 'sam'], ['dave', 'sean', 'peter']], 'peter'), [['amy', 'beth', 'sam']]);
- text: '<code>filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3)</code>应该返回<code>[ ]</code>'
testString: assert.deepEqual(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3), []);
- text: <code>filteredArray</code>函数应该使用<code>for</code>循环
testString: assert.notStrictEqual(filteredArray.toString().search(/for/), -1);
# --hints--
```
</section>
## Challenge Seed
<section id='challengeSeed'>
<div id='js-seed'>
`filteredArray([[10, 8, 3], [14, 6, 23], [3, 18, 6]], 18)`应该返回`[ [10, 8, 3], [14, 6, 23] ]`
```js
function filteredArray(arr, elem) {
let newArr = [];
// change code below this line
// change code above this line
return newArr;
}
// change code here to test different cases:
console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3));
assert.deepEqual(
filteredArray(
[
[10, 8, 3],
[14, 6, 23],
[3, 18, 6]
],
18
),
[
[10, 8, 3],
[14, 6, 23]
]
);
```
</div>
</section>
## Solution
<section id='solution'>
`filteredArray([ ["trumpets", 2], ["flutes", 4], ["saxophones", 2] ], 2)`应返回`[ ["flutes", 4] ]`
```js
function filteredArray(arr, elem) {
let newArr = [];
// change code below this line
for (let i = 0; i<arr.length; i++) {
if (arr[i].indexOf(elem) < 0) {
newArr.push(arr[i]);
}
}
// change code above this line
return newArr;
}
assert.deepEqual(
filteredArray(
[
['trumpets', 2],
['flutes', 4],
['saxophones', 2]
],
2
),
[['flutes', 4]]
);
```
</section>
`filteredArray([ ["amy", "beth", "sam"], ["dave", "sean", "peter"] ], "peter")`应该返回`[ ["amy", "beth", "sam"] ]`
```js
assert.deepEqual(
filteredArray(
[
['amy', 'beth', 'sam'],
['dave', 'sean', 'peter']
],
'peter'
),
[['amy', 'beth', 'sam']]
);
```
`filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3)`应该返回`[ ]`
```js
assert.deepEqual(
filteredArray(
[
[3, 2, 3],
[1, 6, 3],
[3, 13, 26],
[19, 3, 9]
],
3
),
[]
);
```
`filteredArray`函数应该使用`for`循环
```js
assert.notStrictEqual(filteredArray.toString().search(/for/), -1);
```
# --solutions--

View File

@ -1,14 +1,13 @@
---
id: 587d7b7d367417b2b2512b1d
title: 使用 for...in 语句迭代对象
challengeType: 1
forumTopicId: 301162
title: '使用 for...in 语句迭代对象'
---
## Description
<section id='description'>
# --description--
有时候你需要遍历一个对象中的所有键。这需要 JavaScript 中的一个特殊语法:<dfn>for...in</dfn> 语句。以遍历 <code>users</code> 对象的键为例:
有时候你需要遍历一个对象中的所有键。这需要 JavaScript 中的一个特殊语法:<dfn>for...in</dfn> 语句。以遍历 `users` 对象的键为例:
```js
for (let user in users) {
@ -22,15 +21,12 @@ Sarah
Ryan
```
在这个语句中,我们定义了一个<code>user</code>变量,你可以看到,这个变量在 for...in 语句对对象的每一个键的遍历中都会被重置。
<strong>注意:</strong><br>跟数组不同,对象中的键是无序的,因此一个对象中某个键的位置,或者说它出现的相对顺序,在引用或访问该键时是不确定的。
</section>
在这个语句中,我们定义了一个`user`变量,你可以看到,这个变量在 for...in 语句对对象的每一个键的遍历中都会被重置。 **注意:**
跟数组不同,对象中的键是无序的,因此一个对象中某个键的位置,或者说它出现的相对顺序,在引用或访问该键时是不确定的。
## Instructions
<section id='instructions'>
我们已经定义了一个<code>countOnline</code>函数,请在其中使用一个 <dfn>for...in</dfn> 语句来遍历<code>users</code>对象中的用户,并返回<code>online</code>属性为<code>true</code>的用户的数量。
# --instructions--
我们已经定义了一个`countOnline`函数,请在其中使用一个 <dfn>for...in</dfn> 语句来遍历`users`对象中的用户,并返回`online`属性为`true`的用户的数量。
```js
{
@ -46,102 +42,35 @@ Ryan
}
```
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: 函数 <code>countOnline</code> 应该使用 `for in` 语句遍历传入对象的key。
testString: assert(code.match(/for\s*\(\s*(var|let)\s+[a-zA-Z_$]\w*\s+in\s+[a-zA-Z_$]\w*\s*\)\s*{/));
- text: '当传入 <code>{ Alan: { online: false }, Jeff: { online: true }, Sarah: { online: false } }</code> 时,函数 <code>countOnline</code> 应该返回 <code>1</code>。'
testString: assert(countOnline(usersObj1) === 1);
- text: '当传入 <code>{ Alan: { online: true }, Jeff: { online: false }, Sarah: { online: true } }</code> 时,函数 <code>countOnline</code> 应该返回 <code>2</code>。'
testString: assert(countOnline(usersObj2) === 2);
- text: '当传入 <code>{ Alan: { online: false }, Jeff: { online: false }, Sarah: { online: false } }</code> 时,函数 <code>countOnline</code> 应该返回 <code>0</code>。'
testString: assert(countOnline(usersObj3) === 0);
```
</section>
## Challenge Seed
<section id='challengeSeed'>
<div id='js-seed'>
函数 `countOnline` 应该使用 `for in` 语句遍历传入对象的key。
```js
function countOnline(usersObj) {
// change code below this line
// change code above this line
}
assert(
code.match(
/for\s*\(\s*(var|let)\s+[a-zA-Z_$]\w*\s+in\s+[a-zA-Z_$]\w*\s*\)\s*{/
)
);
```
</div>
### After Test
<div id='js-teardown'>
当传入 `{ Alan: { online: false }, Jeff: { online: true }, Sarah: { online: false } }` 时,函数 `countOnline` 应该返回 `1`
```js
const usersObj1 = {
Alan: {
online: false
},
Jeff: {
online: true
},
Sarah: {
online: false
}
}
const usersObj2 = {
Alan: {
online: true
},
Jeff: {
online: false
},
Sarah: {
online: true
}
}
const usersObj3 = {
Alan: {
online: false
},
Jeff: {
online: false
},
Sarah: {
online: false
}
}
assert(countOnline(usersObj1) === 1);
```
</div>
</section>
## Solution
<section id='solution'>
当传入 `{ Alan: { online: true }, Jeff: { online: false }, Sarah: { online: true } }` 时,函数 `countOnline` 应该返回 `2`
```js
function countOnline(usersObj) {
let online = 0;
for(let user in usersObj){
if(usersObj[user].online) {
online++;
}
}
return online;
}
assert(countOnline(usersObj2) === 2);
```
</section>
当传入 `{ Alan: { online: false }, Jeff: { online: false }, Sarah: { online: false } }` 时,函数 `countOnline` 应该返回 `0`
```js
assert(countOnline(usersObj3) === 0);
```
# --solutions--

View File

@ -1,105 +1,51 @@
---
id: 587d7b7d367417b2b2512b1f
title: 修改存储在对象中的数组
challengeType: 1
forumTopicId: 301163
title: 修改存储在对象中的数组
---
## Description
<section id='description'>
# --description--
现在你已经接触到 JavaScript 对象的所有运算。你可以增加、修改和移除键值对,检查某个键是否存在,并且遍历一个对象中的所有键。在你继续学习 JavaScript 的过程中,你会看到对象的更多用法。另外,后续的《高级数据结构》课程还会介绍 ES6 的 <dfn>Map</dfn><dfn>Set</dfn> 对象。这两种对象都跟一般的对象相似,但它们提供了一些额外的特性。现在你已经学到了数组和对象的基础知识,你已经可以继续用 JavaScript 来解决更加复杂的问题了!
</section>
## Instructions
<section id='instructions'>
请你看一下代码编辑器中我们提供的对象。<code>user</code>对象包含 3 个键。<code>data</code>对象包含 5 个键,其中一个包含一个<code>friends</code>数组。从这个例子你可以看到对象作为数据结构是多么的灵活。我们已经写了<code>addFriend</code>函数的一部分,请你完成这个函数,使其接受一个<code>user</code>对象,将<code>friend</code>参数中的名字添加到<code>user.data.friends</code>数组中并返回该数组。
</section>
# --instructions--
## Tests
<section id='tests'>
请你看一下代码编辑器中我们提供的对象。`user`对象包含 3 个键。`data`对象包含 5 个键,其中一个包含一个`friends`数组。从这个例子你可以看到对象作为数据结构是多么的灵活。我们已经写了`addFriend`函数的一部分,请你完成这个函数,使其接受一个`user`对象,将`friend`参数中的名字添加到`user.data.friends`数组中并返回该数组。
```yml
tests:
- text: <code>user</code>对象应该包含<code>name</code>、<code>age</code>和<code>data</code>三个键。
testString: assert('name' in user && 'age' in user && 'data' in user);
- text: <code>addFriend</code>函数应该接受一个<code>user</code>对象和一个<code>friend</code>字符串作为输入参数,并将 friend 插入到<code>user</code>对象的<code>friends</code>数组中。
testString: assert((function() { let L1 = user.data.friends.length; addFriend(user, 'Sean'); let L2 = user.data.friends.length; return (L2 === L1 + 1); })());
- text: '<code>addFriend(user, &quot;Pete&quot;)</code>应该返回<code>[&quot;Sam&quot;, &quot;Kira&quot;, &quot;Tomo&quot;, &quot;Pete&quot;]</code>。'
testString: assert.deepEqual((function() { delete user.data.friends; user.data.friends = ['Sam', 'Kira', 'Tomo']; return addFriend(user, 'Pete') })(), ['Sam', 'Kira', 'Tomo', 'Pete']);
# --hints--
```
</section>
## Challenge Seed
<section id='challengeSeed'>
<div id='js-seed'>
`user`对象应该包含`name``age``data`三个键。
```js
let user = {
name: 'Kenneth',
age: 28,
data: {
username: 'kennethCodesAllDay',
joinDate: 'March 26, 2016',
organization: 'freeCodeCamp',
friends: [
'Sam',
'Kira',
'Tomo'
],
location: {
city: 'San Francisco',
state: 'CA',
country: 'USA'
}
}
};
function addFriend(userObj, friend) {
// change code below this line
// change code above this line
}
console.log(addFriend(user, 'Pete'));
assert('name' in user && 'age' in user && 'data' in user);
```
</div>
</section>
## Solution
<section id='solution'>
`addFriend`函数应该接受一个`user`对象和一个`friend`字符串作为输入参数,并将 friend 插入到`user`对象的`friends`数组中。
```js
let user = {
name: 'Kenneth',
age: 28,
data: {
username: 'kennethCodesAllDay',
joinDate: 'March 26, 2016',
organization: 'freeCodeCamp',
friends: [
'Sam',
'Kira',
'Tomo'
],
location: {
city: 'San Francisco',
state: 'CA',
country: 'USA'
}
}
};
function addFriend(userObj, friend) {
userObj.data.friends.push(friend);
return userObj.data.friends;
}
assert(
(function () {
let L1 = user.data.friends.length;
addFriend(user, 'Sean');
let L2 = user.data.friends.length;
return L2 === L1 + 1;
})()
);
```
</section>
`addFriend(user, "Pete")`应该返回`["Sam", "Kira", "Tomo", "Pete"]`
```js
assert.deepEqual(
(function () {
delete user.data.friends;
user.data.friends = ['Sam', 'Kira', 'Tomo'];
return addFriend(user, 'Pete');
})(),
['Sam', 'Kira', 'Tomo', 'Pete']
);
```
# --solutions--

View File

@ -1,12 +1,12 @@
---
id: 587d7b7c367417b2b2512b19
title: 修改嵌套在对象中的对象
challengeType: 1
forumTopicId: 301164
title: 修改嵌套在对象中的对象
---
## Description
<section id='description'>
# --description--
现在我们来看一个稍微复杂一点的对象。对象中也可以嵌套任意层的对象。对象的属性值可以是 JavaScript 支持的任意类型,包括数组和其他对象。请看以下例子:
```js
@ -24,74 +24,39 @@ let nestedObject = {
};
```
<code>nestedObject</code>有 3 个唯一的键:值为一个数字的<code>id</code>、值为一个字符串的<code>date</code>和值为一个嵌套了其他对象的对象的<code>data</code>。虽然对象中的数据可能很复杂,我们仍能使用上一个挑战中讲的符号来访问我们需要的信息。
</section>
`nestedObject`有 3 个唯一的键:值为一个数字的`id`、值为一个字符串的`date`和值为一个嵌套了其他对象的对象的`data`。虽然对象中的数据可能很复杂,我们仍能使用上一个挑战中讲的符号来访问我们需要的信息。
## Instructions
<section id='instructions'>
我们已经定义了一个<code>userActivity</code>对象,它包含了另一个对象。你可以用上一个挑战中那样的方式来修改被嵌套的对象的属性。请将<code>online</code>属性设为<code>45</code>
</section>
# --instructions--
## Tests
<section id='tests'>
我们已经定义了一个`userActivity`对象,它包含了另一个对象。你可以用上一个挑战中那样的方式来修改被嵌套的对象的属性。请将`online`属性设为`45`
```yml
tests:
- text: <code>userActivity</code>应该含有<code>id</code>、<code>date</code>和<code>data</code>属性。
testString: assert('id' in userActivity && 'date' in userActivity && 'data' in userActivity);
- text: <code>userActivity</code>应该有一个<code>data</code>属性,该属性要是一个含有<code>totalUsers</code>和<code>online</code>属性的对象。
testString: assert('totalUsers' in userActivity.data && 'online' in userActivity.data);
- text: <code>userActivity</code>的<code>data</code>属性值中的<code>online</code>属性应该被设为<code>45</code>。
testString: assert(userActivity.data.online === 45);
- text: 你应该用点符号或者方括号符号来设置<code>online</code>属性。
testString: 'assert.strictEqual(code.search(/online: 45/), -1);'
# --hints--
```
</section>
## Challenge Seed
<section id='challengeSeed'>
<div id='js-seed'>
`userActivity`应该含有`id``date``data`属性。
```js
let userActivity = {
id: 23894201352,
date: 'January 1, 2017',
data: {
totalUsers: 51,
online: 42
}
};
// change code below this line
// change code above this line
console.log(userActivity);
assert(
'id' in userActivity && 'date' in userActivity && 'data' in userActivity
);
```
</div>
</section>
## Solution
<section id='solution'>
`userActivity`应该有一个`data`属性,该属性要是一个含有`totalUsers``online`属性的对象。
```js
let userActivity = {
id: 23894201352,
date: 'January 1, 2017',
data: {
totalUsers: 51,
online: 42
}
};
userActivity.data.online = 45;
assert('totalUsers' in userActivity.data && 'online' in userActivity.data);
```
</section>
`userActivity``data`属性值中的`online`属性应该被设为`45`
```js
assert(userActivity.data.online === 45);
```
你应该用点符号或者方括号符号来设置`online`属性。
```js
assert.strictEqual(code.search(/online: 45/), -1);
```
# --solutions--

View File

@ -1,13 +1,14 @@
---
id: 587d78b2367417b2b2512b0f
title: 使用 pop() 和 shift() 从数组中删除项目
challengeType: 1
forumTopicId: 301165
title: 使用 pop() 和 shift() 从数组中删除项目
---
## Description
<section id='description'>
<code>push()</code><code>unshift()</code>都分别有一个作用基本与之相反的函数:<code>pop()</code><code>shift()</code>。你现在或许已经猜到,与插入元素相反,<code>pop()</code>从数组的末尾<em>移除</em>一个元素,而<code>shift()</code>从数组的开头移除一个元素。<code>pop()</code><code>shift()</code>与对应的<code>push()</code><code>unshift()</code>的关键区别在于,前者不能接受输入参数,而且每次只能修改数组中的一个元素。
# --description--
`push()``unshift()`都分别有一个作用基本与之相反的函数:`pop()``shift()`。你现在或许已经猜到,与插入元素相反,`pop()`从数组的末尾*移除*一个元素,而`shift()`从数组的开头移除一个元素。`pop()``shift()`与对应的`push()``unshift()`的关键区别在于,前者不能接受输入参数,而且每次只能修改数组中的一个元素。
让我们来看以下的例子:
```js
@ -28,60 +29,32 @@ let popped = greetings.pop();
// greetings now equals []
```
</section>
# --instructions--
## Instructions
<section id='instructions'>
我们已经定义了一个<code>popShift</code>函数,它会接收一个数组作为输入参数并返回一个新的数组。请你修改这个函数,使用<code>pop()</code><code>shift()</code>来移除输入的数组的第一个元素和最后一个元素,并将这两个被移除的元素赋值给对应的变量,使得返回的数组包含它们的值。
</section>
我们已经定义了一个`popShift`函数,它会接收一个数组作为输入参数并返回一个新的数组。请你修改这个函数,使用`pop()``shift()`来移除输入的数组的第一个元素和最后一个元素,并将这两个被移除的元素赋值给对应的变量,使得返回的数组包含它们的值。
## Tests
<section id='tests'>
# --hints--
```yml
tests:
- text: '<code>popShift([&quot;challenge&quot;, &quot;is&quot;, &quot;not&quot;, &quot;complete&quot;])</code>应返回<code>[&quot;challenge&quot;, &quot;complete&quot;]</code>'
testString: assert.deepEqual(popShift(['challenge', 'is', 'not', 'complete']), ["challenge", "complete"]);
- text: <code>popShift</code>函数应该使用<code>pop()</code>方法
testString: assert.notStrictEqual(popShift.toString().search(/\.pop\(/), -1);
- text: <code>popShift</code>函数应该使用<code>shift()</code>方法
testString: assert.notStrictEqual(popShift.toString().search(/\.shift\(/), -1);
```
</section>
## Challenge Seed
<section id='challengeSeed'>
<div id='js-seed'>
`popShift(["challenge", "is", "not", "complete"])`应返回`["challenge", "complete"]`
```js
function popShift(arr) {
let popped; // change this line
let shifted; // change this line
return [shifted, popped];
}
// do not change code below this line
console.log(popShift(['challenge', 'is', 'not', 'complete']));
assert.deepEqual(popShift(['challenge', 'is', 'not', 'complete']), [
'challenge',
'complete'
]);
```
</div>
</section>
## Solution
<section id='solution'>
`popShift`函数应该使用`pop()`方法
```js
function popShift(arr) {
let popped = arr.pop(); // change this line
let shifted = arr.shift(); // change this line
return [shifted, popped];
}
assert.notStrictEqual(popShift.toString().search(/\.pop\(/), -1);
```
</section>
`popShift`函数应该使用`shift()`方法
```js
assert.notStrictEqual(popShift.toString().search(/\.shift\(/), -1);
```
# --solutions--

View File

@ -1,14 +1,15 @@
---
id: 587d78b2367417b2b2512b10
title: 使用 splice() 删除项目
challengeType: 1
forumTopicId: 301166
title: 使用 splice() 删除项目
---
## Description
<section id='description'>
在上面的挑战中,我们已经学到了如何利用<code>shift()</code><code>pop()</code>从数组的开头或者末尾移除元素,但如果我们想移除数组中间的一个元素呢?或者想一次移除多个元素呢?这时候我们就需要<code>splice()</code>了。<code>splice()</code>让我们可以从数组中的任意位置<strong>移除任意数量的连续的元素</strong>
<code>splice()</code>最多可以接受 3 个参数,但现在我们先关注前两个。<code>splice()</code>接收的前两个参数基于调用<code>splice()</code>数组中元素的索引。记住,数组的索引是<em>从 0 开始的</em><em>zero-indexed</em>),所以我们要用<code>0</code>来指示数组中的第一个元素。<code>splice()</code>的第一个参数代表从数组中的哪个索引开始移除元素,而第二个参数指示要从数组中删除多少个元素。例如:
# --description--
在上面的挑战中,我们已经学到了如何利用`shift()``pop()`从数组的开头或者末尾移除元素,但如果我们想移除数组中间的一个元素呢?或者想一次移除多个元素呢?这时候我们就需要`splice()`了。`splice()`让我们可以从数组中的任意位置**移除任意数量的连续的元素**
`splice()`最多可以接受 3 个参数,但现在我们先关注前两个。`splice()`接收的前两个参数基于调用`splice()`数组中元素的索引。记住,数组的索引是*从 0 开始的**zero-indexed*),所以我们要用`0`来指示数组中的第一个元素。`splice()`的第一个参数代表从数组中的哪个索引开始移除元素,而第二个参数指示要从数组中删除多少个元素。例如:
```js
let array = ['today', 'was', 'not', 'so', 'great'];
@ -18,7 +19,7 @@ array.splice(2, 2);
// array 现在是 ['today', 'was', 'great']
```
<code>splice()</code>不仅从被调用的数组中移除元素,还会返回一个包含被移除元素的数组:
`splice()`不仅从被调用的数组中移除元素,还会返回一个包含被移除元素的数组:
```js
let array = ['I', 'am', 'feeling', 'really', 'happy'];
@ -27,57 +28,38 @@ let newArray = array.splice(3, 2);
// newArray 是 ['really', 'happy']
```
</section>
# --instructions--
## Instructions
<section id='instructions'>
给定初始化的数组 `arr`。使用 `splice()``arr` 里移除元素,使剩余的元素的和为 `10`
给定初始化的数组 `arr`。使用 `splice()``arr` 里移除元素,使剩余的元素的和为 <code>10</code>
# --hints--
</section>
## Tests
<section id='tests'>
```yml
tests:
- text: 不应该修改这一行 <code>const arr = [2, 4, 5, 1, 7, 5, 2, 1];</code>。
testString: assert(code.replace(/\s/g, '').match(/constarr=\[2,4,5,1,7,5,2,1\];?/));
- text: <code>arr</code> 的剩余元素和应该为 <code>10</code>。
testString: assert.strictEqual(arr.reduce((a, b) => a + b), 10);
- text: 应该利用 <code>arr</code> 的 <code>splice()</code>。
testString: assert(code.replace(/\s/g, '').match(/arr\.splice\(/));
- text: splice 应该只删除 <code>arr</code> 里面的元素,不能给 <code>arr</code> 添加元素。
testString: assert(!code.replace(/\s/g, '').match(/arr\.splice\(\d+,\d+,\d+.*\)/g));
```
</section>
## Challenge Seed
<section id='challengeSeed'>
<div id='js-seed'>
不应该修改这一行 `const arr = [2, 4, 5, 1, 7, 5, 2, 1];`
```js
const arr = [2, 4, 5, 1, 7, 5, 2, 1];
// only change code below this line
// only change code above this line
console.log(arr);
assert(code.replace(/\s/g, '').match(/constarr=\[2,4,5,1,7,5,2,1\];?/));
```
</div>
</section>
## Solution
<section id='solution'>
`arr` 的剩余元素和应该为 `10`
```js
const arr = [2, 4, 5, 1, 7, 5, 2, 1];
arr.splice(1, 4);
assert.strictEqual(
arr.reduce((a, b) => a + b),
10
);
```
</section>
应该利用 `arr``splice()`
```js
assert(code.replace(/\s/g, '').match(/arr\.splice\(/));
```
splice 应该只删除 `arr` 里面的元素,不能给 `arr` 添加元素。
```js
assert(!code.replace(/\s/g, '').match(/arr\.splice\(\d+,\d+,\d+.*\)/g));
```
# --solutions--

View File

@ -1,12 +1,12 @@
---
id: 587d7b7e367417b2b2512b20
title: 使用数组存储数据集合
challengeType: 1
forumTopicId: 301167
title: 使用数组存储数据集合
---
## Description
<section id='description'>
# --description--
以下是<dfn>数组Array</dfn>数据结构的最简单的实现例子。这是一个<dfn>一维数组one-dimensional array</dfn>,它只有一层,或者说在它里面没有包含其它的数组结构。可以看到它里面包含了<dfn>布尔值booleans</dfn><dfn>字符串strings</dfn><dfn>数字numbers</dfn>以及一些其他的 JavaScript 语言中合法的数据类型:
```js
@ -15,8 +15,7 @@ console.log(simpleArray.length);
// logs 7
```
可以在上述例子中看到,所有数组都有一个<dfn>长度length</dfn>属性。可以简单地使用<code>Array.length</code>方法来访问它
下面是一个关于数组的更复杂的例子。这是一个<dfn>多维数组multi-dimensional Array</dfn>),或者说是一个包含了其他数组的数组。可以注意到,在它的内部还包含了 JavaScript 中的<dfn>对象objects</dfn>结构。我们会在后面的小节中讨论该数据结构,但现在你只需要知道数组能够存储复杂的对象类型数据。
可以在上述例子中看到,所有数组都有一个<dfn>长度length</dfn>属性。可以简单地使用`Array.length`方法来访问它。 下面是一个关于数组的更复杂的例子。这是一个<dfn>多维数组multi-dimensional Array</dfn>),或者说是一个包含了其他数组的数组。可以注意到,在它的内部还包含了 JavaScript 中的<dfn>对象objects</dfn>结构。我们会在后面的小节中讨论该数据结构,但现在你只需要知道数组能够存储复杂的对象类型数据
```js
let complexArray = [
@ -43,53 +42,41 @@ let complexArray = [
];
```
</section>
# --instructions--
## Instructions
<section id='instructions'>
我们已经定义了一个名为<code>yourArray</code>的变量。请修改题目中的语句,将一个含有至少 5 个元素的数组赋值给<code>yourArray</code>变量。你的数组应该包含至少一个 <dfn>string</dfn> 类型的数据、一个 <dfn>number</dfn> 类型的数据和一个 <dfn>boolean</dfn> 类型的数据。
</section>
我们已经定义了一个名为`yourArray`的变量。请修改题目中的语句,将一个含有至少 5 个元素的数组赋值给`yourArray`变量。你的数组应该包含至少一个 <dfn>string</dfn> 类型的数据、一个 <dfn>number</dfn> 类型的数据和一个 <dfn>boolean</dfn> 类型的数据。
## Tests
<section id='tests'>
# --hints--
```yml
tests:
- text: yourArray 应该是一个数组。
testString: assert.strictEqual(Array.isArray(yourArray), true);
- text: <code>yourArray</code>至少要包含 5 个元素。
testString: assert.isAtLeast(yourArray.length, 5);
- text: <code>yourArray</code>应该包含至少一个<code>boolean</code>。
testString: assert(yourArray.filter( el => typeof el === 'boolean').length >= 1);
- text: <code>yourArray</code>应该包含至少一个<code>number</code>。
testString: assert(yourArray.filter( el => typeof el === 'number').length >= 1);
- text: <code>yourArray</code>应该包含至少一个<code>string</code>。
testString: assert(yourArray.filter( el => typeof el === 'string').length >= 1);
```
</section>
## Challenge Seed
<section id='challengeSeed'>
<div id='js-seed'>
yourArray 应该是一个数组。
```js
let yourArray; // change this line
assert.strictEqual(Array.isArray(yourArray), true);
```
</div>
</section>
## Solution
<section id='solution'>
`yourArray`至少要包含 5 个元素。
```js
let yourArray = ['a string', 100, true, ['one', 2], 'another string'];
assert.isAtLeast(yourArray.length, 5);
```
</section>
`yourArray`应该包含至少一个`boolean`
```js
assert(yourArray.filter((el) => typeof el === 'boolean').length >= 1);
```
`yourArray`应该包含至少一个`number`
```js
assert(yourArray.filter((el) => typeof el === 'number').length >= 1);
```
`yourArray`应该包含至少一个`string`
```js
assert(yourArray.filter((el) => typeof el === 'string').length >= 1);
```
# --solutions--

View File

@ -1,88 +1,48 @@
---
id: 587d7b7c367417b2b2512b1b
title: 使用 delete 关键字删除对象属性
challengeType: 1
forumTopicId: 301168
title: 使用 delete 关键字删除对象属性
---
## Description
<section id='description'>
现在你已经知道什么是对象以及对象的基本特性和用途。总之,对象是以键值对的形式,灵活、直观地存储结构化数据的一种方式,<strong><em>并且</em></strong>查找对象属性的速度是很快的。在本章剩下的挑战中,我们会讲对象的几种常用操作,这样你能更好地在你的程序中使用这种有用的数据结构。
在之前的挑战中,我们已经试过新增和修改对象中的键值对。现在我们来看如何从一个对象中<em>移除</em>一个键值对。
我们再来看上一个挑战中的<code>foods</code>对象。如果我们想移除<code>apples</code>属性,我们可以使用<code>delete</code>关键字:
# --description--
现在你已经知道什么是对象以及对象的基本特性和用途。总之,对象是以键值对的形式,灵活、直观地存储结构化数据的一种方式,***并且***查找对象属性的速度是很快的。在本章剩下的挑战中,我们会讲对象的几种常用操作,这样你能更好地在你的程序中使用这种有用的数据结构。
在之前的挑战中,我们已经试过新增和修改对象中的键值对。现在我们来看如何从一个对象中*移除*一个键值对。
我们再来看上一个挑战中的`foods`对象。如果我们想移除`apples`属性,我们可以使用`delete`关键字:
```js
delete foods.apples;
```
</section>
# --instructions--
## Instructions
<section id='instructions'>
请你用 delete 关键字来移除<code>foods</code>中的<code>oranges</code><code>plums</code><code>strawberries</code>属性。
</section>
请你用 delete 关键字来移除`foods`中的`oranges``plums``strawberries`属性。
## Tests
<section id='tests'>
# --hints--
```yml
tests:
- text: <code>foods</code>对象应该只含有 3 个键:<code>apples</code>、<code>grapes</code>和<code>bananas</code>。
testString: 'assert(!foods.hasOwnProperty(''oranges'') && !foods.hasOwnProperty(''plums'') && !foods.hasOwnProperty(''strawberries'') && Object.keys(foods).length === 3);'
- text: 你应该用<code>delete</code>关键字来移除<code>oranges</code>、<code>plums</code>和<code>strawberries</code>属性。
testString: assert(code.search(/oranges:/) !== -1 && code.search(/plums:/) !== -1 && code.search(/strawberries:/) !== -1);
```
</section>
## Challenge Seed
<section id='challengeSeed'>
<div id='js-seed'>
`foods`对象应该只含有 3 个键:`apples``grapes``bananas`
```js
let foods = {
apples: 25,
oranges: 32,
plums: 28,
bananas: 13,
grapes: 35,
strawberries: 27
};
// change code below this line
// change code above this line
console.log(foods);
assert(
!foods.hasOwnProperty('oranges') &&
!foods.hasOwnProperty('plums') &&
!foods.hasOwnProperty('strawberries') &&
Object.keys(foods).length === 3
);
```
</div>
</section>
## Solution
<section id='solution'>
你应该用`delete`关键字来移除`oranges``plums``strawberries`属性。
```js
// solution required
let foods = {
apples: 25,
oranges: 32,
plums: 28,
bananas: 13,
grapes: 35,
strawberries: 27
};
delete foods.oranges;
delete foods.plums;
delete foods.strawberries;
console.log(foods);
assert(
code.search(/oranges:/) !== -1 &&
code.search(/plums:/) !== -1 &&
code.search(/strawberries:/) !== -1
);
```
</section>
# --solutions--