让ourArray = [“a”,“b”,“c”];在数组中,每个数组项都有一个索引 。此索引兼作数组中该项的位置,以及您如何引用它。但是,值得注意的是,JavaScript数组是零索引的 ,这意味着数组的第一个元素实际上处于第零位,而不是第一个。为了从数组中检索元素,我们可以将一个索引括在括号中,并将其附加到数组的末尾,或者更常见的是附加到引用数组对象的变量。这称为括号表示法 。例如,如果我们想从
ourArray
检索"a"
并将其分配给变量,我们可以使用以下代码执行此操作: 让ourVariable = ourArray [0];除了访问与索引相关的值,你还可以设置索引使用相同的符号中的值:
// ourVariable等于“a”
ourArray [1] =“不再是b”;使用括号表示法,我们现在将索引1处的项目从
// ourArray现在等于[“a”,“不再b”,“c”];
"b"
重置为"not b anymore"
。 ourArray
数组变量中获取数据元素"a"
并将其赋值给一个变量,我们可以编写如下所示的代码:
+
+```js
+let ourVariable = ourArray[0];
+// ourVariable 的值为 "a"
+```
+
+除了使用 “索引” 来获取某个元素值以外,你还可以通过类似的方法来设置一个索引位置所对应的元素值:
+
+```js
+ourArray[1] = "not b anymore";
+// ourArray 现在的值为 ["a", "not b anymore", "c"];
+```
+
+我们现在已经利用方括号将索引为 1 的元素从"b"
设置为了"not b anymore"
。
+myArray
的第二个位置(索引1
)设置为您想要的任何内容,除了"b"
。 myArray
中第二个元素(索引1
)设置为除了"b"
以外的任意值。
+foods
对象被用于超市收银机的程序中。我们有一些设置selectedFood
功能,我们想检查我们的foods
对象是否存在该食物。这可能看起来像: let selectedFood = getCurrentFood(scanningItem);此代码将评估存储在
让库存=食物[selectedFood];
selectedFood
变量中的值,并在foods
对象中返回该键的值,如果不存在则返回undefined
。括号表示法非常有用,因为有时候对象属性在运行时之前是未知的,或者我们需要以更动态的方式访问它们。 foods
对象,并且有一些程序逻辑会设置selectedFood
,我们需要查询foods
对象来检查某种食物是否存在,我们可以这样写检查逻辑:
+
+```js
+let selectedFood = getCurrentFood(scannedItem);
+let inventory = foods[selectedFood];
+```
+
+上述代码会先计算selectedFood
变量的值,并返回foods
对象中以该值命名的属性对应的值,若没有以该值命名的属性则会返回undefined
。有时候对象的属性名在运行之前是不确定的,或者我们需要动态地访问对象的属性,这时方括号符号就会很有用。
+checkInventory
,它接收一个扫描的项目作为参数。返回foods
对象中的scannedItem
键的当前值。您可以假设只有有效键将作为checkInventory
的参数提供。 checkInventory
函数,它接受一个被扫描到的商品名作为输入参数。它要返回foods
对象中以scannedItem
的值命名的属性的值。只有有效的属性名会作为参数传入checkInventory
,你在完成挑战时不需处理参数无效的情况。
+Array.push()
和Array.unshift()
。两种方法都将一个或多个元素作为参数,并将这些元素添加到调用该方法的数组中; push()
方法将元素添加到数组的末尾, unshift()
将元素添加到开头。考虑以下: 让二十三'='XXIII';
让romanNumerals = ['XXI','XXII'];
romanNumerals.unshift('XIX','XX');
//现在等于['XIX','XX','XXI','XXII']
romanNumerals.push(二十三);
//现在等于['XIX','XX','XXI','XXII','XXIII']请注意,我们也可以传递变量,这使我们可以更灵活地动态修改数组的数据。
Array.push()
和Array.unshift()
。
+这两个方法都接收一个或多个元素作为参数;对一个数组调用这两个方法都可以将输入的元素插入到该数组中;push()
方法将元素插入到一个数组的末尾,而unshift()
方法将元素插入到一个数组的开头。请看以下例子:
+
+```js
+let twentyThree = 'XXIII';
+let romanNumerals = ['XXI', 'XXII'];
+
+romanNumerals.unshift('XIX', 'XX');
+// 数组现在为 ['XIX', 'XX', 'XXI', 'XXII']
+
+romanNumerals.push(twentyThree);
+// 数组现在为 ['XIX', 'XX', 'XXI', 'XXII', 'XXIII']
+```
+注意,我们还可以输入变量,这允许我们很灵活地动态改变我们数组中的数据。
+mixedNumbers
,我们将一个数组作为参数传递。修改函数使用push()
和unshift()
将'I', 2, 'three'
到数组的开头,将7, 'VIII', 9
到结尾,以便返回的数组包含数字的表示形式按顺序1-9。 mixedNumbers
函数,它会接受一个数组作为参数。请你修改这个函数,使用push()
和unshift()
来将'I', 2, 'three'
插入到数组的开头,将7, 'VIII', 9
插入到数组的末尾,使得这个函数返回一个依次包含 1-9 的数组。
+splice()
最多需要三个参数吗?好吧,我们可以更进一步使用splice()
- 除了删除元素之外,我们还可以使用代表一个或多个元素的第三个参数来添加它们。这对于快速切换另一个元素或一组元素非常有用。例如,假设您正在为数组中的一组DOM元素存储颜色方案,并希望根据某些操作动态更改颜色: function colorChange(arr,index,newColor){此函数采用十六进制值数组,删除元素的索引以及用于替换已删除元素的新颜色。返回值是一个包含新修改的颜色方案的数组!虽然这个例子有点过于简单,但我们可以看到利用
arr.splice(index,1,newColor);
返回
}
让colorScheme = ['#878787','#a08794','#bb7e8c','#c9b6be','#d1becf'];
colorScheme = colorChange(colorScheme,2,'#332327');
//我们删除了'#bb7e8c'并在其位置添加了'#332327'
// colorScheme现在等于['#878787','#a08794','#332327','#c9b6be','#d1becf']
splice()
到其最大潜力的值。 splice()
方法可以接受最多 3 个参数吗?我们现在可以进一步了解splice()
。除了移除元素,我们还可以利用它的第三个参数来向数组中添加元素。第三个参数可以是一个或多个元素,这些元素会被添加到数组中。这使我们能够便捷地将数组中的一个或一系列元素换成其他的元素。例如:
+
+```js
+const numbers = [10, 11, 12, 12, 15];
+const startIndex = 3;
+const amountToDelete = 1;
+
+numbers.splice(startIndex, amountToDelete, 13, 14);
+// 第二个 12 被移除,在第二个 12 的索引处添加 13、14。
+console.log(numbers);
+// 返回 [ 10, 11, 12, 13, 14, 15 ]
+```
+
+以一个数字数组开始。接着调用 splice()
方法,在 (3) 的索引位置开始删除元素,删除的元素数量是 (1),(13, 14) 是在删除位置插入的元素,可以在 amountToDelete
后面插入任意数量的元素(以逗号分隔),每个都会被插入。
+htmlColorNames
,它将一组HTML颜色作为参数。使用splice()
修改函数以删除数组的前两个元素,并在各自的位置添加'DarkSalmon'
和'BlanchedAlmond'
'DarkSalmon'
。 htmlColorNames
函数,它以一个 HTML 颜色的数组作为输入参数。请修改这个函数,利用splice()
来移除数组中的前两个元素,并在对应的位置上添加'DarkSalmon'
和'BlanchedAlmond'
。
+让FCC_User = {上面的代码定义了一个名为
用户名:'awesome_coder',
粉丝:572,
积分:1741,
已完成项目:15
};
FCC_User
的对象,它有四个属性 ,每个属性都映射到一个特定的值。如果我们想知道的数量followers
FCC_User
了,我们可以通过写访问属性: let userData = FCC_User.followers;这称为点符号 。或者,我们也可以使用括号访问该属性,如下所示:
// userData等于572
让userData = FCC_User ['粉丝']请注意,带支架的符号 ,我们封闭
// userData等于572
followers
在引号。这是因为括号实际上允许我们传递一个变量以作为属性名称进行评估(提示:请记住这一点以供日后使用!)。如果我们在没有引号的情况下传递了followers
,那么JavaScript引擎会尝试将其作为变量进行评估,而ReferenceError: followers is not defined
将被抛出。 FCC_User
的对象,它有 4 个属性,每个属性映射一个特定的值。如果我们想知道FCC_User
有多少followers
,我们可以这样访问其followers
属性:
+
+```js
+let userData = FCC_User.followers;
+// userData 等于 572
+```
+
+这叫做点符号(dot notation)。我们还可以用方括号符号来访问对象中的属性:
+
+```js
+let userData = FCC_User['followers'];
+// userData 等于 572
+```
+
+注意,在用方括号符号时,我们在括号里写的是字符串followers
(用引号括起)。方括号符号让我们能用一个变量作为属性名来访问对象的属性(请记住)。若我们在方括号中不写引号而直接写followers
,JavaScript 引擎会将其看作一个变量,并抛出一个ReferenceError: followers is not defined
的错误。
+foods
对象。再添加三个条目:价值为13
bananas
,价值为35
grapes
和价值为27
strawberries
。 foods
对象,请为其新增 3 项:值为13
的bananas
属性、值为35
的grapes
属性和值为27
的strawberries
属性。
+foods
是一个对象
+ - text: foods
应该是一个对象。
testString: assert(typeof foods === 'object');
- - text: foods
对象有一个值为13
的关键"bananas"
+ - text: foods
应该有一个值为13
的"bananas"
属性。
testString: assert(foods.bananas === 13);
- - text: foods
对象有一个关键的"grapes"
,价值35
+ - text: foods
应该有一个值为35
的"grapes"
属性。
testString: assert(foods.grapes === 35);
- - text: foods
对象有一个关键的"strawberries"
,值为27
+ - text: foods
应该有一个值为27
的"strawberries"
属性。
testString: assert(foods.strawberries === 27);
- - text: 应使用点或括号表示法设置键值对
+ - text: 你应该用点符号或者方括号符号来设置对象的属性。
testString: assert(code.search(/bananas:/) === -1 && code.search(/grapes:/) === -1 && code.search(/strawberries:/) === -1);
```
@@ -49,7 +78,6 @@ let foods = {
// change code above this line
console.log(foods);
-
```
@@ -62,6 +90,17 @@ console.log(foods);
indexOf()
,它允许我们快速,轻松地检查数组中元素的存在。 indexOf()
接受一个元素作为参数,并在调用时返回该元素的位置或索引,如果该元素在数组中不存在,则返回-1
。例如: 让水果= ['苹果','梨','橙子','桃子','梨子'];
fruits.indexOf('dates')//返回-1
fruits.indexOf('oranges')//返回2
fruits.indexOf('pears')//返回1,元素所在的第一个索引
indexOf()
。这个方法让我们可以便捷地检查某个元素是否存在于一个数组中。indexOf()
方法接受一个元素作为输入参数,并返回该元素在数组中的位置(索引);若该元素不存在于数组中则返回-1
。
+例如:
+
+```js
+let fruits = ['apples', 'pears', 'oranges', 'peaches', 'pears'];
+
+fruits.indexOf('dates'); // 返回 -1
+fruits.indexOf('oranges'); // 返回 2
+fruits.indexOf('pears'); // 返回 1,即第一个出现的 'pears' 元素在数组中的索引为 1
+```
+
+indexOf()
对于快速检查数组中是否存在元素非常有用。我们定义了一个函数quickCheck
,它将一个数组和一个元素作为参数。使用indexOf()
修改函数,以便在传递的元素存在于数组时返回true
如果不存在则返回false
。 indexOf()
在快速检查一个数组中是否存在某个元素时非常有用。我们已经定义了一个quickCheck
函数,它接受一个数组和一个元素作为输入参数。请修改这个函数,利用indexOf()
方法,使得当输入的数组中含有输入的元素时,函数返回true
;不含有输入的元素时,函数返回false
。
+hasOwnProperty()
方法,另一个使用in
关键字。如果我们有一个具有Alan
属性的对象users
,我们可以通过以下任一方式检查其存在: users.hasOwnProperty( '艾伦');
'艾伦'在用户;
//都返回true
hasOwnProperty()
方法,另一个是in
关键字。如果我们有一个users
对象,它有一个Alan
属性,我们可以用以下两种方式之一来检查该属性在对象中是否存在:
+
+```js
+users.hasOwnProperty('Alan');
+'Alan' in users;
+// 都返回 true
+```
+
+users
,其中包含一些用户和一个函数isEveryoneHere
,我们将users
对象作为参数传递给它。完成编写此函数,以便仅当users
对象包含所有四个名称( Alan
, Jeff
, Sarah
和Ryan
)作为键时才返回true
,否则返回false
。 users
对象和一个isEveryoneHere
函数,该函数接受users
对象作为参数。请完成该函数使其在users
对象中包含以下 4 个键Alan
、Jeff
、Sarah
和Ryan
时才返回true
,否则返回false
。
+users
对象仅包含Alan
, Jeff
, Sarah
和Ryan
- testString: 'assert("Alan" in users && "Jeff" in users && "Sarah" in users && "Ryan" in users && Object.keys(users).length === 4, "The users
object only contains the keys Alan
, Jeff
, Sarah
, and Ryan
");'
- - text: 如果Alan
, Jeff
, Sarah
和Ryan
是users
对象的属性,则函数isEveryoneHere
返回true
- testString: 'assert(isEveryoneHere(users) === true, "The function isEveryoneHere
returns true
if Alan
, Jeff
, Sarah
, and Ryan
are properties on the users
object");'
- - text: 如果Alan
, Jeff
, Sarah
和Ryan
不是users
对象的属性,则函数isEveryoneHere
返回false
- testString: 'assert((function() { delete users.Alan; delete users.Jeff; delete users.Sarah; delete users.Ryan; return isEveryoneHere(users) })() === false, "The function isEveryoneHere
returns false
if Alan
, Jeff
, Sarah
, and Ryan
are not properties on the users
object");'
-
+ - text: users
对象应该只含有Alan
、Jeff
、Sarah
和Ryan
4 个键。
+ testString: assert("Alan" in users && "Jeff" in users && "Sarah" in users && "Ryan" in users && Object.keys(users).length === 4);
+ - text: isEveryoneHere
函数在users
对象包含Alan
、Jeff
、Sarah
和Ryan
4 个键时应该返回true
。
+ testString: assert(isEveryoneHere(users) === true);
+ - text: isEveryoneHere
函数在users
对象不包含Alan
、Jeff
、Sarah
或Ryan
4 个键时应该返回false
。
+ testString: assert((function() { delete users.Alan; return isEveryoneHere(users) })() === false);
+ - text: 如果 Jeff
不是 users
对象的属性,函数 isEveryoneHere
应该返回 false
。
+ testString: assert((function() { delete users.Jeff; return isEveryoneHere(users) })() === false);
+ - text: 如果 Sarah
不是 users
对象的属性,函数 isEveryoneHere
应该返回 false
。
+ testString: assert((function() { delete users.Sarah; return isEveryoneHere(users) })() === false);
+ - text: 如果 Ryan
不是 users
对象的属性,函数 isEveryoneHere
应该返回 false
。
+ testString: assert((function() { delete users.Ryan; return isEveryoneHere(users) })() === false);
```
让thisArray = ['sage','迷迭香','欧芹','百里香'];使用扩展语法,我们刚刚实现了一个操作,如果我们使用传统方法,这个操作会更复杂,更冗长。
让那个阵容= ['罗勒','香菜',......这个阿雷,'香菜'];
//现在等于['罗勒','香菜','鼠尾草','迷迭香','欧芹','百里香','香菜']
spreadOut
,它返回变量sentence
,使用spread运算符修改函数,使它返回数组['learning', 'to', 'code', 'is', 'fun']
。 sentence
变量的spreadOut
函数,请修改该函数,利用展开运算符使该函数返回数组['learning', 'to', 'code', 'is', 'fun']
。
+spreadOut
应该返回["learning", "to", "code", "is", "fun"]
'
testString: assert.deepEqual(spreadOut(), ['learning', 'to', 'code', 'is', 'fun']);
- - text: spreadOut
函数应该使用扩展语法
+ - text: spreadOut
函数里应该用到展开语法
testString: assert.notStrictEqual(spreadOut.toString().search(/[...]/), -1);
```
@@ -40,7 +53,6 @@ function spreadOut() {
// do not change code below this line
console.log(spreadOut());
-
```
@@ -54,5 +66,13 @@ console.log(spreadOut());
```js
// solution required
+
+function spreadOut() {
+ let fragment = ['to', 'code'];
+ let sentence = ['learning', ...fragment, 'is', 'fun'];
+ return sentence;
+}
+
```
+
slice()
允许我们选择要复制的数组元素,但在其他几个有用的任务中,ES6的新扩展运算符允许我们使用简单且高度可读的语法轻松地按顺序复制所有数组的元素。扩展语法看起来像这样: ...
在实践中,我们可以使用spread运算符来复制数组,如下所示: let thisArray = [true,true,undefined,false,null];
让thatArray = [... thisArray];
// thatArray等于[true,true,undefined,false,null]
// thisArray保持不变,与thatArray相同
slice()
已经能让我们从一个数组中选择一些元素来复制到新数组中了,而 ES6 中又新引入了一个简洁且可读性强的语法展开运算符(spread operator),它能让我们方便地复制数组中的所有元素。展开语法是这样的:...
+在实践中,我们可以这样用展开运算符来复制一个数组:
+
+```js
+let thisArray = [true, true, undefined, false, null];
+let thatArray = [...thisArray];
+// thatArray 等于 [true, true, undefined, false, null]
+// thisArray 保持不变,等于 thatArray
+```
+
+copyMachine
,它将arr
(数组)和num
(数字)作为参数。该函数应该返回一个由arr
的num
副本组成的新数组。我们为您完成了大部分工作,但它还没有正常工作。使用扩展语法修改函数以使其正常工作(提示:我们已经介绍过的另一种方法可能会派上用场!)。 copyMachine
函数,它接受arr
(一个数组)和num
(一个数字)作为输入参数。该函数应该返回一个由num
个arr
组成的新数组。我们已经为你写好了大部分的代码,但它还不能正确地工作。请修改这个函数,使用展开语法,使该函数正确工作(提示:我们已经学到过的一个方法很适合用在这里!)
+copyMachine([true, false, true], 2)
应返回[[true, false, true], [true, false, true]]
'
+ - text: 'copyMachine([true, false, true], 2)
应该返回[[true, false, true], [true, false, true]]
'
testString: assert.deepEqual(copyMachine([true, false, true], 2), [[true, false, true], [true, false, true]]);
- - text: 'copyMachine([1, 2, 3], 5)
应返回[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
'
+ - text: 'copyMachine([1, 2, 3], 5)
应该返回[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
'
testString: assert.deepEqual(copyMachine([1, 2, 3], 5), [[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]);
- text: 'copyMachine([true, true, null], 1)
应该返回[[true, true, null]]
'
testString: assert.deepEqual(copyMachine([true, true, null], 1), [[true, true, null]]);
- text: 'copyMachine(["it works"], 3)
应该返回[["it works"], ["it works"], ["it works"]]
'
testString: assert.deepEqual(copyMachine(['it works'], 3), [['it works'], ['it works'], ['it works']]);
- - text: copyMachine
函数应该使用带有数组arr
的spread operator
+ - text: copyMachine
函数中应该对数组arr
使用spread operator
。
testString: assert(removeJSComments(code).match(/\.\.\.arr/));
```
@@ -51,12 +64,18 @@ function copyMachine(arr, num) {
// change code here to test different cases:
console.log(copyMachine([true, false, true], 2));
-
```
+### After Test
+slice()
。 slice()
,而不是修改数组,将给定数量的元素复制或提取到新数组,而不改变它所调用的数组。 slice()
只接受2个参数 - 第一个是开始提取的索引,第二个是停止提取的索引(提取将发生,但不包括此索引处的元素)。考虑一下: 让weatherConditions = ['rain','snow','sleet','hail','clear'];实际上,我们通过从现有数组中提取元素来创建一个新数组。
让todaysWeather = weatherConditions.slice(1,3);
//今天天气等于['雪','雨夹雪'];
// weatherConditions仍等于['rain','snow','sleet','hail','clear']
slice()
方法。slice()
并不修改数组,而是复制或者说提取(extract)给定数量的元素到一个新数组里,而调用方法的数组则保持不变。slice()
只接受 2 个输入参数—第一个是开始提取元素的位置(索引),第二个是结束提取元素的位置(索引)。slice 方法会提取直到截止索引的元素,但被提取的元素不包括截止索引对应的元素。请看以下例子:
+
+```js
+let weatherConditions = ['rain', 'snow', 'sleet', 'hail', 'clear'];
+
+let todaysWeather = weatherConditions.slice(1, 3);
+// todaysWeather 等于 ['snow', 'sleet'];
+// weatherConditions 仍然等于 ['rain', 'snow', 'sleet', 'hail', 'clear']
+```
+
+现在我们从一个已有的数组中提取了一些元素,并用这些元素创建了一个新数组。
+forecast
。使用slice()
修改函数以从参数数组中提取信息,并返回包含元素'warm'
和'sunny'
的新数组。 forecast
函数,它接受一个数组作为参数。请修改这个函数,利用slice()
来从输入的数组中提取信息,并返回一个包含元素'warm'
和'sunny'
的新数组。
+让nestedArray = [// top,或first level - 最外面的数组虽然这个例子看似令人费解,但在处理大量数据时,这种复杂程度并非闻所未闻,甚至不同寻常。但是,我们仍然可以使用括号表示法轻松访问此复杂数组的最深层次:
['deep'],//数组中的数组,2个深度级别
[
['更深'],['更深'] // 2个数组嵌套3层深
]
[
[
['deepest'],['最深'] // 2个数组嵌套了4个级别
]
[
[
['deepest-est?'] //一个数组嵌套5层深
]
]
]
]。
的console.log(nestedArray [2] [1] [0] [0] [0]);现在我们知道那条数据在哪里,如果需要,我们可以重置它:
//日志:最深?
nestedArray [2] [1] [0] [0] [0] =“更深”;
的console.log(nestedArray [2] [1] [0] [0] [0]);
//现在记录:更深入
myNestedArray
,它等于一个数组。修改myNestedArray
,使用数据元素的字符串 , 数字和布尔值的任意组合,以便它具有五个深度级别(请记住,最外层的数组是级别1)。某处在第三级上,包括字符串'deep'
,在第四级,包括字符串'deeper'
,并且在第五层上,包括字符串'deepest'
。 myNestedArray
数组变量。请修改myNestedArray
,用字符串(string)、数字(number)或者布尔值(boolean)作为数组的数据元素,使得myNestedArray
刚好有 5 层数组嵌套(记住,最外层的数组是第 1 层)。请在第 3 层的数组中包含字符串'deep'
,在第 4 层的数组中包含字符串'deeper'
,在第 5 层的数组中包含字符串'deepest'
。
+myNestedArray
应仅包含数字,布尔值和字符串作为数据元素
+ - text: myNestedArray
中的数据元素应当只能是字符串、数字或者布尔值。
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: myNestedArray
应该有5个级别的深度
+ - text: myNestedArray
应该刚好有 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: myNestedArray
应该在嵌套3级深度的数组中恰好包含一个字符串"deep"
+ - text: myNestedArray
里应该有且只有一个字符串"deep"
,并且应该出现在第 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: myNestedArray
应该在嵌套4级深度的数组中恰好包含一个字符串"deeper"
deep”
+ - text: myNestedArray
里应该有且只有一个字符串"deeper"
,并且应该出现在第 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: myNestedArray
应该在嵌套5级深度的数组中恰好包含一个字符串"deepest"
myNestedArray
"deepest"
+ - text: myNestedArray
里应该有且只有一个字符串"deepest"
,并且应该出现在第 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);
```
@@ -47,7 +89,6 @@ let myNestedArray = [
['iterate', 1.3849, 7, '8.4876', 'arbitrary', 'depth']
// change code above this line
];
-
```
@@ -60,6 +101,15 @@ let myNestedArray = [
Object.keys()
方法生成一个数组,其中包含存储在对象中的所有键,并传入一个对象作为参数。这将返回一个数组,其中的字符串表示对象中的每个属性。同样,数组中的条目没有特定的顺序。 Object.keys()
方法,使其生成一个包含对象中所有键的数组。这会返回一个由对象中所有键的名称(字符串)组成的数组。再次说明,这个数组中的项的顺序是不确定的。
+getArrayOfUsers
函数,以便它返回一个数组,该数组包含它作为参数接收的对象中的所有属性。 getArrayOfUsers
函数,使其返回一个包含输入的对象的所有属性的数组。
+users
对象仅包含Alan
, Jeff
, Sarah
和Ryan
+ - text: users
对象应该只包含Alan
、Jeff
、Sarah
和Ryan
这 4 个键
testString: assert('Alan' in users && 'Jeff' in users && 'Sarah' in users && 'Ryan' in users && Object.keys(users).length === 4);
- - text: getArrayOfUsers
函数返回一个数组,其中包含users
对象中的所有键
+ - text: getArrayOfUsers
函数应该返回一个包含users
对象中所有键的数组
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);
```
@@ -58,7 +62,6 @@ function getArrayOfUsers(obj) {
}
console.log(getArrayOfUsers(users));
-
```
@@ -71,6 +74,30 @@ console.log(getArrayOfUsers(users));
every()
, forEach()
, map()
等),但是这种技术最灵活并且为我们提供了最大的控制量是一个简单的for
循环。考虑以下: function greaterThanTen(arr){使用
让newArr = [];
for(let i = 0; i <arr.length; i ++){
if(arr [i]> 10){
(ARR [I])newArr.push;
}
}
返回newArr;
}
greaterThanTen([2,12,8,14,80,0,1]);
//返回[12,14,80]
for
循环,此函数遍历并访问数组的每个元素,并使其经受我们创建的简单测试。通过这种方式,我们可以轻松地以编程方式确定哪些数据项大于10
,并返回包含这些项的新数组。 every()
、forEach()
、map()
等等)。而简单的for
循环不仅能实现这些功能,而且相比之下也更灵活。
+请看以下例子:
+
+```js
+function greaterThanTen(arr) {
+ let newArr = [];
+ for (let i = 0; i < arr.length; i++) {
+ if (arr[i] > 10) {
+ newArr.push(arr[i]);
+ }
+ }
+ return newArr;
+}
+
+greaterThanTen([2, 12, 8, 14, 80, 0, 1]);
+// 返回 [12, 14, 80]
+```
+
+这个函数使用一个for
循环来遍历一个数组,逐一对其中的元素进行测试。我们用这个方法简单地以编程的方式找出了数组中大于10
的元素,并返回了一个包含这些元素的数组。
+filteredArray
,它接受arr
,一个嵌套数组和elem
作为参数,并返回一个新数组。 elem
表示在arr
嵌套的一个或多个数组上可能存在或不存在的元素。使用for
循环修改函数,以返回已传递数组的过滤版本,以便删除嵌套在包含elem
arr
中的任何数组。 filteredArray
函数,它接受一个嵌套的数组参数arr
以及一个elem
参数,并要返回一个新数组。arr
数组中的数组可能包含elem
元素,也可能不包含。请修改该函数,用一个for
循环来做筛选,使函数返回一个由arr
中不包含elem
的数组组成的新数组。
+users
对象,这可能看起来像: for(让用户在用户中){在这个语句中,我们定义了一个变量
的console.log(用户);
};
//日志:
艾伦
杰夫
莎拉
瑞安
user
,正如您所看到的,在每次迭代期间,当该语句循环遍历该对象时,该变量被重置为每个对象的键,从而导致每个用户的名称被打印到控制台。 注意: users
对象的键为例:
+
+```js
+for (let user in users) {
+ console.log(user);
+}
+
+// logs:
+Alan
+Jeff
+Sarah
+Ryan
+```
+
+在这个语句中,我们定义了一个user
变量,你可以看到,这个变量在 for...in 语句对对象的每一个键的遍历中都会被重置。
+注意:countOnline
;在此函数中使用for ... in语句循环访问users
对象中的users
并返回其online
属性设置为true
的用户数。 countOnline
函数,请在其中使用一个 for...in 语句来遍历users
对象中的用户,并返回online
属性为true
的用户的数量。
+
+
+```js
+{
+ Alan: {
+ online: false
+ },
+ Jeff: {
+ online: true
+ },
+ Sarah: {
+ online: false
+ }
+}
+```
+
+users
对象包含用户Jeff
和Ryan
, online
设置为true
,用户Alan
和Sarah
online
设置为false
- testString: 'assert(users.Alan.online === false && users.Jeff.online === true && users.Sarah.online === false && users.Ryan.online === true, "The users
object contains users Jeff
and Ryan
with online
set to true
and users Alan
and Sarah
with online
set to false
");'
- - text: 函数countOnline
返回online
属性设置为true
的用户数
- testString: 'assert((function() { users.Harry = {online: true}; users.Sam = {online: true}; users.Carl = {online: true}; return countOnline(users) })() === 5, "The function countOnline
returns the number of users with the online
property set to true
");'
-
+ - text: 函数 countOnline
应该使用 `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: '当传入 { Alan: { online: false }, Jeff: { online: true }, Sarah: { online: false } }
时,函数 countOnline
应该返回 1
。'
+ testString: assert(countOnline(usersObj1) === 1);
+ - text: '当传入 { Alan: { online: true }, Jeff: { online: false }, Sarah: { online: true } }
时,函数 countOnline
应该返回 2
。'
+ testString: assert(countOnline(usersObj2) === 2);
+ - text: '当传入 { Alan: { online: false }, Jeff: { online: false }, Sarah: { online: false } }
时,函数 countOnline
应该返回 0
。'
+ testString: assert(countOnline(usersObj3) === 0);
```
user
对象包含三个键。 data
键包含五个键,其中一个键包含一组friends
。从这里,您可以看到灵活的对象如何作为数据结构。我们已经开始编写一个函数addFriend
。完成编写它以便它获取user
对象并将friend
参数的名称添加到存储在user.data.friends
中的数组并返回该数组。 user
对象包含 3 个键。data
对象包含 5 个键,其中一个包含一个friends
数组。从这个例子你可以看到对象作为数据结构是多么的灵活。我们已经写了addFriend
函数的一部分,请你完成这个函数,使其接受一个user
对象,将friend
参数中的名字添加到user.data.friends
数组中并返回该数组。
+user
对象具有name
, age
和data
键
+ - text: user
对象应该包含name
、age
和data
三个键。
testString: assert('name' in user && 'age' in user && 'data' in user);
- - text: addFriend
函数接受user
对象和friend
字符串作为参数,并将朋友添加到user
对象中的friends
数组
+ - text: addFriend
函数应该接受一个user
对象和一个friend
字符串作为输入参数,并将 friend 插入到user
对象的friends
数组中。
testString: assert((function() { let L1 = user.data.friends.length; addFriend(user, 'Sean'); let L2 = user.data.friends.length; return (L2 === L1 + 1); })());
- - text: 'addFriend(user, "Pete")
应该返回["Sam", "Kira", "Tomo", "Pete"]
'
+ - text: 'addFriend(user, "Pete")
应该返回["Sam", "Kira", "Tomo", "Pete"]
。"
testString: assert.deepEqual((function() { delete user.data.friends; user.data.friends = ['Sam', 'Kira', 'Tomo']; return addFriend(user, 'Pete') })(), ['Sam', 'Kira', 'Tomo', 'Pete']);
```
@@ -61,7 +65,6 @@ function addFriend(userObj, friend) {
}
console.log(addFriend(user, 'Pete'));
-
```
@@ -74,6 +77,30 @@ console.log(addFriend(user, 'Pete'));
让nestedObject = {
id:28802695164,
日期:'2016年12月31日',
数据:{
总用户:99,
在线:80,
onlineStatus:{
活跃:67,
离开:13
}
}
};
nestedObject
有三个唯一的键: id
,其值为数字, date
为字符串的data
, data
,其值为另一个嵌套在其中的对象。虽然结构很快就会变得复杂,但我们仍然可以使用相同的符号来访问我们需要的信息。 nestedObject
有 3 个唯一的键:值为一个数字的id
、值为一个字符串的date
和值为一个嵌套了其他对象的对象的data
。虽然对象中的数据可能很复杂,我们仍能使用上一个挑战中讲的符号来访问我们需要的信息。
+userActivity
,其中包含嵌套在其中的另一个对象。您可以像修改上一个挑战中的属性一样修改此嵌套对象的属性。将online
密钥的值设置为45
。 userActivity
对象,它包含了另一个对象。你可以用上一个挑战中那样的方式来修改被嵌套的对象的属性。请将online
属性设为45
。
+userActivity
具有id
, date
和data
属性
+ - text: userActivity
应该含有id
、date
和data
属性。
testString: assert('id' in userActivity && 'date' in userActivity && 'data' in userActivity);
- - text: userActivity
具有设置为具有密钥totalUsers
和online
的对象的data
密钥
+ - text: userActivity
应该有一个data
属性,该属性要是一个含有totalUsers
和online
属性的对象。
testString: assert('totalUsers' in userActivity.data && 'online' in userActivity.data);
- - text: 嵌套在userActivity
data
键中的online
属性应设置为45
+ - text: userActivity
的data
属性值中的online
属性应该被设为45
。
testString: assert(userActivity.data.online === 45);
- - text: online
属性使用点或括号表示法设置
+ - text: 你应该用点符号或者方括号符号来设置online
属性。
testString: 'assert.strictEqual(code.search(/online: 45/), -1);'
```
@@ -50,7 +71,6 @@ let userActivity = {
// change code above this line
console.log(userActivity);
-
```
@@ -63,6 +83,16 @@ console.log(userActivity);
push()
和unshift()
都有相应的几乎相反的方法: pop()
和shift()
。正如您现在可能已经猜到的那样, pop()
不是添加,而是从数组的末尾删除元素,而shift()
从头开始删除元素。 pop()
和shift()
及其兄弟push()
和unshift()
之间的关键区别在于,两个方法都不接受参数,并且每个方法只允许一次由单个元素修改数组。让我们来看看: 让问候= ['什么事情?','你好','看到你!'];我们还可以使用以下任一方法返回已删除元素的值:
greetings.pop();
//现在等于['whats up?','hello']
greetings.shift();
//现在等于['你好']
let popped = greetings.pop();
//返回'你好'
//问候现在等于[]
push()
和unshift()
都分别有一个作用基本与之相反的函数:pop()
和shift()
。你现在或许已经猜到,与插入元素相反,pop()
从数组的末尾移除一个元素,而shift()
从数组的开头移除一个元素。pop()
和shift()
与对应的push()
和unshift()
的关键区别在于,前者不能接受输入参数,而且每次只能修改数组中的一个元素。
+让我们来看以下的例子:
+
+```js
+let greetings = ['whats up?', 'hello', 'see ya!'];
+
+greetings.pop();
+// now equals ['whats up?', 'hello']
+
+greetings.shift();
+// now equals ['hello']
+```
+
+还可以用这些方法返回移除的元素,像这样:
+
+```js
+let popped = greetings.pop();
+// returns 'hello'
+// greetings now equals []
+```
+
+popShift
,它将一个数组作为参数并返回一个新数组。使用pop()
和shift()
修改函数,删除参数数组的第一个和最后一个元素,并将删除的元素分配给它们对应的变量,以便返回的数组包含它们的值。 popShift
函数,它会接收一个数组作为输入参数并返回一个新的数组。请你修改这个函数,使用pop()
和shift()
来移除输入的数组的第一个元素和最后一个元素,并将这两个被移除的元素赋值给对应的变量,使得返回的数组包含它们的值。
+shift()
和pop()
从数组的开头和结尾删除元素,但是如果我们想要从中间某处删除元素呢?或者一次删除多个元素?好吧,这就是splice()
用武之地splice()
允许我们这样做:从数组中的任何位置删除任意数量的连续元素 。 splice()
可能需要长达3个参数,但现在,我们将重点放在刚第一2.第2个参数splice()
是其代表索引的整数,或位置中,阵列的该splice()
是为呼吁。请记住,数组是零索引的 ,所以为了表示数组的第一个元素,我们将使用0
。 splice()
的第一个参数表示从中开始删除元素的数组的索引,而第二个参数表示要删除的元素的数量。例如: 让array = ['今天','是','不','所以','伟大'];
array.splice(2,2);
//删除以第3个元素开头的2个元素
//数组现在等于['今天','是','很棒']
splice()
不仅修改了它被调用的数组,而且还返回一个包含被删除元素值的新数组: 让array = ['我','我','感觉','真的','快乐'];
let newArray = array.splice(3,2);
// newArray等于['真'','快乐']
shift()
和pop()
从数组的开头或者末尾移除元素,但如果我们想移除数组中间的一个元素呢?或者想一次移除多个元素呢?这时候我们就需要splice()
了。splice()
让我们可以从数组中的任意位置移除任意数量的连续的元素。
+splice()
最多可以接受 3 个参数,但现在我们先关注前两个。splice()
接收的前两个参数基于调用splice()
数组中元素的索引。记住,数组的索引是从 0 开始的(zero-indexed),所以我们要用0
来指示数组中的第一个元素。splice()
的第一个参数代表从数组中的哪个索引开始移除元素,而第二个参数指示要从数组中删除多少个元素。例如:
+
+```js
+let array = ['today', 'was', 'not', 'so', 'great'];
+
+array.splice(2, 2);
+// 从第三个索引位置开始移除 2 个元素
+// array 现在是 ['today', 'was', 'great']
+```
+
+splice()
不仅从被调用的数组中移除元素,还会返回一个包含被移除元素的数组:
+
+```js
+let array = ['I', 'am', 'feeling', 'really', 'happy'];
+
+let newArray = array.splice(3, 2);
+// newArray 是 ['really', 'happy']
+```
+
+sumOfTen
,它将一个数组作为参数,并返回该数组元素的总和。使用splice()
修改函数,使其返回值10
。 10
。
+
+sumOfTen
应该返回10
- testString: 'assert.strictEqual(sumOfTen([2, 5, 1, 5, 2, 1]), 10, "sumOfTen
should return 10");'
- - text: sumOfTen
函数应该使用splice()
方法
- testString: 'assert.notStrictEqual(sumOfTen.toString().search(/\.splice\(/), -1, "The sumOfTen
function should utilize the splice()
method");'
-
+ - text: 不应该修改这一行 const arr = [2, 4, 5, 1, 7, 5, 2, 1];
。
+ testString: assert(code.replace(/\s/g, '').match(/constarr=\[2,4,5,1,7,5,2,1\];?/));
+ - text: arr
的剩余元素和应该为 10
。
+ testString: assert.strictEqual(arr.reduce((a, b) => a + b), 10);
+ - text: 应该利用 arr
的 splice()
。
+ testString: assert(code.replace(/\s/g, '').match(/arr\.splice\(/));
+ - text: splice 应该只删除 arr
里面的元素,不能给 arr
添加元素。
+ testString: assert(!code.replace(/\s/g, '').match(/arr\.splice\(\d+,\d+,\d+.*\)/g));
```
let simpleArray = ['one',2,'three',true,false,undefined,null];所有数组都有一个length属性,如上所示,可以使用语法
的console.log(simpleArray.length);
//记录7
Array.length
轻松访问Array.length
。下面可以看到更复杂的数组实现。这称为多维数组 ,或包含其他数组的数组。请注意,此数组还包含JavaScript 对象 ,我们将在下一节中详细介绍,但是现在,您需要知道的是,数组也能够存储复杂对象。 让complexArray = [
[
{
一:1,
二:2
},
{
三:3,
四:4
}
]
[
{
a:“a”,
b:“b”
},
{
c:“c”,
d:“d”
}
]
]。
Array.length
方法来访问它。
+下面是一个关于数组的更复杂的例子。这是一个多维数组(multi-dimensional Array),或者说是一个包含了其他数组的数组。可以注意到,在它的内部还包含了 JavaScript 中的对象(objects)结构。我们会在后面的小节中讨论该数据结构,但现在你只需要知道数组能够存储复杂的对象类型数据。
+
+```js
+let complexArray = [
+ [
+ {
+ one: 1,
+ two: 2
+ },
+ {
+ three: 3,
+ four: 4
+ }
+ ],
+ [
+ {
+ a: "a",
+ b: "b"
+ },
+ {
+ c: "c",
+ d: "d"
+ }
+ ]
+];
+```
+
+yourArray
的变量。通过为yourArray
变量指定长度至少为5个元素的数组来完成该语句。您的数组应至少包含一个字符串 ,一个数字和一个布尔值 。 yourArray
的变量。请修改题目中的语句,将一个含有至少 5 个元素的数组赋值给yourArray
变量。你的数组应该包含至少一个 string 类型的数据、一个 number 类型的数据和一个 boolean 类型的数据。
+yourArray
至少有5个元素
+ - text: yourArray
至少要包含 5 个元素。
testString: assert.isAtLeast(yourArray.length, 5);
- - text: yourArray
至少包含一个boolean
+ - text: yourArray
应该包含至少一个boolean
。
testString: assert(yourArray.filter( el => typeof el === 'boolean').length >= 1);
- - text: yourArray
至少包含一个number
+ - text: yourArray
应该包含至少一个number
。
testString: assert(yourArray.filter( el => typeof el === 'number').length >= 1);
- - text: yourArray
至少包含一个string
+ - text: yourArray
应该包含至少一个string
。
testString: assert(yourArray.filter( el => typeof el === 'string').length >= 1);
```
@@ -39,7 +78,6 @@ tests:
```js
let yourArray; // change this line
-
```
@@ -52,6 +90,7 @@ let yourArray; // change this line
foods
对象示例。如果我们想删除apples
键,我们可以使用delete
关键字删除它,如下所示: 删除foods.apples;
foods
对象。如果我们想移除apples
属性,我们可以使用delete
关键字:
+
+```js
+delete foods.apples;
+```
+
+foods
对象中删除oranges
, plums
和strawberries
键。 foods
中的oranges
、plums
和strawberries
属性。
+foods
对象只有三个键: apples
, grapes
和bananas
+ - text: foods
对象应该只含有 3 个键:apples
、grapes
和bananas
。
testString: 'assert(!foods.hasOwnProperty(''oranges'') && !foods.hasOwnProperty(''plums'') && !foods.hasOwnProperty(''strawberries'') && Object.keys(foods).length === 3);'
- - text: 使用delete
oranges
, plums
和strawberries
键
+ - text: 你应该用delete
关键字来移除oranges
、plums
和strawberries
属性。
testString: assert(code.search(/oranges:/) !== -1 && code.search(/plums:/) !== -1 && code.search(/strawberries:/) !== -1);
```
@@ -46,7 +57,6 @@ let foods = {
// change code above this line
console.log(foods);
-
```
@@ -60,5 +70,20 @@ console.log(foods);
```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);
```
+