diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3715b4c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,27 @@
+# OS generated files
+.DS_Store
+.DS_Store?
+._*
+.Spotlight-V100
+.Trashes
+ehthumbs.db
+Thumbs.db
+
+# Vim
+[._]*.s[a-v][a-z]
+[._]*.sw[a-p]
+[._]s[a-rt-v][a-z]
+[._]ss[a-gi-z]
+[._]sw[a-p]
+Session.vim
+
+# VSCode
+.vscode/*
+.vscode*.json
+
+# Jetbrains
+.idea/
+
+# Sublime
+*.sublime-workspace
+
diff --git a/01-responsive-web-design/applied-accessibility.md b/01-responsive-web-design/applied-accessibility.md
index d455128..adf01d8 100644
--- a/01-responsive-web-design/applied-accessibility.md
+++ b/01-responsive-web-design/applied-accessibility.md
@@ -11,49 +11,3 @@
Having accessible web content is an ongoing challenge. A great resource for your projects going forward is the W3 Consortium's Web Content Accessibility Guidelines (WCAG). They set the international standard for accessibility and provide a number of criteria you can use to check your work.
-
-# Upcoming Lessons #
-
-Add a Text Alternative to Images for Visually Impaired Accessibility
-
-Know When Alt Text Should be Left Blank
-
-Use Headings to Show Hierarchical Relationships of Content
-
-Jump Straight to the Content Using the main Element
-
-Wrap Content in the article Element
-
-Make Screen Reader Navigation Easier with the header Landmark
-
-Make Screen Reader Navigation Easier with the nav Landmark
-
-Make Screen Reader Navigation Easier with the footer Landmark
-
-Improve Accessibility of Audio Content with the audio Element
-
-Improve Chart Accessibility with the figure Element
-
-Improve Form Field Accessibility with the label Element
-
-Wrap Radio Buttons in a fieldset Element for Better Accessibility
-
-Add an Accessible Date Picker
-
-Standardize Times with the HTML5 datetime Attribute
-
-Make Elements Only Visible to a Screen Reader by Using Custom CSS
-
-Improve Readability with High Contrast Text
-
-Avoid Colorblindness Issues by Using Sufficient Contrast
-
-Avoid Colorblindness Issues by Carefully Choosing Colors that Convey Information
-
-Give Links Meaning by Using Descriptive Link Text
-
-Make Links Navigatable with HTML Access Keys
-
-Use tabindex to Add Keyboard Focus to an Element
-
-Use tabindex to Specify the Order of Keyboard Focus for Several Elements
\ No newline at end of file
diff --git a/01-responsive-web-design/applied-visual-design.md b/01-responsive-web-design/applied-visual-design.md
index 305d863..dce164c 100644
--- a/01-responsive-web-design/applied-visual-design.md
+++ b/01-responsive-web-design/applied-visual-design.md
@@ -6,108 +6,3 @@ At a basic level, most web content provides a user with information. The visual
This section covers some of the basic tools developers use to create their own visual designs.
-# Upcoming Lessons #
-
-Create Visual Balance Using the text-align Property
-
-Adjust the Width of an Element Using the width Property
-
-Adjust the Height of an Element Using the height Property
-
-Use the strong Tag to Make Text Bold
-
-Use the u Tag to Underline Text
-
-Use the em Tag to Italicize Text
-
-Use the del Tag to Strikethrough Text
-
-Create a Horizontal Line Using the hr Element
-
-Adjust the background-color Property of Text
-
-Adjust the Size of a Header Versus a Paragraph Tag
-
-Add a box-shadow to a Card-like Element
-
-Decrease the Opacity of an Element
-
-Use the text-transform Property to Make Text Uppercase
-
-Set the font-size for Multiple Heading Elements
-
-Set the font-weight for Multiple Heading Elements
-
-Set the font-size of Paragraph Text
-
-Set the line-height of Paragraphs
-
-Adjust the Hover State of an Anchor Tag
-
-Change an Element's Relative Position
-
-Move a Relatively Positioned Element with CSS Offsets
-
-Lock an Element to its Parent with Absolute Positioning
-
-Lock an Element to the Browser Window with Fixed Positioning
-
-Push Elements Left or Right with the float Property
-
-Change the Position of Overlapping Elements with the z-index Property
-
-Center an Element Horizontally Using the margin Property
-
-Learn about Complementary Colors
-
-Learn about Tertiary Colors
-
-Adjust the Color of Various Elements to Complementary Colors
-
-Adjust the Hue of a Color
-
-Adjust the Tone of a Color
-
-Create a Gradual CSS Linear Gradient
-
-Use a CSS Linear Gradient to Create a Striped Element
-
-Create Texture by Adding a Subtle Pattern as a Background Image
-
-Use the CSS Transform scale Property to Change the Size of an Element
-
-Use the CSS Transform scale Property to Scale an Element on Hover
-
-Use the CSS Transform Property skewX to Skew an Element Along the X-Axis
-
-Use the CSS Transform Property skewY to Skew an Element Along the Y-Axis
-
-Create a Graphic Using CSS
-
-Create a More Complex Shape Using CSS and HTML
-
-Learn How the CSS @keyframes and animation Properties Work
-
-Use CSS Animation to Change the Hover State of a Button
-
-Modify Fill Mode of an Animation
-
-Create Movement Using CSS Animation
-
-Create Visual Direction by Fading an Element from Left to Right
-
-Animate Elements Continually Using an Infinite Animation Count
-
-Make a CSS Heartbeat using an Infinite Animation Count
-
-Animate Elements at Variable Rates
-
-Animate Multiple Elements at Variable Rates
-
-Change Animation Timing with Keywords
-
-Learn How Bezier Curves Work
-
-Use a Bezier Curve to Move a Graphic
-
-Make Motion More Natural Using a Bezier Curve
\ No newline at end of file
diff --git a/01-responsive-web-design/basic-css.json b/01-responsive-web-design/basic-css.json
index ee7034d..e949b39 100644
--- a/01-responsive-web-design/basic-css.json
+++ b/01-responsive-web-design/basic-css.json
@@ -8,24 +8,24 @@
"id": "bad87fee1348bd9aedf08803",
"title": "Change the Color of Text",
"description": [
- "Now let's change the color of some of our text.",
- "We can do this by changing the style
of your h2
element.",
- "The property that is responsible for the color of an element's text is the color
style property.",
- "Here's how you would set your h2
element's text color to blue:",
+ "现在来让我们修改一下文本的颜色。",
+ "我们通过修改h2
元素里面的 style
。",
+ "color
属性可以控制文本元素颜色。",
+ "以下是改变h2
元素为蓝色的方法:",
"<h2 style=\"color: blue;\">CatPhotoApp</h2>
",
- "Note that it is a good practice to end inline style
declarations with a ;
.",
+ "请注意行内style
最好以;
来结束。",
"
h2
element's style so that its text color is red."
+ "请把h2
元素的文本颜色设置为红色。"
],
"tests": [
{
- "text": "Your h2
element should be red.",
- "testString": "assert($(\"h2\").css(\"color\") === \"rgb(255, 0, 0)\", 'Your h2
element should be red.');"
+ "text": "你的h2
元素应该为红色。",
+ "testString": "assert($(\"h2\").css(\"color\") === \"rgb(255, 0, 0)\", '你的h2
元素应该为红色。');"
},
{
- "text": "Your style
declaration should end with a ;
.",
- "testString": "assert(code.match(/style
declaration should end with a ;
.');"
- }
+ "text": "h2
元素的style
属性的值应该以;
结束。",
+ "testString": "assert(code.match(/h2
元素 style
属性的值应该以 ;
结束。');"
+
],
"challengeType": 0,
"files": {
@@ -75,37 +75,33 @@
"id": "bad87fee1348bd9aedf08805",
"title": "Use CSS Selectors to Style Elements",
"description": [
- "With CSS, there are hundreds of CSS properties
that you can use to change the way an element looks on your page.",
- "When you entered <h2 style=\"color: red\">CatPhotoApp</h2>
, you were styling that individual h2
element with inline CSS
, which stands for Cascading Style Sheets
.",
- "That's one way to specify the style of an element, but there's a better way to apply CSS
.",
- "At the top of your code, create a style
block like this:",
+ "在CSS中,有上百种属性
可以让你改变页面样式。",
+ "通过输入 <h2 style=\"color: red\">CatPhotoApp</h2>
的行内样式
,修改单一的h2
元素的颜色的方式,配置 层叠样式表(CSS)
的方式之一。",
+ "这是改变元素样式的一个特别方法,不过存在着更好的方法来设置层叠样式表(CSS
。",
+ "在代码的顶部,创建一个 style
声明区域,如下方所示:",
"<style>", - "Inside that style block, you can create a
</style>
CSS selector
for all h2
elements. For example, if you wanted all h2
elements to be red, you would add a style rule that looks like this:",
+ "在style样式声明区域内,可以创建一个CSS 选择器
的规则来应用于所有的h2
元素。例如,如果你想所有h2
元素变成红色,可以添加下方的样式规则:",
"<style>", - "Note that it's important to have both opening and closing curly braces (
h2 {color: red;}
</style>
{
and }
) around each element's style rule(s). You also need to make sure that your element's style definition is between the opening and closing style tags. Finally, be sure to add a semicolon to the end of each of your element's style rules.",
+ "注意,在每个元素的样式声明区域里,左右花括号({
和 }
)一定要写全。你需要确定你定义的样式规则位于花括号之间。以及,记得在每个元素样式规则的末尾添加分号。",
"h2
element's style attribute, and instead create a CSS style
block. Add the necessary CSS to turn all h2
elements blue."
+ "删除h2
元素的行内样式,创建style
样式声明区域。添加CSS样式规则使h2
元素变为蓝色。"
],
"tests": [
{
- "text": "Remove the style attribute from your h2
element.",
- "testString": "assert(!$(\"h2\").attr(\"style\"), 'Remove the style attribute from your h2
element.');"
- },
- {
- "text": "Create a style
element.",
- "testString": "assert($(\"style\") && $(\"style\").length > 1, 'Create a style
element.');"
+ "text": "移除h2
元素的行内样式。",
+ "testString": "assert(!$(\"h2\").attr(\"style\"), '移除h2
元素的行内样式。');"
},
{
- "text": "Your h2
element should be blue.",
- "testString": "assert($(\"h2\").css(\"color\") === \"rgb(0, 0, 255)\", 'Your h2
element should be blue.');"
+ "text": "创建一个style
样式声明区域。",
+ "testString": "assert($(\"style\") && $(\"style\").length > 1, '创建一个style
样式声明区域。');"
},
{
- "text": "Ensure that your stylesheet h2
declaration is valid with a semicolon and closing brace.",
- "testString": "assert(code.match(/h2\\s*\\{\\s*color\\s*:.*;\\s*\\}/g), 'Ensure that your stylesheet h2
declaration is valid with a semicolon and closing brace.');"
+ "text": "h2
元素颜色应为蓝色。",
+ "testString": "assert($(\"h2\").css(\"color\") === \"rgb(0, 0, 255)\", 'h2
元素颜色应为蓝色。');"
},
{
- "text": "Make sure all your style
elements are valid and have a closing tag.",
- "testString": "assert(code.match(/<\\/style>/g) && code.match(/<\\/style>/g).length === (code.match(/",
+ " ",
+ "grid-template-columns
属性可以添加一些列,示例如下:",
+ ".container {", + "上面的代码可以在网格容器中添加两列,宽度均为 50px。", + "
display: grid;
grid-template-columns: 50px 50px;
}
grid-template-columns
属性值的个数表示网格的列数,而每个值表示对应列的宽度。",
+ "100px
。"
+ ],
+ "tests": [
+ {
+ "text": "container
类应该有grid-template-columns
属性且有三个100px
作为值。",
+ "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*grid-template-columns\\s*?:\\s*?100px\\s*?100px\\s*?100px\\s*?;[\\s\\S]*}/gi), 'container
类应该有grid-template-columns
属性且有三个100px
作为值。');"
+ }
+ ],
+ "solutions": [],
+ "hints": [],
+ "releasedOn": "Feb 15, 2018",
+ "challengeType": 0,
+ "files": {
+ "indexhtml": {
+ "key": "indexhtml",
+ "ext": "html",
+ "name": "index",
+ "contents": [
+ "",
+ " ",
+ "grid-template-columns
property on a grid container as demonstrated below:",
- ".container {", - "This will give your grid two columns that are 50px wide each.", - "The number of parameters given to the
display: grid;
grid-template-columns: 50px 50px;
}
grid-template-columns
property indicates the number of columns in the grid, and the value of each parameter indicates the width of each column.",
- "100px
wide each."
- ],
- "tests": [
- {
- "text": "container
class should have a grid-template-columns
property with three units of 100px
.",
- "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*grid-template-columns\\s*?:\\s*?100px\\s*?100px\\s*?100px\\s*?;[\\s\\S]*}/gi), 'container
class should have a grid-template-columns
property with three units of 100px
.');"
- }
- ],
- "solutions": [],
- "hints": [],
- "releasedOn": "Feb 15, 2018",
- "challengeType": 0,
- "files": {
- "indexhtml": {
- "key": "indexhtml",
- "ext": "html",
- "name": "index",
- "contents": [
- "",
- " ",
- "grid-template-rows
property in the same way you used grid-template-columns
in previous challenge.",
- "50px
tall each."
- ],
- "tests": [
- {
- "text": "container
class should have a grid-template-rows
property with two units of 50px
.",
- "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*grid-template-rows\\s*?:\\s*?50px\\s*?50px\\s*?;[\\s\\S]*}/gi), 'container
class should have a grid-template-rows
property with two units of 50px
.');"
- }
- ],
- "solutions": [],
- "hints": [],
- "releasedOn": "",
- "challengeType": 0,
- "files": {
- "indexhtml": {
- "key": "indexhtml",
- "ext": "html",
- "name": "index",
- "contents": [
- "",
- " ",
- "px
and em
in CSS Grid to define the size of rows and columns. You can use these as well:",
- "fr
: sets the column or row to a fraction of the available space,",
- "auto
: sets the column or row to the width or height of its content automatically,",
- "%
: adjusts the column or row to the percent width of its container.",
- "Here's the code that generates the output in the preview:",
- "grid-template-columns: auto 50px 10% 2fr 1fr;", - "This snippet creates five columns. The first column is as wide as its content, the second column is 50px, the third column is 10% of its container, and for the last two columns; the remaining space is divided into three sections, two are allocated for the fourth column, and one for the fifth.", - "
container
class should have a grid-template-columns
property that has three columns with the following widths: 1fr, 100px, and 2fr
.",
- "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*grid-template-columns\\s*?:\\s*?1fr\\s*?100px\\s*?2fr\\s*?;[\\s\\S]*}/gi), 'container
class should have a grid-template-columns
property that has three columns with the following widths: 1fr, 100px, and 2fr
.');"
- }
- ],
- "solutions": [],
- "hints": [],
- "releasedOn": "",
- "challengeType": 0,
- "files": {
- "indexhtml": {
- "key": "indexhtml",
- "ext": "html",
- "name": "index",
- "contents": [
- "",
- " ",
- "grid-column-gap
property like this:",
- "grid-column-gap: 10px;", - "This creates 10px of empty space between all of our columns.", - "
20px
gap."
- ],
- "tests": [
- {
- "text": "container
class should have a grid-column-gap
property that has the value of 20px
.",
- "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*grid-column-gap\\s*?:\\s*?20px\\s*?;[\\s\\S]*}/gi), 'container
class should have a grid-column-gap
property that has the value of 20px
.');"
- }
- ],
- "solutions": [],
- "hints": [],
- "releasedOn": "",
- "challengeType": 0,
- "files": {
- "indexhtml": {
- "key": "indexhtml",
- "ext": "html",
- "name": "index",
- "contents": [
- "",
- " ",
- "grid-template-columns
设置网格的列一样,用grid-template-rows
为网格设置行数。",
+ "50px
。"
+ ],
+ "tests": [
+ {
+ "text": "container
类应该有grid-template-rows
属性,且值为两个50px
。",
+ "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*grid-template-rows\\s*?:\\s*?50px\\s*?50px\\s*?;[\\s\\S]*}/gi), 'container
类应该有grid-template-rows
属性,且值为两个50px
。');"
+ }
+ ],
+ "solutions": [],
+ "hints": [],
+ "releasedOn": "",
+ "challengeType": 0,
+ "files": {
+ "indexhtml": {
+ "key": "indexhtml",
+ "ext": "html",
+ "name": "index",
+ "contents": [
+ "",
+ " ",
+ "grid-row-gap
in the same way that you added a gap in between columns in the previous challenge.",
- "5px
tall."
- ],
- "tests": [
- {
- "text": "container
class should have a grid-row-gap
property that has the value of 5px
.",
- "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*grid-row-gap\\s*?:\\s*?5px\\s*?;[\\s\\S]*}/gi), 'container
class should have a grid-row-gap
property that has the value of 5px
.');"
+ },
+ {
+ "id": "5a9036ee38fddaf9a66b5d34",
+ "title": "Use CSS Grid units to Change the Size of Columns and Rows",
+ "description": [
+ "在 CSS 网格中,可以使用绝对定位和相对定位单位如px
和em
来确定行或列的大小。下面的单位也可以使用:",
+ "fr
:设置列或行占剩余空间的一个比例,",
+ "auto
:设置列宽或行高自动等于它的内容的宽度或高度,",
+ "%
:将列或行调整为它的容器宽度或高度的百分比,",
+ "最右侧的预览区中的效果通过下面的代码实现:",
+ "grid-template-columns: auto 50px 10% 2fr 1fr;", + "这段代添加了五个列。第一列的宽与它的内容宽度相等;第二列宽 50px;第三列宽是它容器的 10%;最后两列,将剩余的宽度平均分成三份,第四列占两份,第五列占一份。", + "
container
类应该有grid-template-columns
属性,且生成宽为1fr, 100px
和2fr
的三列。",
+ "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*grid-template-columns\\s*?:\\s*?1fr\\s*?100px\\s*?2fr\\s*?;[\\s\\S]*}/gi), 'container
类应该有grid-template-columns
属性,且生成宽为1fr, 100px
和2fr
的三列。');"
+ }
+ ],
+ "solutions": [],
+ "hints": [],
+ "releasedOn": "",
+ "challengeType": 0,
+ "files": {
+ "indexhtml": {
+ "key": "indexhtml",
+ "ext": "html",
+ "name": "index",
+ "contents": [
+ "",
+ " ",
+ "grid-column-gap
:",
+ "grid-column-gap: 10px;", + "这会在我们创建的所有列之间添加 10px 的空白间隙。", + "
20px
的间隙。"
+ ],
+ "tests": [
+ {
+ "text": "container
类应该有grid-column-gap
属性且值为20px
。",
+ "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*grid-column-gap\\s*?:\\s*?20px\\s*?;[\\s\\S]*}/gi), 'container
类应该有grid-column-gap
属性且值为20px
。');"
+ }
+ ],
+ "solutions": [],
+ "hints": [],
+ "releasedOn": "",
+ "challengeType": 0,
+ "files": {
+ "indexhtml": {
+ "key": "indexhtml",
+ "ext": "html",
+ "name": "index",
+ "contents": [
+ "",
+ " ",
+ "grid-gap
is a shorthand property for grid-row-gap
and grid-column-gap
from the previous two challenges that's more convenient to use. If grid-gap
has one value, it will create a gap between all rows and columns. However, if there are two values, it will use the first one to set the gap between the rows and the second value for the columns.",
- "grid-gap
to introduce a 10px
gap between the rows and 20px
gap between the columns."
- ],
- "tests": [
- {
- "text": "container
class should have a grid-gap
property that introduces 10px
gap between the rows and 20px
gap between the columns.",
- "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*grid-gap\\s*?:\\s*?10px\\s*?20px\\s*?;[\\s\\S]*}/gi), 'container
class should have a grid-gap
property that introduces 10px
gap between the rows and 20px
gap between the columns.');"
+ },
+ {
+ "id": "5a9036ee38fddaf9a66b5d36",
+ "title": "Create a Row Gap using grid-row-gap",
+ "description": [
+ "和上个挑战在两列之间添加间隙一样,你可以用grid-row-gap
在两行之间添加间隙。",
+ "5px
的间隙。"
+ ],
+ "tests": [
+ {
+ "text": "container
类应该有grid-row-gap
属性且值为5px
。",
+ "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*grid-row-gap\\s*?:\\s*?5px\\s*?;[\\s\\S]*}/gi), 'container
类应该有grid-row-gap
属性且值为5px
。');"
+ }
+ ],
+ "solutions": [],
+ "hints": [],
+ "releasedOn": "",
+ "challengeType": 0,
+ "files": {
+ "indexhtml": {
+ "key": "indexhtml",
+ "ext": "html",
+ "name": "index",
+ "contents": [
+ "",
+ " ",
+ "grid-gap
是grid-row-gap
和grid-column-gap
的简写,它更方便使用。如果grid-gap
有一个值,行与行之间和列与列之间将添加等于该值的间隙。但是,如果有两个值,第一个值将作为行间隙的高度值,第二个值是列间隙的宽度值。",
+ "grid-gap
在行之间添加10px
的间隙,在列之间添加20px
的间隙。"
+ ],
+ "tests": [
+ {
+ "text": "container
类应该有grid-gap
属性,在行之间引入10px
的间隙,在列之间引入20px
的间隙。",
+ "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*grid-gap\\s*?:\\s*?10px\\s*?20px\\s*?;[\\s\\S]*}/gi), 'container
类应该有grid-gap
属性,在行之间引入10px
的间隙,在列之间引入20px
的间隙。');"
+ }
+ ],
+ "solutions": [],
+ "hints": [],
+ "releasedOn": "",
+ "challengeType": 0,
+ "files": {
+ "indexhtml": {
+ "key": "indexhtml",
+ "ext": "html",
+ "name": "index",
+ "contents": [
+ "",
+ "grid-column
property is the first one for use on the grid items themselves.",
- "The hypothetical horizontal and vertical lines that create the grid are referred to as lines. These lines are numbered starting with 1 at the top left corner of the grid and move right for columns and down for rows, counting upward.",
- "This is what the lines look like for a 3x3 grid:",
- "column lines
1
2
3
4
row lines
1
2
3
4
grid-column
property in conjunction with the line numbers you want the item to start and stop at.",
- "Here's an example:",
- "grid-column: 1 / 3;", - "This will make the item start at the first vertical line of the grid on the left and span to the 3rd line of the grid, consuming two columns.", - "
item5
consume the last two columns of the grid."
- ],
- "tests": [
- {
- "text": "item5
class should have a grid-column
property that has the value of 2 / 4
.",
- "testString": "assert(code.match(/.item5\\s*?{[\\s\\S]*grid-column\\s*?:\\s*?2\\s*?\\/\\s*?4\\s*?;[\\s\\S]*}/gi), 'item5
class should have a grid-column
property that has the value of 2 / 4
.');"
+ },
+ {
+ "id": "5a90372638fddaf9a66b5d38",
+ "title": "Use grid-column to Control Spacing",
+ "description": [
+ "到目前为止,所有的讨论都是围绕网格容器的。grid-column
属性是第一个用于网格项本身的属性。",
+ "网格的假想水平线和垂直线被称为线(lines)。这些线在网格的左上角从 1 开始编号,垂直线向右、水平线向下累加计数。",
+ "这是一个 3x3 网格的线条:",
+ "column lines
1
2
3
4
row lines
1
2
3
4
grid-column
属性定义网格项开始和结束的位置,进而控制每个网格项占用的列数。",
+ "示例如下:",
+ "grid-column: 1 / 3;", + "这会让网格项从左侧第一条线开始到第三条线结束,占用两列。", + "
item5
的网格项占用网格的最后两列。"
+ ],
+ "tests": [
+ {
+ "text": "item5
类应该有grid-column
属性且其值为2 / 4
。",
+ "testString": "assert(code.match(/.item5\\s*?{[\\s\\S]*grid-column\\s*?:\\s*?2\\s*?\\/\\s*?4\\s*?;[\\s\\S]*}/gi), 'item5
类应该有grid-column
属性且其值为2 / 4
。');"
+ }
+ ],
+ "solutions": [],
+ "hints": [],
+ "releasedOn": "",
+ "challengeType": 0,
+ "files": {
+ "indexhtml": {
+ "key": "indexhtml",
+ "ext": "html",
+ "name": "index",
+ "contents": [
+ "",
+ " ",
+ "grid-row
属性来确定开始和结束的水平线。",
+ "item5
的元素占用最后两行。"
+ ],
+ "tests": [
+ {
+ "text": "item5
类应该有grid-row
属性且值为2 / 4
。",
+ "testString": "assert(code.match(/.item5\\s*?{[\\s\\S]*grid-row\\s*?:\\s*?2\\s*?\\/\\s*?4\\s*?;[\\s\\S]*}/gi), 'item5
类应该有grid-row
属性且值为2 / 4
。');"
+ }
+ ],
+ "solutions": [],
+ "hints": [],
+ "releasedOn": "",
+ "challengeType": 0,
+ "files": {
+ "indexhtml": {
+ "key": "indexhtml",
+ "ext": "html",
+ "name": "index",
+ "contents": [
+ "",
+ " ",
+ "grid-row
property on a grid item.",
- "item5
class consume the last two rows."
- ],
- "tests": [
- {
- "text": "item5
class should have a grid-row
property that has the value of 2 / 4
.",
- "testString": "assert(code.match(/.item5\\s*?{[\\s\\S]*grid-row\\s*?:\\s*?2\\s*?\\/\\s*?4\\s*?;[\\s\\S]*}/gi), 'item5
class should have a grid-row
property that has the value of 2 / 4
.');"
+ },
+ {
+ "id": "5a90374338fddaf9a66b5d3a",
+ "title": "Align an Item Horizontally using justify-self",
+ "description": [
+ "在 CSS 网格中,每个网格项的内容分别位于被称为单元格(cell)的框内。你可以使用网格项的justify-self
属性,设置其内容的位置在单元格内沿行轴对齐的方式。默认情况下,这个属性的值是stretch
,这将使内容占满整个单元格的宽度。该 CSS 网格属性也可以使用其他的值:",
+ "start
:使内容在单元格左侧对齐,",
+ "center
:使内容在单元格居中对齐,",
+ "end
:使内容在单元格右侧对齐,",
+ "justify-self
属性让类为item2
的网格项居中。"
+ ],
+ "tests": [
+ {
+ "text": "item2
类应该有justify-self
属性且值为center
。",
+ "testString": "assert(code.match(/.item2\\s*?{[\\s\\S]*justify-self\\s*?:\\s*?center\\s*?;[\\s\\S]*}/gi), 'item2
类应该有justify-self
属性且值为center
。');"
+ }
+ ],
+ "solutions": [],
+ "hints": [],
+ "releasedOn": "",
+ "challengeType": 0,
+ "files": {
+ "indexhtml": {
+ "key": "indexhtml",
+ "ext": "html",
+ "name": "index",
+ "contents": [
+ "",
+ " ",
+ "align-self
属性。对于该属性,你能使用在上一个挑战中可用于justify-self
属性的任一个值。",
+ "end
使类为item3
的网格项底端对齐。"
+ ],
+ "tests": [
+ {
+ "text": "item3
类应该有align-self
属性且值为end
。",
+ "testString": "assert(code.match(/.item3\\s*?{[\\s\\S]*align-self\\s*?:\\s*?end\\s*?;[\\s\\S]*}/gi), 'item3
类应该有align-self
属性且值为end
。');"
+ }
+ ],
+ "solutions": [],
+ "hints": [],
+ "releasedOn": "",
+ "challengeType": 0,
+ "files": {
+ "indexhtml": {
+ "key": "indexhtml",
+ "ext": "html",
+ "name": "index",
+ "contents": [
+ "",
+ " ",
+ "justify-self
property on a grid item. By default, this property has a value of stretch
, which will make the content fill the whole width of the cell. This CSS Grid property accepts other values as well:",
- "start
: aligns the content at the left of the cell,",
- "center
: aligns the content in the center of the cell,",
- "end
: aligns the content at the right of the cell.",
- "justify-self
property to center the item with the class item2
."
- ],
- "tests": [
- {
- "text": "item2
class should have a justify-self
property that has the value of center
.",
- "testString": "assert(code.match(/.item2\\s*?{[\\s\\S]*justify-self\\s*?:\\s*?center\\s*?;[\\s\\S]*}/gi), 'item2
class should have a justify-self
property that has the value of center
.');"
+ },
+ {
+ "id": "5a90376038fddaf9a66b5d3c",
+ "title": "Align All Items Horizontally using justify-items",
+ "description": [
+ "有时你想让在 CSS 网格中的网格项共享对齐方式。你可以像之前学习的那样单独使他们对齐,也可以对网格容器使用justify-items
使它们一次性沿行轴对齐。对于这个属性你能使用在之前的两个挑战中学到的所有值,与之前不同的是,它将使网格中所有的网格项按所设置的方式对齐。",
+ "container
类应该有justify-items
属性且值为center
。",
+ "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*justify-items\\s*?:\\s*?center\\s*?;[\\s\\S]*}/gi), 'container
类应该有justify-items
属性且值为center
。');"
+ }
+ ],
+ "solutions": [],
+ "hints": [],
+ "releasedOn": "",
+ "challengeType": 0,
+ "files": {
+ "indexhtml": {
+ "key": "indexhtml",
+ "ext": "html",
+ "name": "index",
+ "contents": [
+ "",
+ " ",
+ "align-items
属性可以给网格中所有的网格项设置沿列轴对齐的方式。",
+ "container
类应该有align-items
属性且值为end
。",
+ "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*align-items\\s*?:\\s*?end\\s*?;[\\s\\S]*}/gi), 'container
类应该有align-items
属性且值为end
。');"
+ }
+ ],
+ "solutions": [],
+ "hints": [],
+ "releasedOn": "",
+ "challengeType": 0,
+ "files": {
+ "indexhtml": {
+ "key": "indexhtml",
+ "ext": "html",
+ "name": "index",
+ "contents": [
+ "",
+ " ",
+ "align-self
property on an item. This property accepts all of the same values as justify-self
from the last challenge.",
- "item3
vertically at the end
."
- ],
- "tests": [
- {
- "text": "item3
class should have a align-self
property that has the value of end
.",
- "testString": "assert(code.match(/.item3\\s*?{[\\s\\S]*align-self\\s*?:\\s*?end\\s*?;[\\s\\S]*}/gi), 'item3
class should have a align-self
property that has the value of end
.');"
+ },
+ {
+ "id": "5a94fe0569fb03452672e45c",
+ "title": "Divide the Grid Into an Area Template",
+ "description": [
+ "你可以将网格中的一些网格单元格组合成一个区域(area),并为该区域指定一个自定义名称。你可以通过给容器加上grid-template-areas
来实现:",
+ "grid-template-areas:", + "上面的代码将顶部三个单元格合并成一个名为
\"header header header\"
\"advert content content\"
\"footer footer footer\";
header
的区域,将底部三个单元格合并为一个名为footer
的区域,并在中间行生成两个区域————advert
和content
。",
+ "注意:.
)来表示一个空单元格",
+ "advert
的区域变成空单元格。"
+ ],
+ "tests": [
+ {
+ "text": "container
类应该有类似于最右侧预览区的grid-template-areas
属性且用.
代替advert
。",
+ "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*grid-template-areas\\s*?:\\s*?\"\\s*?header\\s*?header\\s*?header\\s*?\"\\s*?\"\\s*?.\\s*?content\\s*?content\\s*?\"\\s*?\"\\s*?footer\\s*?footer\\s*?footer\\s*?\"\\s*?;[\\s\\S]*}/gi), 'container
类应该有类似于最右侧预览区的grid-template-areas
属性且用.
代替advert
。');"
+ }
+ ],
+ "solutions": [],
+ "hints": [],
+ "releasedOn": "",
+ "challengeType": 0,
+ "files": {
+ "indexhtml": {
+ "key": "indexhtml",
+ "ext": "html",
+ "name": "index",
+ "contents": [
+ "",
+ " ",
+ "grid-area
:",
+ ".item1 { grid-area: header; }", + "这样,类名为
item1
的网格项就被放到了header
区域里。这种情况下,网格项将使用整个顶行,因为这一行被名为 header 区域。",
+ "grid-area
属性,把类为item5
元素放到footer
区域。"
+ ],
+ "tests": [
+ {
+ "text": "item5
类应该有grid-area
属性且值为footer
。",
+ "testString": "assert(code.match(/.item5\\s*?{[\\s\\S]*grid-area\\s*?:\\s*?footer\\s*?;[\\s\\S]*}/gi), 'item5
类应该有grid-area
属性且值为footer
。');"
+ }
+ ],
+ "solutions": [],
+ "hints": [],
+ "releasedOn": "",
+ "challengeType": 0,
+ "files": {
+ "indexhtml": {
+ "key": "indexhtml",
+ "ext": "html",
+ "name": "index",
+ "contents": [
+ "",
+ " ",
+ "justify-items
on your grid container. This property can accept all the same values you learned about in the previous two challenges, the difference being that it will move all the items in our grid to the desired alignment.",
- "container
class should have a justify-items
property that has the value of center
.",
- "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*justify-items\\s*?:\\s*?center\\s*?;[\\s\\S]*}/gi), 'container
class should have a justify-items
property that has the value of center
.');"
+ },
+ {
+ "id": "5a94fe2669fb03452672e45e",
+ "title": "Use grid-area Without Creating an Areas Template",
+ "description": [
+ "你在上一次挑战中学到的grid-area
属性有另一种使用方式。如果网格中没有定义区域模板,你也可以像这样为它添加一个模板:",
+ "item1 { grid-area: 1/1/2/4; }", + "这里使用了你之前学习的线号来定义网格项的区域。上例中数字代表这些值:", + "
grid-area: 起始水平线 / 起始垂直线 / 末尾水平线 / 终止垂直线 ;", + "因此,示例中的网格项将占用第 1 条和第 2 条水平线之间的行及第 1 条和第 4 条垂直线之间的列。", + "
grid-area
属性将类为item5
的元素放置在第 3 条和第 4 条水平线及第 1 条和第 4 条垂直线之间的区域内。"
+ ],
+ "tests": [
+ {
+ "text": "item5
类应该有grid-area
属性且值为3/1/4/4
。",
+ "testString": "assert(code.match(/.item5\\s*?{[\\s\\S]*grid-area\\s*?:\\s*?3\\s*?\\/\\s*?1\\s*?\\/\\s*?4\\s*?\\/\\s*?4\\s*?;[\\s\\S]*}/gi), 'item5
类应该有grid-area
属性且值为3/1/4/4
。');"
+ }
+ ],
+ "solutions": [],
+ "hints": [],
+ "releasedOn": "",
+ "challengeType": 0,
+ "files": {
+ "indexhtml": {
+ "key": "indexhtml",
+ "ext": "html",
+ "name": "index",
+ "contents": [
+ "",
+ " ",
+ "grid-template-columns
和grid-template-rows
定义网格结构时,你需要为添加的每一行和每一列都输入一个值。",
+ "如果要添加带 100 行高度相同的网格,单独放入 100 个值不太实际。幸运的是,有一种更好的方法——使用repeat
方法指定行或列的重复次数,后面加上逗号以及需要重复的值。",
+ "这里有一个添加 100 行网格的例子,使每行高度均为 50px:",
+ "grid-template-rows: repeat(100, 50px);", + "你还可以用 repeat 方法重复多个值,并在定义网格结构时与其他值一起使用。举个例子:", + "
grid-template-columns: repeat(2, 1fr 50px) 20px;", + "效果相当于:", + "
grid-template-columns: 1fr 50px 1fr 50px 20px;", + "注意:
1fr 50px
重复了两次,后面跟着 20px。",
+ "repeat
代替grid-template-columns
属性的值中的重复代码。"
+ ],
+ "tests": [
+ {
+ "text": "container
类应该有grid-template-columns
属性且设置重复 3 列,宽为1fr
。",
+ "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*grid-template-columns\\s*?:\\s*?repeat\\s*?\\(\\s*?3\\s*?,\\s*?1fr\\s*?\\)\\s*?;[\\s\\S]*}/gi), 'container
类应该有grid-template-columns
属性且设置重复 3 列,宽为1fr
。');"
+ }
+ ],
+ "solutions": [],
+ "hints": [],
+ "releasedOn": "",
+ "challengeType": 0,
+ "files": {
+ "indexhtml": {
+ "key": "indexhtml",
+ "ext": "html",
+ "name": "index",
+ "contents": [
+ "",
+ " ",
+ "align-items
property on a grid container will set the vertical alignment for all the items in our grid.",
- "container
class should have a align-items
property that has the value of end
.",
- "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*align-items\\s*?:\\s*?end\\s*?;[\\s\\S]*}/gi), 'container
class should have a align-items
property that has the value of end
.');"
+ },
+ {
+ "id": "5a94fe4469fb03452672e460",
+ "title": "Limit Item Size Using the minmax Function",
+ "description": [
+ "此外,内置函数minmax
也可以可用于设置grid-template-columns
和grid-template-rows
的值。它的作用是在网格容器改变大小时限制网格项的大小。为此,你需要指定网格项允许的尺寸范围。例如:",
+ "grid-template-columns: 100px minmax(50px, 200px);", + "在上面的代码中,
grid-template-columns
被设置为添加两列,第一列 100px 宽,第二列宽度最小值是 50px,最大值是 200px。",
+ "minmax
函数替换repeat
函数中的1fr
,限定其最小值为90px
,最大值为1fr
,你可以调整最右侧的预览面板查看效果。"
+ ],
+ "tests": [
+ {
+ "text": "container
类应该有grid-template-columns
属性且设置重复 3 列,每列宽度最小值为90px
,最大值为1fr
。",
+ "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*grid-template-columns\\s*?:\\s*?repeat\\s*?\\(\\s*?3\\s*?,\\s*?minmax\\s*?\\(\\s*?90px\\s*?,\\s*?1fr\\s*?\\)\\s*?\\)\\s*?;[\\s\\S]*}/gi), 'container
类应该有grid-template-columns
属性且设置重复 3 列,每列宽度最小值90px
,最大值1fr
。');"
+ }
+ ],
+ "solutions": [],
+ "hints": [],
+ "releasedOn": "",
+ "challengeType": 0,
+ "files": {
+ "indexhtml": {
+ "key": "indexhtml",
+ "ext": "html",
+ "name": "index",
+ "contents": [
+ "",
+ " ",
+ "auto-fill
和minmax
来更灵活地布局。",
+ "在最右侧的预览区中,grid-template-columns
被设置为:",
+ "repeat(auto-fill, minmax(60px, 1fr));", + "上面的代码效果:列的宽度会随容器大小改变,在可以插入一个 60px 宽的列之前,当前行的所有列会一直拉伸。(译者注:动手试试你将更明白。)", + "注意:
auto-fill
和repeat
来填充网格,其中列宽的最小值为60px
,最大值为1fr
。你可以调整最右侧的预览区大小,查看自动填充效果。"
+ ],
+ "tests": [
+ {
+ "text": "container
类应该有grid-template-columns
属性且使用repeat
和auto-fill
,以便将最小宽度为60px
,最大宽度为1fr
的列填充至网格。",
+ "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*grid-template-columns\\s*?:\\s*?repeat\\s*?\\(\\s*?auto-fill\\s*?,\\s*?minmax\\s*?\\(\\s*?60px\\s*?,\\s*?1fr\\s*?\\)\\s*?\\)\\s*?;[\\s\\S]*}/gi), 'container
类应该有grid-template-columns
属性且使用repeat
和auto-fill
,以便将最小宽度为60px
,最大宽度为1fr
的列填充至网格。');"
+ }
+ ],
+ "solutions": [],
+ "hints": [],
+ "releasedOn": "",
+ "challengeType": 0,
+ "files": {
+ "indexhtml": {
+ "key": "indexhtml",
+ "ext": "html",
+ "name": "index",
+ "contents": [
+ "",
+ "grid-template-areas
on the container like this:",
- "grid-template-areas:", - "The code above merges the top three cells together into an area named
\"header header header\"
\"advert content content\"
\"footer footer footer\";
header
, the bottom three cells into a footer
area, and it makes two areas in the middle row; advert
and content
.",
- "Note.
) to designate an empty cell in the grid.",
- "advert
becomes an empty cell."
- ],
- "tests": [
- {
- "text": "container
class should have a grid-template-areas
property similar to the preview but has .
instead of the advert
area.",
- "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*grid-template-areas\\s*?:\\s*?\"\\s*?header\\s*?header\\s*?header\\s*?\"\\s*?\"\\s*?.\\s*?content\\s*?content\\s*?\"\\s*?\"\\s*?footer\\s*?footer\\s*?footer\\s*?\"\\s*?;[\\s\\S]*}/gi), 'container
class should have a grid-template-areas
propertiy similar to the preview but has .
instead of the advert
area.');"
+ },
+ {
+ "id": "5a94fe6269fb03452672e462",
+ "title": "Create Flexible Layouts Using auto-fit",
+ "description": [
+ "auto-fit
效果几乎和auto-fill
一样。不同点仅在于,当容器的大小大于各网格项之和时,auto-fill
将会持续地在一端放入空行或空列,这样就会使所有网格项挤到另一边;而auto-fit
则不会在一端放入空行或空列,而是会将所有网格项拉伸至合适的大小。",
+ "注意:auto-fit
和repeat
来填充网格,其中列宽的最小值为60px
,最大值为1fr
。你可以调整最右侧的预览区以查看差异。"
+ ],
+ "tests": [
+ {
+ "text": "container2
类应该有grid-template-columns
属性,且使用repeat
和auto-fit
以便将最小宽度为60px
,最大宽度为1fr
的列放入网格。",
+ "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*grid-template-columns\\s*?:\\s*?repeat\\s*?\\(\\s*?auto-fit\\s*?,\\s*?minmax\\s*?\\(\\s*?60px\\s*?,\\s*?1fr\\s*?\\)\\s*?\\)\\s*?;[\\s\\S]*}/gi), 'container2
类应该有grid-template-columns
属性,且使用repeat
和auto-fit
以便将最小宽度为60px
,最大宽度为1fr
的列放入网格。');"
+ }
+ ],
+ "solutions": [],
+ "hints": [],
+ "releasedOn": "",
+ "challengeType": 0,
+ "files": {
+ "indexhtml": {
+ "key": "indexhtml",
+ "ext": "html",
+ "name": "index",
+ "contents": [
+ "",
+ " ",
+ "grid-area
property on an item like this:",
- ".item1 { grid-area: header; }", - "This lets the grid know that you want the
item1
class to go in the area named header
. In this case, the item will use the entire top row because that whole row is named as the header area.",
- "item5
class in the footer
area using the grid-area
property."
- ],
- "tests": [
- {
- "text": "item5
class should have a grid-area
property that has the value of footer
.",
- "testString": "assert(code.match(/.item5\\s*?{[\\s\\S]*grid-area\\s*?:\\s*?footer\\s*?;[\\s\\S]*}/gi), 'item5
class should have a grid-area
property that has the value of footer
.');"
- }
- ],
- "solutions": [],
- "hints": [],
- "releasedOn": "",
- "challengeType": 0,
- "files": {
- "indexhtml": {
- "key": "indexhtml",
- "ext": "html",
- "name": "index",
- "contents": [
- "",
- " ",
- "grid-area
property you learned in the last challenge can be used in another way. If your grid doesn't have an areas template to reference, you can create an area on the fly for an item to be placed like this:",
- "item1 { grid-area: 1/1/2/4; }", - "This is using the line numbers you learned about earlier to define where the area for this item will be. The numbers in the example above represent these values:", - "
grid-area: horizontal line to start at / vertical line to start at / horizontal line to end at / vertical line to end at;", - "So the item in the example will consume the rows between lines 1 and 2, and the columns between lines 1 and 4.", - "
grid-area
property, place the element with item5
class between the third and fourth horizontal lines and between the first and fourth vertical lines."
- ],
- "tests": [
- {
- "text": "item5
class should have a grid-area
property that has the value of 3/1/4/4
.",
- "testString": "assert(code.match(/.item5\\s*?{[\\s\\S]*grid-area\\s*?:\\s*?3\\s*?\\/\\s*?1\\s*?\\/\\s*?4\\s*?\\/\\s*?4\\s*?;[\\s\\S]*}/gi), 'item5
class should have a grid-area
property that has the value of 3/1/4/4
.');"
- }
- ],
- "solutions": [],
- "hints": [],
- "releasedOn": "",
- "challengeType": 0,
- "files": {
- "indexhtml": {
- "key": "indexhtml",
- "ext": "html",
- "name": "index",
- "contents": [
- "",
- " ",
- "grid-template-columns
and grid-template-rows
to define the structure of a grid, you entered a value for each row or column you created.",
- "Lets say you want a grid with 100 rows of the same height. It isn't very practical to insert 100 values individually. Fortunately, there's a better way - by using the repeat
function to specify the number of times you want your column or row to be repeated, followed by a comma and the value you want to repeat.",
- "Here's an example that would create the 100 row grid, each row at 50px tall.",
- "grid-template-rows: repeat(100, 50px);", - "You can also repeat multiple values with the repeat function, and insert the function amongst other values when defining a grid structure. Here's what I mean:", - "
grid-template-columns: repeat(2, 1fr 50px) 20px;", - "This translates to:", - "
grid-template-columns: 1fr 50px 1fr 50px 20px;", - "Note
1fr 50px
is repeated twice followed by 20px.",
- "repeat
to remove repetition from the grid-template-columns
property."
- ],
- "tests": [
- {
- "text": "container
class should have a grid-template-columns
property that is set to repeat 3 columns with the width of 1fr
.",
- "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*grid-template-columns\\s*?:\\s*?repeat\\s*?\\(\\s*?3\\s*?,\\s*?1fr\\s*?\\)\\s*?;[\\s\\S]*}/gi), 'container
class should have a grid-template-columns
property that is set to repeat 3 columns with the width of 1fr
.');"
- }
- ],
- "solutions": [],
- "hints": [],
- "releasedOn": "",
- "challengeType": 0,
- "files": {
- "indexhtml": {
- "key": "indexhtml",
- "ext": "html",
- "name": "index",
- "contents": [
- "",
- " ",
- "grid-template-columns
and grid-template-rows
called minmax
. It's used to limit the size of items when the grid container changes size. To do this you need to specify the acceptable size range for your item. Here is an example:",
- "grid-template-columns: 100px minmax(50px, 200px);", - "In the code above,
grid-template-columns
is set to create two columns; the first is 100px wide, and the second has the minimum width of 50px and the maximum width of 200px.",
- "minmax
function, replace the 1fr
in the repeat
function with a column size that has the minimum width of 90px
and the maximum width of 1fr
, and resize the preview panel to see the effect."
- ],
- "tests": [
- {
- "text": "container
class should have a grid-template-columns
property that is set to repeat 3 columns with the minimum width of 90px
and maximum width of 1fr
.",
- "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*grid-template-columns\\s*?:\\s*?repeat\\s*?\\(\\s*?3\\s*?,\\s*?minmax\\s*?\\(\\s*?90px\\s*?,\\s*?1fr\\s*?\\)\\s*?\\)\\s*?;[\\s\\S]*}/gi), 'container
class should have a grid-template-columns
property that is set to repeat 3 columns with the minimum width of 90px
and maximum width of 1fr
.');"
- }
- ],
- "solutions": [],
- "hints": [],
- "releasedOn": "",
- "challengeType": 0,
- "files": {
- "indexhtml": {
- "key": "indexhtml",
- "ext": "html",
- "name": "index",
- "contents": [
- "",
- " ",
- "auto-fill
with minmax
.",
- "In the preview, grid-template-columns
is set to",
- "repeat(auto-fill, minmax(60px, 1fr));", - "When the container changes size, this setup keeps inserting 60px columns and stretching them until it can insert another one.", - "Note
auto-fill
with repeat
to fill the grid with columns that have a minimum width of 60px
and maximum of 1fr
. Then resize the preview to see auto-fill in action."
- ],
- "tests": [
- {
- "text": "container
class should have a grid-template-columns
property with repeat
and auto-fill
that will fill the grid with columns that have a minimum width of 60px
and maximum of 1fr
.",
- "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*grid-template-columns\\s*?:\\s*?repeat\\s*?\\(\\s*?auto-fill\\s*?,\\s*?minmax\\s*?\\(\\s*?60px\\s*?,\\s*?1fr\\s*?\\)\\s*?\\)\\s*?;[\\s\\S]*}/gi), 'container
class should have a grid-template-columns
property with repeat
and auto-fill
that will fill the grid with columns that have a minimum width of 60px
and maximum of 1fr
.');"
- }
- ],
- "solutions": [],
- "hints": [],
- "releasedOn": "",
- "challengeType": 0,
- "files": {
- "indexhtml": {
- "key": "indexhtml",
- "ext": "html",
- "name": "index",
- "contents": [
- "",
- "auto-fit
works almost identically to auto-fill
. The only difference is that when the container's size exceeds the size of all the items combined, auto-fill
keeps inserting empty rows or columns and pushes your items to the side, while auto-fit
collapses those empty rows or columns and stretches your items to fit the size of the container.",
- "Noteauto-fit
with repeat
to fill the grid with columns that have a minimum width of 60px
and maximum of 1fr
. Then resize the preview to see the difference."
- ],
- "tests": [
- {
- "text": "container2
class should have a grid-template-columns
property with repeat
and auto-fit
that will fill the grid with columns that have a minimum width of 60px
and maximum of 1fr
.",
- "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*grid-template-columns\\s*?:\\s*?repeat\\s*?\\(\\s*?auto-fit\\s*?,\\s*?minmax\\s*?\\(\\s*?60px\\s*?,\\s*?1fr\\s*?\\)\\s*?\\)\\s*?;[\\s\\S]*}/gi), 'container2
class should have a grid-template-columns
property with repeat
and auto-fit
that will fill the grid with columns that have a minimum width of 60px
and maximum of 1fr
.');"
- }
- ],
- "solutions": [],
- "hints": [],
- "releasedOn": "",
- "challengeType": 0,
- "files": {
- "indexhtml": {
- "key": "indexhtml",
- "ext": "html",
- "name": "index",
- "contents": [
- "",
- " ",
- "400px
or more, make the header area occupy the top row completely and the footer area occupy the bottom row completely."
- ],
- "tests": [
- {
- "text": "When the viewport is 400px
or more, container
class should have a grid-template-areas
property in which the footer and header areas occupy the top and bottom rows respectively and advert and content occupy the left and right columns of the middle row.",
- "testString": "assert(code.match(/@media\\s*?\\(\\s*?min-width\\s*?:\\s*?400px\\s*?\\)[\\s\\S]*.container\\s*?{[\\s\\S]*grid-template-areas\\s*?:\\s*?\"\\s*?header\\s*?header\\s*?\"\\s*?\"\\s*?advert\\s*?content\\s*?\"\\s*?\"\\s*?footer\\s*?footer\\s*?\"\\s*?;[\\s\\S]*}/gi), 'When the viewport is 400px
or more, container
class should have a grid-template-areas
property in which the footer and header areas occupy the top and bottom rows respectively and advert and content occupy the left and right columns of the middle row.');"
- }
- ],
- "solutions": [],
- "hints": [],
- "releasedOn": "",
- "challengeType": 0,
- "files": {
- "indexhtml": {
- "key": "indexhtml",
- "ext": "html",
- "name": "index",
- "contents": [
- "",
- " ",
- "display
and grid-template-columns
properties of the element with the item3
class, you create a grid within your grid.",
- "item3
class into a grid with two columns with a width of auto
and 1fr
using display
and grid-template-columns
."
- ],
- "tests": [
- {
- "text": "item3
class should have a grid-template-columns
property with auto
and 1fr
as values.",
- "testString": "assert(code.match(/.item3\\s*?{[\\s\\S]*grid-template-columns\\s*?:\\s*?auto\\s*?1fr\\s*?;[\\s\\S]*}/gi), 'item3
class should have a grid-template-columns
property with auto
and 1fr
as values.');"
- },
- {
- "text": "item3
class should have a display
property with the value of grid
.",
- "testString": "assert(code.match(/.item3\\s*?{[\\s\\S]*display\\s*?:\\s*?grid\\s*?;[\\s\\S]*}/gi), 'item3
class should have a display
property with the value of grid
.');"
+ },
+ {
+ "id": "5a94fe7769fb03452672e463",
+ "title": "Use Media Queries to Create Responsive Layouts",
+ "description": [
+ "通过使用媒体查询重新排列网格区域,更改网格尺寸以及重新排列网格项位置,CSS 网格能轻松地使网站更具响应性。",
+ "在最右侧的预览区中,当网页可视区域的宽不小于 300px 时,列数从 1 变为 2。并且,广告(advertisement)区域完全占据左列。",
+ "400px
时,使 header 区域完全占据最顶行,footer 区域完全占据最底行。"
+ ],
+ "tests": [
+ {
+ "text": "当网页可视区域的宽在400px
及以上时,container
类应该有grid-template-areas
属性且使得 footer 和 header 区域分别占据顶行和底行,advert 和 content 区域分别占据中间行的左和右列。",
+ "testString": "assert(code.match(/@media\\s*?\\(\\s*?min-width\\s*?:\\s*?400px\\s*?\\)[\\s\\S]*.container\\s*?{[\\s\\S]*grid-template-areas\\s*?:\\s*?\"\\s*?header\\s*?header\\s*?\"\\s*?\"\\s*?advert\\s*?content\\s*?\"\\s*?\"\\s*?footer\\s*?footer\\s*?\"\\s*?;[\\s\\S]*}/gi), '当网页可视区域的宽在400px
及以上时,container
类应该有grid-template-areas
属性且使得 footer 和 header 区域分别占据顶行和底行,advert 和 content 区域分别占据中间行的左和右列。');"
+ }
+ ],
+ "solutions": [],
+ "hints": [],
+ "releasedOn": "",
+ "challengeType": 0,
+ "files": {
+ "indexhtml": {
+ "key": "indexhtml",
+ "ext": "html",
+ "name": "index",
+ "contents": [
+ "",
+ " ",
+ "item3
的元素的display
和grid-template-columns
属性,就会得到一个嵌套的网格。",
+ "display
和grid-template-columns
,使类为item3
元素转换为有两列且宽度为auto
和1fr
的网格。"
+ ],
+ "tests": [
+ {
+ "text": "item3
类应该有grid-template-columns
属性且值为auto
和1fr
。",
+ "testString": "assert(code.match(/.item3\\s*?{[\\s\\S]*grid-template-columns\\s*?:\\s*?auto\\s*?1fr\\s*?;[\\s\\S]*}/gi), 'item3
类应该有grid-template-columns
属性且将auto
和1fr
作为值。');"
+ },
+ {
+ "text": "item3
类有display
属性且值为grid
。",
+ "testString": "assert(code.match(/.item3\\s*?{[\\s\\S]*display\\s*?:\\s*?grid\\s*?;[\\s\\S]*}/gi), 'item3
类有display
属性且值为grid
。');"
+ }
+ ],
+ "solutions": [],
+ "hints": [],
+ "releasedOn": "",
+ "challengeType": 0,
+ "files": {
+ "indexhtml": {
+ "key": "indexhtml",
+ "ext": "html",
+ "name": "index",
+ "contents": [
+ "",
+ " ",
+ "@media (max-width: 100px) { /* CSS Rules */ }
",
- "and the following media query returns the content when the device's height is more than or equal to 350px:",
+ "以下定义的媒体查询,是当设备高度大于或等于 350px 时返回内容:",
"@media (min-height: 350px) { /* CSS Rules */ }
",
- "Remember, the CSS inside the media query is applied only if the media type matches that of the device being used.",
+ "只有当媒体类型与当前设备匹配时,才应用媒体查询中的 CSS。",
"p
tag has a font-size
of 10px when the device's height is less than or equal to 800px."
+ "增加一个设备的高度小于或等于 800px 时,p
标签的 font-size
为 10px 的媒体查询。"
],
"tests": [
{
- "text": "Your p
element should have the font-size
of 10px when the device height
is less than or equal to 800px.",
- "testString": "assert($('p').css('font-size') == '10px', 'Your p
element should have the font-size
of 10px when the device height
is less than or equal to 800px.');"
+ "text": "当设备 height
小于或等于 800px 时,p
元素 font-size
应为 10px。",
+ "testString": "assert($('p').css('font-size') == '10px', '当设备 height
小于或等于 800px 时,p
元素 font-size
应为 10px。');"
},
{
- "text": "Declare a @media
query for devices with a height
less than or equal to 800px.",
- "testString": "assert(code.match(/@media\\s?\\(max-height:\\s*?800px\\)/g), 'Declare a @media
query for devices with a height
less than or equal to 800px.');"
+ "text": "使用 @media
为 height
小于或等于 800px 的设备添加一个媒体查询。",
+ "testString": "assert(code.match(/@media\\s?\\(max-height:\\s*?800px\\)/g), '使用 @media
为 height
小于或等于 800px 的设备添加一个媒体查询。');"
}
],
"releasedOn": "Feb 17, 2017",
@@ -58,26 +58,26 @@
"id": "587d78b1367417b2b2512b09",
"title": "Make an Image Responsive",
"description": [
- "Making images responsive with CSS is actually very simple. Instead of applying an absolute width to an element:",
+ "用 CSS 来让图片自适应其实很简单。不要使用绝对单位:",
"img { width: 720px; }
",
- "You can use:",
+ "你应该使用:",
"img {", - "The
max-width: 100%;
display: block;
height: auto;
}
max-width
property of 100% scales the image to fit the width of its container, but the image won't stretch wider than its original width. Setting the display
property to block changes the image from an inline element (its default), to a block element on its own line. The height
property of auto keeps the original aspect ratio of the image.",
+ "max-width
属性能让图片以 100% 的最大宽度适应其父容器的宽度,但图片不会拉伸得比原始宽度还宽。将 display
属性设置为 block
可以让 image 标签从内联元素(默认值)更改为块级元素。设置 height
属性为 auto 保持图片的原始宽高比。",
"img
tag to make it responsive to the size of its container. It should display as a block-level element, it should fit the full width of its container without stretching, and it should keep its original aspect ratio."
+ "给 img
标签增加样式规则使它自适应容器尺寸。应声明为块级元素,应适应它容器的宽度,应保持原本的宽高比。"
],
"tests": [
{
- "text": "Your img
tag should have a max-width
set to 100%.",
- "testString": "assert(code.match(/max-width:\\s*?100%;/g), 'Your img
tag should have a max-width
set to 100%.');"
+ "text": "img
标签应设置 max-width
为 100%。",
+ "testString": "assert(code.match(/max-width:\\s*?100%;/g), 'img
标签应设置 max-width
为 100%。');"
},
{
- "text": "Your img
tag should have a display
set to block.",
- "testString": "assert($('img').css('display') == 'block', 'Your img
tag should have a display
set to block.');"
+ "text": "img
标签应设置 display
为 block。",
+ "testString": "assert($('img').css('display') == 'block', 'img
标签应设置 display
为 block。');"
},
{
- "text": "Your img
tag should have a height
set to auto.",
- "testString": "assert(code.match(/height:\\s*?auto;/g), 'Your img
tag should have a height
set to auto.');"
+ "text": "img
标签应设置 height
为 auto。",
+ "testString": "assert(code.match(/height:\\s*?auto;/g), 'img
标签应设置 height
为 auto。');"
}
],
"releasedOn": "Feb 17, 2017",
@@ -105,20 +105,20 @@
"id": "587d78b1367417b2b2512b0a",
"title": "Use a Retina Image for Higher Resolution Displays",
"description": [
- "The simplest way to make your images appear \"retina\" (and optimize them for retina displays) is to define their width
and height
values as only half of what the original file is.",
- "Here is an example of an image that is only using half of the original height and width:",
- "<style>", + "为优化图片在高分辨率设备下的显示效果,最简单的方式是定义它们的
img { height: 250px; width: 250px; }
</style>
<img src="coolPic500x500" alt="A most excellent picture">
width
和 height
值为源文件宽高的一半。",
+ "这是一个图片宽高设置为源文件一半的例子:",
+ "<style>", "
img { height: 250px; width: 250px; }
</style>
<img src="coolPic500x500" alt="一张高质量的图片">
width
and height
of the img
tag to half of their original values. In this case, both the original height
and the original width
are 200px."
+ "设置 img
标签的 width
和 height
为它们原始宽高的一半。在这个例子中,原始 height
和原始 width
的值都为 200px。"
],
"tests": [
{
- "text": "Your img
tag should have a width
of 100 pixels.",
- "testString": "assert($('img').css('width') == '100px', 'Your img
tag should have a width
of 100 pixels.');"
+ "text": "img
标签的 width
值应为 100px。",
+ "testString": "assert($('img').css('width') == '100px', 'img
标签的 width
值应为 100px。');"
},
{
- "text": "Your img
tag should have a height
of 100 pixels.",
- "testString": "assert($('img').css('height') == '100px', 'Your img
tag should have a height
of 100 pixels.');"
+ "text": "img
标签应含有 100px 的 height
。",
+ "testString": "assert($('img').css('height') == '100px', 'img
标签应含有 100px 的 height
。');"
}
],
"releasedOn": "Feb 17, 2017",
@@ -146,20 +146,20 @@
"id": "587d78b1367417b2b2512b0c",
"title": "Make Typography Responsive",
"description": [
- "Instead of using em
or px
to size text, you can use viewport units for responsive typography. Viewport units, like percentages, are relative units, but they are based off different items. Viewport units are relative to the viewport dimensions (width or height) of a device, and percentages are relative to the size of the parent container element.",
- "The four different viewport units are:",
- "vw: 10vw
would be 10% of the viewport's width.vh: 3vh
would be 3% of the viewport's height.vmin: 70vmin
would be 70% of the viewport's smaller dimension (height vs. width).vmax: 100vmax
would be 100% of the viewport's bigger dimension (height vs. width).em
或 px
去设置文本大小, 你还可以用视窗单位来做响应式排版。视窗单位还有百分比,它们都是相对单位,但却基于不同的参照物。视窗单位相对于设备的视窗尺寸 (宽度或高度) ,百分比是相对于父级元素的大小。",
+ "四个不同的视窗单位分别是:",
+ "vw
:如 10vw
的意思是视窗宽度的 10%。vh:
如 3vh
的意思是视窗高度的 3%。vmin:
如 70vmin
的意思是视窗中较小尺寸的 70% (高度 VS 宽度)。vmax:
如 100vmax
的意思是视窗中较大尺寸的 100% (高度 VS 宽度)。width
of the h2
tag to 80% of the viewport's width and the width
of the paragraph as 75% of the viewport's smaller dimension."
+ "设置 h2
标签 width
为视窗宽度的 80%,并且段落 width
为视窗高度和宽度中较小值的 70%。"
],
"tests": [
{
- "text": "Your h2
tag should have a width
of 80vw.",
- "testString": "assert(code.match(/h2\\s*?{\\s*?width:\\s*?80vw;\\s*?}/g), 'Your h2
tag should have a width
of 80vw.');"
+ "text": "h2
标签 width
应为 80vw。",
+ "testString": "assert(code.match(/h2\\s*?{\\s*?width:\\s*?80vw;\\s*?}/g), 'h2
标签的 width
应为 80vw。');"
},
{
- "text": "Your p
tag should have a width
of 75vmin.",
- "testString": "assert(code.match(/p\\s*?{\\s*?width:\\s*?75vmin;\\s*?}/g), 'Your p
tag should have a width
of 75vmin.');"
+ "text": "p
标签 width
应为 75vmin。",
+ "testString": "assert(code.match(/p\\s*?{\\s*?width:\\s*?75vmin;\\s*?}/g), 'p
标签的 width
应为 75vmin。');"
}
],
"releasedOn": "Feb 17, 2017",
diff --git a/01-responsive-web-design/responsive-web-design-principles.md b/01-responsive-web-design/responsive-web-design-principles.md
index b7cf4fb..08812dd 100644
--- a/01-responsive-web-design/responsive-web-design-principles.md
+++ b/01-responsive-web-design/responsive-web-design-principles.md
@@ -1,13 +1 @@
-# Introduction to the Responsive Web Design Principles #
-
-Today, there are many types of devices that can access the web. They range from large desktop computers to small mobile phones. These devices have different screen sizes, resolutions, and processing power. Responsive Web Design is an approach to designing web content that responds to the constraints of different devices. The page structure and CSS rules should be flexible to accommodate these differences. In general, design the page's CSS to your target audience. If you expect most of your traffic to be from mobile users, take a 'mobile-first' approach. Then add conditional rules for larger screen sizes. If your visitors are desktop users, then design for larger screens with conditional rules for smaller sizes. CSS gives you the tools to write different style rules, then apply them depending on the device displaying the page. This section will cover the basic ways to use CSS for Responsive Web Design.
-
-# Upcoming Lessons #
-
-Create a Media Query
-
-Make an Image Responsive
-
-Use a Retina Image for Higher Resolution Displays
-
-Make Typography Responsive
\ No newline at end of file
+如今,从大屏的台式电脑到小屏的手机,我们有各式各样的设备可以上网。这些设备有着不同的屏幕尺寸、分辨率和处理能力。响应式 Web 设计是一种能自如响应不同尺寸设备的设计方法。能使页面结构和 CSS 规则能够灵活应用于不同设备之间的差异。一般来说,页面的 CSS 是设计给目标用户看的。如果你预计网站的大部分流量来自移动端,那么应该采取“移动端优先”的策略,再为 PC 端做兼容。如果你预计网站的大部分流量来自 PC 端,那么应该采取“PC 端优先”的策略,再为移动端做兼容。CSS 提供了书写不同样式规则的工具,然后根据显示网页的设备应用它们。本节将介绍使用 CSS 来响应 Web 设计的基本方法。
diff --git a/01-responsive-web-design/responsive-web-design-projects.json b/01-responsive-web-design/responsive-web-design-projects.json
index da24157..9636a99 100644
--- a/01-responsive-web-design/responsive-web-design-projects.json
+++ b/01-responsive-web-design/responsive-web-design-projects.json
@@ -8,21 +8,21 @@
"id": "bd7158d8c442eddfaeb5bd18",
"title": "Build a Tribute Page",
"description": [
- "Objective: Build a CodePen.io app that is functionally similar to this: https://codepen.io/freeCodeCamp/full/zNqgVx.",
- "Fulfill the below user stories and get all of the tests to pass. Give it your own personal style.",
- "You can use HTML, JavaScript, and CSS to complete this project. Plain CSS is recommended because that is what the lessons have covered so far and you should get some practice with plain CSS. You can use Bootstrap or SASS if you choose. Additional technologies (just for example jQuery, React, Angular, or Vue) are not recommended for this project, and using them is at your own risk. Other projects will give you a chance to work with different technology stacks like React. We will accept and try to fix all issue reports that use the suggested technology stack for this project. Happy coding!",
- "User Story #1: My tribute page should have an element with a corresponding id=\"main\"
, which contains all other elements.",
- "User Story #2: I should see an element with a corresponding id=\"title\"
, which contains a string (i.e. text) that describes the subject of the tribute page (e.g. \"Dr. Norman Borlaug\").",
- "User Story #3: I should see a div
element with a corresponding id=\"img-div\"
.",
- "User Story #4: Within the img-div
element, I should see an img
element with a corresponding id=\"image\"
.",
- "User Story #5: Within the img-div
element, I should see an element with a corresponding id=\"img-caption\"
that contains textual content describing the image shown in img-div
.",
- "User Story #6: I should see an element with a corresponding id=\"tribute-info\"
, which contains textual content describing the subject of the tribute page.",
- "User Story #7: I should see an a
element with a corresponding id=\"tribute-link\"
, which links to an outside site that contains additional information about the subject of the tribute page. HINT: You must give your element an attribute of target
and set it to _blank
in order for your link to open in a new tab (i.e. target=\"_blank\"
).",
- "User Story #8: The img
element should responsively resize, relative to the width of its parent element, without exceeding its original size.",
- "User Story #9: The img
element should be centered within its parent element.",
- "You can build your project by forking this CodePen pen. Or you can use this CDN link to run the tests in any environment you like: https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js
.",
- "Once you're done, submit the URL to your working project with all its tests passing.",
- "Remember to use the Read-Search-Ask method if you get stuck."
+ "目标:使用 CodePen.io 搭建一个与这个功能上相似的 app:https://codepen.io/freeCodeCamp/full/zNqgVx。",
+ "在满足以下 用户故事 并能通过所有测试的前提下,你可以根据自己的喜好来美化你的 app。",
+ "你可以使用 HTML、JavaScript 以及 CSS 来完成项目,由于目前我们只学到了 CSS,因此建议你只使用 CSS 完成这个项目,顺便还可以巩固一下之前学到的内容。你也可以使用 Bootstrap 或者是 SASS。在当前的项目中,不推荐使用其他技术如 jQurey、React、Angular 或者是 Vue,因为一旦出现问题,风险自担。但在别的项目中我们仍有机会去使用不同的技术栈比如 React,我们会接受并尽力处理你在使用建议的技术栈过程中遇到的问题,编码愉快!",
+ "用户故事 #1:我的致敬页应有对应 id=\"main\"
的元素, 其中包含其他的所有元素",
+ "用户故事 #2:我应该看到一个具有相应 id=\"title\"
的元素,其中包含描述致敬页主题的字符串 (即文本),如 \"Dr. Norman Borlaug\"。",
+ "用户故事 #3:我应该看到一个带有对应 id=\"img-div\"
的 div
元素。",
+ "用户故事 #4:在 img-div
元素内,我应该看见有对应 id=\"image\"
的 img
元素",
+ "用户故事 #5:在 img-div
元素内,我应该看见一个具有相应 id=\"img-caption\"
的元素,其中包含对 img-div
中图像的描述。",
+ "用户故事 #6:我应该看见具有对应 id=\"tribute-info\"
的元素,其中包含描述致敬页主题的文本内容",
+ "用户故事 #7:我应该看见具有对应 id=\"tribute-link\"
的元素,它链接到一个包含有关致敬页主题额外信息的外部网页,提示: 你必须为元素提供 target
属性,并设置为 _blank
以便在新选项卡中打开连接 (例 target=\"_blank\"
)。",
+ "用户故事 #8:img
元素应相对于其父元素的宽度响应地调整大小,但不超过其原始大小。",
+ "用户故事 #9:img
在其父元素内居中。",
+ "你可以通过 fork 此 CodePen 来构建项目,或者你可以使用此 CDN 链接在你喜欢的任何环境中运行测试:https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js
。",
+ "完成项目并通过所有测试后, 输入你的项目在 CodePen 上的链接",
+ "要是卡住的话,记得使用 Read-Search-Ask。"
],
"releasedOn": "January 1, 2016",
"tests": [],
@@ -33,28 +33,28 @@
"id": "587d78af367417b2b2512b03",
"title": "Build a Survey Form",
"description": [
- "Objective: Build a CodePen.io app that is functionally similar to this: https://codepen.io/freeCodeCamp/full/VPaoNP.",
- "Fulfill the below user stories and get all of the tests to pass. Give it your own personal style.",
- "You can use HTML, JavaScript, and CSS to complete this project. Plain CSS is recommended because that is what the lessons have covered so far and you should get some practice with plain CSS. You can use Bootstrap or SASS if you choose. Additional technologies (just for example jQuery, React, Angular, or Vue) are not recommended for this project, and using them is at your own risk. Other projects will give you a chance to work with different technology stacks like React. We will accept and try to fix all issue reports that use the suggested technology stack for this project. Happy coding!",
- "User Story #1: I can see a title with id=\"title\"
in H1 sized text.",
- "User Story #2: I can see a short explanation with id=\"description\"
in P sized text.",
- "User Story #3: I can see a form
with id=\"survey-form\"
.",
- "User Story #4: Inside the form element, I am required to enter my name in a field with id=\"name\"
.",
- "User Story #5: Inside the form element, I am required to enter an email in a field with id=\"email\"
.",
- "User Story #6: If I enter an email that is not formatted correctly, I will see an HTML5 validation error.",
- "User Story #7: Inside the form, I can enter a number in a field with id=\"number\"
.",
- "User Story #8: If I enter non-numbers in the number input, I will see an HTML5 validation error.",
- "User Story #9: If I enter numbers outside the range of the number input, which are defined by the min
and max
attributes, I will see an HTML5 validation error.",
- "User Story #10: For the name, email, and number input fields inside the form I can see corresponding labels that describe the purpose of each field with the following ids: id=\"name-label\"
, id=\"email-label\"
, and id=\"number-label\"
.",
- "User Story #11: For the name, email, and number input fields, I can see placeholder text that gives me a description or instructions for each field.",
- "User Story #12: Inside the form element, I can select an option from a dropdown that has a corresponding id=\"dropdown\"
.",
- "User Story #13: Inside the form element, I can select a field from one or more groups of radio buttons. Each group should be grouped using the name
attribute.",
- "User Story #14: Inside the form element, I can select several fields from a series of checkboxes, each of which must have a value
attribute.",
- "User Story #15: Inside the form element, I am presented with a textarea
at the end for additional comments.",
- "User Story #16: Inside the form element, I am presented with a button with id=\"submit\"
to submit all my inputs.",
- "You can build your project by forking this CodePen pen. Or you can use this CDN link to run the tests in any environment you like: https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js
",
- "Once you're done, submit the URL to your working project with all its tests passing.",
- "Remember to use the Read-Search-Ask method if you get stuck."
+ "目标:使用CodePen.iohttps://codepen.io/freeCodeCamp/full/VPaoNP。",
+ "在满足以下 user stories 并能通过所有测试的前提下,你可以根据自己的喜好来美化你的 app。",
+ "你可以使用 HTML、JavaScript 以及 CSS 来完成项目,由于目前我们只学到了 CSS,因此建议你只使用 CSS 完成这个项目,顺便还可以巩固一下之前学到的内容。你也可以使用 Bootstrap 或者是 SASS。在当前的项目中,不推荐使用其他技术如 jQurey、React、Angular 或者是 Vue,因为一旦出现问题,风险自担。但在别的项目中我们仍有机会去使用不同的技术栈比如 React,我们会接受并尽力处理你在使用建议的技术栈过程中遇到的问题,编码愉快!",
+ "用户故事 #1:我能看见一个 H1 大小 id=\"title\"
的标题。",
+ "用户故事 #1:我能看见一个 P 大小 id=\"description\"
的简述文字。",
+ "用户故事 #3:我能看见一个 id=\"survey-form\"
的 form
。",
+ "用户故事 #4:在 form 元素内, 我需要在 id=\"name\"
的字段中输入我的名字。",
+ "用户故事 #5:在 form 元素内, 我需要在 id=\"email\"
的字段中输入邮箱。",
+ "用户故事 #6:如果我输入了格式不正确的邮箱,我将会看见验证错误信息。",
+ "用户故事 #7:id=\"number\" 的字段中输入数字。",
+ "用户故事 #8:如果我在数字输入框内输入非数字,我将会看见验证错误信息。",
+ "用户故事 #9:如果我输入的数字超出了范围(使用 min
和 max
属性定义),我将会看见验证错误信息。",
+ "用户故事 #10:对于表单中的名称,邮箱和数字输入框应该使用对应 id 为:id=\"name-label\"
, id=\"email-label\"
, 和 id=\"number-label\"
的描述标签",
+ "用户故事 #11:在表单中的名称,邮箱和数字输入框中,我能看到各自的描述文字作为占位符。",
+ "用户故事 #12:在表单元素内,我可以在 id=\"dropdown\"
的下拉列表中选择一个选项。",
+ "用户故事 #13:在表单元素内,我可以从一组或多组单选按钮中选择一个字段。每组使用 name code> 属性进行分组。",
+ "用户故事 #14:在表单元素内,我可以从一系列复选框中选择几个字段,每个复选框都必须具有 value 属性。",
+ "用户故事 #15:在表单元素内,我能看见在最后有个 textarea
用于附加注释。",
+ "用户故事 #16:在表单元素内,我能看见一个 id=\"submit\"
的按钮,用于提交我所有的输入。",
+ "你可以通过 fork 此 this CodePen pen 来构建项目,或者你可以使用此 CDN 链接在你喜欢的任何环境中运行测试:https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js
。",
+ "完成项目并通过所有测试后, 输入你的项目在 CodePen 上的链接。",
+ "要是卡住的话,记得使用 Read-Search-Ask。"
],
"releasedOn": "January 15, 2017",
"tests": [],
@@ -150,4 +150,4 @@
"challengeType": 3
}
]
-}
\ No newline at end of file
+}
diff --git a/01-responsive-web-design/responsive-web-design-projects.md b/01-responsive-web-design/responsive-web-design-projects.md
index b5e154d..9c035e6 100644
--- a/01-responsive-web-design/responsive-web-design-projects.md
+++ b/01-responsive-web-design/responsive-web-design-projects.md
@@ -10,16 +10,4 @@ In this section you get the chance to:
* Build a Technical Documentation Page
* Build a Personal Portfolio Webpage
-By the end of this, you would have 5 responsive websites under your belt that you can show off to friends, family, employers, etc. Have fun and remember to use the Read-Search-Ask method if you get stuck.
-# Upcoming Lessons #
-
-Build a Tribute Page
-
-Build a Survey Form
-
-Build a Product Landing Page
-
-Build a Technical Documentation Page
-
-Build a Personal Portfolio Webpage
\ No newline at end of file
diff --git a/02-javascript-algorithms-and-data-structures/basic-algorithm-scripting.md b/02-javascript-algorithms-and-data-structures/basic-algorithm-scripting.md
index deeef5e..420ffed 100644
--- a/02-javascript-algorithms-and-data-structures/basic-algorithm-scripting.md
+++ b/02-javascript-algorithms-and-data-structures/basic-algorithm-scripting.md
@@ -9,37 +9,3 @@ In this section we will learn to solve basic algorithm problems using JavaScript
## Hint ##
If you get stuck, try using console.log() to log variable values to the console. This will help to debug problems.
-
-# Upcoming Lessons #
-
-Convert Celsius to Fahrenheit
-
-Reverse a String
-
-Factorialize a Number
-
-Find the Longest Word in a String
-
-Return Largest Numbers in Arrays
-
-Confirm the Ending
-
-Repeat a String Repeat a String
-
-Truncate a String
-
-Finders Keepers
-
-Boo who
-
-Title Case a Sentence
-
-Slice and Splice
-
-Falsy Bouncer
-
-Where do I Belong
-
-Mutations
-
-Chunky Monkey
\ No newline at end of file
diff --git a/02-javascript-algorithms-and-data-structures/basic-data-structures.md b/02-javascript-algorithms-and-data-structures/basic-data-structures.md
index dc11d35..7d1d651 100644
--- a/02-javascript-algorithms-and-data-structures/basic-data-structures.md
+++ b/02-javascript-algorithms-and-data-structures/basic-data-structures.md
@@ -1,45 +1,3 @@
# Introduction to the Basic Data Structure Challenges #
Data can be stored and accessed in many different ways, both in Javascript and other languages. This section will teach you how to manipulate arrays, as well as access and copy the information within them. It will also teach you how to manipulate and access the data within Javascript objects, using both dot and bracket notation. When you're done with this section, you should understand the basic properties and differences between arrays and objects, as well as how to choose which to use for a given purpose.
-
-# Upcoming Lessons #
-
-Use an Array to Store a Collection of Data
-
-Access an Array's Contents Using Bracket Notation
-
-Add Items to an Array with push() and unshift()
-
-Remove Items from an Array with pop() and shift()
-
-Remove Items Using splice()
-
-Add Items Using splice()
-
-Copy Array Items Using slice()
-
-Copy an Array with the Spread Operator
-
-Combine Arrays with the Spread Operator
-
-Check For The Presence of an Element With indexOf()
-
-Iterate Through All an Array's Items Using For Loops
-
-Create complex multi-dimensional arrays
-
-Add Key-Value Pairs to JavaScript Objects
-
-Modify an Object Nested Within an Object
-
-Access Property Names with Bracket Notation
-
-Use the delete Keyword to Remove Object Properties
-
-Check if an Object has a Property
-
-Iterate Through the Keys of an Object with a for...in Statement
-
-Generate an Array of All Object Keys with Object.keys()
-
-Modify an Array Stored in an Object
\ No newline at end of file
diff --git a/02-javascript-algorithms-and-data-structures/basic-javascript.md b/02-javascript-algorithms-and-data-structures/basic-javascript.md
index eca570f..1b46fe2 100644
--- a/02-javascript-algorithms-and-data-structures/basic-javascript.md
+++ b/02-javascript-algorithms-and-data-structures/basic-javascript.md
@@ -1,219 +1,3 @@
# Introduction to JavaScript #
JavaScript is a high-level programming language that all modern web browsers support. It is also one of the core technologies of the web, along with HTML and CSS that you may have learned previously. This section will cover basic JavaScript programming concepts, which range from variables and arithmetic to objects and loops.
-
-# Upcoming Lessons #
-
-Comment Your JavaScript Code
-
-Declare JavaScript Variables
-
-Storing Values with the Assignment Operator
-
-Initializing Variables with the Assignment Operator
-
-Understanding Uninitialized Variables
-
-Understanding Case Sensitivity in Variables
-
-Add Two Numbers with JavaScript
-
-Subtract One Number from Another with JavaScript
-
-Multiply Two Numbers with JavaScript
-
-Divide One Number by Another with JavaScript
-
-Increment a Number with JavaScript
-
-Decrement a Number with JavaScript
-
-Create Decimal Numbers with JavaScript
-
-Multiply Two Decimals with JavaScript
-
-Divide One Decimal by Another with JavaScript
-
-Finding a Remainder in JavaScript
-
-Compound Assignment With Augmented Addition
-
-Compound Assignment With Augmented Subtraction
-
-Compound Assignment With Augmented Multiplication
-
-Compound Assignment With Augmented Division
-
-Declare String Variables
-
-Escaping Literal Quotes in Strings
-
-Quoting Strings with Single Quotes
-
-Escape Sequences in Strings
-
-Concatenating Strings with Plus Operator
-
-Concatenating Strings with the Plus Equals Operator
-
-Constructing Strings with Variables
-
-Appending Variables to Strings
-
-Find the Length of a String
-
-Use Bracket Notation to Find the First Character in a String
-
-Understand String Immutability
-
-Use Bracket Notation to Find the Nth Character in a String
-
-Use Bracket Notation to Find the Last Character in a String
-
-Use Bracket Notation to Find the Nth-to-Last Character in a String
-
-Word Blanks
-
-Store Multiple Values in one Variable using JavaScript Arrays
-
-Nest one Array within Another Array
-
-Access Array Data with Indexes
-
-Modify Array Data With Indexes
-
-Access Multi-Dimensional Arrays With Indexes
-
-Manipulate Arrays With push()
-
-Manipulate Arrays With pop()
-
-Manipulate Arrays With shift()
-
-Manipulate Arrays With unshift()
-
-Shopping List
-
-Write Reusable JavaScript with Functions
-
-Passing Values to Functions with Arguments
-
-Global Scope and Functions
-
-Local Scope and Functions
-
-Global vs. Local Scope in Functions
-
-Return a Value from a Function with Return
-
-Understanding Undefined Value returned from a Function
-
-Assignment with a Returned Value
-
-Stand in Line
-
-Understanding Boolean Values
-
-Use Conditional Logic with If Statements
-
-Comparison with the Equality Operator
-
-Comparison with the Strict Equality Operator
-
-Practice comparing different values
-
-Comparison with the Inequality Operator
-
-Comparison with the Strict Inequality Operator
-
-Comparison with the Greater Than Operator
-
-Comparison with the Greater Than Or Equal To Operator
-
-Comparison with the Less Than Operator
-
-Comparison with the Less Than Or Equal To Operator
-
-Comparisons with the Logical And Operator
-
-Comparisons with the Logical Or Operator
-
-Introducing Else Statements
-
-Introducing Else If Statements
-
-Logical Order in If Else Statements
-
-Chaining If Else Statements
-
-Golf Code
-
-Selecting from Many Options with Switch Statements
-
-Adding a Default Option in Switch Statements
-
-Multiple Identical Options in Switch Statements
-
-Replacing If Else Chains with Switch
-
-Returning Boolean Values from Functions
-
-Return Early Pattern for Functions
-
-Counting Cards
-
-Build JavaScript Objects
-
-Accessing Object Properties with Dot Notation
-
-Accessing Object Properties with Bracket Notation
-
-Accessing Object Properties with Variables
-
-Updating Object Properties
-
-Add New Properties to a JavaScript Object
-
-Delete Properties from a JavaScript Object
-
-Using Objects for Lookups
-
-Testing Objects for Properties
-
-Manipulating Complex Objects
-
-Accessing Nested Objects
-
-Accessing Nested Arrays
-
-Record Collection
-
-Iterate with JavaScript While Loops
-
-Iterate with JavaScript For Loops
-
-Iterate Odd Numbers With a For Loop
-
-Count Backwards With a For Loop
-
-Iterate Through an Array with a For Loop
-
-Nesting For Loops
-
-Iterate with JavaScript Do...While Loops
-
-Profile Lookup
-
-Generate Random Fractions with JavaScript
-
-Generate Random Whole Numbers with JavaScript
-
-Generate Random Whole Numbers within a Range
-
-Use the parseInt Function
-
-Use the parseInt Function with a Radix
-
-Use the Conditional (Ternary) Operator
-
-Use Multiple Conditional (Ternary) Operators
\ No newline at end of file
diff --git a/02-javascript-algorithms-and-data-structures/debugging.md b/02-javascript-algorithms-and-data-structures/debugging.md
index 4f173d5..b4375fb 100644
--- a/02-javascript-algorithms-and-data-structures/debugging.md
+++ b/02-javascript-algorithms-and-data-structures/debugging.md
@@ -38,30 +38,4 @@ Debugging is frustrating, but it helps to develop (and follow) a step-by-step ap
For example, if function A works and returns what it's supposed to, then function B may have the issue. Or start checking values in a block of code from the middle to try to cut the search space in half. A problem in one spot indicates a bug in the first half of the code. If not, it's likely in the second.
-This section will cover a couple helpful tools to find bugs, and some of the common forms they take. Fortunately, debugging is a learnable skill that just requires a little patience and practice to master.
-
-# Upcoming Lessons #
-
-Use the JavaScript Console to Check the Value of a Variable
-
-Understanding the Differences between the freeCodeCamp and Browser Console
-
-Use typeof to Check the Type of a Variable
-
-Catch Misspelled Variable and Function Names
-
-Catch Unclosed Parentheses, Brackets, Braces and Quotes
-
-Catch Mixed Usage of Single and Double Quotes
-
-Catch Use of Assignment Operator Instead of Equality Operator
-
-Catch Missing Open and Closing Parenthesis After a Function Call
-
-Catch Arguments Passed in the Wrong Order When Calling a Function
-
-Catch Off By One Errors When Using Indexing
-
-Use Caution When Reinitializing Variables Inside a Loop
-
-Prevent Infinite Loops with a Valid Terminal Condition
\ No newline at end of file
+This section will cover a couple helpful tools to find bugs, and some of the common forms they take. Fortunately, debugging is a learnable skill that just requires a little patience and practice to master.
\ No newline at end of file
diff --git a/02-javascript-algorithms-and-data-structures/es6.md b/02-javascript-algorithms-and-data-structures/es6.md
index 1a15076..0d4b7df 100644
--- a/02-javascript-algorithms-and-data-structures/es6.md
+++ b/02-javascript-algorithms-and-data-structures/es6.md
@@ -23,57 +23,3 @@ The most recent standardized version is called ECMAScript 6 (ES6), released in 2
## Note ##
Not all browsers support ES6 features. If you use ES6 in your own projects, you may need to use a program (transpiler) to convert your ES6 code into ES5 until browsers support ES6.
-
-# Upcoming Lessons #
-
-Explore Differences Between the var and let Keywords
-
-Compare Scopes of the var and let Keywords
-
-Declare a Read-Only Variable with the const Keyword
-
-Mutate an Array Declared with const
-
-Prevent Object Mutation
-
-Use Arrow Functions to Write Concise Anonymous Functions
-
-Write Arrow Functions with Parameters
-
-Write Higher Order Arrow Functions
-
-Set Default Parameters for Your Functions
-
-Use the Rest Operator with Function Parameters
-
-Use the Spread Operator to Evaluate Arrays In-Place
-
-Use Destructuring Assignment to Assign Variables from Objects
-
-Use Destructuring Assignment to Assign Variables from Nested Objects
-
-Use Destructuring Assignment to Assign Variables from Arrays
-
-Use Destructuring Assignment with the Rest Operator to Reassign Array Elements
-
-Use Destructuring Assignment to Pass an Object as a Function's Parameters
-
-Create Strings using Template Literals
-
-Write Concise Object Literal Declarations Using Simple Fields
-
-Write Concise Declarative Functions with ES6
-
-Use class Syntax to Define a Constructor Function
-
-Use getters and setters to Control Access to an Object
-
-Understand the Differences Between import and require
-
-Use export to Reuse a Code Block
-
-Use * to Import Everything from a File
-
-Create an Export Fallback with export default
-
-Import a Default Export
\ No newline at end of file
diff --git a/02-javascript-algorithms-and-data-structures/functional-programming.md b/02-javascript-algorithms-and-data-structures/functional-programming.md
index 76ba821..c731e82 100644
--- a/02-javascript-algorithms-and-data-structures/functional-programming.md
+++ b/02-javascript-algorithms-and-data-structures/functional-programming.md
@@ -12,52 +12,4 @@ Functional programming follows a few core principles:
* Functions have minimal side effects in the program
-The functional programming software development approach breaks a program into small, testable parts. This section covers basic functional programming principles in JavaScript.
-
-# Upcoming Lessons #
-
-Learn About Functional Programming
-
-Understand Functional Programming Terminology
-
-Understand the Hazards of Using Imperative Code
-
-Avoid Mutations and Side Effects Using Functional Programming
-
-Pass Arguments to Avoid External Dependence in a Function
-
-Refactor Global Variables Out of Functions
-
-Use the map Method to Extract Data from an Array
-
-Implement map on a Prototype
-
-Use the filter Method to Extract Data from an Array
-
-Implement the filter Method on a Prototype
-
-Return Part of an Array Using the slice Method
-
-Remove Elements from an Array Using slice Instead of splice
-
-Combine Two Arrays Using the concat Method
-
-Add Elements to the End of an Array Using concat Instead of push
-
-Use the reduce Method to Analyze Data
-
-Sort an Array Alphabetically using the sort Method
-
-Return a Sorted Array Without Changing the Original Array
-
-Split a String into an Array Using the split Method
-
-Combine an Array into a String Using the join Method
-
-Apply Functional Programming to Convert Strings to URL Slugs
-
-Use the every Method to Check that Every Element in an Array Meets a Criteria
-
-Use the some Method to Check that Any Elements in an Array Meet a Criteria
-
-Introduction to Currying and Partial Application
\ No newline at end of file
+The functional programming software development approach breaks a program into small, testable parts. This section covers basic functional programming principles in JavaScript.
\ No newline at end of file
diff --git a/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting.json b/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting.json
index a4a3929..53827f4 100644
--- a/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting.json
+++ b/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting.json
@@ -8,38 +8,38 @@
"id": "a3566b1109230028080c9345",
"title": "Sum All Numbers in a Range",
"description": [
- "We'll pass you an array of two numbers. Return the sum of those two numbers plus the sum of all the numbers between them.",
- "The lowest number will not always come first.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
+ "给出一个含有两个数字的数组,我们需要写一个函数,让它返回这两个数字间所有数字(包含这两个数字)的总和。",
+ "注意,较小数不一定总是出现在数组的第一个元素。",
+ "如果你遇到了问题,请点击 帮助。"
],
"hints": [
- "Use Math.max() to find the maximum value of two numbers.",
- "Use Math.min() to find the minimum value of two numbers.",
- "Remember to that you must add all the numbers in between so this would require a way to get those numbers."
+ "使用 Math.max()
来获取两数中较大的数。",
+ "使用 Math.min()
来获取两数中较小的数。",
+ "注意,既然需要对两数之间的所有数求和,那就先要考虑好如何获取这些数。"
],
"solutions": [
"function sumAll(arr) {\n var sum = 0;\n arr.sort(function(a,b) {return a-b;});\n for (var i = arr[0]; i <= arr[1]; i++) {\n sum += i; \n }\n return sum;\n}"
],
"tests": [
{
- "text": "sumAll([1, 4])
should return a number.",
- "testString": "assert(typeof sumAll([1, 4]) === 'number', 'sumAll([1, 4])
should return a number.');"
+ "text": "sumAll([1, 4])
应该返回一个数字。",
+ "testString": "assert(typeof sumAll([1, 4]) === 'number', 'sumAll([1, 4])
应该返回一个数字。');"
},
{
- "text": "sumAll([1, 4])
should return 10.",
- "testString": "assert.deepEqual(sumAll([1, 4]), 10, 'sumAll([1, 4])
should return 10.');"
+ "text": "sumAll([1, 4])
应该返回 10。",
+ "testString": "assert.deepEqual(sumAll([1, 4]), 10, 'sumAll([1, 4])
应该返回 10。');"
},
{
- "text": "sumAll([4, 1])
should return 10.",
- "testString": "assert.deepEqual(sumAll([4, 1]), 10, 'sumAll([4, 1])
should return 10.');"
+ "text": "sumAll([4, 1])
应该返回 10。",
+ "testString": "assert.deepEqual(sumAll([4, 1]), 10, 'sumAll([4, 1])
应该返回 10。');"
},
{
- "text": "sumAll([5, 10])
should return 45.",
- "testString": "assert.deepEqual(sumAll([5, 10]), 45, 'sumAll([5, 10])
should return 45.');"
+ "text": "sumAll([5, 10])
应该返回 45。",
+ "testString": "assert.deepEqual(sumAll([5, 10]), 45, 'sumAll([5, 10])
应该返回 45。');"
},
{
- "text": "sumAll([10, 5])
should return 45.",
- "testString": "assert.deepEqual(sumAll([10, 5]), 45, 'sumAll([10, 5])
should return 45.');"
+ "text": "sumAll([10, 5])
应该返回 45。",
+ "testString": "assert.deepEqual(sumAll([10, 5]), 45, 'sumAll([10, 5])
应该返回 45。');"
}
],
"MDNlinks": [
@@ -70,73 +70,73 @@
"id": "a5de63ebea8dbee56860f4f2",
"title": "Diff Two Arrays",
"description": [
- "Compare two arrays and return a new array with any items only found in one of the two given arrays, but not both. In other words, return the symmetric difference of the two arrays.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code.",
- "Note
You can return the array with its elements in any order."
+ "在这道题目中,我们需要写一个函数,比较两个数组,返回一个新的数组。这个新数组需要包含传入的两个数组所有元素中,仅在其中一个数组里出现的元素。如果某个元素同时出现在两个数组中,则不应包含在返回的数组里。换言之,我们需要返回这两个数组的对称差。",
+ "如果你遇到了问题,请点击 帮助。",
+ "注意:
返回数组中的元素顺序不会影响测试结果。"
],
"solutions": [
"function diffArray(arr1, arr2) {\n var newArr = [];\n var h1 = Object.create(null);\n arr1.forEach(function(e) {\n h1[e] = e;\n });\n \n var h2 = Object.create(null);\n arr2.forEach(function(e) {\n h2[e] = e;\n });\n \n Object.keys(h1).forEach(function(e) {\n if (!(e in h2)) newArr.push(h1[e]);\n });\n Object.keys(h2).forEach(function(e) {\n if (!(e in h1)) newArr.push(h2[e]);\n });\n // Same, same; but different.\n return newArr;\n}"
],
"tests": [
{
- "text": "diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5])
should return an array.",
- "testString": "assert(typeof diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]) === \"object\", 'diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5])
should return an array.');"
+ "text": "diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5])
应该返回一个数组。",
+ "testString": "assert(typeof diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]) === \"object\", 'diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5])
应该返回一个数组。');"
},
{
- "text": "[\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
should return [\"pink wool\"]
.",
- "testString": "assert.sameMembers(diffArray([\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [\"pink wool\"], '[\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
should return [\"pink wool\"]
.');"
+ "text": "[\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
应该返回 [\"pink wool\"]
。",
+ "testString": "assert.sameMembers(diffArray([\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [\"pink wool\"], '[\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
应该返回 [\"pink wool\"]
。');"
},
{
- "text": "[\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
should return an array with one item.",
- "testString": "assert(diffArray([\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]).length === 1, '[\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
should return an array with one item.');"
+ "text": "[\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
应该返回一个长度为 1 的数组。",
+ "testString": "assert(diffArray([\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]).length === 1, '[\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
应该返回一个长度为 1 的数组。');"
},
{
- "text": "[\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
should return [\"diorite\", \"pink wool\"]
.",
- "testString": "assert.sameMembers(diffArray([\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [\"diorite\", \"pink wool\"], '[\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
should return [\"diorite\", \"pink wool\"]
.');"
+ "text": "[\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
应该返回 [\"diorite\", \"pink wool\"]
。",
+ "testString": "assert.sameMembers(diffArray([\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [\"diorite\", \"pink wool\"], '[\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
应该返回 [\"diorite\", \"pink wool\"]
。');"
},
{
- "text": "[\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
should return an array with two items.",
- "testString": "assert(diffArray([\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]).length === 2, '[\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
should return an array with two items.');"
+ "text": "[\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
应该返回一个长度为 2 的数组。",
+ "testString": "assert(diffArray([\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]).length === 2, '[\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
应该返回一个长度为 2 的数组。');"
},
{
- "text": "[\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
should return []
.",
- "testString": "assert.sameMembers(diffArray([\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [], '[\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
should return []
.');"
+ "text": "[\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
应该返回 []
。",
+ "testString": "assert.sameMembers(diffArray([\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [], '[\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
应该返回 []
。');"
},
{
- "text": "[\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
should return an empty array.",
- "testString": "assert(diffArray([\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]).length === 0, '[\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
should return an empty array.');"
+ "text": "[\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
应该返回一个空数组。",
+ "testString": "assert(diffArray([\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]).length === 0, '[\"andesite\", \"grass\", \"dirt\", \"dead shrub\"], [\"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
应该返回一个空数组。');"
},
{
- "text": "[1, 2, 3, 5], [1, 2, 3, 4, 5]
should return [4]
.",
- "testString": "assert.sameMembers(diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]), [4], '[1, 2, 3, 5], [1, 2, 3, 4, 5]
should return [4]
.');"
+ "text": "[1, 2, 3, 5], [1, 2, 3, 4, 5]
应该返回 [4]
。",
+ "testString": "assert.sameMembers(diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]), [4], '[1, 2, 3, 5], [1, 2, 3, 4, 5]
应该返回 [4]
。');"
},
{
- "text": "[1, 2, 3, 5], [1, 2, 3, 4, 5]
should return an array with one item.",
- "testString": "assert(diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]).length === 1, '[1, 2, 3, 5], [1, 2, 3, 4, 5]
should return an array with one item.');"
+ "text": "[1, 2, 3, 5], [1, 2, 3, 4, 5]
应该返回一个长度为 1 的数组。",
+ "testString": "assert(diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]).length === 1, '[1, 2, 3, 5], [1, 2, 3, 4, 5]
应该返回一个长度为 1 的数组。');"
},
{
- "text": "[1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]
should return [\"piglet\", 4]
.",
- "testString": "assert.sameMembers(diffArray([1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]), [\"piglet\", 4], '[1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]
should return [\"piglet\", 4]
.');"
+ "text": "[1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]
应该返回 [\"piglet\", 4]
。",
+ "testString": "assert.sameMembers(diffArray([1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]), [\"piglet\", 4], '[1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]
应该返回 [\"piglet\", 4]
。');"
},
{
- "text": "[1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]
should return an array with two items.",
- "testString": "assert(diffArray([1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]).length === 2, '[1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]
should return an array with two items.');"
+ "text": "[1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]
应该返回一个长度为 2 的数组。",
+ "testString": "assert(diffArray([1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]).length === 2, '[1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]
应该返回一个长度为 2 的数组。');"
},
{
- "text": "[], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]
should return [\"snuffleupagus\", \"cookie monster\", \"elmo\"]
.",
- "testString": "assert.sameMembers(diffArray([], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]), [\"snuffleupagus\", \"cookie monster\", \"elmo\"], '[], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]
should return [\"snuffleupagus\", \"cookie monster\", \"elmo\"]
.');"
+ "text": "[], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]
应该返回 [\"snuffleupagus\", \"cookie monster\", \"elmo\"]
。",
+ "testString": "assert.sameMembers(diffArray([], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]), [\"snuffleupagus\", \"cookie monster\", \"elmo\"], '[], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]
应该返回 [\"snuffleupagus\", \"cookie monster\", \"elmo\"]
。');"
},
{
- "text": "[], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]
should return an array with three items.",
- "testString": "assert(diffArray([], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]).length === 3, '[], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]
should return an array with three items.');"
+ "text": "[], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]
应该返回一个长度为 3 的数组。",
+ "testString": "assert(diffArray([], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]).length === 3, '[], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]
应该返回一个长度为 3 的数组。');"
},
{
- "text": "[1, \"calf\", 3, \"piglet\"], [7, \"filly\"]
should return [1, \"calf\", 3, \"piglet\", 7, \"filly\"]
.",
- "testString": "assert.sameMembers(diffArray([1, \"calf\", 3, \"piglet\"], [7, \"filly\"]), [1, \"calf\", 3, \"piglet\", 7, \"filly\"], '[1, \"calf\", 3, \"piglet\"], [7, \"filly\"]
should return [1, \"calf\", 3, \"piglet\", 7, \"filly\"]
.');"
+ "text": "[1, \"calf\", 3, \"piglet\"], [7, \"filly\"]
应该返回 [1, \"calf\", 3, \"piglet\", 7, \"filly\"]
。",
+ "testString": "assert.sameMembers(diffArray([1, \"calf\", 3, \"piglet\"], [7, \"filly\"]), [1, \"calf\", 3, \"piglet\", 7, \"filly\"], '[1, \"calf\", 3, \"piglet\"], [7, \"filly\"]
应该返回 [1, \"calf\", 3, \"piglet\", 7, \"filly\"]
。');"
},
{
- "text": "[1, \"calf\", 3, \"piglet\"], [7, \"filly\"]
should return an array with six items.",
- "testString": "assert(diffArray([1, \"calf\", 3, \"piglet\"], [7, \"filly\"]).length === 6, '[1, \"calf\", 3, \"piglet\"], [7, \"filly\"]
should return an array with six items.');"
+ "text": "[1, \"calf\", 3, \"piglet\"], [7, \"filly\"]
应该返回一个长度为 6 的数组。",
+ "testString": "assert(diffArray([1, \"calf\", 3, \"piglet\"], [7, \"filly\"]).length === 6, '[1, \"calf\", 3, \"piglet\"], [7, \"filly\"]
应该返回一个长度为 6 的数组。');"
}
],
"MDNlinks": [
@@ -156,7 +156,7 @@
"contents": [
"function diffArray(arr1, arr2) {",
" var newArr = [];",
- " // Same, same; but different.",
+ " // 这是一个党异伐同的过程",
" return newArr;",
"}",
"",
@@ -171,34 +171,34 @@
"id": "a39963a4c10bc8b4d4f06d7e",
"title": "Seek and Destroy",
"description": [
- "You will be provided with an initial array (the first argument in the destroyer function), followed by one or more arguments. Remove all elements from the initial array that are of the same value as these arguments.",
- "Note
You have to use the arguments
object.",
- "Remember to use Read-Search-Ask if you get stuck. Write your own code."
+ "在这道题目中,我们要写一个叫 destroyer
的函数。传给它的第一个参数是数组,我们称他为初始数组。后续的参数数量是不确定的,可能有一个或多个。你需要做的是,从初始数组中移除所有与后续参数相等的元素,并返回移除元素后的数组。",
+ "注意:
你可以使用 arguments
对象,也可以使用 ...
,即“剩余参数”(Rest Parameters)语法。",
+ "如果你遇到了问题,请点击 帮助。"
],
"tests": [
{
- "text": "destroyer([1, 2, 3, 1, 2, 3], 2, 3)
should return [1, 1]
.",
- "testString": "assert.deepEqual(destroyer([1, 2, 3, 1, 2, 3], 2, 3), [1, 1], 'destroyer([1, 2, 3, 1, 2, 3], 2, 3)
should return [1, 1]
.');"
+ "text": "destroyer([1, 2, 3, 1, 2, 3], 2, 3)
应该返回 [1, 1]
。",
+ "testString": "assert.deepEqual(destroyer([1, 2, 3, 1, 2, 3], 2, 3), [1, 1], 'destroyer([1, 2, 3, 1, 2, 3], 2, 3)
应该返回 [1, 1]
。');"
},
{
- "text": "destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3)
should return [1, 5, 1]
.",
- "testString": "assert.deepEqual(destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3), [1, 5, 1], 'destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3)
should return [1, 5, 1]
.');"
+ "text": "destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3)
应该返回 [1, 5, 1]
。",
+ "testString": "assert.deepEqual(destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3), [1, 5, 1], 'destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3)
应该返回 [1, 5, 1]
。');"
},
{
- "text": "destroyer([3, 5, 1, 2, 2], 2, 3, 5)
should return [1]
.",
- "testString": "assert.deepEqual(destroyer([3, 5, 1, 2, 2], 2, 3, 5), [1], 'destroyer([3, 5, 1, 2, 2], 2, 3, 5)
should return [1]
.');"
+ "text": "destroyer([3, 5, 1, 2, 2], 2, 3, 5)
应该返回 [1]
。",
+ "testString": "assert.deepEqual(destroyer([3, 5, 1, 2, 2], 2, 3, 5), [1], 'destroyer([3, 5, 1, 2, 2], 2, 3, 5)
应该返回 [1]
。');"
},
{
- "text": "destroyer([2, 3, 2, 3], 2, 3)
should return []
.",
- "testString": "assert.deepEqual(destroyer([2, 3, 2, 3], 2, 3), [], 'destroyer([2, 3, 2, 3], 2, 3)
should return []
.');"
+ "text": "destroyer([2, 3, 2, 3], 2, 3)
应该返回 []
。",
+ "testString": "assert.deepEqual(destroyer([2, 3, 2, 3], 2, 3), [], 'destroyer([2, 3, 2, 3], 2, 3)
应该返回 []
。');"
},
{
- "text": "destroyer([\"tree\", \"hamburger\", 53], \"tree\", 53)
should return [\"hamburger\"]
.",
- "testString": "assert.deepEqual(destroyer([\"tree\", \"hamburger\", 53], \"tree\", 53), [\"hamburger\"], 'destroyer([\"tree\", \"hamburger\", 53], \"tree\", 53)
should return [\"hamburger\"]
.');"
+ "text": "destroyer([\"tree\", \"hamburger\", 53], \"tree\", 53)
应该返回 [\"hamburger\"]
。",
+ "testString": "assert.deepEqual(destroyer([\"tree\", \"hamburger\", 53], \"tree\", 53), [\"hamburger\"], 'destroyer([\"tree\", \"hamburger\", 53], \"tree\", 53)
应该返回 [\"hamburger\"]
。');"
},
{
- "text": "destroyer([\"possum\", \"trollo\", 12, \"safari\", \"hotdog\", 92, 65, \"grandma\", \"bugati\", \"trojan\", \"yacht\"], \"yacht\", \"possum\", \"trollo\", \"safari\", \"hotdog\", \"grandma\", \"bugati\", \"trojan\")
should return [12,92,65]
.",
- "testString": "assert.deepEqual(destroyer([\"possum\", \"trollo\", 12, \"safari\", \"hotdog\", 92, 65, \"grandma\", \"bugati\", \"trojan\", \"yacht\"], \"yacht\", \"possum\", \"trollo\", \"safari\", \"hotdog\", \"grandma\", \"bugati\", \"trojan\"), [12,92,65], 'destroyer([\"possum\", \"trollo\", 12, \"safari\", \"hotdog\", 92, 65, \"grandma\", \"bugati\", \"trojan\", \"yacht\"], \"yacht\", \"possum\", \"trollo\", \"safari\", \"hotdog\", \"grandma\", \"bugati\", \"trojan\")
should return [12,92,65]
.');"
+ "text": "destroyer([\"possum\", \"trollo\", 12, \"safari\", \"hotdog\", 92, 65, \"grandma\", \"bugati\", \"trojan\", \"yacht\"], \"yacht\", \"possum\", \"trollo\", \"safari\", \"hotdog\", \"grandma\", \"bugati\", \"trojan\")
应该返回 [12,92,65]
。",
+ "testString": "assert.deepEqual(destroyer([\"possum\", \"trollo\", 12, \"safari\", \"hotdog\", 92, 65, \"grandma\", \"bugati\", \"trojan\", \"yacht\"], \"yacht\", \"possum\", \"trollo\", \"safari\", \"hotdog\", \"grandma\", \"bugati\", \"trojan\"), [12,92,65], 'destroyer([\"possum\", \"trollo\", 12, \"safari\", \"hotdog\", 92, 65, \"grandma\", \"bugati\", \"trojan\", \"yacht\"], \"yacht\", \"possum\", \"trollo\", \"safari\", \"hotdog\", \"grandma\", \"bugati\", \"trojan\")
应该返回 [12,92,65]
。');"
}
],
"isRequired": true,
@@ -217,7 +217,7 @@
"name": "index",
"contents": [
"function destroyer(arr) {",
- " // Remove all the values",
+ " // 删掉那些值",
" return arr;",
"}",
"",
@@ -232,37 +232,37 @@
"id": "a8e512fbe388ac2f9198f0fa",
"title": "Wherefore art thou",
"description": [
- "Make a function that looks through an array of objects (first argument) and returns an array of all objects that have matching name and value pairs (second argument). Each name and value pair of the source object has to be present in the object from the collection if it is to be included in the returned array.",
- "For example, if the first argument is [{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }]
, and the second argument is { last: \"Capulet\" }
, then you must return the third object from the array (the first argument), because it contains the name and its value, that was passed on as the second argument.",
- "Remember to use Read-Search-Ask if you get stuck. Write your own code."
+ "在这道题目中,我们要写一个函数,它接收两个参数:第一个参数是对象数组,第二个参数是一个对象。我们需要从对象数组中找出与第二个参数相等或包含第二个参数的所有对象,并以对象数组的形式返回。其中,相等的意思是原数组中的对象与第二个参数中对象的所有键值对完全相等;包含的意思是只要第二个参数中对象的所有键存在于原数组对象中,且它们对应的值相同即可。",
+ "比如,如果第一个参数是 [{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }]
,第二个参数是 { last: \"Capulet\" }
。那么你需要以对象数组的形式返回第一个参数中的第三个元素,因为它包含第二个参数中定义的键 last
,且对应的值 \"Capulet\"
相同",
+ "如果你遇到了问题,请点击 帮助。"
],
"solutions": [
"function whatIsInAName(collection, source) {\n var arr = [];\n var keys = Object.keys(source);\n collection.forEach(function(e) {\n if(keys.every(function(key) {return e[key] === source[key];})) {\n arr.push(e); \n }\n });\n return arr;\n}"
],
"tests": [
{
- "text": "whatIsInAName([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" })
should return [{ first: \"Tybalt\", last: \"Capulet\" }]
.",
- "testString": "assert.deepEqual(whatIsInAName([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" }), [{ first: \"Tybalt\", last: \"Capulet\" }], 'whatIsInAName([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" })
should return [{ first: \"Tybalt\", last: \"Capulet\" }]
.');"
+ "text": "whatIsInAName([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" })
应该返回 [{ first: \"Tybalt\", last: \"Capulet\" }]
。",
+ "testString": "assert.deepEqual(whatIsInAName([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" }), [{ first: \"Tybalt\", last: \"Capulet\" }], 'whatIsInAName([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" })
应该返回 [{ first: \"Tybalt\", last: \"Capulet\" }]
。');"
},
{
- "text": "whatIsInAName([{ \"apple\": 1 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2 }], { \"apple\": 1 })
should return [{ \"apple\": 1 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2 }]
.",
- "testString": "assert.deepEqual(whatIsInAName([{ \"apple\": 1 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2 }], { \"apple\": 1 }), [{ \"apple\": 1 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2 }], 'whatIsInAName([{ \"apple\": 1 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2 }], { \"apple\": 1 })
should return [{ \"apple\": 1 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2 }]
.');"
+ "text": "whatIsInAName([{ \"apple\": 1 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2 }], { \"apple\": 1 })
应该返回 [{ \"apple\": 1 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2 }]
。",
+ "testString": "assert.deepEqual(whatIsInAName([{ \"apple\": 1 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2 }], { \"apple\": 1 }), [{ \"apple\": 1 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2 }], 'whatIsInAName([{ \"apple\": 1 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2 }], { \"apple\": 1 })
应该返回 [{ \"apple\": 1 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2 }]
。');"
},
{
- "text": "whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], { \"apple\": 1, \"bat\": 2 })
should return [{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }]
.",
- "testString": "assert.deepEqual(whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], { \"apple\": 1, \"bat\": 2 }), [{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], 'whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], { \"apple\": 1, \"bat\": 2 })
should return [{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }]
.');"
+ "text": "whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], { \"apple\": 1, \"bat\": 2 })
应该返回 [{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }]
。",
+ "testString": "assert.deepEqual(whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], { \"apple\": 1, \"bat\": 2 }), [{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], 'whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], { \"apple\": 1, \"bat\": 2 })
应该返回 [{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }]
。');"
},
{
- "text": "whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], { \"apple\": 1, \"cookie\": 2 })
should return [{ \"apple\": 1, \"bat\": 2, \"cookie\": 2 }]
.",
- "testString": "assert.deepEqual(whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], { \"apple\": 1, \"cookie\": 2 }), [{ \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], 'whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], { \"apple\": 1, \"cookie\": 2 })
should return [{ \"apple\": 1, \"bat\": 2, \"cookie\": 2 }]
.');"
+ "text": "whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], { \"apple\": 1, \"cookie\": 2 })
应该返回 [{ \"apple\": 1, \"bat\": 2, \"cookie\": 2 }]
。",
+ "testString": "assert.deepEqual(whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], { \"apple\": 1, \"cookie\": 2 }), [{ \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], 'whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }], { \"apple\": 1, \"cookie\": 2 })
应该返回 [{ \"apple\": 1, \"bat\": 2, \"cookie\": 2 }]
。');"
},
{
- "text": "whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }, { \"bat\":2 }], { \"apple\": 1, \"bat\": 2 })
should return [{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\":2 }]
.",
- "testString": "assert.deepEqual(whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }, {\"bat\":2}], { \"apple\": 1, \"bat\": 2 }), [{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\":2 }], 'whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }, { \"bat\":2 }], { \"apple\": 1, \"bat\": 2 })
should return [{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\":2 }]
.');"
+ "text": "whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }, { \"bat\":2 }], { \"apple\": 1, \"bat\": 2 })
应该返回 [{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\":2 }]
。",
+ "testString": "assert.deepEqual(whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }, {\"bat\":2}], { \"apple\": 1, \"bat\": 2 }), [{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\":2 }], 'whatIsInAName([{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1 }, { \"apple\": 1, \"bat\": 2, \"cookie\": 2 }, { \"bat\":2 }], { \"apple\": 1, \"bat\": 2 })
应该返回 [{ \"apple\": 1, \"bat\": 2 }, { \"apple\": 1, \"bat\": 2, \"cookie\":2 }]
。');"
},
{
- "text": "whatIsInAName([{\"a\": 1, \"b\": 2, \"c\": 3}], {\"a\": 1, \"b\": 9999, \"c\": 3})
should return []
",
- "testString": "assert.deepEqual(whatIsInAName([{ \"a\": 1, \"b\": 2, \"c\": 3 }], { \"a\": 1, \"b\": 9999, \"c\": 3 }), [], 'whatIsInAName([{\"a\": 1, \"b\": 2, \"c\": 3}], {\"a\": 1, \"b\": 9999, \"c\": 3})
should return []
');"
+ "text": "whatIsInAName([{\"a\": 1, \"b\": 2, \"c\": 3}], {\"a\": 1, \"b\": 9999, \"c\": 3})
应该返回 []
。",
+ "testString": "assert.deepEqual(whatIsInAName([{ \"a\": 1, \"b\": 2, \"c\": 3 }], { \"a\": 1, \"b\": 9999, \"c\": 3 }), [], 'whatIsInAName([{\"a\": 1, \"b\": 2, \"c\": 3}], {\"a\": 1, \"b\": 9999, \"c\": 3})
应该返回 []
。');"
}
],
"MDNlinks": [
@@ -281,10 +281,10 @@
"function whatIsInAName(collection, source) {",
" // What's in a name?",
" var arr = [];",
- " // Only change code below this line",
+ " // 请把你的代码写在这条注释以下",
" ",
" ",
- " // Only change code above this line",
+ " // 请把你的代码写在这条注释以上",
" return arr;",
"}",
"",
@@ -299,32 +299,32 @@
"id": "a103376db3ba46b2d50db289",
"title": "Spinal Tap Case",
"description": [
- "Convert a string to spinal case. Spinal case is all-lowercase-words-joined-by-dashes.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
+ "在这道题目中,我们需要写一个函数,把一个字符串转换为“短线连接格式”。短线连接格式的意思是,所有字母都是小写,且用 -
连接。比如,对于 Hello World
,应该转换为 hello-world
;对于 I love_Javascript-VeryMuch
,应该转换为 i-love-javascript-very-much
。",
+ "如果你遇到了问题,请点击 帮助。"
],
"solutions": [
"function spinalCase(str) {\n // \"It's such a fine line between stupid, and clever.\"\n // --David St. Hubbins\n str = str.replace(/([a-z](?=[A-Z]))/g, '$1 ');\n return str.toLowerCase().replace(/\\ |\\_/g, '-');\n}"
],
"tests": [
{
- "text": "spinalCase(\"This Is Spinal Tap\")
should return \"this-is-spinal-tap\"
.",
- "testString": "assert.deepEqual(spinalCase(\"This Is Spinal Tap\"), \"this-is-spinal-tap\", 'spinalCase(\"This Is Spinal Tap\")
should return \"this-is-spinal-tap\"
.');"
+ "text": "spinalCase(\"This Is Spinal Tap\")
应该返回 \"this-is-spinal-tap\"
。",
+ "testString": "assert.deepEqual(spinalCase(\"This Is Spinal Tap\"), \"this-is-spinal-tap\", 'spinalCase(\"This Is Spinal Tap\")
应该返回 \"this-is-spinal-tap\"
。');"
},
{
- "text": "spinalCase(\"thisIsSpinalTap\")
should return \"this-is-spinal-tap\"
.",
- "testString": "assert.strictEqual(spinalCase('thisIsSpinalTap'), \"this-is-spinal-tap\", 'spinalCase(\"thisIsSpinalTap\")
should return \"this-is-spinal-tap\"
.');"
+ "text": "spinalCase(\"thisIsSpinalTap\")
应该返回 \"this-is-spinal-tap\"
。",
+ "testString": "assert.strictEqual(spinalCase('thisIsSpinalTap'), \"this-is-spinal-tap\", 'spinalCase(\"thisIsSpinalTap\")
应该返回 \"this-is-spinal-tap\"
。');"
},
{
- "text": "spinalCase(\"The_Andy_Griffith_Show\")
should return \"the-andy-griffith-show\"
.",
- "testString": "assert.strictEqual(spinalCase(\"The_Andy_Griffith_Show\"), \"the-andy-griffith-show\", 'spinalCase(\"The_Andy_Griffith_Show\")
should return \"the-andy-griffith-show\"
.');"
+ "text": "spinalCase(\"The_Andy_Griffith_Show\")
应该返回 \"the-andy-griffith-show\"
。",
+ "testString": "assert.strictEqual(spinalCase(\"The_Andy_Griffith_Show\"), \"the-andy-griffith-show\", 'spinalCase(\"The_Andy_Griffith_Show\")
应该返回 \"the-andy-griffith-show\"
。');"
},
{
- "text": "spinalCase(\"Teletubbies say Eh-oh\")
should return \"teletubbies-say-eh-oh\"
.",
- "testString": "assert.strictEqual(spinalCase(\"Teletubbies say Eh-oh\"), \"teletubbies-say-eh-oh\", 'spinalCase(\"Teletubbies say Eh-oh\")
should return \"teletubbies-say-eh-oh\"
.');"
+ "text": "spinalCase(\"Teletubbies say Eh-oh\")
应该返回 \"teletubbies-say-eh-oh\"
。",
+ "testString": "assert.strictEqual(spinalCase(\"Teletubbies say Eh-oh\"), \"teletubbies-say-eh-oh\", 'spinalCase(\"Teletubbies say Eh-oh\")
应该返回 \"teletubbies-say-eh-oh\"
。');"
},
{
- "text": "spinalCase(\"AllThe-small Things\")
should return \"all-the-small-things\"
.",
- "testString": "assert.strictEqual(spinalCase(\"AllThe-small Things\"), \"all-the-small-things\", 'spinalCase(\"AllThe-small Things\")
should return \"all-the-small-things\"
.');"
+ "text": "spinalCase(\"AllThe-small Things\")
应该返回 \"all-the-small-things\"
。",
+ "testString": "assert.strictEqual(spinalCase(\"AllThe-small Things\"), \"all-the-small-things\", 'spinalCase(\"AllThe-small Things\")
应该返回 \"all-the-small-things\"
。');"
}
],
"MDNlinks": [
@@ -340,8 +340,7 @@
"name": "index",
"contents": [
"function spinalCase(str) {",
- " // \"It's such a fine line between stupid, and clever.\"",
- " // --David St. Hubbins",
+ "",
" return str;",
"}",
"",
@@ -356,43 +355,43 @@
"id": "aa7697ea2477d1316795783b",
"title": "Pig Latin",
"description": [
- "Translate the provided string to pig latin.",
- "Pig Latin takes the first consonant (or consonant cluster) of an English word, moves it to the end of the word and suffixes an \"ay\".",
- "If a word begins with a vowel you just add \"way\" to the end.",
- "Input strings are guaranteed to be English words in all lowercase.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
+ "在这道题目中,我们需要写一个函数,把传入的字符串翻译成“儿童黑话”。",
+ "儿童黑话的基本转换规则很简单,只需要把一个英文单词的第一个辅音字母或第一组辅音从移到单词的结尾,并在后面加上 ay
即可。在英语中,字母 a、e、i、o、u 为元音,其余的字母均为辅音。辅音从的意思是连续的多个辅音字母。",
+ "额外地,如果单词本身是以元音开头的,那只需要在结尾加上 way
。",
+ "在本题中,传入的单词一定会是英文单词,且所有字母均为小写。",
+ "如果你遇到了问题,请点击 帮助。"
],
"solutions": [
"function translatePigLatin(str) {\n if (isVowel(str.charAt(0))) return str + \"way\";\n var front = [];\n str = str.split('');\n while (str.length && !isVowel(str[0])) {\n front.push(str.shift());\n }\n return [].concat(str, front).join('') + 'ay';\n}\n\nfunction isVowel(c) {\n return ['a', 'e', 'i', 'o', 'u'].indexOf(c.toLowerCase()) !== -1;\n}"
],
"tests": [
{
- "text": "translatePigLatin(\"california\")
should return \"aliforniacay\".",
- "testString": "assert.deepEqual(translatePigLatin(\"california\"), \"aliforniacay\", 'translatePigLatin(\"california\")
should return \"aliforniacay\".');"
+ "text": "translatePigLatin(\"california\")
应该返回 \"aliforniacay\"。",
+ "testString": "assert.deepEqual(translatePigLatin(\"california\"), \"aliforniacay\", 'translatePigLatin(\"california\")
应该返回 \"aliforniacay\"。');"
},
{
- "text": "translatePigLatin(\"paragraphs\")
should return \"aragraphspay\".",
- "testString": "assert.deepEqual(translatePigLatin(\"paragraphs\"), \"aragraphspay\", 'translatePigLatin(\"paragraphs\")
should return \"aragraphspay\".');"
+ "text": "translatePigLatin(\"paragraphs\")
应该返回 \"aragraphspay\"。",
+ "testString": "assert.deepEqual(translatePigLatin(\"paragraphs\"), \"aragraphspay\", 'translatePigLatin(\"paragraphs\")
应该返回 \"aragraphspay\"。');"
},
{
- "text": "translatePigLatin(\"glove\")
should return \"oveglay\".",
- "testString": "assert.deepEqual(translatePigLatin(\"glove\"), \"oveglay\", 'translatePigLatin(\"glove\")
should return \"oveglay\".');"
+ "text": "translatePigLatin(\"glove\")
应该返回 \"oveglay\"。",
+ "testString": "assert.deepEqual(translatePigLatin(\"glove\"), \"oveglay\", 'translatePigLatin(\"glove\")
应该返回 \"oveglay\"。');"
},
{
- "text": "translatePigLatin(\"algorithm\")
should return \"algorithmway\".",
- "testString": "assert.deepEqual(translatePigLatin(\"algorithm\"), \"algorithmway\", 'translatePigLatin(\"algorithm\")
should return \"algorithmway\".');"
+ "text": "translatePigLatin(\"algorithm\")
应该返回 \"algorithmway\"。",
+ "testString": "assert.deepEqual(translatePigLatin(\"algorithm\"), \"algorithmway\", 'translatePigLatin(\"algorithm\")
应该返回 \"algorithmway\"。');"
},
{
- "text": "translatePigLatin(\"eight\")
should return \"eightway\".",
- "testString": "assert.deepEqual(translatePigLatin(\"eight\"), \"eightway\", 'translatePigLatin(\"eight\")
should return \"eightway\".');"
+ "text": "translatePigLatin(\"eight\")
应该返回 \"eightway\"。",
+ "testString": "assert.deepEqual(translatePigLatin(\"eight\"), \"eightway\", 'translatePigLatin(\"eight\")
应该返回 \"eightway\"。');"
},
{
- "text": "Should handle words where the first vowel comes in the end of the word.",
- "testString": "assert.deepEqual(translatePigLatin(\"schwartz\"), \"artzschway\", 'Should handle words where the first vowel comes in the end of the word.');"
+ "text": "你的代码应当能够处理第一个元音字母在单词结尾的情况。比如 translatePigLatin(\"she\")
应该返回 \"eshay\"。",
+ "testString": "assert.deepEqual(translatePigLatin(\"she\"), \"eshay\", '你的代码应当能够处理第一个元音字母在单词结尾的情况。比如 translatePigLatin(\"she\")
应该返回 \"eshay\"。');"
},
{
- "text": "Should handle words without vowels.",
- "testString": "assert.deepEqual(translatePigLatin(\"rhythm\"), \"rhythmay\", 'Should handle words without vowels.');"
+ "text": "你的代码应当能够处理单词中不含元音字母的情况。比如 translatePigLatin(\"rhythm\")
应该返回 \"rhythmay\"。",
+ "testString": "assert.deepEqual(translatePigLatin(\"rhythm\"), \"rhythmay\", '你的代码应当能够处理单词中不含元音字母的情况。比如 translatePigLatin(\"rhythm\")
应该返回 \"rhythmay\"。');"
}
],
"MDNlinks": [
@@ -425,36 +424,36 @@
"id": "a0b5010f579e69b815e7c5d6",
"title": "Search and Replace",
"description": [
- "Perform a search and replace on the sentence using the arguments provided and return the new sentence.",
- "First argument is the sentence to perform the search and replace on.",
- "Second argument is the word that you will be replacing (before).",
- "Third argument is what you will be replacing the second argument with (after).",
- "Note
Preserve the case of the first character in the original word when you are replacing it. For example if you mean to replace the word \"Book\" with the word \"dog\", it should be replaced as \"Dog\"",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
+ "在这道题目中,我们需要写一个字符串的搜索与替换函数,它的返回值为完成替换后的新字符串。",
+ "这个函数接收的第一个参数为待替换的句子。",
+ "第二个参数为句中需要被替换的单词。",
+ "第三个参数为替换后的单词。",
+ "注意:
你需要保留被替换单词首字母的大小写格式。即如果传入的第二个参数为 \"Book\",第三个参数为 \"dog\",那么替换后的结果应为 \"Dog\"",
+ "如果你遇到了问题,请点击 帮助。"
],
"solutions": [
"function myReplace(str, before, after) {\n if (before.charAt(0) === before.charAt(0).toUpperCase()) {\n after = after.charAt(0).toUpperCase() + after.substring(1);\n } else {\n after = after.charAt(0).toLowerCase() + after.substring(1);\n }\n return str.replace(before, after);\n}"
],
"tests": [
{
- "text": "myReplace(\"Let us go to the store\", \"store\", \"mall\")
should return \"Let us go to the mall\".",
- "testString": "assert.deepEqual(myReplace(\"Let us go to the store\", \"store\", \"mall\"), \"Let us go to the mall\", 'myReplace(\"Let us go to the store\", \"store\", \"mall\")
should return \"Let us go to the mall\".');"
+ "text": "myReplace(\"Let us go to the store\", \"store\", \"mall\")
应该返回 \"Let us go to the mall\"。",
+ "testString": "assert.deepEqual(myReplace(\"Let us go to the store\", \"store\", \"mall\"), \"Let us go to the mall\", 'myReplace(\"Let us go to the store\", \"store\", \"mall\")
应该返回 \"Let us go to the mall\"。');"
},
{
- "text": "myReplace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\")
should return \"He is Sitting on the couch\".",
- "testString": "assert.deepEqual(myReplace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\"), \"He is Sitting on the couch\", 'myReplace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\")
should return \"He is Sitting on the couch\".');"
+ "text": "myReplace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\")
应该返回 \"He is Sitting on the couch\"。",
+ "testString": "assert.deepEqual(myReplace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\"), \"He is Sitting on the couch\", 'myReplace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\")
应该返回 \"He is Sitting on the couch\"。');"
},
{
- "text": "myReplace(\"This has a spellngi error\", \"spellngi\", \"spelling\")
should return \"This has a spelling error\".",
- "testString": "assert.deepEqual(myReplace(\"This has a spellngi error\", \"spellngi\", \"spelling\"), \"This has a spelling error\", 'myReplace(\"This has a spellngi error\", \"spellngi\", \"spelling\")
should return \"This has a spelling error\".');"
+ "text": "myReplace(\"This has a spellngi error\", \"spellngi\", \"spelling\")
应该返回 \"This has a spelling error\"。",
+ "testString": "assert.deepEqual(myReplace(\"This has a spellngi error\", \"spellngi\", \"spelling\"), \"This has a spelling error\", 'myReplace(\"This has a spellngi error\", \"spellngi\", \"spelling\")
应该返回 \"This has a spelling error\"。');"
},
{
- "text": "myReplace(\"His name is Tom\", \"Tom\", \"john\")
should return \"His name is John\".",
- "testString": "assert.deepEqual(myReplace(\"His name is Tom\", \"Tom\", \"john\"), \"His name is John\", 'myReplace(\"His name is Tom\", \"Tom\", \"john\")
should return \"His name is John\".');"
+ "text": "myReplace(\"His name is Tom\", \"Tom\", \"john\")
应该返回 \"His name is John\"。",
+ "testString": "assert.deepEqual(myReplace(\"His name is Tom\", \"Tom\", \"john\"), \"His name is John\", 'myReplace(\"His name is Tom\", \"Tom\", \"john\")
应该返回 \"His name is John\"。');"
},
{
- "text": "myReplace(\"Let us get back to more Coding\", \"Coding\", \"algorithms\")
should return \"Let us get back to more Algorithms\".",
- "testString": "assert.deepEqual(myReplace(\"Let us get back to more Coding\", \"Coding\", \"algorithms\"), \"Let us get back to more Algorithms\", 'myReplace(\"Let us get back to more Coding\", \"Coding\", \"algorithms\")
should return \"Let us get back to more Algorithms\".');"
+ "text": "myReplace(\"Let us get back to more Coding\", \"Coding\", \"algorithms\")
应该返回 \"Let us get back to more Algorithms\"。",
+ "testString": "assert.deepEqual(myReplace(\"Let us get back to more Coding\", \"Coding\", \"algorithms\"), \"Let us get back to more Algorithms\", 'myReplace(\"Let us get back to more Coding\", \"Coding\", \"algorithms\")
应该返回 \"Let us get back to more Algorithms\"。');"
}
],
"MDNlinks": [
@@ -485,28 +484,27 @@
"id": "afd15382cdfb22c9efe8b7de",
"title": "DNA Pairing",
"description": [
- "The DNA strand is missing the pairing element. Take each character, get its pair, and return the results as a 2d array.",
- "Base pairs are a pair of AT and CG. Match the missing element to the provided character.",
- "Return the provided character as the first element in each array.",
- "For example, for the input GCG, return [[\"G\", \"C\"], [\"C\",\"G\"],[\"G\", \"C\"]]",
- "The character and its pair are paired up in an array, and all the arrays are grouped into one encapsulating array.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
+ "在这道题目中,我们需要写一个函数,为 DNA 中的碱基配对。这个函数只接收一个表示碱基的字符串为参数,最后返回完成配对的二维数组。",
+ "碱基对 由一对碱基组成。碱基有四种,分别为 A(腺嘌呤)、T(胸腺嘧啶)、G(鸟嘌呤)和 C(胞嘧啶)。配对原则是:A 与 T 配对,C 与 G 配对。我们需要根据这个原则对传入的所有碱基进行配对。",
+ "对于每个传入的碱基,我们应采用数组的形式展示配对结果。其中,传入的碱基需要作为数组的第一个元素出现。最终返回的数组中应当包含参数中每一个碱基的配对结果。",
+ "比如,传入的参数是 GCG,那么函数的返回值应为 [[\"G\", \"C\"], [\"C\",\"G\"],[\"G\", \"C\"]]",
+ "如果你遇到了问题,请点击 帮助。"
],
"solutions": [
"var lookup = Object.create(null);\nlookup.A = 'T';\nlookup.T = 'A';\nlookup.C = 'G';\nlookup.G = 'C';\n\nfunction pairElement(str) {\n return str.split('').map(function(p) {return [p, lookup[p]];});\n}"
],
"tests": [
{
- "text": "pairElement(\"ATCGA\")
should return [[\"A\",\"T\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"G\",\"C\"],[\"A\",\"T\"]]
.",
- "testString": "assert.deepEqual(pairElement(\"ATCGA\"),[[\"A\",\"T\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"G\",\"C\"],[\"A\",\"T\"]], 'pairElement(\"ATCGA\")
should return [[\"A\",\"T\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"G\",\"C\"],[\"A\",\"T\"]]
.');"
+ "text": "pairElement(\"ATCGA\")
应该返回 [[\"A\",\"T\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"G\",\"C\"],[\"A\",\"T\"]]
。",
+ "testString": "assert.deepEqual(pairElement(\"ATCGA\"),[[\"A\",\"T\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"G\",\"C\"],[\"A\",\"T\"]], 'pairElement(\"ATCGA\")
应该返回 [[\"A\",\"T\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"G\",\"C\"],[\"A\",\"T\"]]
。');"
},
{
- "text": "pairElement(\"TTGAG\")
should return [[\"T\",\"A\"],[\"T\",\"A\"],[\"G\",\"C\"],[\"A\",\"T\"],[\"G\",\"C\"]]
.",
- "testString": "assert.deepEqual(pairElement(\"TTGAG\"),[[\"T\",\"A\"],[\"T\",\"A\"],[\"G\",\"C\"],[\"A\",\"T\"],[\"G\",\"C\"]], 'pairElement(\"TTGAG\")
should return [[\"T\",\"A\"],[\"T\",\"A\"],[\"G\",\"C\"],[\"A\",\"T\"],[\"G\",\"C\"]]
.');"
+ "text": "pairElement(\"TTGAG\")
应该返回 [[\"T\",\"A\"],[\"T\",\"A\"],[\"G\",\"C\"],[\"A\",\"T\"],[\"G\",\"C\"]]
。",
+ "testString": "assert.deepEqual(pairElement(\"TTGAG\"),[[\"T\",\"A\"],[\"T\",\"A\"],[\"G\",\"C\"],[\"A\",\"T\"],[\"G\",\"C\"]], 'pairElement(\"TTGAG\")
应该返回 [[\"T\",\"A\"],[\"T\",\"A\"],[\"G\",\"C\"],[\"A\",\"T\"],[\"G\",\"C\"]]
。');"
},
{
- "text": "pairElement(\"CTCTA\")
should return [[\"C\",\"G\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"T\",\"A\"],[\"A\",\"T\"]]
.",
- "testString": "assert.deepEqual(pairElement(\"CTCTA\"),[[\"C\",\"G\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"T\",\"A\"],[\"A\",\"T\"]], 'pairElement(\"CTCTA\")
should return [[\"C\",\"G\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"T\",\"A\"],[\"A\",\"T\"]]
.');"
+ "text": "pairElement(\"CTCTA\")
应该返回 [[\"C\",\"G\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"T\",\"A\"],[\"A\",\"T\"]]
。",
+ "testString": "assert.deepEqual(pairElement(\"CTCTA\"),[[\"C\",\"G\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"T\",\"A\"],[\"A\",\"T\"]], 'pairElement(\"CTCTA\")
应该返回 [[\"C\",\"G\"],[\"T\",\"A\"],[\"C\",\"G\"],[\"T\",\"A\"],[\"A\",\"T\"]]
。');"
}
],
"MDNlinks": [
@@ -536,33 +534,33 @@
"id": "af7588ade1100bde429baf20",
"title": "Missing letters",
"description": [
- "Find the missing letter in the passed letter range and return it.",
- "If all letters are present in the range, return undefined.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
+ "在这道题目中,我们需要写一个函数,找到传入的字符串里缺失的字母并返回它。",
+ "判断缺失的依据是字母顺序,比如 abcdfg 中缺失了 e。而 abcdef 中就没有字母缺失,此时我们需要返回 undefined
。",
+ "如果你遇到了问题,请点击 帮助。"
],
"solutions": [
"function fearNotLetter (str) {\n for (var i = str.charCodeAt(0); i <= str.charCodeAt(str.length - 1); i++) {\n var letter = String.fromCharCode(i);\n if (str.indexOf(letter) === -1) {\n return letter;\n }\n }\n \n return undefined;\n}"
],
"tests": [
{
- "text": "fearNotLetter(\"abce\")
should return \"d\".",
- "testString": "assert.deepEqual(fearNotLetter('abce'), 'd', 'fearNotLetter(\"abce\")
should return \"d\".');"
+ "text": "fearNotLetter(\"abce\")
应该返回 \"d\"。",
+ "testString": "assert.deepEqual(fearNotLetter('abce'), 'd', 'fearNotLetter(\"abce\")
应该返回 \"d\"。');"
},
{
- "text": "fearNotLetter(\"abcdefghjklmno\")
should return \"i\".",
- "testString": "assert.deepEqual(fearNotLetter('abcdefghjklmno'), 'i', 'fearNotLetter(\"abcdefghjklmno\")
should return \"i\".');"
+ "text": "fearNotLetter(\"abcdefghjklmno\")
应该返回 \"i\"。",
+ "testString": "assert.deepEqual(fearNotLetter('abcdefghjklmno'), 'i', 'fearNotLetter(\"abcdefghjklmno\")
应该返回 \"i\"。');"
},
{
- "text": "fearNotLetter(\"stvwx\")
should return \"u\".",
- "testString": "assert.deepEqual(fearNotLetter('stvwx'), 'u', 'fearNotLetter(\"stvwx\")
should return \"u\".');"
+ "text": "fearNotLetter(\"stvwx\")
应该返回 \"u\"。",
+ "testString": "assert.deepEqual(fearNotLetter('stvwx'), 'u', 'fearNotLetter(\"stvwx\")
应该返回 \"u\"。');"
},
{
- "text": "fearNotLetter(\"bcdf\")
should return \"e\".",
- "testString": "assert.deepEqual(fearNotLetter('bcdf'), 'e', 'fearNotLetter(\"bcdf\")
should return \"e\".');"
+ "text": "fearNotLetter(\"bcdf\")
应该返回 \"e\"。",
+ "testString": "assert.deepEqual(fearNotLetter('bcdf'), 'e', 'fearNotLetter(\"bcdf\")
应该返回 \"e\"。');"
},
{
- "text": "fearNotLetter(\"abcdefghijklmnopqrstuvwxyz\")
should return undefined.",
- "testString": "assert.isUndefined(fearNotLetter('abcdefghijklmnopqrstuvwxyz'), 'fearNotLetter(\"abcdefghijklmnopqrstuvwxyz\")
should return undefined.');"
+ "text": "fearNotLetter(\"abcdefghijklmnopqrstuvwxyz\")
应该返回 undefined
。",
+ "testString": "assert.isUndefined(fearNotLetter('abcdefghijklmnopqrstuvwxyz'), 'fearNotLetter(\"abcdefghijklmnopqrstuvwxyz\")
应该返回 undefined
。');"
}
],
"MDNlinks": [
@@ -592,31 +590,30 @@
"id": "a105e963526e7de52b219be9",
"title": "Sorted Union",
"description": [
- "Write a function that takes two or more arrays and returns a new array of unique values in the order of the original provided arrays.",
- "In other words, all values present from all arrays should be included in their original order, but with no duplicates in the final array.",
- "The unique numbers should be sorted by their original order, but the final array should not be sorted in numerical order.",
- "Check the assertion tests for examples.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
+ "在这道题目中,我们需要写一个函数,它接收两个或多个数组为参数。我们需要对这些数组中所有元素进行去除重复元素的处理,并以数组的形式返回去重结果。",
+ "需要注意的是,结果数组中的元素顺序必须与其传入的顺序保持一致。",
+ "如有疑问,请先浏览下方的测试用例。",
+ "如果你遇到了问题,请点击 帮助。"
],
"solutions": [
"function uniteUnique(arr) {\n return [].slice.call(arguments).reduce(function(a, b) {\n return [].concat(a, b.filter(function(e) {return a.indexOf(e) === -1;}));\n }, []);\n}"
],
"tests": [
{
- "text": "uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1])
should return [1, 3, 2, 5, 4]
.",
- "testString": "assert.deepEqual(uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]), [1, 3, 2, 5, 4], 'uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1])
should return [1, 3, 2, 5, 4]
.');"
+ "text": "uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1])
应该返回 [1, 3, 2, 5, 4]
。",
+ "testString": "assert.deepEqual(uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]), [1, 3, 2, 5, 4], 'uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1])
应该返回 [1, 3, 2, 5, 4]
。');"
},
{
- "text": "uniteUnique([1, 3, 2], [1, [5]], [2, [4]])
should return [1, 3, 2, [5], [4]]
.",
- "testString": "assert.deepEqual(uniteUnique([1, 3, 2], [1, [5]], [2, [4]]), [1, 3, 2, [5], [4]], 'uniteUnique([1, 3, 2], [1, [5]], [2, [4]])
should return [1, 3, 2, [5], [4]]
.');"
+ "text": "uniteUnique([1, 3, 2], [1, [5]], [2, [4]])
应该返回 [1, 3, 2, [5], [4]]
。",
+ "testString": "assert.deepEqual(uniteUnique([1, 3, 2], [1, [5]], [2, [4]]), [1, 3, 2, [5], [4]], 'uniteUnique([1, 3, 2], [1, [5]], [2, [4]])
应该返回 [1, 3, 2, [5], [4]]
。');"
},
{
- "text": "uniteUnique([1, 2, 3], [5, 2, 1])
should return [1, 2, 3, 5]
.",
- "testString": "assert.deepEqual(uniteUnique([1, 2, 3], [5, 2, 1]), [1, 2, 3, 5], 'uniteUnique([1, 2, 3], [5, 2, 1])
should return [1, 2, 3, 5]
.');"
+ "text": "uniteUnique([1, 2, 3], [5, 2, 1])
应该返回 [1, 2, 3, 5]
。",
+ "testString": "assert.deepEqual(uniteUnique([1, 2, 3], [5, 2, 1]), [1, 2, 3, 5], 'uniteUnique([1, 2, 3], [5, 2, 1])
应该返回 [1, 2, 3, 5]
。');"
},
{
- "text": "uniteUnique([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8])
should return [1, 2, 3, 5, 4, 6, 7, 8]
.",
- "testString": "assert.deepEqual(uniteUnique([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8]), [1, 2, 3, 5, 4, 6, 7, 8], 'uniteUnique([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8])
should return [1, 2, 3, 5, 4, 6, 7, 8]
.');"
+ "text": "uniteUnique([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8])
应该返回 [1, 2, 3, 5, 4, 6, 7, 8]
。",
+ "testString": "assert.deepEqual(uniteUnique([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8]), [1, 2, 3, 5, 4, 6, 7, 8], 'uniteUnique([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8])
应该返回 [1, 2, 3, 5, 4, 6, 7, 8]
。');"
}
],
"MDNlinks": [
@@ -646,40 +643,40 @@
"id": "a6b0bb188d873cb2c8729495",
"title": "Convert HTML Entities",
"description": [
- "Convert the characters &
, <
, >
, \"
(double quote), and '
(apostrophe), in a string to their corresponding HTML entities.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
+ "在这道题目中,我们需要写一个转换 HTML entity 的函数。需要转换的 HTML entity 有 &
、<
、>
、\"
(双引号)和 '
(单引号)。转换的规则你可以在 W3C 官网找到。",
+ "如果你遇到了问题,请点击 帮助。"
],
"solutions": [
"var MAP = { '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''};\n\nfunction convertHTML(str) {\n return str.replace(/[&<>\"']/g, function(c) {\n return MAP[c];\n });\n}"
],
"tests": [
{
- "text": "convertHTML(\"Dolce & Gabbana\")
should return Dolce & Gabbana
.",
- "testString": "assert.match(convertHTML(\"Dolce & Gabbana\"), /Dolce & Gabbana/, 'convertHTML(\"Dolce & Gabbana\")
should return Dolce & Gabbana
.');"
+ "text": "convertHTML(\"Dolce & Gabbana\")
应该返回 Dolce & Gabbana
。",
+ "testString": "assert.match(convertHTML(\"Dolce & Gabbana\"), /Dolce & Gabbana/, 'convertHTML(\"Dolce & Gabbana\")
应该返回 Dolce & Gabbana
。');"
},
{
- "text": "convertHTML(\"Hamburgers < Pizza < Tacos\")
should return Hamburgers < Pizza < Tacos
.",
- "testString": "assert.match(convertHTML(\"Hamburgers < Pizza < Tacos\"), /Hamburgers < Pizza < Tacos/, 'convertHTML(\"Hamburgers < Pizza < Tacos\")
should return Hamburgers < Pizza < Tacos
.');"
+ "text": "convertHTML(\"Hamburgers < Pizza < Tacos\")
应该返回 Hamburgers < Pizza < Tacos
。",
+ "testString": "assert.match(convertHTML(\"Hamburgers < Pizza < Tacos\"), /Hamburgers < Pizza < Tacos/, 'convertHTML(\"Hamburgers < Pizza < Tacos\")
应该返回 Hamburgers < Pizza < Tacos
。');"
},
{
- "text": "convertHTML(\"Sixty > twelve\")
should return Sixty > twelve
.",
- "testString": "assert.match(convertHTML(\"Sixty > twelve\"), /Sixty > twelve/, 'convertHTML(\"Sixty > twelve\")
should return Sixty > twelve
.');"
+ "text": "convertHTML(\"Sixty > twelve\")
应该返回 Sixty > twelve
。",
+ "testString": "assert.match(convertHTML(\"Sixty > twelve\"), /Sixty > twelve/, 'convertHTML(\"Sixty > twelve\")
应该返回 Sixty > twelve
。');"
},
{
- "text": "convertHTML('Stuff in \"quotation marks\"')
should return Stuff in "quotation marks"
.",
- "testString": "assert.match(convertHTML('Stuff in \"quotation marks\"'), /Stuff in "quotation marks"/, 'convertHTML('Stuff in \"quotation marks\"')
should return Stuff in "quotation marks"
.');"
+ "text": "convertHTML('Stuff in \"quotation marks\"')
应该返回 Stuff in "quotation marks"
。",
+ "testString": "assert.match(convertHTML('Stuff in \"quotation marks\"'), /Stuff in "quotation marks"/, 'convertHTML('Stuff in \"quotation marks\"')
应该返回 Stuff in "quotation marks"
。');"
},
{
- "text": "convertHTML(\"Schindler's List\")
should return Schindler's List
.",
- "testString": "assert.match(convertHTML(\"Schindler's List\"), /Schindler's List/, 'convertHTML(\"Schindler's List\")
should return Schindler's List
.');"
+ "text": "convertHTML(\"Schindler's List\")
应该返回 Schindler's List
。",
+ "testString": "assert.match(convertHTML(\"Schindler's List\"), /Schindler's List/, 'convertHTML(\"Schindler's List\")
应该返回 Schindler's List
。');"
},
{
- "text": "convertHTML(\"<>\")
should return <>
.",
- "testString": "assert.match(convertHTML('<>'), /<>/, 'convertHTML(\"<>\")
should return <>
.');"
+ "text": "convertHTML(\"<>\")
应该返回 <>
。",
+ "testString": "assert.match(convertHTML('<>'), /<>/, 'convertHTML(\"<>\")
应该返回 <>
。');"
},
{
- "text": "convertHTML(\"abc\")
should return abc
.",
- "testString": "assert.strictEqual(convertHTML('abc'), 'abc', 'convertHTML(\"abc\")
should return abc
.');"
+ "text": "convertHTML(\"abc\")
应该返回 abc
。",
+ "testString": "assert.strictEqual(convertHTML('abc'), 'abc', 'convertHTML(\"abc\")
应该返回 abc
。');"
}
],
"MDNlinks": [
@@ -1309,4 +1306,4 @@
}
}
]
-}
\ No newline at end of file
+}
diff --git a/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting.md b/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting.md
index c59fe06..5e14193 100644
--- a/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting.md
+++ b/02-javascript-algorithms-and-data-structures/intermediate-algorithm-scripting.md
@@ -2,46 +2,4 @@
This is a stub introduction
-# Upcoming Lessons #
-
-Sum All Numbers in a Range
-
-Diff Two Arrays
-
-Seek and Destroy
-
-Wherefore art thou
-
-Spinal Tap Case
-
-Pig Latin
-
-Search and Replace
-
-DNA Pairing
-
-Missing letters
-
-Sorted Union
-
-Convert HTML Entities
-
-Sum All Odd Fibonacci Numbers
-
-Sum All Primes
-
-Smallest Common Multiple
-
-Drop it
-
-Steamroller
-
-Binary Agents
-
-Everything Be True
-
-Arguments Optional
-
-Make a Person
-
-Map the Debris
\ No newline at end of file
+Help us make it real on [GitHub](https://github.com/freeCodeCamp/learn/tree/master/src/introductions).
\ No newline at end of file
diff --git a/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects.json b/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects.json
index 7170145..ab46cbc 100644
--- a/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects.json
+++ b/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects.json
@@ -8,65 +8,65 @@
"id": "aaa48de84e1ecc7c742e1124",
"title": "Palindrome Checker",
"description": [
- "Return true
if the given string is a palindrome. Otherwise, return false
.",
- "A palindrome is a word or sentence that's spelled the same way both forward and backward, ignoring punctuation, case, and spacing.",
- "Note
You'll need to remove all non-alphanumeric characters (punctuation, spaces and symbols) and turn everything into the same case (lower or upper case) in order to check for palindromes.",
- "We'll pass strings with varying formats, such as \"racecar\"
, \"RaceCar\"
, and \"race CAR\"
among others.",
- "We'll also pass strings with special symbols, such as \"2A3*3a2\"
, \"2A3 3a2\"
, and \"2_A3*3#A2\"
.",
- "Remember to use Read-Search-Ask if you get stuck. Write your own code."
+ "如果给定的一个字符串是回文,那么返回true
,否则返回false
。",
+ "palindrome(回文),指在忽略标点符号、大小写和空格的前提下,正着读和反着读一模一样。",
+ "注意:
检查回文时,你需要先除去所有非字母数字的字符(标点、空格和符号)并且将所有字符转换成字母大写或字母小写。",
+ "我们将会传入不同格式的字符串,例如:\"racecar\"
、\"RaceCar\"
、\"race CAR\"
等等。",
+ "我们也会传入一些包含特殊符号的字符串,例如\"2A3*3a2\"
,\"2A3 3a2\"
和\"2_A3*3#A2\"
。",
+ "如果你遇到了问题,请点击帮助。"
],
"tests": [
{
- "text": "palindrome(\"eye\")
should return a boolean.",
- "testString": "assert(typeof palindrome(\"eye\") === \"boolean\", 'palindrome(\"eye\")
should return a boolean.');"
+ "text": "palindrome(\"eye\")
应该返回一个布尔值。",
+ "testString": "assert(typeof palindrome(\"eye\") === \"boolean\", 'palindrome(\"eye\")
应该返回一个布尔值。');"
},
{
- "text": "palindrome(\"eye\")
should return true.",
- "testString": "assert(palindrome(\"eye\") === true, 'palindrome(\"eye\")
should return true.');"
+ "text": "palindrome(\"eye\")
应该返回 true。",
+ "testString": "assert(palindrome(\"eye\") === true, 'palindrome(\"eye\")
应该返回 true。');"
},
{
- "text": "palindrome(\"_eye\")
should return true.",
- "testString": "assert(palindrome(\"_eye\") === true, 'palindrome(\"_eye\")
should return true.');"
+ "text": "palindrome(\"_eye\")
应该返回 true。",
+ "testString": "assert(palindrome(\"_eye\") === true, 'palindrome(\"_eye\")
应该返回 true。');"
},
{
- "text": "palindrome(\"race car\")
should return true.",
- "testString": "assert(palindrome(\"race car\") === true, 'palindrome(\"race car\")
should return true.');"
+ "text": "palindrome(\"race car\")
应该返回 true。",
+ "testString": "assert(palindrome(\"race car\") === true, 'palindrome(\"race car\")
应该返回 true。');"
},
{
- "text": "palindrome(\"not a palindrome\")
should return false.",
- "testString": "assert(palindrome(\"not a palindrome\") === false, 'palindrome(\"not a palindrome\")
should return false.');"
+ "text": "palindrome(\"not a palindrome\")
应该返回 false。",
+ "testString": "assert(palindrome(\"not a palindrome\") === false, 'palindrome(\"not a palindrome\")
应该返回 false。');"
},
{
- "text": "palindrome(\"A man, a plan, a canal. Panama\")
should return true.",
- "testString": "assert(palindrome(\"A man, a plan, a canal. Panama\") === true, 'palindrome(\"A man, a plan, a canal. Panama\")
should return true.');"
+ "text": "palindrome(\"A man, a plan, a canal. Panama\")
应该返回 true。",
+ "testString": "assert(palindrome(\"A man, a plan, a canal. Panama\") === true, 'palindrome(\"A man, a plan, a canal. Panama\")
应该返回 true。');"
},
{
- "text": "palindrome(\"never odd or even\")
should return true.",
- "testString": "assert(palindrome(\"never odd or even\") === true, 'palindrome(\"never odd or even\")
should return true.');"
+ "text": "palindrome(\"never odd or even\")
应该返回 true。",
+ "testString": "assert(palindrome(\"never odd or even\") === true, 'palindrome(\"never odd or even\")
应该返回 true。');"
},
{
- "text": "palindrome(\"nope\")
should return false.",
- "testString": "assert(palindrome(\"nope\") === false, 'palindrome(\"nope\")
should return false.');"
+ "text": "palindrome(\"nope\")
应该返回 false。",
+ "testString": "assert(palindrome(\"nope\") === false, 'palindrome(\"nope\")
应该返回 false。');"
},
{
- "text": "palindrome(\"almostomla\")
should return false.",
- "testString": "assert(palindrome(\"almostomla\") === false, 'palindrome(\"almostomla\")
should return false.');"
+ "text": "palindrome(\"almostomla\")
应该返回 false。",
+ "testString": "assert(palindrome(\"almostomla\") === false, 'palindrome(\"almostomla\")
应该返回 false。');"
},
{
- "text": "palindrome(\"My age is 0, 0 si ega ym.\")
should return true.",
- "testString": "assert(palindrome(\"My age is 0, 0 si ega ym.\") === true, 'palindrome(\"My age is 0, 0 si ega ym.\")
should return true.');"
+ "text": "palindrome(\"My age is 0, 0 si ega ym.\")
应该返回 true。",
+ "testString": "assert(palindrome(\"My age is 0, 0 si ega ym.\") === true, 'palindrome(\"My age is 0, 0 si ega ym.\")
应该返回 true。');"
},
{
- "text": "palindrome(\"1 eye for of 1 eye.\")
should return false.",
- "testString": "assert(palindrome(\"1 eye for of 1 eye.\") === false, 'palindrome(\"1 eye for of 1 eye.\")
should return false.');"
+ "text": "palindrome(\"1 eye for of 1 eye.\")
应该返回 false。",
+ "testString": "assert(palindrome(\"1 eye for of 1 eye.\") === false, 'palindrome(\"1 eye for of 1 eye.\")
应该返回 false。');"
},
{
- "text": "palindrome(\"0_0 (: /-\\ :) 0-0\")
should return true.",
- "testString": "assert(palindrome(\"0_0 (: /-\\ :) 0-0\") === true, 'palindrome(\"0_0 (: /-\\ :) 0-0\")
should return true.');"
+ "text": "palindrome(\"0_0 (: /-\\ :) 0-0\")
应该返回 true。",
+ "testString": "assert(palindrome(\"0_0 (: /-\\ :) 0-0\") === true, 'palindrome(\"0_0 (: /-\\ :) 0-0\")
应该返回 true。');"
},
{
- "text": "palindrome(\"five|\\_/|four\")
should return false.",
- "testString": "assert(palindrome(\"five|\\_/|four\") === false, 'palindrome(\"five|\\_/|four\")
should return false.');"
+ "text": "palindrome(\"five|\\_/|four\")
应该返回 false。",
+ "testString": "assert(palindrome(\"five|\\_/|four\") === false, 'palindrome(\"five|\\_/|four\")
应该返回 false。');"
}
],
"isRequired": true,
@@ -102,117 +102,117 @@
"id": "a7f4d8f2483413a6ce226cac",
"title": "Roman Numeral Converter",
"description": [
- "Convert the given number into a roman numeral.",
- "All roman numerals answers should be provided in upper-case.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
+ "把传入的数字转变为罗马数字。",
+ "转换后的罗马数字字母必须都是大写。",
+ "如果你遇到了问题,请点击帮助。"
],
"solutions": [
"function convertToRoman(num) {\n var ref = [['M', 1000], ['CM', 900], ['D', 500], ['CD', 400], ['C', 100], ['XC', 90], ['L', 50], ['XL', 40], ['X', 10], ['IX', 9], ['V', 5], ['IV', 4], ['I', 1]];\n var res = [];\n ref.forEach(function(p) {\n while (num >= p[1]) {\n res.push(p[0]);\n num -= p[1];\n }\n });\n return res.join('');\n}"
],
"tests": [
{
- "text": "convertToRoman(2)
should return \"II\".",
- "testString": "assert.deepEqual(convertToRoman(2), \"II\", 'convertToRoman(2)
should return \"II\".');"
+ "text": "convertToRoman(2)
应该返回 \"II\"。",
+ "testString": "assert.deepEqual(convertToRoman(2), \"II\", 'convertToRoman(2)
应该返回 \"II\"。');"
},
{
- "text": "convertToRoman(3)
should return \"III\".",
- "testString": "assert.deepEqual(convertToRoman(3), \"III\", 'convertToRoman(3)
should return \"III\".');"
+ "text": "convertToRoman(3)
应该返回 \"III\"。",
+ "testString": "assert.deepEqual(convertToRoman(3), \"III\", 'convertToRoman(3)
应该返回 \"III\"。');"
},
{
- "text": "convertToRoman(4)
should return \"IV\".",
- "testString": "assert.deepEqual(convertToRoman(4), \"IV\", 'convertToRoman(4)
should return \"IV\".');"
+ "text": "convertToRoman(4)
应该返回 \"IV\"。",
+ "testString": "assert.deepEqual(convertToRoman(4), \"IV\", 'convertToRoman(4)
应该返回 \"IV\"。');"
},
{
- "text": "convertToRoman(5)
should return \"V\".",
- "testString": "assert.deepEqual(convertToRoman(5), \"V\", 'convertToRoman(5)
should return \"V\".');"
+ "text": "convertToRoman(5)
应该返回 \"V\"。",
+ "testString": "assert.deepEqual(convertToRoman(5), \"V\", 'convertToRoman(5)
应该返回 \"V\"。');"
},
{
- "text": "convertToRoman(9)
should return \"IX\".",
- "testString": "assert.deepEqual(convertToRoman(9), \"IX\", 'convertToRoman(9)
should return \"IX\".');"
+ "text": "convertToRoman(9)
应该返回 \"IX\"。",
+ "testString": "assert.deepEqual(convertToRoman(9), \"IX\", 'convertToRoman(9)
应该返回 \"IX\"。');"
},
{
- "text": "convertToRoman(12)
should return \"XII\".",
- "testString": "assert.deepEqual(convertToRoman(12), \"XII\", 'convertToRoman(12)
should return \"XII\".');"
+ "text": "convertToRoman(12)
应该返回 \"XII\"。",
+ "testString": "assert.deepEqual(convertToRoman(12), \"XII\", 'convertToRoman(12)
应该返回 \"XII\"。');"
},
{
- "text": "convertToRoman(16)
should return \"XVI\".",
- "testString": "assert.deepEqual(convertToRoman(16), \"XVI\", 'convertToRoman(16)
should return \"XVI\".');"
+ "text": "convertToRoman(16)
应该返回 \"XVI\"。",
+ "testString": "assert.deepEqual(convertToRoman(16), \"XVI\", 'convertToRoman(16)
应该返回 \"XVI\"。');"
},
{
- "text": "convertToRoman(29)
should return \"XXIX\".",
- "testString": "assert.deepEqual(convertToRoman(29), \"XXIX\", 'convertToRoman(29)
should return \"XXIX\".');"
+ "text": "convertToRoman(29)
应该返回 \"XXIX\"。",
+ "testString": "assert.deepEqual(convertToRoman(29), \"XXIX\", 'convertToRoman(29)
应该返回 \"XXIX\"。');"
},
{
- "text": "convertToRoman(44)
should return \"XLIV\".",
- "testString": "assert.deepEqual(convertToRoman(44), \"XLIV\", 'convertToRoman(44)
should return \"XLIV\".');"
+ "text": "convertToRoman(44)
应该返回 \"XLIV\"。",
+ "testString": "assert.deepEqual(convertToRoman(44), \"XLIV\", 'convertToRoman(44)
应该返回 \"XLIV\"。');"
},
{
- "text": "convertToRoman(45)
should return \"XLV\"",
- "testString": "assert.deepEqual(convertToRoman(45), \"XLV\", 'convertToRoman(45)
should return \"XLV\"');"
+ "text": "convertToRoman(45)
应该返回 \"XLV\"。",
+ "testString": "assert.deepEqual(convertToRoman(45), \"XLV\", 'convertToRoman(45)
应该返回 \"XLV\"。');"
},
{
- "text": "convertToRoman(68)
should return \"LXVIII\"",
- "testString": "assert.deepEqual(convertToRoman(68), \"LXVIII\", 'convertToRoman(68)
should return \"LXVIII\"');"
+ "text": "convertToRoman(68)
应该返回 \"LXVIII\"。",
+ "testString": "assert.deepEqual(convertToRoman(68), \"LXVIII\", 'convertToRoman(68)
应该返回 \"LXVIII\"。');"
},
{
- "text": "convertToRoman(83)
should return \"LXXXIII\"",
- "testString": "assert.deepEqual(convertToRoman(83), \"LXXXIII\", 'convertToRoman(83)
should return \"LXXXIII\"');"
+ "text": "convertToRoman(83)
应该返回 \"LXXXIII\"。",
+ "testString": "assert.deepEqual(convertToRoman(83), \"LXXXIII\", 'convertToRoman(83)
应该返回 \"LXXXIII\"。');"
},
{
- "text": "convertToRoman(97)
should return \"XCVII\"",
- "testString": "assert.deepEqual(convertToRoman(97), \"XCVII\", 'convertToRoman(97)
should return \"XCVII\"');"
+ "text": "convertToRoman(97)
应该返回 \"XCVII\"。",
+ "testString": "assert.deepEqual(convertToRoman(97), \"XCVII\", 'convertToRoman(97)
应该返回 \"XCVII\"。');"
},
{
- "text": "convertToRoman(99)
should return \"XCIX\"",
- "testString": "assert.deepEqual(convertToRoman(99), \"XCIX\", 'convertToRoman(99)
should return \"XCIX\"');"
+ "text": "convertToRoman(99)
应该返回 \"XCIX\"。",
+ "testString": "assert.deepEqual(convertToRoman(99), \"XCIX\", 'convertToRoman(99)
应该返回 \"XCIX\"。');"
},
{
- "text": "convertToRoman(400)
should return \"CD\"",
- "testString": "assert.deepEqual(convertToRoman(400), \"CD\", 'convertToRoman(400)
should return \"CD\"');"
+ "text": "convertToRoman(400)
应该返回 \"CD\"。",
+ "testString": "assert.deepEqual(convertToRoman(400), \"CD\", 'convertToRoman(400)
应该返回 \"CD\"。');"
},
{
- "text": "convertToRoman(500)
should return \"D\"",
- "testString": "assert.deepEqual(convertToRoman(500), \"D\", 'convertToRoman(500)
should return \"D\"');"
+ "text": "convertToRoman(500)
应该返回 \"D\"。",
+ "testString": "assert.deepEqual(convertToRoman(500), \"D\", 'convertToRoman(500)
应该返回 \"D\"。');"
},
{
- "text": "convertToRoman(501)
should return \"DI\"",
- "testString": "assert.deepEqual(convertToRoman(501), \"DI\", 'convertToRoman(501)
should return \"DI\"');"
+ "text": "convertToRoman(501)
应该返回 \"DI\"。",
+ "testString": "assert.deepEqual(convertToRoman(501), \"DI\", 'convertToRoman(501)
应该返回 \"DI\"。');"
},
{
- "text": "convertToRoman(649)
should return \"DCXLIX\"",
- "testString": "assert.deepEqual(convertToRoman(649), \"DCXLIX\", 'convertToRoman(649)
should return \"DCXLIX\"');"
+ "text": "convertToRoman(649)
应该返回 \"DCXLIX\"。",
+ "testString": "assert.deepEqual(convertToRoman(649), \"DCXLIX\", 'convertToRoman(649)
应该返回 \"DCXLIX\"。');"
},
{
- "text": "convertToRoman(798)
should return \"DCCXCVIII\"",
- "testString": "assert.deepEqual(convertToRoman(798), \"DCCXCVIII\", 'convertToRoman(798)
should return \"DCCXCVIII\"');"
+ "text": "convertToRoman(798)
应该返回 \"DCCXCVIII\"。",
+ "testString": "assert.deepEqual(convertToRoman(798), \"DCCXCVIII\", 'convertToRoman(798)
应该返回 \"DCCXCVIII\"。');"
},
{
- "text": "convertToRoman(891)
should return \"DCCCXCI\"",
- "testString": "assert.deepEqual(convertToRoman(891), \"DCCCXCI\", 'convertToRoman(891)
should return \"DCCCXCI\"');"
+ "text": "convertToRoman(891)
应该返回 \"DCCCXCI\"。",
+ "testString": "assert.deepEqual(convertToRoman(891), \"DCCCXCI\", 'convertToRoman(891)
应该返回 \"DCCCXCI\"。');"
},
{
- "text": "convertToRoman(1000)
should return \"M\"",
- "testString": "assert.deepEqual(convertToRoman(1000), \"M\", 'convertToRoman(1000)
should return \"M\"');"
+ "text": "convertToRoman(1000)
应该返回 \"M\"。",
+ "testString": "assert.deepEqual(convertToRoman(1000), \"M\", 'convertToRoman(1000)
应该返回 \"M\"。');"
},
{
- "text": "convertToRoman(1004)
should return \"MIV\"",
- "testString": "assert.deepEqual(convertToRoman(1004), \"MIV\", 'convertToRoman(1004)
should return \"MIV\"');"
+ "text": "convertToRoman(1004)
应该返回 \"MIV\"。",
+ "testString": "assert.deepEqual(convertToRoman(1004), \"MIV\", 'convertToRoman(1004)
应该返回 \"MIV\"。');"
},
{
- "text": "convertToRoman(1006)
should return \"MVI\"",
- "testString": "assert.deepEqual(convertToRoman(1006), \"MVI\", 'convertToRoman(1006)
should return \"MVI\"');"
+ "text": "convertToRoman(1006)
应该返回 \"MVI\"。",
+ "testString": "assert.deepEqual(convertToRoman(1006), \"MVI\", 'convertToRoman(1006)
应该返回 \"MVI\"。');"
},
{
- "text": "convertToRoman(1023)
should return \"MXXIII\"",
- "testString": "assert.deepEqual(convertToRoman(1023), \"MXXIII\", 'convertToRoman(1023)
should return \"MXXIII\"');"
+ "text": "convertToRoman(1023)
应该返回 \"MXXIII\"。",
+ "testString": "assert.deepEqual(convertToRoman(1023), \"MXXIII\", 'convertToRoman(1023)
应该返回 \"MXXIII\"。');"
},
{
- "text": "convertToRoman(2014)
should return \"MMXIV\"",
- "testString": "assert.deepEqual(convertToRoman(2014), \"MMXIV\", 'convertToRoman(2014)
should return \"MMXIV\"');"
+ "text": "convertToRoman(2014)
应该返回 \"MMXIV\"。",
+ "testString": "assert.deepEqual(convertToRoman(2014), \"MMXIV\", 'convertToRoman(2014)
应该返回 \"MMXIV\"。');"
},
{
- "text": "convertToRoman(3999)
should return \"MMMCMXCIX\"",
- "testString": "assert.deepEqual(convertToRoman(3999), \"MMMCMXCIX\", 'convertToRoman(3999)
should return \"MMMCMXCIX\"');"
+ "text": "convertToRoman(3999)
应该返回 \"MMMCMXCIX\"。",
+ "testString": "assert.deepEqual(convertToRoman(3999), \"MMMCMXCIX\", 'convertToRoman(3999)
应该返回 \"MMMCMXCIX\"。');"
}
],
"MDNlinks": [
@@ -244,31 +244,31 @@
"id": "56533eb9ac21ba0edf2244e2",
"title": "Caesars Cipher",
"description": [
- "One of the simplest and most widely known ciphers is a Caesar cipher
, also known as a shift cipher
. In a shift cipher
the meanings of the letters are shifted by some set amount.",
- "A common modern use is the ROT13 cipher, where the values of the letters are shifted by 13 places. Thus 'A' ↔ 'N', 'B' ↔ 'O' and so on.",
- "Write a function which takes a ROT13 encoded string as input and returns a decoded string.",
- "All letters will be uppercase. Do not transform any non-alphabetic character (i.e. spaces, punctuation), but do pass them on.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
+ "世界上最简单、最著名的加密方法是凯撒密码
,也叫移位密码
。在移位密码
中,明文中的字母通过按照一个固定数目进行偏移后被替换成新的字母。",
+ "ROT13 是一个被广泛使用的编码技术,明文中的所有字母都被移动 13 位。因此,'A' ↔ 'N', 'B' ↔ 'O' 等等。",
+ "请编写一个函数,用于解码一个被 ROT13 编码的字符串,然后返回解码后的结果。",
+ "所有解码后的字母都必须为字母大写。请不要解码非字母的字符(例如,空格、标点符号),但你需要在结果中保留它们。",
+ "如果你遇到了问题,请点击帮助。"
],
"solutions": [
"var lookup = {\n 'A': 'N','B': 'O','C': 'P','D': 'Q',\n 'E': 'R','F': 'S','G': 'T','H': 'U',\n 'I': 'V','J': 'W','K': 'X','L': 'Y',\n 'M': 'Z','N': 'A','O': 'B','P': 'C',\n 'Q': 'D','R': 'E','S': 'F','T': 'G',\n 'U': 'H','V': 'I','W': 'J','X': 'K',\n 'Y': 'L','Z': 'M' \n};\n\nfunction rot13(encodedStr) {\n var codeArr = encodedStr.split(\"\"); // String to Array\n var decodedArr = []; // Your Result goes here\n // Only change code below this line\n \n decodedArr = codeArr.map(function(letter) {\n if(lookup.hasOwnProperty(letter)) {\n letter = lookup[letter];\n }\n return letter;\n });\n\n // Only change code above this line\n return decodedArr.join(\"\"); // Array to String\n}"
],
"tests": [
{
- "text": "rot13(\"SERR PBQR PNZC\")
should decode to FREE CODE CAMP
",
- "testString": "assert(rot13(\"SERR PBQR PNZC\") === \"FREE CODE CAMP\", 'rot13(\"SERR PBQR PNZC\")
should decode to FREE CODE CAMP
');"
+ "text": "rot13(\"SERR PBQR PNZC\")
应解码为FREE CODE CAMP
。",
+ "testString": "assert(rot13(\"SERR PBQR PNZC\") === \"FREE CODE CAMP\", 'rot13(\"SERR PBQR PNZC\")
应解码为FREE CODE CAMP
。');"
},
{
- "text": "rot13(\"SERR CVMMN!\")
should decode to FREE PIZZA!
",
- "testString": "assert(rot13(\"SERR CVMMN!\") === \"FREE PIZZA!\", 'rot13(\"SERR CVMMN!\")
should decode to FREE PIZZA!
');"
+ "text": "rot13(\"SERR CVMMN!\")
应解码为FREE PIZZA!
。",
+ "testString": "assert(rot13(\"SERR CVMMN!\") === \"FREE PIZZA!\", 'rot13(\"SERR CVMMN!\")
应解码为FREE PIZZA!
。');"
},
{
- "text": "rot13(\"SERR YBIR?\")
should decode to FREE LOVE?
",
- "testString": "assert(rot13(\"SERR YBIR?\") === \"FREE LOVE?\", 'rot13(\"SERR YBIR?\")
should decode to FREE LOVE?
');"
+ "text": "rot13(\"SERR YBIR?\")
应解码为FREE LOVE?
。",
+ "testString": "assert(rot13(\"SERR YBIR?\") === \"FREE LOVE?\", 'rot13(\"SERR YBIR?\")
应解码为FREE LOVE?
。');"
},
{
- "text": "rot13(\"GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT.\")
should decode to THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.
",
- "testString": "assert(rot13(\"GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT.\") === \"THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.\", 'rot13(\"GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT.\")
should decode to THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.
');"
+ "text": "rot13(\"GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT.\")
应解码为THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.
。",
+ "testString": "assert(rot13(\"GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT.\") === \"THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.\", 'rot13(\"GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT.\")
应解码为THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.
。');"
}
],
"MDNlinks": [
@@ -301,123 +301,123 @@
"id": "aff0395860f5d3034dc0bfc9",
"title": "Telephone Number Validator",
"description": [
- "Return true
if the passed string looks like a valid US phone number.",
- "The user may fill out the form field any way they choose as long as it has the format of a valid US number. The following are examples of valid formats for US numbers (refer to the tests below for other variants):",
+ "如果传入的字符串是一个有效的美国电话号码格式,则返回true
。",
+ "只要是有效的美国电话号码的格式,用户可以按照他们的方式填写表单中的电话号码。以下是一些正确的例子(其他格式变形请参考以下例子):",
"555-555-5555
(555)555-5555
(555) 555-5555
555 555 5555
5555555555
1 555 555 5555
",
- "For this challenge you will be presented with a string such as 800-692-7753
or 8oo-six427676;laskdjf
. Your job is to validate or reject the US phone number based on any combination of the formats provided above. The area code is required. If the country code is provided, you must confirm that the country code is 1
. Return true
if the string is a valid US phone number; otherwise return false
.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code."
+ "在这个挑战中,你将会看到例如800-692-7753
或者8oo-six427676;laskdjf
的号码。你的任务是根据上面不同的格式组合,判断它是否美国号码。区号是必须的。如果提供国家代码,则必须确认国家代码为1
。如果这是有效的美国电话就返回true
,否则返回false
。",
+ "如果你遇到了问题,请点击帮助。"
],
"solutions": [
"var re = /^([+]?1[\\s]?)?((?:[(](?:[2-9]1[02-9]|[2-9][02-8][0-9])[)][\\s]?)|(?:(?:[2-9]1[02-9]|[2-9][02-8][0-9])[\\s.-]?)){1}([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2}[\\s.-]?){1}([0-9]{4}){1}$/;\n\nfunction telephoneCheck(str) {\n return re.test(str);\n}\n\ntelephoneCheck(\"555-555-5555\");"
],
"tests": [
{
- "text": "telephoneCheck(\"555-555-5555\")
should return a boolean.",
- "testString": "assert(typeof telephoneCheck(\"555-555-5555\") === \"boolean\", 'telephoneCheck(\"555-555-5555\")
should return a boolean.');"
+ "text": "telephoneCheck(\"555-555-5555\")
应该返回布尔值。",
+ "testString": "assert(typeof telephoneCheck(\"555-555-5555\") === \"boolean\", 'telephoneCheck(\"555-555-5555\")
应该返回布尔值。');"
},
{
- "text": "telephoneCheck(\"1 555-555-5555\")
should return true.",
- "testString": "assert(telephoneCheck(\"1 555-555-5555\") === true, 'telephoneCheck(\"1 555-555-5555\")
should return true.');"
+ "text": "telephoneCheck(\"1 555-555-5555\")
应该返回 true。",
+ "testString": "assert(telephoneCheck(\"1 555-555-5555\") === true, 'telephoneCheck(\"1 555-555-5555\")
应该返回 true。');"
},
{
- "text": "telephoneCheck(\"1 (555) 555-5555\")
should return true.",
- "testString": "assert(telephoneCheck(\"1 (555) 555-5555\") === true, 'telephoneCheck(\"1 (555) 555-5555\")
should return true.');"
+ "text": "telephoneCheck(\"1 (555) 555-5555\")
应该返回 true。",
+ "testString": "assert(telephoneCheck(\"1 (555) 555-5555\") === true, 'telephoneCheck(\"1 (555) 555-5555\")
应该返回 true。');"
},
{
- "text": "telephoneCheck(\"5555555555\")
should return true.",
- "testString": "assert(telephoneCheck(\"5555555555\") === true, 'telephoneCheck(\"5555555555\")
should return true.');"
+ "text": "telephoneCheck(\"5555555555\")
应该返回 true。",
+ "testString": "assert(telephoneCheck(\"5555555555\") === true, 'telephoneCheck(\"5555555555\")
应该返回 true。');"
},
{
- "text": "telephoneCheck(\"555-555-5555\")
should return true.",
- "testString": "assert(telephoneCheck(\"555-555-5555\") === true, 'telephoneCheck(\"555-555-5555\")
should return true.');"
+ "text": "telephoneCheck(\"555-555-5555\")
应该返回 true。",
+ "testString": "assert(telephoneCheck(\"555-555-5555\") === true, 'telephoneCheck(\"555-555-5555\")
应该返回 true。');"
},
{
- "text": "telephoneCheck(\"(555)555-5555\")
should return true.",
- "testString": "assert(telephoneCheck(\"(555)555-5555\") === true, 'telephoneCheck(\"(555)555-5555\")
should return true.');"
+ "text": "telephoneCheck(\"(555)555-5555\")
应该返回 true。",
+ "testString": "assert(telephoneCheck(\"(555)555-5555\") === true, 'telephoneCheck(\"(555)555-5555\")
应该返回 true。');"
},
{
- "text": "telephoneCheck(\"1(555)555-5555\")
should return true.",
- "testString": "assert(telephoneCheck(\"1(555)555-5555\") === true, 'telephoneCheck(\"1(555)555-5555\")
should return true.');"
+ "text": "telephoneCheck(\"1(555)555-5555\")
应该返回 true。",
+ "testString": "assert(telephoneCheck(\"1(555)555-5555\") === true, 'telephoneCheck(\"1(555)555-5555\")
应该返回 true。');"
},
{
- "text": "telephoneCheck(\"555-5555\")
should return false.",
- "testString": "assert(telephoneCheck(\"555-5555\") === false, 'telephoneCheck(\"555-5555\")
should return false.');"
+ "text": "telephoneCheck(\"555-5555\")
应该返回 false。",
+ "testString": "assert(telephoneCheck(\"555-5555\") === false, 'telephoneCheck(\"555-5555\")
应该返回 false。');"
},
{
- "text": "telephoneCheck(\"5555555\")
should return false.",
- "testString": "assert(telephoneCheck(\"5555555\") === false, 'telephoneCheck(\"5555555\")
should return false.');"
+ "text": "telephoneCheck(\"5555555\")
应该返回 false。",
+ "testString": "assert(telephoneCheck(\"5555555\") === false, 'telephoneCheck(\"5555555\")
应该返回 false。');"
},
{
- "text": "telephoneCheck(\"1 555)555-5555\")
should return false.",
- "testString": "assert(telephoneCheck(\"1 555)555-5555\") === false, 'telephoneCheck(\"1 555)555-5555\")
should return false.');"
+ "text": "telephoneCheck(\"1 555)555-5555\")
应该返回 false。",
+ "testString": "assert(telephoneCheck(\"1 555)555-5555\") === false, 'telephoneCheck(\"1 555)555-5555\")
应该返回 false。');"
},
{
- "text": "telephoneCheck(\"1 555 555 5555\")
should return true.",
- "testString": "assert(telephoneCheck(\"1 555 555 5555\") === true, 'telephoneCheck(\"1 555 555 5555\")
should return true.');"
+ "text": "telephoneCheck(\"1 555 555 5555\")
应该返回 true。",
+ "testString": "assert(telephoneCheck(\"1 555 555 5555\") === true, 'telephoneCheck(\"1 555 555 5555\")
应该返回 true。');"
},
{
- "text": "telephoneCheck(\"1 456 789 4444\")
should return true.",
- "testString": "assert(telephoneCheck(\"1 456 789 4444\") === true, 'telephoneCheck(\"1 456 789 4444\")
should return true.');"
+ "text": "telephoneCheck(\"1 456 789 4444\")
应该返回 true。",
+ "testString": "assert(telephoneCheck(\"1 456 789 4444\") === true, 'telephoneCheck(\"1 456 789 4444\")
应该返回 true。');"
},
{
- "text": "telephoneCheck(\"123**&!!asdf#\")
should return false.",
- "testString": "assert(telephoneCheck(\"123**&!!asdf#\") === false, 'telephoneCheck(\"123**&!!asdf#\")
should return false.');"
+ "text": "telephoneCheck(\"123**&!!asdf#\")
应该返回 false。",
+ "testString": "assert(telephoneCheck(\"123**&!!asdf#\") === false, 'telephoneCheck(\"123**&!!asdf#\")
应该返回 false。');"
},
{
- "text": "telephoneCheck(\"55555555\")
should return false.",
- "testString": "assert(telephoneCheck(\"55555555\") === false, 'telephoneCheck(\"55555555\")
should return false.');"
+ "text": "telephoneCheck(\"55555555\")
应该返回 false。",
+ "testString": "assert(telephoneCheck(\"55555555\") === false, 'telephoneCheck(\"55555555\")
应该返回 false。');"
},
{
- "text": "telephoneCheck(\"(6054756961)\")
should return false",
- "testString": "assert(telephoneCheck(\"(6054756961)\") === false, 'telephoneCheck(\"(6054756961)\")
should return false');"
+ "text": "telephoneCheck(\"(6054756961)\")
应该返回 false。",
+ "testString": "assert(telephoneCheck(\"(6054756961)\") === false, 'telephoneCheck(\"(6054756961)\")
应该返回 false。');"
},
{
- "text": "telephoneCheck(\"2 (757) 622-7382\")
should return false.",
- "testString": "assert(telephoneCheck(\"2 (757) 622-7382\") === false, 'telephoneCheck(\"2 (757) 622-7382\")
should return false.');"
+ "text": "telephoneCheck(\"2 (757) 622-7382\")
应该返回 false。",
+ "testString": "assert(telephoneCheck(\"2 (757) 622-7382\") === false, 'telephoneCheck(\"2 (757) 622-7382\")
应该返回 false。');"
},
{
- "text": "telephoneCheck(\"0 (757) 622-7382\")
should return false.",
- "testString": "assert(telephoneCheck(\"0 (757) 622-7382\") === false, 'telephoneCheck(\"0 (757) 622-7382\")
should return false.');"
+ "text": "telephoneCheck(\"0 (757) 622-7382\")
应该返回 false。",
+ "testString": "assert(telephoneCheck(\"0 (757) 622-7382\") === false, 'telephoneCheck(\"0 (757) 622-7382\")
应该返回 false。');"
},
{
- "text": "telephoneCheck(\"-1 (757) 622-7382\")
should return false",
- "testString": "assert(telephoneCheck(\"-1 (757) 622-7382\") === false, 'telephoneCheck(\"-1 (757) 622-7382\")
should return false');"
+ "text": "telephoneCheck(\"-1 (757) 622-7382\")
应该返回 false。",
+ "testString": "assert(telephoneCheck(\"-1 (757) 622-7382\") === false, 'telephoneCheck(\"-1 (757) 622-7382\")
应该返回 false。');"
},
{
- "text": "telephoneCheck(\"2 757 622-7382\")
should return false.",
- "testString": "assert(telephoneCheck(\"2 757 622-7382\") === false, 'telephoneCheck(\"2 757 622-7382\")
should return false.');"
+ "text": "telephoneCheck(\"2 757 622-7382\")
应该返回 false。",
+ "testString": "assert(telephoneCheck(\"2 757 622-7382\") === false, 'telephoneCheck(\"2 757 622-7382\")
应该返回 false。');"
},
{
- "text": "telephoneCheck(\"10 (757) 622-7382\")
should return false.",
- "testString": "assert(telephoneCheck(\"10 (757) 622-7382\") === false, 'telephoneCheck(\"10 (757) 622-7382\")
should return false.');"
+ "text": "telephoneCheck(\"10 (757) 622-7382\")
应该返回 false。",
+ "testString": "assert(telephoneCheck(\"10 (757) 622-7382\") === false, 'telephoneCheck(\"10 (757) 622-7382\")
应该返回 false。');"
},
{
- "text": "telephoneCheck(\"27576227382\")
should return false.",
- "testString": "assert(telephoneCheck(\"27576227382\") === false, 'telephoneCheck(\"27576227382\")
should return false.');"
+ "text": "telephoneCheck(\"27576227382\")
应该返回 false。",
+ "testString": "assert(telephoneCheck(\"27576227382\") === false, 'telephoneCheck(\"27576227382\")
应该返回 false。');"
},
{
- "text": "telephoneCheck(\"(275)76227382\")
should return false.",
- "testString": "assert(telephoneCheck(\"(275)76227382\") === false, 'telephoneCheck(\"(275)76227382\")
should return false.');"
+ "text": "telephoneCheck(\"(275)76227382\")
应该返回 false。",
+ "testString": "assert(telephoneCheck(\"(275)76227382\") === false, 'telephoneCheck(\"(275)76227382\")
应该返回 false。');"
},
{
- "text": "telephoneCheck(\"2(757)6227382\")
should return false.",
- "testString": "assert(telephoneCheck(\"2(757)6227382\") === false, 'telephoneCheck(\"2(757)6227382\")
should return false.');"
+ "text": "telephoneCheck(\"2(757)6227382\")
应该返回 false。",
+ "testString": "assert(telephoneCheck(\"2(757)6227382\") === false, 'telephoneCheck(\"2(757)6227382\")
应该返回 false。');"
},
{
- "text": "telephoneCheck(\"2(757)622-7382\")
should return false.",
- "testString": "assert(telephoneCheck(\"2(757)622-7382\") === false, 'telephoneCheck(\"2(757)622-7382\")
should return false.');"
+ "text": "telephoneCheck(\"2(757)622-7382\")
应该返回 false。",
+ "testString": "assert(telephoneCheck(\"2(757)622-7382\") === false, 'telephoneCheck(\"2(757)622-7382\")
应该返回 false。');"
},
{
- "text": "telephoneCheck(\"555)-555-5555\")
should return false.",
- "testString": "assert(telephoneCheck(\"555)-555-5555\") === false, 'telephoneCheck(\"555)-555-5555\")
should return false.');"
+ "text": "telephoneCheck(\"555)-555-5555\")
应该返回 false。",
+ "testString": "assert(telephoneCheck(\"555)-555-5555\") === false, 'telephoneCheck(\"555)-555-5555\")
应该返回 false。');"
},
{
- "text": "telephoneCheck(\"(555-555-5555\")
should return false.",
- "testString": "assert(telephoneCheck(\"(555-555-5555\") === false, 'telephoneCheck(\"(555-555-5555\")
should return false.');"
+ "text": "telephoneCheck(\"(555-555-5555\")
应该返回 false。",
+ "testString": "assert(telephoneCheck(\"(555-555-5555\") === false, 'telephoneCheck(\"(555-555-5555\")
应该返回 false。');"
},
{
- "text": "telephoneCheck(\"(555)5(55?)-5555\")
should return false.",
- "testString": "assert(telephoneCheck(\"(555)5(55?)-5555\") === false, 'telephoneCheck(\"(555)5(55?)-5555\")
should return false.');"
+ "text": "telephoneCheck(\"(555)5(55?)-5555\")
应该返回 false。",
+ "testString": "assert(telephoneCheck(\"(555)5(55?)-5555\") === false, 'telephoneCheck(\"(555)5(55?)-5555\")
应该返回 false。');"
}
],
"MDNlinks": [
@@ -447,42 +447,42 @@
"id": "aa2e6f85cab2ab736c9a9b24",
"title": "Cash Register",
"description": [
- "Design a cash register drawer function checkCashRegister()
that accepts purchase price as the first argument (price
), payment as the second argument (cash
), and cash-in-drawer (cid
) as the third argument.",
- "cid
is a 2D array listing available currency.",
- "The checkCashRegister()
function should always return an object with a status
key and a change
key.",
- "Return {status: \"INSUFFICIENT_FUNDS\", change: []}
if cash-in-drawer is less than the change due, or if you cannot return the exact change.",
- "Return {status: \"CLOSED\", change: [...]}
with cash-in-drawer as the value for the key change
if it is equal to the change due.",
- "Otherwise, return {status: \"OPEN\", change: [...]}
, with the change due in coins and bills, sorted in highest to lowest order, as the value of the change
key.",
- "Remember to use Read-Search-Ask if you get stuck. Try to pair program. Write your own code.",
- "Currency Unit Amount Penny $0.01 (PENNY) Nickel $0.05 (NICKEL) Dime $0.1 (DIME) Quarter $0.25 (QUARTER) Dollar $1 (DOLLAR) Five Dollars $5 (FIVE) Ten Dollars $10 (TEN) Twenty Dollars $20 (TWENTY) One-hundred Dollars $100 (ONE HUNDRED)
"
+ "编写一个用于收银机的函数checkCashRegister()
、传入售价为第一个参数(price
)、支付金额为第二个参数(price
)、收银机內的金额为第三个参数(cid
)。",
+ "cid
是包含货币面值的二维数组。",
+ "函数checkCashRegister()
必须返回含有status
键值和change
键值的对象。",
+ "如果收银机內的金额少于应找回的零钱数,或者你无法返回确切的数目时,返回{status: \"INSUFFICIENT_FUNDS\", change: []}
。",
+ "如果收银机內的金额等于应找回的零钱数,返回{status: \"CLOSED\", change: [...]}
,其中change
键值是收银机內的金额。",
+ "否则,返回{status: \"OPEN\", change: [...]}
,其中change
键值是应找回的零钱数,并且它的面值由高到低排序。",
+ "如果你遇到了问题,请点击帮助。",
+ "货币单位 | 面值 |
---|---|
Penny | $0.01 (PENNY) |
Nickel | $0.05 (NICKEL) |
Dime | $0.1 (DIME) |
Quarter | $0.25 (QUARTER) |
Dollar | $1 (DOLLAR) |
Five Dollars | $5 (FIVE) |
Ten Dollars | $10 (TEN) |
Twenty Dollars | $20 (TWENTY) |
One-hundred Dollars | $100 (ONE HUNDRED) |
checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])
should return an object.",
- "testString": "assert.deepEqual(Object.prototype.toString.call(checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])), '[object Object]', 'checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])
should return an object.');"
+ "text": "checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])
应该返回一个对象。",
+ "testString": "assert.deepEqual(Object.prototype.toString.call(checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])), '[object Object]', 'checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])
应该返回一个对象。');"
},
{
- "text": "checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])
should return {status: \"OPEN\", change: [[\"QUARTER\", 0.5]]}
.",
- "testString": "assert.deepEqual(checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]]), {status: \"OPEN\", change: [[\"QUARTER\", 0.5]]}, 'checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])
should return {status: \"OPEN\", change: [[\"QUARTER\", 0.5]]}
.');"
+ "text": "checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])
应该返回{status: \"OPEN\", change: [[\"QUARTER\", 0.5]]}
。",
+ "testString": "assert.deepEqual(checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]]), {status: \"OPEN\", change: [[\"QUARTER\", 0.5]]}, 'checkCashRegister(19.5, 20, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])
应该返回{status: \"OPEN\", change: [[\"QUARTER\", 0.5]]}
。');"
},
{
- "text": "checkCashRegister(3.26, 100, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])
should return {status: \"OPEN\", change: [[\"TWENTY\", 60], [\"TEN\", 20], [\"FIVE\", 15], [\"ONE\", 1], [\"QUARTER\", 0.5], [\"DIME\", 0.2], [\"PENNY\", 0.04]]}
.",
- "testString": "assert.deepEqual(checkCashRegister(3.26, 100, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]]), {status: \"OPEN\", change: [[\"TWENTY\", 60], [\"TEN\", 20], [\"FIVE\", 15], [\"ONE\", 1], [\"QUARTER\", 0.5], [\"DIME\", 0.2], [\"PENNY\", 0.04]]}, 'checkCashRegister(3.26, 100, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])
should return {status: \"OPEN\", change: [[\"TWENTY\", 60], [\"TEN\", 20], [\"FIVE\", 15], [\"ONE\", 1], [\"QUARTER\", 0.5], [\"DIME\", 0.2], [\"PENNY\", 0.04]]}
.');"
+ "text": "checkCashRegister(3.26, 100, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])
应该返回{status: \"OPEN\", change: [[\"TWENTY\", 60], [\"TEN\", 20], [\"FIVE\", 15], [\"ONE\", 1], [\"QUARTER\", 0.5], [\"DIME\", 0.2], [\"PENNY\", 0.04]]}
。",
+ "testString": "assert.deepEqual(checkCashRegister(3.26, 100, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]]), {status: \"OPEN\", change: [[\"TWENTY\", 60], [\"TEN\", 20], [\"FIVE\", 15], [\"ONE\", 1], [\"QUARTER\", 0.5], [\"DIME\", 0.2], [\"PENNY\", 0.04]]}, 'checkCashRegister(3.26, 100, [[\"PENNY\", 1.01], [\"NICKEL\", 2.05], [\"DIME\", 3.1], [\"QUARTER\", 4.25], [\"ONE\", 90], [\"FIVE\", 55], [\"TEN\", 20], [\"TWENTY\", 60], [\"ONE HUNDRED\", 100]])
应该返回{status: \"OPEN\", change: [[\"TWENTY\", 60], [\"TEN\", 20], [\"FIVE\", 15], [\"ONE\", 1], [\"QUARTER\", 0.5], [\"DIME\", 0.2], [\"PENNY\", 0.04]]}
。');"
},
{
- "text": "checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])
should return {status: \"INSUFFICIENT_FUNDS\", change: []}
.",
- "testString": "assert.deepEqual(checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), {status: \"INSUFFICIENT_FUNDS\", change: []}, 'checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])
should return {status: \"INSUFFICIENT_FUNDS\", change: []}
.');"
+ "text": "checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])
应该返回{status: \"INSUFFICIENT_FUNDS\", change: []}
。",
+ "testString": "assert.deepEqual(checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), {status: \"INSUFFICIENT_FUNDS\", change: []}, 'checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])
应该返回{status: \"INSUFFICIENT_FUNDS\", change: []}
。');"
},
{
- "text": "checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 1], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])
should return {status: \"INSUFFICIENT_FUNDS\", change: []}
.",
- "testString": "assert.deepEqual(checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 1], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), {status: \"INSUFFICIENT_FUNDS\", change: []}, 'checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 1], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])
should return {status: \"INSUFFICIENT_FUNDS\", change: []}
.');"
+ "text": "checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 1], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])
应该返回{status: \"INSUFFICIENT_FUNDS\", change: []}
。",
+ "testString": "assert.deepEqual(checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 1], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), {status: \"INSUFFICIENT_FUNDS\", change: []}, 'checkCashRegister(19.5, 20, [[\"PENNY\", 0.01], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 1], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])
应该返回{status: \"INSUFFICIENT_FUNDS\", change: []}
。');"
},
{
- "text": "checkCashRegister(19.5, 20, [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])
should return {status: \"CLOSED\", change: [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]}
.",
- "testString": "assert.deepEqual(checkCashRegister(19.5, 20, [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), {status: \"CLOSED\", change: [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]}, 'checkCashRegister(19.5, 20, [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])
should return {status: \"CLOSED\", change: [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]}
.');"
+ "text": "checkCashRegister(19.5, 20, [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])
应该返回{status: \"CLOSED\", change: [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]}
。",
+ "testString": "assert.deepEqual(checkCashRegister(19.5, 20, [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]), {status: \"CLOSED\", change: [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]}, 'checkCashRegister(19.5, 20, [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]])
应该返回{status: \"CLOSED\", change: [[\"PENNY\", 0.5], [\"NICKEL\", 0], [\"DIME\", 0], [\"QUARTER\", 0], [\"ONE\", 0], [\"FIVE\", 0], [\"TEN\", 0], [\"TWENTY\", 0], [\"ONE HUNDRED\", 0]]}
。');"
}
],
"isRequired": true,
diff --git a/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects.md b/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects.md
index f24f147..6123a26 100644
--- a/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects.md
+++ b/02-javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects.md
@@ -15,15 +15,3 @@ In this section you will create the following small JavaScript programs:
Have fun and remember to use the Read-Search-Ask method if you get stuck.
Good Luck!
-
-# Upcoming Lessons #
-
-Palindrome Checker
-
-Roman Numeral Converter
-
-Caesars Cipher
-
-Telephone Number Validator
-
-Cash Register
\ No newline at end of file
diff --git a/02-javascript-algorithms-and-data-structures/object-oriented-programming.json b/02-javascript-algorithms-and-data-structures/object-oriented-programming.json
index 18d0f52..e55e814 100644
--- a/02-javascript-algorithms-and-data-structures/object-oriented-programming.json
+++ b/02-javascript-algorithms-and-data-structures/object-oriented-programming.json
@@ -8,27 +8,27 @@
"id": "587d7dac367417b2b2512b73",
"title": "Create a Basic JavaScript Object",
"description": [
- "Think about things people see everyday, like cars, shops, and birds. These are all objects
: tangible things people can observe and interact with.",
- "What are some qualities of these objects
? A car has wheels. Shops sell items. Birds have wings.",
- "These qualities, or properties
, define what makes up an object
. Note that similar objects
share the same properties
, but may have different values for those properties
. For example, all cars have wheels, but not all cars have the same number of wheels.",
- "Objects
in JavaScript are used to model real-world objects, giving them properties
and behavior just like their real-world counterparts. Here's an example using these concepts to create a duck
object
:",
+ "想想我们在生活中每天都可见到的事物:比如汽车、商店以及小鸟等。它们都是物体
:即人们可以观察和与之互动的实体事物。",
+ "那么这些物体
都有哪些特征呢?比如汽车的特征是有轮子,商店是用来出售商品的,而小鸟的特征是有翅膀。",
+ "这些特征,或者说是属性
定义了一个物体
由什么构成的。需要注意的是:那些相似的物体
可以拥有相同的属性
,但是这些属性
可能会有不同的值。举个例子:所有的汽车都有轮子,但并不是所有汽车的轮子个数都是一样的。",
+ "JavaScript 中的对象
可以用来描述现实世界中的物体,并赋予他们属性
和行为,就像它们在现实世界中的对应物一样。下面是使用这些概念来创建一个duck 对象
的示例:",
"let duck = {", - "This
name: \"Aflac\",
numLegs: 2
};
duck
object
has two property/value pairs: a name
of \"Aflac\" and a numLegs
of 2.",
+ "这个duck 对象
有两组键值对:一个是name
属性,它的值是 \"Aflac\";另一个是numLegs
属性,它的值是 2。",
"dog
object
with name
and numLegs
properties, and set them to a string and a number, respectively."
+ "创建一个dog 对象
,并给这个对象添加两个属性:name
和numLegs
,同时把这两个属性的值分别设为字符串和数字。"
],
"tests": [
{
- "text": "dog
should be an object
.",
- "testString": "assert(typeof(dog) === 'object', 'dog
should be an object
.');"
+ "text": "dog
应该是一个object
。",
+ "testString": "assert(typeof(dog) === 'object', 'dog
应该是一个object
');"
},
{
- "text": "dog
should have a name
property set to a string
.",
- "testString": "assert(typeof(dog.name) === 'string', 'dog
should have a name
property set to a string
.');"
+ "text": "dog
应该有一个name
属性,且它的值是一个字符串。",
+ "testString": "assert(typeof(dog.name) === 'string', 'dog
应该有一个name
属性,且它的值是一个字符串。');"
},
{
- "text": "dog
should have a numLegs
property set to a number
.",
- "testString": "assert(typeof(dog.numLegs) === 'number', 'dog
should have a numLegs
property set to a number
.');"
+ "text": "dog
应该有一个numLegs
属性,且它的值是一个数字
。",
+ "testString": "assert(typeof(dog.numLegs) === 'number', 'dog
应该有一个numLegs
属性,且它的值是一个数字
。');"
}
],
"solutions": [
@@ -56,20 +56,20 @@
"id": "587d7dac367417b2b2512b74",
"title": "Use Dot Notation to Access the Properties of an Object",
"description": [
- "The last challenge created an object
with various properties
, now you'll see how to access the values of those properties
. Here's an example:",
- "let duck = {
name: \"Aflac\",
numLegs: 2
};
console.log(duck.name);
// This prints \"Aflac\" to the console
",
- "Dot notation is used on the object
name, duck
, followed by the name of the property
, name
, to access the value of \"Aflac\".",
+ "在上一个挑战中,我们创建了一个拥有不同属性
的对象
,现在我们来看看该如何访问这些属性
:",
+ "let duck = {
name: \"Aflac\",
numLegs: 2
};
console.log(duck.name);
// 这段代码会在控制台中输出 \"Aflac\"
",
+ "我们可以用“点号表示法”来访问对象的属性,只需要在对象
名称后面加上.
以及属性
名即可。比如,duck.name
就可以访问到 \"Aflac\"。",
"
",
- "Print both properties
of the dog
object below to your console."
+ "请在控制台里面输出dog
对象中两个属性
对应的值。"
],
"tests": [
{
- "text": "Your should use console.log
to print the value for the name
property of the dog
object.",
- "testString": "assert(/console.log\\(.*dog\\.name.*\\)/g.test(code), 'Your should use console.log
to print the value for the name
property of the dog
object.');"
+ "text": "你应该使用console.log
来将dog
对象的name
属性值输出到控制台。",
+ "testString": "assert(/console.log\\(.*dog\\.name.*\\)/g.test(code), '你应该使用console.log
来将dog
对象的name
属性值输出到控制台。');"
},
{
- "text": "Your should use console.log
to print the value for the numLegs
property of the dog
object.",
- "testString": "assert(/console.log\\(.*dog\\.numLegs.*\\)/g.test(code), 'Your should use console.log
to print the value for the numLegs
property of the dog
object.');"
+ "text": "你应该使用console.log
来将dog
对象的numLegs
属性值输出到控制台。",
+ "testString": "assert(/console.log\\(.*dog\\.numLegs.*\\)/g.test(code), '你应该使用console.log
来将dog
对象的numLegs
属性值输出到控制台。');"
}
],
"solutions": [
@@ -88,7 +88,7 @@
" name: \"Spot\",",
" numLegs: 4",
"};",
- "// Add your code below this line",
+ "// 请把你的代码写在这条注释以下 ",
"",
""
],
@@ -101,22 +101,22 @@
"id": "587d7dad367417b2b2512b75",
"title": "Create a Method on an Object",
"description": [
- "Objects
can have a special type of property
, called a method
.",
- "Methods
are properties
that are functions. This adds different behavior to an object
. Here is the duck
example with a method:",
- "let duck = {
name: \"Aflac\",
numLegs: 2,
sayName: function() {return \"The name of this duck is \" + duck.name + \".\";}
};
duck.sayName();
// Returns \"The name of this duck is Aflac.\"
",
- "The example adds the sayName
method
, which is a function that returns a sentence giving the name of the duck
.",
- "Notice that the method
accessed the name
property in the return statement using duck.name
. The next challenge will cover another way to do this.",
+ "对象
可以有一个叫做方法
的特殊属性
。",
+ "方法
其实是一个值为函数的属性
,它可以为一个对象
添加不同的行为。以下就是一个带有方法属性的duck
示例:",
+ "let duck = {
name: \"Aflac\",
numLegs: 2,
sayName: function() {return \"The name of this duck is \" + duck.name + \".\";}
};
duck.sayName();
// 返回了: \"The name of this duck is Aflac.\"
",
+ "这个例子给duck
对象添加了一个sayName 方法
,这个方法返回一个包含duck
名字的句子。",
+ "注意:这个方法
在返回语句中使用duck.name
的方式来获取name
的属性值。在下一个挑战中我们将会使用另外一种方法来实现。",
"
",
- "Using the dog
object
, give it a method called sayLegs
. The method should return the sentence \"This dog has 4 legs.\""
+ "给dog 对象
设置一个名为sayLegs
的方法,并让它返回 \"This dog has 4 legs.\" 这句话。"
],
"tests": [
{
- "text": "dog.sayLegs()
should be a function.",
- "testString": "assert(typeof(dog.sayLegs) === 'function', 'dog.sayLegs()
should be a function.');"
+ "text": "dog.sayLegs()
应该是一个函数。",
+ "testString": "assert(typeof(dog.sayLegs) === 'function', 'dog.sayLegs()
应该是一个函数。');"
},
{
- "text": "dog.sayLegs()
should return the given string - note that punctuation and spacing matter.",
- "testString": "assert(dog.sayLegs() === 'This dog has 4 legs.', 'dog.sayLegs()
should return the given string - note that punctuation and spacing matter.');"
+ "text": "dog.sayLegs()
应该返回给定的字符串,需要注意标点和间距的问题。",
+ "testString": "assert(dog.sayLegs() === 'This dog has 4 legs.', 'dog.sayLegs()
应该返回给定的字符串,需要注意标点和间距的问题。');"
}
],
"solutions": [
@@ -148,24 +148,24 @@
"id": "587d7dad367417b2b2512b76",
"title": "Make Code More Reusable with the this Keyword",
"description": [
- "The last challenge introduced a method
to the duck
object. It used duck.name
dot notation to access the value for the name
property within the return statement:",
+ "在上一个挑战中我们了解了该如何给duck
对象设置一个方法
属性。然后我们通过使用“点号表示法”duck.name
来获取name
的属性值而不需要使用return语句:",
"sayName: function() {return \"The name of this duck is \" + duck.name + \".\";}
",
- "While this is a valid way to access the object's property, there is a pitfall here. If the variable name changes, any code referencing the original name would need to be updated as well. In a short object definition, it isn't a problem, but if an object has many references to its properties there is a greater chance for error.",
- "A way to avoid these issues is with the this
keyword:",
+ "虽然这是访问对象属性的有效方法,但是这里有一个陷阱。如果变量名发生了改变,那么引用了原始名称的任何代码都需要更新。在一个简短的对象定义中这并不是问题,但是如果对象有很多对其属性的引用,那么发生错误的可能性就更大了。",
+ "我们可以使用this
关键字这个方法来避免这一问题:",
"let duck = {
name: \"Aflac\",
numLegs: 2,
sayName: function() {return \"The name of this duck is \" + this.name + \".\";}
};
",
- "this
is a deep topic, and the above example is only one way to use it. In the current context, this
refers to the object that the method is associated with: duck
.",
- "If the object's name is changed to mallard
, it is not necessary to find all the references to duck
in the code. It makes the code reusable and easier to read.",
+ "this
是一个很复杂的知识点,而上面那个例子也只是使用this
的一种方法而已。在当前的上下文环境中,this
指向的就是与这个方法有关联的duck
对象。",
+ "如果把对象的变量名改为mallard
,那使用this
就没有必要在代码中找到所有指向duck
的部分,这样可以使得代码更具有可读性和复用性。",
"
",
- "Modify the dog.sayLegs
method to remove any references to dog
. Use the duck
example for guidance."
+ "修改dog.sayLegs
方法以将所有直接对dog
的引用删除。可以参考上面的例子。"
],
"tests": [
{
- "text": "dog.sayLegs()
should return the given string.",
- "testString": "assert(dog.sayLegs() === 'This dog has 4 legs.', 'dog.sayLegs()
should return the given string.');"
+ "text": "dog.sayLegs()
应该返回一个指定的字符串。",
+ "testString": "assert(dog.sayLegs() === 'This dog has 4 legs.', 'dog.sayLegs()
应该返回一个指定的字符串。');"
},
{
- "text": "Your code should use the this
keyword to access the numLegs
property of dog
.",
- "testString": "assert(code.match(/this\\.numLegs/g), 'Your code should use the this
keyword to access the numLegs
property of dog
.');"
+ "text": "你的代码应该使用this
关键字来访问dog
对象的numLegs
属性值。",
+ "testString": "assert(code.match(/this\\.numLegs/g), '你的代码应该使用this
关键字来访问dog
对象的numLegs
属性值。');"
}
],
"solutions": [
@@ -197,27 +197,27 @@
"id": "587d7dad367417b2b2512b77",
"title": "Define a Constructor Function",
"description": [
- "Constructors
are functions that create new objects. They define properties and behaviors that will belong to the new object. Think of them as a blueprint for the creation of new objects.",
- "Here is an example of a constructor
:",
+ "构造函数
用以创建一个新对象,并给这个新对象定义属性和行为。因此这是创建新对象的一个最基本的方式。",
+ "以下就是一个构造函数
的示例:",
"function Bird() {
this.name = \"Albert\";
this.color = \"blue\";
this.numLegs = 2;
}
",
- "This constructor
defines a Bird
object with properties name
, color
, and numLegs
set to Albert, blue, and 2, respectively.",
- "Constructors
follow a few conventions:",
- "Constructors
are defined with a capitalized name to distinguish them from other functions that are not constructors
.Constructors
use the keyword this
to set properties of the object they will create. Inside the constructor
, this
refers to the new object it will create.Constructors
define properties and behaviors instead of returning a value as other functions might.
",
+ "这个构造函数
定义了一个Bird
对象,其属性name
、color
和numLegs
的值分别被设置为Albert、blue和 2。",
+ "构造函数
遵循一些惯例规则:",
+ "构造函数
函数名的首字母最好大写,这是为了方便我们区分构造函数
和其他非构造函数。构造函数
使用this
关键字来给它将创建的这个对象设置新的属性。在构造函数
里面,this
指向的就是它新创建的这个对象。构造函数
定义了属性和行为就可创建对象,而不是像其他函数一样需要设置返回值。
",
"
",
- "Create a constructor
, Dog
, with properties name
, color
, and numLegs
that are set to a string, a string, and a number, respectively."
+ "创建一个构造函数
:Dog
。给其添加name
,color
和numLegs
属性并分别给它们设置为:字符串,字符串和数字。"
],
"tests": [
{
- "text": "Dog
should have a name
property set to a string.",
- "testString": "assert(typeof (new Dog()).name === 'string', 'Dog
should have a name
property set to a string.');"
+ "text": "Dog
应该有一个name
属性且它的值是一个字符串。",
+ "testString": "assert(typeof (new Dog()).name === 'string', 'Dog
应该有一个name
属性且它的值是一个字符串。');"
},
{
- "text": "Dog
should have a color
property set to a string.",
- "testString": "assert(typeof (new Dog()).color === 'string', 'Dog
should have a color
property set to a string.');"
+ "text": "Dog
应该有一个color
属性且它的值是一个字符串。",
+ "testString": "assert(typeof (new Dog()).color === 'string', 'Dog
应该有一个color
属性且它的值是一个字符串。');"
},
{
- "text": "Dog
should have a numLegs
property set to a number.",
- "testString": "assert(typeof (new Dog()).numLegs === 'number', 'Dog
should have a numLegs
property set to a number.');"
+ "text": "Dog
应该有一个numLegs
属性且它的值是一个数字。",
+ "testString": "assert(typeof (new Dog()).numLegs === 'number', 'Dog
应该有一个numLegs
属性且它的值是一个数字。');"
}
],
"solutions": [
@@ -241,24 +241,24 @@
"id": "587d7dad367417b2b2512b78",
"title": "Use a Constructor to Create Objects",
"description": [
- "Here's the Bird
constructor from the previous challenge:",
- "function Bird() {
this.name = \"Albert\";
this.color = \"blue\";
this.numLegs = 2;
// \"this\" inside the constructor always refers to the object being created
}
let blueBird = new Bird();
",
- "Notice that the new
operator is used when calling a constructor. This tells JavaScript to create a new instance
of Bird
called blueBird
. Without the new
operator, this
inside the constructor would not point to the newly created object, giving unexpected results.",
- "Now blueBird
has all the properties defined inside the Bird
constructor:",
+ "在上一个挑战中,我们用所学到的知识创建了一个Bird
构造函数:",
+ "function Bird() {
this.name = \"Albert\";
this.color = \"blue\";
this.numLegs = 2;
// 构造函数里面的 \"this\" 总是指向新创建的实例。
}
let blueBird = new Bird();
",
+ "注意:通过构造函数创建对象的时候要使用new
操作符。因为只有这样,JavaScript 才知道要给Bird
这个构造函数创建一个新的实例
:blueBird
。如果不使用new
操作符来新建对象,那么构造函数里面的this
就无法指向新创建的这个对象实例,从而产生不可预见的错误。",
+ "现在blueBird
这个实例就继承了Bird
这个构造函数的所有属性,如下:",
"blueBird.name; // => Albert
blueBird.color; // => blue
blueBird.numLegs; // => 2
",
- "Just like any other object, its properties can be accessed and modified:",
+ "由构造函数创建的实例也和其他对象一样,它的属性可以被访问和修改:",
"blueBird.name = 'Elvira';
blueBird.name; // => Elvira
",
"
",
- "Use the Dog
constructor from the last lesson to create a new instance of Dog
, assigning it to a variable hound
."
+ "使用上一个课时中的Dog
构造函数创建一个Dog
的新实例,并把它赋值给变量hound
。"
],
"tests": [
{
- "text": "hound
should be created using the Dog
constructor.",
- "testString": "assert(hound instanceof Dog, 'hound
should be created using the Dog
constructor.');"
+ "text": "hound
应该是通过Dog
构造函数来创建的。",
+ "testString": "assert(hound instanceof Dog, 'hound
应该是通过Dog
构造函数来创建的。');"
},
{
- "text": "Your code should use the new
operator to create an instance
of Dog
.",
- "testString": "assert(code.match(/new/g), 'Your code should use the new
operator to create an instance
of Dog
.');"
+ "text": "你的代码中应该使用new
操作符来创建Dog
构造函数的新实例
。",
+ "testString": "assert(code.match(/new/g), '你的代码中应该使用new
操作符来创建Dog
构造函数的新实例
。');"
}
],
"solutions": [
@@ -278,7 +278,7 @@
" this.color = \"brown\";",
" this.numLegs = 4;",
"}",
- "// Add your code below this line",
+ "// 请把你的代码写在这条注释以下",
"",
""
],
@@ -291,36 +291,36 @@
"id": "587d7dae367417b2b2512b79",
"title": "Extend Constructors to Receive Arguments",
"description": [
- "The Bird
and Dog
constructors from last challenge worked well. However, notice that all Birds
that are created with the Bird
constructor are automatically named Albert, are blue in color, and have two legs. What if you want birds with different values for name and color? It's possible to change the properties of each bird manually but that would be a lot of work:",
+ "上一个挑战中Bird
和Dog
构造函数运行得不错。但是,注意到没有:所有通过Bird
构造函数创建出来的实例Birds
都自动的取名为 Albert,颜色都是蓝色,还都有两条腿。如果你想要新创建出来的小鸟们拥有不同的名字和颜色要怎么办呢?当然,手动的去修改每一个小鸟实例自己的属性也是可以实现的,只是会增加很多无谓的工作量:",
"let swan = new Bird();
swan.name = \"Carlos\";
swan.color = \"white\";
",
- "Suppose you were writing a program to keep track of hundreds or even thousands of different birds in an aviary. It would take a lot of time to create all the birds, then change the properties to different values for every one.",
- "To more easily create different Bird
objects, you can design your Bird constructor to accept parameters:",
+ "假如你写了一个程序来追踪一个鸟舍里面的几百只甚至几千只不同的小鸟,你将会花费很多时间去创建所有的小鸟实例并给它们的属性一一修改为不同的值。",
+ "为了减轻创建不同Bird
对象的工作量,你可以给你的Bird
设置为可以接收参数的构造函数:",
"function Bird(name, color) {
this.name = name;
this.color = color;
this.numLegs = 2;
}
",
- "Then pass in the values as arguments to define each unique bird into the Bird
constructor:",
+ "然后将值通过参数的方式传递给Bird
构造函数来定义每一个唯一的小鸟实例:",
"let cardinal = new Bird(\"Bruce\", \"red\");
",
- "This gives a new instance of Bird
with name and color properties set to Bruce and red, respectively. The numLegs
property is still set to 2.",
- "The cardinal
has these properties:",
+ "这给Bird
的名字和颜色属性分别赋值为 Bruce 和红色提供了另外一种方法。但numLegs
属性被默认赋值为 2。",
+ "cardinal
有以下这些属性:",
"cardinal.name // => Bruce
cardinal.color // => red
cardinal.numLegs // => 2
",
- "The constructor is more flexible. It's now possible to define the properties for each Bird
at the time it is created, which is one way that JavaScript constructors are so useful. They group objects together based on shared characteristics and behavior and define a blueprint that automates their creation.",
+ "这样一来构造函数就变得很灵活了。现在可以直接定义每个Bird
实例在创建时的属性,这是 JavaScript 构造函数非常实用的用法之一。它们根据共同或相似的属性和行为将对象归纳为一组,并能够自动的创建各自实例。",
"
",
- "Create another Dog
constructor. This time, set it up to take the parameters name
and color
, and have the property numLegs
fixed at 4. Then create a new Dog
saved in a variable terrier
. Pass it two strings as arguments for the name
and color
properties."
+ "创建另一个Dog
构造函数。这一次,给它设置两个参数:name
和color
,同时给numLegs
赋值为 4。然后创建一个新Dog
实例保存为变量名:terrier
,再将两个字符串通过参数的形式传入name
和color
属性。"
],
"tests": [
{
- "text": "Dog
should receive an argument for name
.",
- "testString": "assert((new Dog('Clifford')).name === 'Clifford', 'Dog
should receive an argument for name
.');"
+ "text": "Dog
应该接收一个name
参数。",
+ "testString": "assert((new Dog('Clifford')).name === 'Clifford', 'Dog
应该接收一个name
参数。');"
},
{
- "text": "Dog
should receive an argument for color
.",
- "testString": "assert((new Dog('Clifford', 'yellow')).color === 'yellow', 'Dog
should receive an argument for color
.');"
+ "text": "Dog
应该接收一个color
参数。",
+ "testString": "assert((new Dog('Clifford', 'yellow')).color === 'yellow', 'Dog
应该接收一个color
参数。');"
},
{
- "text": "Dog
should have property numLegs
set to 4.",
- "testString": "assert((new Dog('Clifford')).numLegs === 4, 'Dog
should have property numLegs
set to 4.');"
+ "text": "Dog
应该有一个numLegs
属性且值为 4。",
+ "testString": "assert((new Dog('Clifford')).numLegs === 4, 'Dog
应该有一个numLegs
属性且值为 4。');"
},
{
- "text": "terrier
should be created using the Dog
constructor.",
- "testString": "assert(terrier instanceof Dog, 'terrier
should be created using the Dog
constructor.');"
+ "text": "terrier
应该是通过Dog
构造函数创建的。",
+ "testString": "assert(terrier instanceof Dog, 'terrier
应该是通过Dog
构造函数创建的。');"
}
],
"solutions": [
@@ -350,21 +350,21 @@
"id": "587d7dae367417b2b2512b7a",
"title": "Verify an Object's Constructor with instanceof",
"description": [
- "Anytime a constructor function creates a new object, that object is said to be an instance
of its constructor. JavaScript gives a convenient way to verify this with the instanceof
operator. instanceof
allows you to compare an object to a constructor, returning true
or false
based on whether or not that object was created with the constructor. Here's an example:",
+ "凡是通过构造函数创建出的新对象,都叫做这个构造函数的实例
。JavaScript 提供了一种很简便的方法来验证这个事实,那就是通过instanceof
操作符。instanceof
允许你将对象与构造函数之间进行比较,根据对象是否由这个构造函数创建的返回true
或者false
。以下是一个示例:",
"let Bird = function(name, color) {
this.name = name;
this.color = color;
this.numLegs = 2;
}
let crow = new Bird(\"Alexis\", \"black\");
crow instanceof Bird; // => true
",
- "If an object is created without using a constructor, instanceof
will verify that it is not an instance of that constructor:",
+ "如果一个对象不是使用构造函数创建的,那么instanceof
将会验证这个对象不是构造函数的实例:",
"let canary = {
name: \"Mildred\",
color: \"Yellow\",
numLegs: 2
};
canary instanceof Bird; // => false
",
"
",
- "Create a new instance of the House
constructor, calling it myHouse
and passing a number of bedrooms. Then, use instanceof
to verify that it is an instance of House
."
+ "给House
构造函数创建一个新实例,取名为myHouse
并且传递一个数字给bedrooms参数。然后使用instanceof
操作符验证这个对象是否为House
的实例。"
],
"tests": [
{
- "text": "myHouse
should have a numBedrooms
attribute set to a number.",
- "testString": "assert(typeof myHouse.numBedrooms === 'number', 'myHouse
should have a numBedrooms
attribute set to a number.');"
+ "text": "myHouse
应该有一个numBedrooms
属性被赋值为一个数字。",
+ "testString": "assert(typeof myHouse.numBedrooms === 'number', 'myHouse
应该有一个numBedrooms
属性被赋值为一个数字。');"
},
{
- "text": "Be sure to verify that myHouse
is an instance of House
using the instanceof
operator.",
- "testString": "assert(/myHouse\\s*instanceof\\s*House/.test(code), 'Be sure to verify that myHouse
is an instance of House
using the instanceof
operator.');"
+ "text": "请务必使用instanceof
操作符验证myHouse
这个对象是House
构造函数的一个实例。",
+ "testString": "assert(/myHouse\\s*instanceof\\s*House/.test(code), '请务必使用instanceof
操作符验证myHouse
这个对象是House
构造函数的一个实例。');"
}
],
"solutions": [
@@ -385,7 +385,7 @@
" this.numBedrooms = numBedrooms;",
"}",
"",
- "// Add your code below this line",
+ "// 请把你的代码写在这条注释以下",
"",
"",
""
@@ -399,23 +399,23 @@
"id": "587d7dae367417b2b2512b7b",
"title": "Understand Own Properties",
"description": [
- "In the following example, the Bird
constructor defines two properties: name
and numLegs
:",
+ "请看下面的实例,Bird
构造函数定义了两个属性:name
和numLegs
:",
"function Bird(name) {
this.name = name;
this.numLegs = 2;
}
let duck = new Bird(\"Donald\");
let canary = new Bird(\"Tweety\");
",
- "name
and numLegs
are called own
properties, because they are defined directly on the instance object. That means that duck
and canary
each has its own separate copy of these properties.",
- "In fact every instance of Bird
will have its own copy of these properties.",
- "The following code adds all of the own
properties of duck
to the array ownProps
:",
+ "name
和numLegs
被叫做自身
属性,因为他们是直接在实例对象上定义的。这就意味着duck
和canary
这两个对象分别拥有这些属性的独立副本。",
+ "事实上,Bird
的这些实例都将拥有这些属性的独立副本。",
+ "以下的代码将duck
里面所有的自身
属性都存到一个叫 code>ownProps
的数组里面:",
"let ownProps = [];
for (let property in duck) {
if(duck.hasOwnProperty(property)) {
ownProps.push(property);
}
}
console.log(ownProps); // prints [ \"name\", \"numLegs\" ]
",
"
",
- "Add the own
properties of canary
to the array ownProps
."
+ "将canary
对象里面的自身
属性添加到ownProps
数组里面。"
],
"tests": [
{
- "text": "ownProps
should include the values \"numLegs\"
and \"name\"
.",
- "testString": "assert(ownProps.indexOf('name') !== -1 && ownProps.indexOf('numLegs') !== -1, 'ownProps
should include the values \"numLegs\"
and \"name\"
.');"
+ "text": "ownProps
应该包含\"numLegs\"
和\"name\"
两个属性的值。",
+ "testString": "assert(ownProps.indexOf('name') !== -1 && ownProps.indexOf('numLegs') !== -1, 'ownProps
应该包含\"numLegs\"
和\"name\"
两个属性的值。');"
},
{
- "text": "Solve this challenge without using the built in method Object.keys()
.",
- "testString": "assert(!/\\Object.keys/.test(code), 'Solve this challenge without using the built in method Object.keys()
.');"
+ "text": "在不使用内置方法Object.keys()
的情况下完成这个挑战。",
+ "testString": "assert(!/\\Object.keys/.test(code), '在不使用内置方法Object.keys()
的情况下完成这个挑战。');"
}
],
"solutions": [
@@ -437,7 +437,7 @@
"",
"let canary = new Bird(\"Tweety\");",
"let ownProps = [];",
- "// Add your code below this line",
+ "// 请把你的代码写在这条注释以下",
"",
"",
""
@@ -451,29 +451,29 @@
"id": "587d7dae367417b2b2512b7c",
"title": "Use Prototype Properties to Reduce Duplicate Code",
"description": [
- "Since numLegs
will probably have the same value for all instances of Bird
, you essentially have a duplicated variable numLegs
inside each Bird
instance.",
- "This may not be an issue when there are only two instances, but imagine if there are millions of instances. That would be a lot of duplicated variables.",
- "A better way is to use Bird’s
prototype
. The prototype
is an object that is shared among ALL instances of Bird
. Here's how to add numLegs
to the Bird prototype
:",
+ "所有Bird
实例可能会有相同的numLegs
值,所以在每一个Bird
的实例中本质上都有一个重复的变量numLegs
。",
+ "当只有两个实例时可能并不是什么问题,但想象一下如果有数百万个实例,这将会产生许许多多重复的变量。",
+ "这里有一个更好的方法可以解决上述问题,那就是使用Bird
的原型
。原型
是一个可以在所有Bird
实例之间共享的对象。以下是一个在Bird prototype
中添加numLegs
属性的示例:",
"Bird.prototype.numLegs = 2;
",
- "Now all instances of Bird
have the numLegs
property.",
- "console.log(duck.numLegs); // prints 2
console.log(canary.numLegs); // prints 2
",
- "Since all instances automatically have the properties on the prototype
, think of a prototype
as a \"recipe\" for creating objects.",
- "Note that the prototype
for duck
and canary
is part of the Bird
constructor as Bird.prototype
. Nearly every object in JavaScript has a prototype
property which is part of the constructor function that created it.",
+ "现在所有的Bird
实例都拥有了共同的numLegs
属性值。",
+ "console.log(duck.numLegs); // 在控制台输出 2
console.log(canary.numLegs); // 在控制台输出 2
",
+ "由于所有的实例都可以继承原型
上的属性,所以可以把原型
看作是创建对象的 \"配方\"。",
+ "请注意:duck
和canary
的原型
是Bird
构造函数原型Bird.prototype
的一部分。JavaScript 中几乎所有的对象都有一个原型
属性,这个属性是属于它所在的构造函数的一部分。",
"
",
- "Add a numLegs
property to the prototype
of Dog
"
+ "给Dog
的原型
添加一个numLegs
属性。"
],
"tests": [
{
- "text": "beagle
should have a numLegs
property.",
- "testString": "assert(beagle.numLegs !== undefined, 'beagle
should have a numLegs
property.');"
+ "text": "beagle
应该有一个numLegs
属性。",
+ "testString": "assert(beagle.numLegs !== undefined, 'beagle
应该有一 numLegs
属性。');"
},
{
- "text": "beagle.numLegs
should be a number.",
- "testString": "assert(typeof(beagle.numLegs) === 'number' , 'beagle.numLegs
should be a number.');"
+ "text": "beagle.numLegs
应该是一个数字。",
+ "testString": "assert(typeof(beagle.numLegs) === 'number' , 'beagle.numLegs
应该是一个数字。');"
},
{
- "text": "numLegs
should be a prototype
property not an own
property.",
- "testString": "assert(beagle.hasOwnProperty('numLegs') === false, 'numLegs
should be a prototype
property not an own
property.');"
+ "text": "numLegs
应该是一个原型
属性而不是一个自身
属性。",
+ "testString": "assert(beagle.hasOwnProperty('numLegs') === false, 'numLegs
应该是一个原型
属性而不是一个自身
属性。');"
}
],
"solutions": [
@@ -494,7 +494,7 @@
"",
"",
"",
- "// Add your code above this line",
+ "// 请把你的代码写在这条注释以下",
"let beagle = new Dog(\"Snoopy\");"
],
"head": [],
@@ -506,25 +506,25 @@
"id": "587d7daf367417b2b2512b7d",
"title": "Iterate Over All Properties",
"description": [
- "You have now seen two kinds of properties: own
properties and prototype
properties. Own
properties are defined directly on the object instance itself. And prototype
properties are defined on the prototype
.",
- "function Bird(name) {
this.name = name; //own property
}
Bird.prototype.numLegs = 2; // prototype property
let duck = new Bird(\"Donald\");
",
- "Here is how you add duck’s
own
properties to the array ownProps
and prototype
properties to the array prototypeProps
:",
- "let ownProps = [];
let prototypeProps = [];
for (let property in duck) {
if(duck.hasOwnProperty(property)) {
ownProps.push(property);
} else {
prototypeProps.push(property);
}
}
console.log(ownProps); // prints [\"name\"]
console.log(prototypeProps); // prints [\"numLegs\"]
",
+ "现在你已经了解了两种属性: 自身
属性和原型
属性。自身
属性是直接在对象上定义的。而原型
属性是定义在prototype
上的:",
+ "function Bird(name) {
this.name = name; // 自身属性
}
Bird.prototype.numLegs = 2; // 原型属性
let duck = new Bird(\"Donald\");
",
+ "这个示例会告诉你如何将duck
的自身
属性和原型
属性分别添加到ownProps
数组和prototypeProps
数组里面:",
+ "let ownProps = [];
let prototypeProps = [];
for (let property in duck) {
if(duck.hasOwnProperty(property)) {
ownProps.push(property);
} else {
prototypeProps.push(property);
}
}
console.log(ownProps); // 输出 [\"name\"]
console.log(prototypeProps); // 输出 [\"numLegs\"]
",
"
",
- "Add all of the own
properties of beagle
to the array ownProps
. Add all of the prototype
properties of Dog
to the array prototypeProps
."
+ "将beagle
的所有属性都添加到ownProps
数组里面去。将Dog
的所有原型
属性添加到prototypeProps
数组中。"
],
"tests": [
{
- "text": "The ownProps
array should include \"name\"
.",
- "testString": "assert(ownProps.indexOf('name') !== -1, 'The ownProps
array should include \"name\"
.');"
+ "text": "这个ownProps
数组应该包含\"name\"
这个值。",
+ "testString": "assert(ownProps.indexOf('name') !== -1, '这个ownProps
属性应该包含\"name\"
这个值。');"
},
{
- "text": "The prototypeProps
array should include \"numLegs\"
.",
- "testString": "assert(prototypeProps.indexOf('numLegs') !== -1, 'The prototypeProps
array should include \"numLegs\"
.');"
+ "text": "这个prototypeProps
数组应该包含\"numLegs\"
这个值。",
+ "testString": "assert(prototypeProps.indexOf('numLegs') !== -1, '这个prototypeProps
数组应该包含\"numLegs\"
这个值。');"
},
{
- "text": "Solve this challenge without using the built in method Object.keys()
.",
- "testString": "assert(!/\\Object.keys/.test(code), 'Solve this challenge without using the built in method Object.keys()
.');"
+ "text": "在不使用内置方法Object.keys()
的情况下完成这个挑战。",
+ "testString": "assert(!/\\Object.keys/.test(code), '在不使用内置方法Object.keys()
的情况下完成这个挑战。');"
}
],
"solutions": [
@@ -550,7 +550,7 @@
"let ownProps = [];",
"let prototypeProps = [];",
"",
- "// Add your code below this line ",
+ "// 请把你的代码写在这条注释以下 ",
"",
"",
""
@@ -564,27 +564,27 @@
"id": "587d7daf367417b2b2512b7e",
"title": "Understand the Constructor Property",
"description": [
- "There is a special constructor
property located on the object instances duck
and beagle
that were created in the previous challenges:",
- "let duck = new Bird();
let beagle = new Dog();
console.log(duck.constructor === Bird); //prints true
console.log(beagle.constructor === Dog); //prints true
",
- "Note that the constructor
property is a reference to the constructor function that created the instance.",
- "The advantage of the constructor
property is that it's possible to check for this property to find out what kind of object it is. Here's an example of how this could be used:",
+ "在上一个挑战中创建的实例对象duck
和beagle
都有一个特殊的constructor
属性:",
+ "let duck = new Bird();
let beagle = new Dog();
console.log(duck.constructor === Bird); //输出 true
console.log(beagle.constructor === Dog); //输出 true
",
+ "需要注意到的是这个constructor
属性是对创建这个实例的构造函数的一个引用。",
+ "constructor
属性存在的一个优势是,我们可以通过检查这个属性来找出它是一个什么样的对象。下面是一个例子,来看看是怎么使用的:",
"function joinBirdFraternity(candidate) {
if (candidate.constructor === Bird) {
return true;
} else {
return false;
}
}
",
- "Note
Since the constructor
property can be overwritten (which will be covered in the next two challenges) it’s generally better to use the instanceof
method to check the type of an object.",
+ "注意:
由于constructor
属性可以被重写(在下面两节挑战中将会遇到),所以使用instanceof
方法来检查对象的类型会更好。",
"
",
- "Write a joinDogFraternity
function that takes a candidate
parameter and, using the constructor
property, return true
if the candidate is a Dog
, otherwise return false
."
+ "写一个joinDogFraternity
函数,传入一个candidate
参数并使用constructor
属性来判断传入的 candidate 是不是Dog
创建的对象实例,如果是,就返回true
,否则返回false
。"
],
"tests": [
{
- "text": "joinDogFraternity
should be defined as a function.",
- "testString": "assert(typeof(joinDogFraternity) === 'function', 'joinDogFraternity
should be defined as a function.');"
+ "text": "joinDogFraternity
应该被定义为一个函数。",
+ "testString": "assert(typeof(joinDogFraternity) === 'function', 'joinDogFraternity
应该被定义为一个函数。');"
},
{
- "text": "joinDogFraternity
should return true ifcandidate
is an instance of Dog
.",
- "testString": "assert(joinDogFraternity(new Dog(\"\")) === true, 'joinDogFraternity
should return true ifcandidate
is an instance of Dog
.');"
+ "text": "如果candidate
是Dog
的一个对象实例,则joinDogFraternity
函数应该返回true
。",
+ "testString": "assert(joinDogFraternity(new Dog(\"\")) === true, '如果candidate
是Dog
的一个对象实例,则joinDogFraternity
函数应该返回true
。');"
},
{
- "text": "joinDogFraternity
should use the constructor
property.",
- "testString": "assert(/\\.constructor/.test(code) && !/instanceof/.test(code), 'joinDogFraternity
should use the constructor
property.');"
+ "text": "joinDogFraternity
中应该用到constructor
属性。",
+ "testString": "assert(/\\.constructor/.test(code) && !/instanceof/.test(code), 'joinDogFraternity
中应该用到constructor
属性。');"
}
],
"solutions": [
@@ -603,7 +603,7 @@
" this.name = name;",
"}",
"",
- "// Add your code below this line",
+ "// 请把你的代码写在这条注释以下",
"function joinDogFraternity(candidate) {",
" ",
"}",
@@ -618,31 +618,31 @@
"id": "587d7daf367417b2b2512b7f",
"title": "Change the Prototype to a New Object",
"description": [
- "Up until now you have been adding properties to the prototype
individually:",
+ "到目前为止,你已经可以单独给prototype
添加属性了:",
"Bird.prototype.numLegs = 2;
",
- "This becomes tedious after more than a few properties.",
+ "这将在添加许多属性的时候变得单调乏味。",
"Bird.prototype.eat = function() {
console.log(\"nom nom nom\");
}
Bird.prototype.describe = function() {
console.log(\"My name is \" + this.name);
}
",
- "A more efficient way is to set the prototype
to a new object that already contains the properties. This way, the properties are added all at once:",
+ "一种更有效的方法就是给对象的prototype
设置为一个已经包含了属性的新对象。这样一来,所有属性都可以一次性添加进来:",
"Bird.prototype = {
numLegs: 2,
eat: function() {
console.log(\"nom nom nom\");
},
describe: function() {
console.log(\"My name is \" + this.name);
}
};
",
"
",
- "Add the property numLegs
and the two methods eat()
and describe()
to the prototype
of Dog
by setting the prototype
to a new object."
+ "通过给prototype
设置为新对象的方法,在Dog
构造函数的原型
上添加一个属性numLegs
以及两个方法:eat()
和describe()
。"
],
"tests": [
{
- "text": "Dog.prototype
should be set to a new object.",
- "testString": "assert((/Dog\\.prototype\\s*?=\\s*?{/).test(code), 'Dog.prototype
should be set to a new object.');"
+ "text": "Dog.prototype
应该被设置为一个新对象。",
+ "testString": "assert((/Dog\\.prototype\\s*?=\\s*?{/).test(code), 'Dog.prototype
应该被设置为一个新对象。');"
},
{
- "text": "Dog.prototype
should have the property numLegs
.",
- "testString": "assert(Dog.prototype.numLegs !== undefined, 'Dog.prototype
should have the property numLegs
.');"
+ "text": "Dog.prototype
应该拥有属性numLegs
。",
+ "testString": "assert(Dog.prototype.numLegs !== undefined, 'Dog.prototype
应该拥有属性numLegs
。');"
},
{
- "text": "Dog.prototype
should have the method eat()
.",
- "testString": "assert(typeof Dog.prototype.eat === 'function', 'Dog.prototype
should have the method eat()
.'); "
+ "text": "Dog.prototype
应该拥有方法eat()
。",
+ "testString": "assert(typeof Dog.prototype.eat === 'function', 'Dog.prototype
应该拥有方法eat()
。'); "
},
{
- "text": "Dog.prototype
should have the method describe()
.",
- "testString": "assert(typeof Dog.prototype.describe === 'function', 'Dog.prototype
should have the method describe()
.'); "
+ "text": "Dog.prototype
应该拥有方法describe()
。",
+ "testString": "assert(typeof Dog.prototype.describe === 'function', 'Dog.prototype
应该拥有方法describe()
。'); "
}
],
"solutions": [
@@ -662,7 +662,7 @@
"}",
"",
"Dog.prototype = {",
- " // Add your code below this line",
+ " // 请把你的代码写在这条注释以下",
" ",
"};"
],
@@ -1419,4 +1419,4 @@
}
}
]
-}
\ No newline at end of file
+}
diff --git a/02-javascript-algorithms-and-data-structures/object-oriented-programming.md b/02-javascript-algorithms-and-data-structures/object-oriented-programming.md
index a0a014d..4918604 100644
--- a/02-javascript-algorithms-and-data-structures/object-oriented-programming.md
+++ b/02-javascript-algorithms-and-data-structures/object-oriented-programming.md
@@ -7,57 +7,3 @@ As its name implies, object oriented programming organizes code into object defi
The object structure makes it flexible within a program. Objects can transfer information by calling and passing data to another object's methods. Also, new classes can receive, or inherit, all the features from a base or parent class. This helps to reduce repeated code.
Your choice of programming approach depends on a few factors. These include the type of problem, as well as how you want to structure your data and algorithms. This section covers object oriented programming principles in JavaScript.
-
-# Upcoming Lessons #
-
-Create a Basic JavaScript Object
-
-Use Dot Notation to Access the Properties of an Object
-
-Create a Method on an Object
-
-Make Code More Reusable with the this Keyword
-
-Define a Constructor Function
-
-Use a Constructor to Create Objects
-
-Extend Constructors to Receive Arguments
-
-Verify an Object's Constructor with instanceof
-
-Understand Own Properties
-
-Use Prototype Properties to Reduce Duplicate Code
-
-Iterate Over All Properties
-
-Understand the Constructor Property
-
-Change the Prototype to a New Object
-
-Remember to Set the Constructor Property when Changing the Prototype
-
-Understand Where an Object’s Prototype Comes From
-
-Understand the Prototype Chain
-
-Use Inheritance So You Don't Repeat Yourself
-
-Inherit Behaviors from a Supertype
-
-Set the Child's Prototype to an Instance of the Parent
-
-Reset an Inherited Constructor Property
-
-Add Methods After Inheritance
-
-Override Inherited Methods
-
-Use a Mixin to Add Common Behavior Between Unrelated Objects
-
-Use Closure to Protect Properties Within an Object from Being Modified Externally
-
-Understand the Immediately Invoked Function Expression (IIFE)
-
-Use an IIFE to Create a Module
\ No newline at end of file
diff --git a/02-javascript-algorithms-and-data-structures/regular-expressions.md b/02-javascript-algorithms-and-data-structures/regular-expressions.md
index e95af47..9289429 100644
--- a/02-javascript-algorithms-and-data-structures/regular-expressions.md
+++ b/02-javascript-algorithms-and-data-structures/regular-expressions.md
@@ -1,69 +1,3 @@
# Introduction to the Regular Expression Challenges #
Regular expressions are special strings that represent a search pattern. Also known as "regex" or "regexp", they help programmers match, search, and replace text. Regular expressions can appear cryptic because a few characters have special meaning. The goal is to combine the symbols and text into a pattern that matches what you want, but only what you want. This section will cover the characters, a few shortcuts, and the common uses for writing regular expressions.
-
-# Upcoming Lessons #
-
-Using the Test Method
-
-Match Literal Strings
-
-Match a Literal String with Different Possibilities
-
-Ignore Case While Matching
-
-Extract Matches
-
-Find More Than the First Match
-
-Match Anything with Wildcard Period
-
-Match Single Character with Multiple Possibilities
-
-Match Letters of the Alphabet
-
-Match Numbers and Letters of the Alphabet
-
-Match Single Characters Not Specified
-
-Match Characters that Occur One or More Times
-
-Match Characters that Occur Zero or More Times
-
-Find Characters with Lazy Matching
-
-Find One or More Criminals in a Hunt
-
-Match Beginning String Patterns
-
-Match Ending String Patterns
-
-Match All Letters and Numbers
-
-Match Everything But Letters and Numbers
-
-Match All Numbers
-
-Match All Non-Numbers
-
-Restrict Possible Usernames
-
-Match Whitespace
-
-Match Non-Whitespace Characters
-
-Specify Upper and Lower Number of Matches
-
-Specify Only the Lower Number of Matches
-
-Specify Exact Number of Matches
-
-Check for All or None
-
-Positive and Negative Lookahead
-
-Reuse Patterns Using Capture Groups
-
-Use Capture Groups to Search and Replace
-
-Remove Whitespace from Start and End
\ No newline at end of file
diff --git a/03-front-end-libraries/bootstrap.md b/03-front-end-libraries/bootstrap.md
index b0155e9..fe21a10 100644
--- a/03-front-end-libraries/bootstrap.md
+++ b/03-front-end-libraries/bootstrap.md
@@ -9,67 +9,3 @@ Bootstrap is a front-end framework used to design responsive web pages and web a
* navigation
This section introduces some of the ways to use Bootstrap in your web projects.
-
-# Upcoming Lessons #
-
-Use Responsive Design with Bootstrap Fluid Containers
-
-Make Images Mobile Responsive
-
-Center Text with Bootstrap
-
-Create a Bootstrap Button
-
-Create a Block Element Bootstrap Button
-
-Taste the Bootstrap Button Color Rainbow
-
-Call out Optional Actions with btn-info
-
-Warn Your Users of a Dangerous Action with btn-danger
-
-Use the Bootstrap Grid to Put Elements Side By Side
-
-Ditch Custom CSS for Bootstrap
-
-Use a span to Target Inline Elements
-
-Create a Custom Heading
-
-Add Font Awesome Icons to our Buttons
-
-Add Font Awesome Icons to all of our Buttons
-
-Responsively Style Radio Buttons
-
-Responsively Style Checkboxes
-
-Style Text Inputs as Form Controls
-
-Line up Form Elements Responsively with Bootstrap
-
-Create a Bootstrap Headline
-
-House our page within a Bootstrap container-fluid div
-
-Create a Bootstrap Row
-
-Split Your Bootstrap Row
-
-Create Bootstrap Wells
-
-Add Elements within Your Bootstrap Wells
-
-Apply the Default Bootstrap Button Style
-
-Create a Class to Target with jQuery Selectors
-
-Add id Attributes to Bootstrap Elements
-
-Label Bootstrap Wells
-
-Give Each Element a Unique id
-
-Label Bootstrap Buttons
-
-Use Comments to Clarify Code
\ No newline at end of file
diff --git a/03-front-end-libraries/data-visualization-with-d3.md b/03-front-end-libraries/data-visualization-with-d3.md
index 70652b1..6b13e81 100644
--- a/03-front-end-libraries/data-visualization-with-d3.md
+++ b/03-front-end-libraries/data-visualization-with-d3.md
@@ -5,63 +5,3 @@ D3.js, or D3, stands for Data Driven Documents. D3 is a JavaScript library to cr
D3 takes input data and maps it into a visual representation of that data. It supports many different data formats. D3 lets you bind (or attach) the data to the Document Object Model (DOM). You use HTML or SVG elements with D3's built-in methods to transform the data into a visualization.
D3 gives you a lot of control over the presentation of data. This section covers the basic functionality and how to create visualizations with the D3 library.
-
-# Upcoming Lessons #
-
-Add Document Elements with D3
-
-Select a Group of Elements with D3
-
-Work with Data in D3
-
-Work with Dynamic Data in D3
-
-Add Inline Styling to Elements
-
-Change Styles Based on Data
-
-Add Classes with D3
-
-Update the Height of an Element Dynamically
-
-Change the Presentation of a Bar Chart
-
-Learn About SVG in D3
-
-Display Shapes with SVG
-
-Create a Bar for Each Data Point in the Set
-
-Dynamically Set the Coordinates for Each Bar
-
-Dynamically Change the Height of Each Bar
-
-Invert SVG Elements
-
-Change the Color of an SVG Element
-
-Add Labels to D3 Elements
-
-Style D3 Labels
-
-Add a Hover Effect to a D3 Element
-
-Add a Tooltip to a D3 Element
-
-Create a Scatterplot with SVG Circles
-
-Add Attributes to the Circle Elements
-
-Add Labels to Scatter Plot Circles
-
-Create a Linear Scale with D3
-
-Set a Domain and a Range on a Scale
-
-Use the d3.max and d3.min Functions to Find Minimum and Maximum Values in a Dataset
-
-Use Dynamic Scales
-
-Use a Pre-Defined Scale to Place Elements
-
-Add Axes to a Visualization
\ No newline at end of file
diff --git a/03-front-end-libraries/front-end-libraries-projects.md b/03-front-end-libraries/front-end-libraries-projects.md
index ed13447..086d4ed 100644
--- a/03-front-end-libraries/front-end-libraries-projects.md
+++ b/03-front-end-libraries/front-end-libraries-projects.md
@@ -3,15 +3,3 @@
This introduction is a stub
Help us make it real on GitHub.
-
-# Upcoming Lessons #
-
-Build a Random Quote Machine
-
-Build a Markdown Previewer
-
-Build a Drum Machine
-
-Build a JavaScript Calculator
-
-Build a Pomodoro Clock
\ No newline at end of file
diff --git a/03-front-end-libraries/jquery.md b/03-front-end-libraries/jquery.md
index 0fcb9a3..9036451 100644
--- a/03-front-end-libraries/jquery.md
+++ b/03-front-end-libraries/jquery.md
@@ -1,41 +1,3 @@
# Introduction to jQuery #
jQuery is one of the many libraries for JavaScript. It is designed to simplify scripting done on the client side. jQuery's most recognizable characteristic is its dollar sign ($) syntax. With it, you can easily manipulate elements, create animations and handle input events.
-
-# Upcoming Lessons #
-
-Learn How Script Tags and Document Ready Work
-
-Target HTML Elements with Selectors Using jQuery
-
-Target Elements by Class Using jQuery
-
-Target Elements by id Using jQuery
-
-Delete Your jQuery Functions
-
-Target the Same Element with Multiple jQuery Selectors
-
-Remove Classes from an Element with jQuery
-
-Change the CSS of an Element Using jQuery
-
-Disable an Element Using jQuery
-
-Change Text Inside an Element Using jQuery
-
-Remove an Element Using jQuery
-
-Use appendTo to Move Elements with jQuery
-
-Clone an Element Using jQuery
-
-Target the Parent of an Element Using jQuery
-
-Target the Children of an Element Using jQuery
-
-Target a Specific Child of an Element Using jQuery
-
-Target Even Elements Using jQuery
-
-Use jQuery to Modify the Entire Page
\ No newline at end of file
diff --git a/03-front-end-libraries/json-apis-and-ajax.md b/03-front-end-libraries/json-apis-and-ajax.md
index 6db5ac9..8469bae 100644
--- a/03-front-end-libraries/json-apis-and-ajax.md
+++ b/03-front-end-libraries/json-apis-and-ajax.md
@@ -9,23 +9,3 @@ User experience benefits from asynchronous processes in several ways. Pages load
The data transferred between the browser and server is often in a format called JavaScript Object Notation (JSON). JSON resembles JavaScript object literal syntax, except that it's transferred as a string. Once received, it can be converted into an object and used in a script.
This section covers how to transfer and use data using AJAX technologies with a freeCodeCamp API.
-
-# Upcoming Lessons #
-
-Handle Click Events with JavaScript using the onclick property
-
-Change Text with click Events
-
-Get JSON with the JavaScript XMLHttpRequest Method
-
-Access the JSON Data from an API
-
-Convert JSON Data to HTML
-
-Render Images from Data Sources
-
-Pre-filter JSON to Get the Data You Need
-
-Get Geolocation Data to Find A User's GPS Coordinates
-
-Post Data with the JavaScript XMLHttpRequest Method
\ No newline at end of file
diff --git a/03-front-end-libraries/react-and-redux.md b/03-front-end-libraries/react-and-redux.md
index 4830e43..5027fdc 100644
--- a/03-front-end-libraries/react-and-redux.md
+++ b/03-front-end-libraries/react-and-redux.md
@@ -6,24 +6,3 @@ In a React Redux app, you create a single Redux store that manages the state of
Improve this intro on GitHub.
-# Upcoming Lessons #
-
-Getting Started with React Redux
-
-Manage State Locally First
-
-Extract State Logic to Redux
-
-Use Provider to Connect Redux to React
-
-Map State to Props
-
-Map Dispatch to Props
-
-Connect Redux to React
-
-Connect Redux to the Messages App
-
-Extract Local State into Redux
-
-Moving Forward From Here
\ No newline at end of file
diff --git a/03-front-end-libraries/react.md b/03-front-end-libraries/react.md
index 8a95f80..6994d97 100644
--- a/03-front-end-libraries/react.md
+++ b/03-front-end-libraries/react.md
@@ -3,101 +3,3 @@
React, popularized by Facebook, is a open-source JavaScript library for building user interfaces. With JSX, it is used to create components, handle state and props, utilize event listeners and certain life cycle methods to update data as it changes.
React combines HTML with JavaScript functionality to create its own markup language, JSX. This section will introduce you to all of these concepts and how to implement them for use with your own projects.
-
-# Upcoming Lessons #
-
-Create a Simple JSX Element
-
-Create a Complex JSX Element
-
-Add Comments in JSX
-
-Render HTML Elements to the DOM
-
-Define an HTML Class in JSX
-
-Learn About Self-Closing JSX Tags
-
-Create a Stateless Functional Component
-
-Create a React Component
-
-Create a Component with Composition
-
-Use React to Render Nested Components
-
-Compose React Components
-
-Render a Class Component to the DOM
-
-Write a React Component from Scratch
-
-Pass Props to a Stateless Functional Component
-
-Pass an Array as Props
-
-Use Default Props
-
-Override Default Props
-
-Use PropTypes to Define the Props You Expect
-
-Access Props Using this.props
-
-Review Using Props with Stateless Functional Components
-
-Create a Stateful Component
-
-Render State in the User Interface
-
-Render State in the User Interface Another Way
-
-Set State with this.setState
-
-Bind 'this' to a Class Method
-
-Use State to Toggle an Element
-
-Write a Simple Counter
-
-Create a Controlled Input
-
-Create a Controlled Form
-
-Pass State as Props to Child Components
-
-Pass a Callback as Props
-
-Use the Lifecycle Method componentWillMount
-
-Use the Lifecycle Method componentDidMount
-
-Add Event Listeners
-
-Manage Updates with Lifecycle Methods
-
-Optimize Re-Renders with shouldComponentUpdate
-
-Introducing Inline Styles
-
-Add Inline Styles in React
-
-Use Advanced JavaScript in React Render Method
-
-Render with an If/Else Condition
-
-Use && for a More Concise Conditional
-
-Use a Ternary Expression for Conditional Rendering
-
-Render Conditionally from Props
-
-Change Inline CSS Conditionally Based on Component State
-
-Use Array.map() to Dynamically Render Elements
-
-Give Sibling Elements a Unique Key Attribute
-
-Use Array.filter() to Dynamically Filter an Array
-
-Render React on the Server with renderToString
\ No newline at end of file
diff --git a/03-front-end-libraries/redux.md b/03-front-end-libraries/redux.md
index b5bfc9f..0f6568d 100644
--- a/03-front-end-libraries/redux.md
+++ b/03-front-end-libraries/redux.md
@@ -3,39 +3,3 @@
Redux is a predictable state container for JavaScript apps. It helps you write applications that behave consistently, run in different environments (client, server, and native), and are easy to test. While you can use Redux with any view library, it's introduced here before being combined with React.
Improve this intro on GitHub.
-
-# Upcoming Lessons #
-
-Create a Redux Store
-
-Get State from the Redux Store
-
-Define a Redux Action
-
-Define an Action Creator
-
-Dispatch an Action Event
-
-Handle an Action in the Store
-
-Use a Switch Statement to Handle Multiple Actions
-
-Use const for Action Types
-
-Register a Store Listener
-
-Combine Multiple Reducers
-
-Send Action Data to the Store
-
-Use Middleware to Handle Asynchronous Actions
-
-Write a Counter with Redux
-
-Never Mutate State
-
-Use the Spread Operator on Arrays
-
-Remove an Item from an Array
-
-Copy an Object with Object.assign
\ No newline at end of file
diff --git a/03-front-end-libraries/sass.md b/03-front-end-libraries/sass.md
index 2bf96aa..e300f6b 100644
--- a/03-front-end-libraries/sass.md
+++ b/03-front-end-libraries/sass.md
@@ -9,23 +9,3 @@ There are two syntaxes available for Sass. The first, known as SCSS (Sassy CSS)
The second and older syntax, known as the indented syntax (or sometimes just "Sass"), uses indentation rather than brackets to indicate nesting of selectors, and newlines rather than semicolons to separate properties. Files using this syntax have the .sass extension.
This section introduces the basic features of Sass.
-
-# Upcoming Lessons #
-
-Store Data with Sass Variables
-
-Nest CSS with Sass
-
-Create Reusable CSS with Mixins
-
-Use @if and @else to Add Logic To Your Styles
-
-Use @for to Create a Sass Loop
-
-Use @each to Map Over Items in a List
-
-Apply a Style Until a Condition is Met with @while
-
-Split Your Styles into Smaller Chunks with Partials
-
-Extend One Set of CSS Styles to Another Element
\ No newline at end of file
diff --git a/04-data-visualization/data-visualization-projects.md b/04-data-visualization/data-visualization-projects.md
index 91f9a00..ab8cc32 100644
--- a/04-data-visualization/data-visualization-projects.md
+++ b/04-data-visualization/data-visualization-projects.md
@@ -3,15 +3,3 @@
This introduction is a stub
Help us make it real on GitHub.
-
-# Upcoming Lessons #
-
-Visualize Data with a Bar Chart
-
-Visualize Data with a Scatterplot Graph
-
-Visualize Data with a Heat Map
-
-Visualize Data with a Choropleth Map
-
-Visualize Data with a Treemap Diagram
\ No newline at end of file
diff --git a/04-data-visualization/data-visualization-with-d3.md b/04-data-visualization/data-visualization-with-d3.md
index 70652b1..6b13e81 100644
--- a/04-data-visualization/data-visualization-with-d3.md
+++ b/04-data-visualization/data-visualization-with-d3.md
@@ -5,63 +5,3 @@ D3.js, or D3, stands for Data Driven Documents. D3 is a JavaScript library to cr
D3 takes input data and maps it into a visual representation of that data. It supports many different data formats. D3 lets you bind (or attach) the data to the Document Object Model (DOM). You use HTML or SVG elements with D3's built-in methods to transform the data into a visualization.
D3 gives you a lot of control over the presentation of data. This section covers the basic functionality and how to create visualizations with the D3 library.
-
-# Upcoming Lessons #
-
-Add Document Elements with D3
-
-Select a Group of Elements with D3
-
-Work with Data in D3
-
-Work with Dynamic Data in D3
-
-Add Inline Styling to Elements
-
-Change Styles Based on Data
-
-Add Classes with D3
-
-Update the Height of an Element Dynamically
-
-Change the Presentation of a Bar Chart
-
-Learn About SVG in D3
-
-Display Shapes with SVG
-
-Create a Bar for Each Data Point in the Set
-
-Dynamically Set the Coordinates for Each Bar
-
-Dynamically Change the Height of Each Bar
-
-Invert SVG Elements
-
-Change the Color of an SVG Element
-
-Add Labels to D3 Elements
-
-Style D3 Labels
-
-Add a Hover Effect to a D3 Element
-
-Add a Tooltip to a D3 Element
-
-Create a Scatterplot with SVG Circles
-
-Add Attributes to the Circle Elements
-
-Add Labels to Scatter Plot Circles
-
-Create a Linear Scale with D3
-
-Set a Domain and a Range on a Scale
-
-Use the d3.max and d3.min Functions to Find Minimum and Maximum Values in a Dataset
-
-Use Dynamic Scales
-
-Use a Pre-Defined Scale to Place Elements
-
-Add Axes to a Visualization
\ No newline at end of file
diff --git a/04-data-visualization/json-apis-and-ajax.md b/04-data-visualization/json-apis-and-ajax.md
index 6db5ac9..8469bae 100644
--- a/04-data-visualization/json-apis-and-ajax.md
+++ b/04-data-visualization/json-apis-and-ajax.md
@@ -9,23 +9,3 @@ User experience benefits from asynchronous processes in several ways. Pages load
The data transferred between the browser and server is often in a format called JavaScript Object Notation (JSON). JSON resembles JavaScript object literal syntax, except that it's transferred as a string. Once received, it can be converted into an object and used in a script.
This section covers how to transfer and use data using AJAX technologies with a freeCodeCamp API.
-
-# Upcoming Lessons #
-
-Handle Click Events with JavaScript using the onclick property
-
-Change Text with click Events
-
-Get JSON with the JavaScript XMLHttpRequest Method
-
-Access the JSON Data from an API
-
-Convert JSON Data to HTML
-
-Render Images from Data Sources
-
-Pre-filter JSON to Get the Data You Need
-
-Get Geolocation Data to Find A User's GPS Coordinates
-
-Post Data with the JavaScript XMLHttpRequest Method
\ No newline at end of file
diff --git a/05-apis-and-microservices/apis-and-microservices-projects.md b/05-apis-and-microservices/apis-and-microservices-projects.md
index 083d248..de93522 100644
--- a/05-apis-and-microservices/apis-and-microservices-projects.md
+++ b/05-apis-and-microservices/apis-and-microservices-projects.md
@@ -3,15 +3,3 @@
This introduction is a stub
Help us make it real on [GitHub](https://github.com/freeCodeCamp/learn/tree/master/src/introductions).
-
-# Upcoming Lessons #
-
-Timestamp Microservice
-
-Request Header Parser Microservice
-
-URL Shortener Microservice
-
-Exercise Tracker
-
-File Metadata Microservice
\ No newline at end of file
diff --git a/05-apis-and-microservices/basic-node-and-express.md b/05-apis-and-microservices/basic-node-and-express.md
index a31817d..418eb4e 100644
--- a/05-apis-and-microservices/basic-node-and-express.md
+++ b/05-apis-and-microservices/basic-node-and-express.md
@@ -15,29 +15,3 @@ Express, while not included with Node.js, is another module often used with it.
While there are alternatives to using Express, its simplicity makes it a good place to begin when learning the interaction between a backend powered by Node.js and the frontend. Working on these challenges will involve you writing your code on Glitch on our starter project. After completing each challenge you can copy your public Glitch url (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicly visible for our testing.
Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!
-
-# Upcoming Lessons #
-
-Meet the Node console
-
-Start a Working Express Server
-
-Serve an HTML File
-
-Serve Static Assets
-
-Serve JSON on a Specific Route
-
-Use the .env File
-
-Implement a Root-Level Request Logger Middleware
-
-Chain Middleware to Create a Time Server
-
-Get Route Parameter Input from the Client
-
-Get Query Parameter Input from the Client
-
-Use body-parser to Parse POST Requests
-
-Get Data from POST Requests
\ No newline at end of file
diff --git a/05-apis-and-microservices/managing-packages-with-npm.json b/05-apis-and-microservices/managing-packages-with-npm.json
index 05d6f0f..6b6e589 100644
--- a/05-apis-and-microservices/managing-packages-with-npm.json
+++ b/05-apis-and-microservices/managing-packages-with-npm.json
@@ -8,21 +8,21 @@
"id": "587d7fb3367417b2b2512bfb",
"title": "How to Use package.json, the Core of Any Node.js Project or npm Package",
"description": [
- "The file package.json is the center of any Node.js project or npm package. It stores information about your project just like the -section in a HTML document describes the content of a webpage. The package.json consists of a single JSON-object where information is stored in \"key\": value-pairs. There are only two required fields in a minimal package.json - name and version - but it’s a good practice to provide additional information about your project that could be useful to future users or maintainers.",
- "The author-field",
- "If you go to the Glitch project that you set up previously and look at on the left side of your screen, you’ll find the file tree where you can see an overview of the various files in your project. Under the file tree’s back-end section, you’ll find package.json - the file that we’ll be improving in the next couple of challenges.",
- "One of the most common pieces of information in this file is the author-field that specifies who’s the creator of a project. It can either be a string or an object with contact details. The object is recommended for bigger projects but in our case, a simple string like the following example will do.",
+ "package.json 是任何 Node.js 项目或 npm 包的中心。它存储项目的相关信息,就像 HTML 文档中的 区域是用来描述网页的通用信息(元信息)一样。package.json 由单个 JSON 对象组成,它以键值对的形式存储项目的信息。一个最小的 package.json 文件至少包含两个必须字段:name 和 version——但是提供有关项目的附加信息是一个更好的做法,在以后它可能对你的用户或者维护者有所帮助。",
+ "author 字段",
+ "如果你转到之前设置的 Glitch 项目并查看屏幕左侧,你会看到一个文件树,你可以在其中查看项目中各种文件的概述。在文件树的末尾部分,你会看到 package.json——我们将在接下来的几个挑战中改进这个文件。",
+ "这个文件中最常见的信息之一是 author 字段,它指定了谁是项目的创建者。它可以是字符串,也可以是带有联系人详细信息的对象。对于较大的项目,建议使用对象,但是在我们的例子中,一个简单的字符串就可以了,比如下面的例子。",
"\"author\": \"Jane Doe\",
",
- "Instructions",
- "Add your name to the author-field in the package.json of your Glitch project.",
- "Remember that you’re writing JSON.",
- "All field-names must use double-quotes (\"), e.g. \"author\"",
- "All fields must be separated with a comma (,)"
+ "说明",
+ "将你的名字添加到 Glitch 项目中,package.json 的 author 字段。",
+ "请记住,你正在编写 JSON 文件。",
+ "所有的字段名必须使用双引号(\")包裹, 比如:\"author\"",
+ "所有字段必须用逗号(,)分隔"
],
"tests": [
{
- "text": "package.json should have a valid \"author\" key",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert(packJson.author, '\"author\" is missing'); }, xhr => { throw new Error(xhr.responseText); })"
+ "text": "package.json 应该有一个有效的 \"author\" 键",
+ "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert(packJson.author, '缺少 \"author\"'); }, xhr => { throw new Error(xhr.responseText); })"
}
],
"solutions": [],
@@ -33,18 +33,18 @@
"id": "587d7fb3367417b2b2512bfc",
"title": "Add a Description to Your package.json",
"description": [
- "The next part of a good package.json is the description-field, where a short but informative description about your project belongs.",
- "If you some day plan to publishing a package to npm, remember that this is the string that should sell your idea to the user when they decide whether to install your package or not. However, that’s not the only use case for the description: Since it’s a great way to summarize what a project does, it’s just as important for your normal Node.js-projects to help other developers, future maintainers or even your future self understand the project quickly.",
- "Regardless of what you plan for your project, a description is definitely recommended. Let’s add something similar to this:",
+ "一个好的 package.json 文件的下一部分就是 description 字段, 通过简洁的文字来描述你的项目。",
+ "如果你计划将来把这个包发布到 npm, 请注意 description 字段的作用是告知用户这个包的用途,这样用户就可以决定是否要安装你发布的包。然而,这并不是描述信息的唯一使用场景:它也是一种很好的总结项目的方式,对于一个普通的 Node.js 项目来说,它可以帮助其它开发者、未来的维护者以及你自己快速地了解项目,这同样非常重要。",
+ "无论你如何计划项目,都建议你使用描述信息。我们来添加类似这样的信息:",
"\"description\": \"A project that does something awesome\",
",
- "Instructions",
- "Add a description to the package.json in your Glitch project.",
- "Remember to use double-quotes for field-names (\") and commas (,) to separate fields."
+ "说明",
+ "在 Glitch 项目的 package.json 中添加描述。",
+ "请记住使用 (\")包裹字段名并且使用(,)分隔字段"
],
"tests": [
{
- "text": "package.json should have a valid \"description\" key",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert(packJson.description, '\"description\" is missing'); }, xhr => { throw new Error(xhr.responseText); })"
+ "text": "package.json 应该有一个有效的 \"description\" 键",
+ "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert(packJson.description, '缺少 \"description\"'); }, xhr => { throw new Error(xhr.responseText); })"
}
],
"solutions": [],
@@ -55,26 +55,26 @@
"id": "587d7fb4367417b2b2512bfd",
"title": "Add Keywords to Your package.json",
"description": [
- "The keywords-field is where you can describe your project using related keywords.",
- "Example",
+ "你可以在 keywords 字段中使用相关的关键字描述项目。",
+ "例子",
"\"keywords\": [ \"descriptive\", \"related\", \"words\" ],
",
- "As you can see, this field is structured as an array of double-quoted strings.",
- "Instructions",
- "Add an array of suitable strings to the keywords-field in the package.json of your Glitch project.",
- "One of the keywords should be freecodecamp."
+ "正如你所见,这个字段的结构是一个由双引号字符串组成的数组。",
+ "说明",
+ "在 Glitch 项目的 package.json 中,给 keywords 添加适当的字符串数组。",
+ "关键词之一应该是 freecodecamp。"
],
"tests": [
{
- "text": "package.json should have a valid \"keywords\" key",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert(packJson.keywords, '\"keywords\" is missing'); }, xhr => { throw new Error(xhr.responseText); })"
+ "text": "package.json 应该有一个有效的 \"keywords\" 键",
+ "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert(packJson.keywords, '缺少 \"keywords\"'); }, xhr => { throw new Error(xhr.responseText); })"
},
{
- "text": "\"keywords\" field should be an Array",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.isArray(packJson.keywords, '\"keywords\" is not an array'); }, xhr => { throw new Error(xhr.responseText); })"
+ "text": "\"keywords\" 应该是一个数组",
+ "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.isArray(packJson.keywords, '\"keywords\" 不是一个数组'); }, xhr => { throw new Error(xhr.responseText); })"
},
{
- "text": "\"keywords\" should include \"freecodecamp\"",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.include(packJson.keywords, 'freecodecamp', '\"keywords\" does not include \"freecodecamp\"'); }, xhr => { throw new Error(xhr.responseText); })"
+ "text": "\"keywords\" 中应该包含关键词 \"freecodecamp\"",
+ "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.include(packJson.keywords, 'freecodecamp', '\"keywords\" 未包含 \"freecodecamp\"'); }, xhr => { throw new Error(xhr.responseText); })"
}
],
"solutions": [],
@@ -85,18 +85,18 @@
"id": "587d7fb4367417b2b2512bfe",
"title": "Add a License to Your package.json",
"description": [
- "The license-field is where you inform users of your project what they are allowed to do with it.",
- "Some common licenses for open source projects include MIT and BSD. http://choosealicense.com is a great resource if you want to learn more about what license could fit your project.",
- "License information is not required. Copyright laws in most countries will give you ownership of what you create by default. However, it’s always a good practice to explicitly state what users can and can’t do.",
- "Example",
+ "license 字段是你告知用户允许他们拿这个项目干什么的地方。",
+ "常见的开源协议是 MIT 和 BSD。如果你想了解更多适合你项目的许可证的信息,那么 http://choosealicense.com 是一个不错的网站。",
+ "许可证信息并不是必须的。大多数国家的版权法会默认让你拥有自己创作的作品的所有权。但是,明确说明用户可以做什么和不能做什么会是一个很好的做法。",
+ "例子",
"\"license\": \"MIT\",
",
- "Instructions",
- "Fill the license-field in the package.json of your Glitch project as you find suitable."
+ "说明",
+ "在 Glitch 项目的 package.json 中填写合适的 license 字段。"
],
"tests": [
{
- "text": "package.json should have a valid \"license\" key",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert(packJson.license, '\"license\" is missing'); }, xhr => { throw new Error(xhr.responseText); })"
+ "text": "package.json 应该有一个有效的 \"license\" 键",
+ "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert(packJson.license, '缺少 \"license\"'); }, xhr => { throw new Error(xhr.responseText); })"
}
],
"solutions": [],
@@ -107,16 +107,16 @@
"id": "587d7fb4367417b2b2512bff",
"title": "Add a Version to Your package.json",
"description": [
- "The version is together with name one of the required fields in a package.json. This field describes the current version of your project.",
- "Example",
+ "在 package.json 中 version 和 name 是所必填的字段之一。version 字段描述了当前项目的版本。",
+ "例子",
"\"version\": \"1.2\",
",
- "Instructions",
- "Add a version to the package.json in your Glitch project."
+ "说明",
+ "在 Glitch 项目中的 package.json 中添加一个版本号。"
],
"tests": [
{
- "text": "package.json should have a valid \"version\" key",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert(packJson.version, '\"version\" is missing'); }, xhr => { throw new Error(xhr.responseText); })"
+ "text": "package.json 应该包含一个有效的 \"version\" 键",
+ "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert(packJson.version, '缺少 \"version\"'); }, xhr => { throw new Error(xhr.responseText); })"
}
],
"solutions": [],
@@ -127,24 +127,24 @@
"id": "587d7fb4367417b2b2512c00",
"title": "Expand Your Project with External Packages from npm",
"description": [
- "One of the biggest reasons to use a package manager is their powerful dependency management. Instead of manually having to make sure that you get all dependencies whenever you set up a project on a new computer, npm automatically installs everything for you. But how can npm know exactly what your project needs? Meet the dependencies-section of your package.json.",
- "In the dependencies-section, packages your project require are stored using the following format:",
+ "使用包管理器的最大原因之一是它们强大的依赖管理特性。在新的计算机上开始一个项目时,不用手动确认你已安装所有的依赖,npm 会自动为你安装它们。但是 npm 如何准确的知道你项目需要哪些依赖呢?我们来看看 package.json 中 dependencies 这一部分。",
+ "在 dependencies 这一部分,你的项目需要按照下面这种格式来存储这些依赖包:",
"\"dependencies\": {
",
" \"package-name\": \"version\",
",
" \"express\": \"4.14.0\"
",
"}
",
- "Instructions",
- "Add version 2.14.0 of the package moment to the dependencies-field of your package.json",
- "Moment is a handy library for working with time and dates."
+ "说明",
+ "在 package.json 的 dependencies 字段中添加一个版本号为 2.14.0 的 moment 包",
+ "Moment 是一个非常方便的库,它用来处理时间和日期。"
],
"tests": [
{
- "text": "\"dependencies\" should include \"moment\"",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'moment', '\"dependencies\" does not include \"moment\"'); }, xhr => { throw new Error(xhr.responseText); })"
+ "text": "\"dependencies\" 应该包含 \"moment\"",
+ "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'moment', '\"dependencies\" 未包含 \"moment\"'); }, xhr => { throw new Error(xhr.responseText); })"
},
{
- "text": "\"moment\" version should be \"2.14.0\"",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.match(packJson.dependencies.moment, /^[\\^\\~]?2\\.14\\.0/, 'Wrong version of \"moment\" installed. It should be 2.14.0'); }, xhr => { throw new Error(xhr.responseText); })"
+ "text": "\"moment\" 的版本应该是 \"2.14.0\"",
+ "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.match(packJson.dependencies.moment, /^[\\^\\~]?2\\.14\\.0/, '安装的 \"moment\" 版本有误。它应该是 2.14.0'); }, xhr => { throw new Error(xhr.responseText); })"
}
],
"solutions": [],
@@ -155,29 +155,29 @@
"id": "587d7fb5367417b2b2512c01",
"title": "Manage npm Dependencies By Understanding Semantic Versioning",
"description": [
- "Versions of the npm packages in the dependencies-section of your package.json follow what’s called Semantic Versioning (SemVer), an industry standard for software versioning aiming to make it easier to manage dependencies. Libraries, frameworks or other tools published on npm should use SemVer in order to clearly communicate what kind of changes that projects who depend on the package can expect if they update.",
- "SemVer doesn’t make sense in projects without public APIs - so unless your project is similar to the examples above, use another versioning format.",
- "So why do you need to understand SemVer?",
- "Knowing SemVer can be useful when you develop software that use external dependencies (which you almost always do). One day, your understanding of these numbers will save you from accidentally introducing breaking changes to your project without understanding why things “that worked yesterday” suddenly doesn’t.",
- "This is how Semantic Versioning works according to the official website:",
- "Given a version number MAJOR.MINOR.PATCH, increment the:",
- "MAJOR version when you make incompatible API changes,",
- "MINOR version when you add functionality in a backwards-compatible manner, and",
- "PATCH version when you make backwards-compatible bug fixes.",
- "This means that PATCHes are bug fixes and MINORs add new features but neither of them break what worked before. Finally, MAJORs add changes that won’t work with earlier versions.",
- "Example",
- "A semantic version number: 1.3.8",
- "Instructions",
- "In the dependencies-section of your package.json, change the version of moment to match MAJOR version 2, MINOR version 10 and PATCH version 2"
+ "在 package.json 中,dependencies 这部分的 npm 包的版本号遵循所谓的语义化版本(SemVer),它是一种软件版本控制的行业标准,旨在使管理依赖项更加容易。在 npm 上发布的库、框架或其它工具都应该使用语义化版本(SemVer),以便让使用该依赖包的用户能够在依赖包需要升级时,提前规划自己的项目需要为之做出的改动。",
+ "在没有公共 API 的项目中,语义化版本(SemVer)没有意义——除非你的项目与上面的例子类似,否则请使用其它的版本控制方式吧。",
+ "为什么你需要了解语义化版本(SemVer)?",
+ "在开发使用外部依赖项的软件(大多数情况都是这样)时,了解语义化版本(SemVer)会很有用。有一天你会明白这些数字的含义,在项目中它可以避免你意外地引入一些非向下兼容的更改,同时也能避免“昨天还能好好的运行,今天就不行了”这种情况发生。",
+ "根据语义化版本(SemVer)官方网站,它是这样规定的:",
+ "版本格式:主版本号.次版本号.修订号
,版本号递增规则如下:",
+ "主版本号:当你做了不向下兼容的公共 API 修改,",
+ "次版本号:当你添加了向下兼容的新功能,",
+ "修订号:当你做了向下兼容的问题修正。",
+ "这意味着修订号是用来修复错误的,次版本号则是添加了新功能,但它们都没有破坏之前的功能。最后,主版本号的变更则是添加了对早期版本不兼容的更改。",
+ "例子",
+ "一个语义化的版本号:1.3.8",
+ "说明",
+ "在 package.json 中,修改 dependencies 里的 moment 的版本号,让它的主版本是 2,次版本号是 10,修订号是 2。"
],
"tests": [
{
- "text": "\"dependencies\" should include \"moment\"",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'moment', '\"dependencies\" does not include \"moment\"'); }, xhr => { throw new Error(xhr.responseText); })"
+ "text": "\"dependencies\" 应该包含 \"moment\"",
+ "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'moment', '\"dependencies\" 未包含 \"moment\"'); }, xhr => { throw new Error(xhr.responseText); })"
},
{
- "text": "\"moment\" version should be \"2.10.2\"",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.match(packJson.dependencies.moment, /^[\\^\\~]?2\\.10\\.2/, 'Wrong version of \"moment\". It should be 2.10.2'); }, xhr => { throw new Error(xhr.responseText); })"
+ "text": "\"moment\" 的版本号应该是 \"2.10.2\"",
+ "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.match(packJson.dependencies.moment, /^[\\^\\~]?2\\.10\\.2/, '\"moment\" 的版本号有误。它应该是 2.10.2'); }, xhr => { throw new Error(xhr.responseText); })"
}
],
"solutions": [],
@@ -188,22 +188,22 @@
"id": "587d7fb5367417b2b2512c02",
"title": "Use the Tilde-Character to Always Use the Latest Patch Version of a Dependency",
"description": [
- "In the last challenge, we told npm to only include a specific version of a package. That’s a useful way to freeze your dependencies if you need to make sure that different parts of your project stay compatible with each other. But in most use cases you don’t want to miss bug fixes, since they often include important security patches and (hopefully) don’t break things in doing so.",
- "To allow a npm dependency to get updated to the latest PATCH-version, you can prefix the dependency’s version with the tilde-character (~). In package.json, our current rule for how npm may upgrade moment is to use a specific version only (2.10.2), but we want to allow the latest 2.10.x-version.",
- "Example",
- "\"some-package-name\": \"~1.3.8\" allows updates to any 1.3.x version.
",
- "Instructions",
- "Use the tilde-character (~) to prefix the version of moment in your dependencies and allow npm to update it to any new PATCH release.",
- "Note that the version numbers themselves not should be changed."
+ "在最后一个挑战中,我们告诉 npm 只包含特定版本的依赖包。如果想让项目各个部分保持相互兼容,锁定依赖包版本是一个有效的办法。但是大多数情况下,我们并不希望错过依赖项的问题修复,因为它们通常包含重要的安全补丁,而且它们理论上也会兼容我们既有的代码。",
+ "为了让 npm 依赖项更新到最新的修订版,你可以在依赖包的版本号前加一个波浪符号(~)。在 package.json 中,我们当前的 moment 依赖包更新规则是:仅使用特定版本(2.10.2),但我们想用它最新的 2.10.x 版本。",
+ "例子",
+ "\"some-package-name\": \"~1.3.8\" 定义这个包允许使用的版本为 1.3.x。
",
+ "说明",
+ "在 dependencies 中,给 moment 的版本号添加波浪符号(~)前缀,允许 npm 将其更新为最新的修订版。",
+ "请注意,原本的版本号不用更改。"
],
"tests": [
{
- "text": "\"dependencies\" should include \"moment\"",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'moment', '\"dependencies\" does not include \"moment\"'); }, xhr => { throw new Error(xhr.responseText); })"
+ "text": "\"dependencies\" 应该包含 \"moment\"",
+ "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'moment', '\"dependencies\" 未包含 \"moment\"'); }, xhr => { throw new Error(xhr.responseText); })"
},
{
- "text": "\"moment\" version should match \"~2.10.2\"",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.match(packJson.dependencies.moment, /^\\~2\\.10\\.2/, 'Wrong version of \"moment\". It should be ~2.10.2'); }, xhr => { throw new Error(xhr.responseText); })"
+ "text": "\"moment\" 的版本号应该是 \"~2.10.2\"",
+ "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.match(packJson.dependencies.moment, /^\\~2\\.10\\.2/, '\"moment\" 版本号有误,它应该是 ~2.10.2'); }, xhr => { throw new Error(xhr.responseText); })"
}
],
"solutions": [],
@@ -214,22 +214,22 @@
"id": "587d7fb5367417b2b2512c03",
"title": "Use the Caret-Character to Use the Latest Minor Version of a Dependency",
"description": [
- "Similar to how the tilde (~) we learned about in the last challenge allow npm to install the latest PATCH for a dependency, the caret (^) allows npm to install future updates as well. The difference is that the caret will allow both MINOR updates and PATCHes.",
- "At the moment, your current version of moment should be ~2.10.2 which allows npm to install to the latest 2.10.x-version. If we instead were to use the caret (^) as our version prefix, npm would instead be allowed to update to any 2.x.x-version.",
- "Example",
- "\"some-package-name\": \"^1.3.8\" allows updates to any 1.x.x version.
",
- "Instructions",
- "Use the caret-character (^) to prefix the version of moment in your dependencies and allow npm to update it to any new MINOR release.",
- "Note that the version numbers themselves not should be changed."
+ "和上一个挑战中我们学到的波浪符号(~)来安装最新的修订版依赖一样,使用插入符号(^)允许 npm 来安装功能更新。它们的不同之处在于:插入符号(^)允许次版本和修订版更新。",
+ "此刻,你项目中的 moment 依赖包的版本应该是 ~2.10.2,这意味着 npm 可以安装 2.10.x 版的 moment,如果使用插入符号(^)来替换版本号的前缀,那么 npm 可以安装的版本则是 2.x.x。",
+ "例子",
+ "\"some-package-name\": \"^1.3.8\" 定义这个包允许使用的版本为 1.x.x。
",
+ "说明",
+ "使用插入符号(^)为依赖项中的 moment 版本添加前缀,允许 npm 更新依赖包到任意向下兼容的新功能版。",
+ "请注意,原本的版本号不用更改。"
],
"tests": [
{
"text": "\"dependencies\" should include \"moment\"",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'moment', '\"dependencies\" does not include \"moment\"'); }, xhr => { throw new Error(xhr.responseText); })"
+ "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'moment', '\"dependencies\" 未包含 \"moment\"'); }, xhr => { throw new Error(xhr.responseText); })"
},
{
"text": "\"moment\" version should match \"^2.x.x\"",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.match(packJson.dependencies.moment, /^\\^2\\./, 'Wrong version of \"moment\". It should be ^2.10.2'); }, xhr => { throw new Error(xhr.responseText); })"
+ "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.match(packJson.dependencies.moment, /^\\^2\\./, '\"moment\" 的版本号有误,它应该是 ^2.10.2'); }, xhr => { throw new Error(xhr.responseText); })"
}
],
"solutions": [],
@@ -240,17 +240,17 @@
"id": "587d7fb5367417b2b2512c04",
"title": "Remove a Package from Your Dependencies",
"description": [
- "Now you’ve tested a few ways you can manage dependencies of your project by using the package.json's dependencies-section. You’ve included external packages by adding them to the file and even told npm what types of versions you want by using special characters as the tilde (~) or the caret (^).",
- "But what if you want to remove an external package that you no longer need? You might already have guessed it - Just remove the corresponding \"key\": value-pair for that from your dependencies.",
- "This same method applies to removing other fields in your package.json as well",
- "Instructions",
- "Remove the package moment from your dependencies.",
- "Make sure you have the right amount of commas after removing it."
+ "在 package.json 中 dependencies 这一部分,目前尝试了一些管理依赖的方式。你已经添加了一些外部的依赖包到项目中,甚至通过一些特殊的字符比如波浪符号(~)或者插入符号(^)来告诉 npm 你想要的版本类型。",
+ "但是,如果想要删除不需要的依赖包,该怎么办呢?你可能已经猜到了——只需要删除 dependencies 中的键值对就行了。",
+ "同样的方法也适用于删除 package.json 中的其它字段",
+ "说明",
+ "删除 moment 依赖包。",
+ "删除依赖包后,确保没有多余的逗号。"
],
"tests": [
{
- "text": "\"dependencies\" should not include \"moment\"",
- "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.notProperty(packJson.dependencies, 'moment', '\"dependencies\" still includes \"moment\"'); }, xhr => { throw new Error(xhr.responseText); })"
+ "text": "\"dependencies\" 不包含 \"moment\"",
+ "testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.notProperty(packJson.dependencies, 'moment', '\"dependencies\" 中仍然有 \"moment\"'); }, xhr => { throw new Error(xhr.responseText); })"
}
],
"solutions": [],
diff --git a/05-apis-and-microservices/managing-packages-with-npm.md b/05-apis-and-microservices/managing-packages-with-npm.md
index 24a7097..1a43f5b 100644
--- a/05-apis-and-microservices/managing-packages-with-npm.md
+++ b/05-apis-and-microservices/managing-packages-with-npm.md
@@ -1,36 +1,13 @@
-# Introduction to the Managing Packages with npm Challenges #
+# 挑战简介——使用 npm 管理包 #
-The Node Package Manager (npm) is a command-line tool used by developers to share and control modules (or packages) of JavaScript code written for use with Node.js.
+Node 包管理器(npm)是一种命令行工具,开发人员使用它来分享和管理 Node.js 编写的 JavaScript 模块(包)。
-When starting a new project, npm generates a package.json file. This file lists the package dependencies for your project. Since npm packages are regularly updated, the package.json file allows you to set specific version numbers for each dependency. This ensures that updates to a package don't break your project.
+启动新项目时,npm 会生成一个 package.json 文件。此文件列出了项目的所有依赖。因为依赖包是有规律可循的,package.json 文件允许为每个依赖项设置特定的版本号。以确保这些依赖包更新时不会破坏你的项目。
-npm saves packages in a folder named nodemodules. These packages can be installed in two ways:
+npm 会保存依赖包放入叫 nodemodules 的文件夹内。这些依赖包可以通过两种方式安装:
-globally in a root nodemodules folder, accessible by all projects.
-locally within a project's own node_modules folder, accessible only to that project.
+全局安装的依赖包会放在根目录下叫 nodemodules 的文件夹内,以供所有项目使用
+本地安装的依赖包会放在项目内叫 node_modules 的文件夹内,只可以在当前项目使用
-Most developers prefer to install packages local to each project to create a separation between the dependencies of different projects. Working on these challenges will involve you writing your code on Glitch on our starter project. After completing each challenge you can copy your public Glitch url (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicly visible for our testing.
-Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe!
-
-# Upcoming Lessons #
-
-How to Use package.json, the Core of Any Node.js Project or npm Package
-
-Add a Description to Your package.json
-
-Add Keywords to Your package.json
-
-Add a License to Your package.json
-
-Add a Version to Your package.json
-
-Expand Your Project with External Packages from npm
-
-Manage npm Dependencies By Understanding Semantic Versioning
-
-Use the Tilde-Character to Always Use the Latest Patch Version of a Dependency
-
-Use the Caret-Character to Use the Latest Minor Version of a Dependency
-
-Remove a Package from Your Dependencies
\ No newline at end of file
+为了能隔离不同项目之间的依赖,大多数开发者更喜欢在本地项目内安装依赖包。你需要在 Glitch 里启动这个项目并编写相应的代码来应对这些挑战。完成每个挑战后,你可以将 Glitch 地址公开(到你的应用主页)并复制它们,放到挑战题中进行测试!你可以选择另外的平台编写项目代码,但是必须设置为可公开访问,以便我们进行测试。可以使用这个链接在 Glitch 上开始项目,或者克隆这个 GitHub 仓库链接来开始项目!如果你使用 Glitch,请记住将项目链接保存到安全的地方!
diff --git a/05-apis-and-microservices/mongodb-and-mongoose.md b/05-apis-and-microservices/mongodb-and-mongoose.md
index fe705c2..cbc0c25 100644
--- a/05-apis-and-microservices/mongodb-and-mongoose.md
+++ b/05-apis-and-microservices/mongodb-and-mongoose.md
@@ -75,29 +75,3 @@ Almost done! We have created our new database and created an user to access it,
* That's it! This is the URI you will add to your application to connect to your database. Keep this URI safe somewhere, so you can use it later!
* Feel free to create separate databases for different applications, if they don't have an use for the same data. You just need to create the sandbox, user and obtain the new URI.
-
-# Upcoming Lessons #
-
-Install and Set Up Mongoose
-
-Create a Model
-
-Create and Save a Record of a Model
-
-Create Many Records with model.create()
-
-Use model.find() to Search Your Database
-
-Use model.findOne() to Return a Single Matching Document from Your Database
-
-Use model.findById() to Search Your Database By _id
-
-Perform Classic Updates by Running Find, Edit, then Save
-
-Perform New Updates on a Document Using model.findOneAndUpdate()
-
-Delete One Document Using model.findByIdAndRemove
-
-Delete Many Documents with model.remove()
-
-Chain Search Query Helpers to Narrow Search Results
\ No newline at end of file
diff --git a/06-information-security-and-quality-assurance/advanced-node-and-express.md b/06-information-security-and-quality-assurance/advanced-node-and-express.md
index 999aa52..f1eb377 100644
--- a/06-information-security-and-quality-assurance/advanced-node-and-express.md
+++ b/06-information-security-and-quality-assurance/advanced-node-and-express.md
@@ -3,49 +3,3 @@
Authentication is the process or action of verifying the identity of a user or process. Up to this point you have not been able to create an app utilizing this key concept.
The most common and easiest to use authentication middleware for Node.js is Passport. It is easy to learn, light-weight, and extremely flexible allowing for many strategies, which we will talk about in later challenges. In addition to authentication we will also look at template engines which allow for use of Pug and web sockets which allow for real time communication between all your clients and your server. Working on these challenges will involve you writing your code on Glitch on our starter project. After completing each challenge you can copy your public glitch url (to the homepage of your app) into the challenge screen to test it! Optionally you may choose to write your project on another platform but it must be publicaly visible for our testing. Start this project on Glitch using this link or clone this repository on GitHub! If you use Glitch, remember to save the link to your project somewhere safe.
-
-# Upcoming Lessons #
-
-Set up a Template Engine
-
-Use a Template Engine's Powers
-
-Set up Passport
-
-Serialization of a User Object
-
-Implement the Serialization of a Passport User
-
-Authentication Strategies
-
-How to Use Passport Strategies
-
-Create New Middleware
-
-How to Put a Profile Together
-
-Logging a User Out
-
-Registration of New Users
-
-Hashing Your Passwords
-
-Clean Up Your Project with Modules
-
-Implementation of Social Authentication
-
-Implementation of Social Authentication II
-
-Implementation of Social Authentication III
-
-Set up the Environment
-
-Communicate by Emitting
-
-Handle a Disconnect
-
-Authentication with Socket.IO
-
-Announce New Users
-
-Send and Display Chat Messages
\ No newline at end of file
diff --git a/06-information-security-and-quality-assurance/information-security-and-quality-assurance-projects.md b/06-information-security-and-quality-assurance/information-security-and-quality-assurance-projects.md
index 270fb76..a169cee 100644
--- a/06-information-security-and-quality-assurance/information-security-and-quality-assurance-projects.md
+++ b/06-information-security-and-quality-assurance/information-security-and-quality-assurance-projects.md
@@ -4,14 +4,3 @@ This introduction is a stub
Help us make it real on [GitHub](https://github.com/freeCodeCamp/learn/tree/master/src/introductions).
-# Upcoming Lessons #
-
-Metric-Imperial Converter
-
-Issue Tracker
-
-Personal Library
-
-Stock Price Checker
-
-Anonymous Message Board
\ No newline at end of file
diff --git a/06-information-security-and-quality-assurance/information-security-with-helmetjs.json b/06-information-security-and-quality-assurance/information-security-with-helmetjs.json
index bfc897b..6eda557 100644
--- a/06-information-security-and-quality-assurance/information-security-with-helmetjs.json
+++ b/06-information-security-and-quality-assurance/information-security-with-helmetjs.json
@@ -8,12 +8,12 @@
"id": "587d8247367417b2b2512c36",
"title": "Install and Require Helmet",
"description": [
- "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.",
- "Helmet helps you secure your Express apps by setting various HTTP headers. Install the package, then require it."
+ "注意,本项目在 这个 Glitch 项目 的基础上进行开发。你也可以从 GitHub 上克隆。",
+ "Helmet 通过配置不同的 HTTP 头部信息来使你的 Express 应用更加安全。安装,并引入 Helmet 这个包。"
],
"tests": [
{
- "text": "\"helmet\" dependency should be in package.json",
+ "text": "package.json 文件应该有 \"helmet\" 这个依赖包",
"testString": "getUserInput => $.get(getUserInput('url') + '/_api/package.json').then(data => { var packJson = JSON.parse(data); assert.property(packJson.dependencies, 'helmet'); }, xhr => { throw new Error(xhr.responseText); })"
}
],
@@ -26,12 +26,12 @@
"id": "587d8247367417b2b2512c37",
"title": "Hide Potentially Dangerous Information Using helmet.hidePoweredBy()",
"description": [
- "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.",
- "Hackers can exploit known vulnerabilities in Express/Node if they see that your site is powered by Express. X-Powered-By: Express is sent in every request coming from Express by default. The helmet.hidePoweredBy() middleware will remove the X-Powered-By header. You can also explicitly set the header to something else, to throw people off. e.g. app.use(helmet.hidePoweredBy({ setTo: 'PHP 4.2.0' }))"
+ "温馨提醒,本项目在 这个 Glitch 项目 的基础上进行开发。你也可以从 GitHub 上克隆。",
+ "如果黑客发现你的网站是用 Express 搭建的,那么他们就可以利用 Express 或 Node 现存的漏洞来攻击你的网站。X-Powered-By: Express
默认情况下会被添加到所有响应的头部。不过 helmet.hidePoweredBy() 中间件可以帮你移除 X-Powered-By 头。你甚至可以把头设置成其它的值。 如 app.use(helmet.hidePoweredBy({ setTo: 'PHP 4.2.0' }))
"
],
"tests": [
{
- "text": "helmet.hidePoweredBy() middleware should be mounted correctly",
+ "text": "helmet.hidePoweredBy() 中间件应该被正确加载",
"testString": "getUserInput => $.get(getUserInput('url') + '/_api/app-info').then(data => { assert.include(data.appStack, 'hidePoweredBy'); assert.notEqual(data.headers['x-powered-by'], 'Express')}, xhr => { throw new Error(xhr.responseText); })"
}
],
@@ -44,17 +44,17 @@
"id": "587d8247367417b2b2512c38",
"title": "Mitigate the Risk of Clickjacking with helmet.frameguard()",
"description": [
- "As a reminder, this project is being built upon the following starter project on Glitch, or cloned from GitHub.",
- "Your page could be put in a or