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最好以;来结束。", "
", - "Change your 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(/\\s*CatPhotoApp\\s*<\\/h2>/),' Your style declaration should end with a ; .');" - } + "text": "h2元素的style 属性的值应该以;结束。", + "testString": "assert(code.match(/\\s*CatPhotoApp\\s*<\\/h2>/),'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>
</style>
", - "Inside that style block, you can create a 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>
  h2 {color: red;}
</style>
", - "Note that it's important to have both opening and closing curly braces ({ 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.", + "注意,在每个元素的样式声明区域里,左右花括号({})一定要写全。你需要确定你定义的样式规则位于花括号之间。以及,记得在每个元素样式规则的末尾添加分号。", "
", - "Delete your 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(//g) || []).length, 'Make sure all your style elements are valid and have a closing tag.');" + "text": "确保你的样式声明里的h2规则需以花括号所包括,和分号结束。", + "testString": "assert(code.match(/h2\\s*\\{\\s*color\\s*:.*;\\s*\\}/g), '确保你的样式声明里的h2规则需以花括号所包括,和分号结束。');" } ], "challengeType": 0, @@ -156,33 +152,33 @@ "id": "bad87fee1348bd9aecf08806", "title": "Use a CSS Class to Style an Element", "description": [ - "Classes are reusable styles that can be added to HTML elements.", - "Here's an example CSS class declaration:", + "CSS 的class具有可重用性,可应用于各种 HTML 元素。", + "一个 CSSclass声明示例,如下所示:", "
<style>
  .blue-text {
    color: blue;
  }
</style>
", - "You can see that we've created a CSS class called blue-text within the <style> tag.", - "You can apply a class to an HTML element like this:", + "可以看到,我们在<style>样式声明区域里,创建了一个名为blue-textclass选择器。", + "你可以将 CSSclass选择器应用到一个HTML元素里,如下所示:", "<h2 class=\"blue-text\">CatPhotoApp</h2>", - "Note that in your CSS style element, class names start with a period. In your HTML elements' class attribute, the class name does not include the period.", + "注意你的style样式区域声明里,class需以句号开头。而在你的HTML元素里的class属性的类名,不需要包含句号", "
", - "Inside your style element, change the h2 selector to .red-text and update the color's value from blue to red.", - "Give your h2 element the class attribute with a value of 'red-text'." + "在style样式声明里,h2元素选择器改为.red-text的 CSS class 择器,同时将颜色blue变为red。", + "在你的h2元素里,添加一个class属性,且值为'red-text'。" ], "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 h2 element should have the class red-text.", - "testString": "assert($(\"h2\").hasClass(\"red-text\"), 'Your h2 element should have the class red-text.');" + "text": "你的h2元素应含有red-text class 选择器。", + "testString": "assert($(\"h2\").hasClass(\"red-text\"), '你的h2元素应含有red-text class 选择器。');" }, { - "text": "Your stylesheet should declare a red-text class and have its color set to red.", - "testString": "assert(code.match(/\\.red-text\\s*\\{\\s*color\\s*:\\s*red;\\s*\\}/g), 'Your stylesheet should declare a red-text class and have its color set to red.');" + "text": "你的style样式声明区域里应该包含一个red-text class 选择器,并且它的颜色应为红色。", + "testString": "assert(code.match(/\\.red-text\\s*\\{\\s*color\\s*:\\s*red;\\s*\\}/g), '你的style样式声明区域里应该包含一个red-text class 选择器,并且它的颜色应为红色。');" }, { - "text": "Do not use inline style declarations like style=\"color: red\" in your h2 element.", - "testString": "assert($(\"h2\").attr(\"style\") === undefined, 'Do not use inline style declarations like style=\"color: red\" in your h2 element.');" + "text": "不要在h2元素里使用style=\"color: red\"的行内样式 。", + "testString": "assert($(\"h2\").attr(\"style\") === undefined, '不要在h2元素里使用style=\"color: red\"的行内样式 。');" } ], "challengeType": 0, @@ -239,28 +235,28 @@ "id": "bad87fee1348bd9aefe08806", "title": "Style Multiple Elements with a CSS Class", "description": [ - "Classes allow you to use the same CSS styles on multiple HTML elements. You can see this by applying your red-text class to the first p element." + "通过 CSS class 选择器,多个 HTML 元素可以使用相同的 CSS 样式规则。你可以将red-text class 选择器应用在第一个p元素上。" ], "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 h2 element should have the class red-text.", - "testString": "assert($(\"h2\").hasClass(\"red-text\"), 'Your h2 element should have the class red-text.');" + "text": "你的h2元素应该含有名为red-text 的 class 选择器。", + "testString": "assert($(\"h2\").hasClass(\"red-text\"), '你的h2元素应该含有名为red-text 的 class 选择器。');" }, { - "text": "Your first p element should be red.", - "testString": "assert($(\"p:eq(0)\").css(\"color\") === \"rgb(255, 0, 0)\", 'Your first p element should be red.');" + "text": "你的第一个p元素应该为红色。", + "testString": "assert($(\"p:eq(0)\").css(\"color\") === \"rgb(255, 0, 0)\", '你的第一个p元素应该为红色。');" }, { - "text": "Your second and third p elements should not be red.", - "testString": "assert(!($(\"p:eq(1)\").css(\"color\") === \"rgb(255, 0, 0)\") && !($(\"p:eq(2)\").css(\"color\") === \"rgb(255, 0, 0)\"), 'Your second and third p elements should not be red.');" + "text": "你的第二和第三个p元素不应该为红色。", + "testString": "assert(!($(\"p:eq(1)\").css(\"color\") === \"rgb(255, 0, 0)\") && !($(\"p:eq(2)\").css(\"color\") === \"rgb(255, 0, 0)\"), '你的第二和第三个p元素不应该为红色。');" }, { - "text": "Your first p element should have the class red-text.", - "testString": "assert($(\"p:eq(0)\").hasClass(\"red-text\"), 'Your first p element should have the class red-text.');" + "text": "你的第一个p元素应该包含名为red-text的 class 选择器。", + "testString": "assert($(\"p:eq(0)\").hasClass(\"red-text\"), '你的第一个p 元素应该包含名为red-text的 class 选择器。');" } ], "challengeType": 0, @@ -317,15 +313,15 @@ "id": "bad87fee1348bd9aedf08806", "title": "Change the Font Size of an Element", "description": [ - "Font size is controlled by the font-size CSS property, like this:", + "字体大小由font-size的 CSS 属性控制,如下所示:", "
h1 {
  font-size: 30px;
}
", "
", - "Inside the same <style> tag that contains your red-text class, create an entry for p elements and set the font-size to 16 pixels (16px)." + "在包含red-text class 的<style>声明区域的里,创建一个p元素样式规则,并设置font-size为 16 像素(16px)。" ], "tests": [ { - "text": "Between the style tags, give the p elements font-size of 16px. Browser and Text zoom should be at 100%.", - "testString": "assert(code.match(/p\\s*{\\s*font-size\\s*:\\s*16\\s*px\\s*;\\s*}/i), 'Between the style tags, give the p elements font-size of 16px. Browser and Text zoom should be at 100%.');" + "text": "在style样式声明区域里,p元素的font-size的值应为16px,浏览器和文本缩放应设置为 100%。", + "testString": "assert(code.match(/p\\s*{\\s*font-size\\s*:\\s*16\\s*px\\s*;\\s*}/i), '在style样式声明区域里,p元素的font-size的值应为16px,浏览器和文本缩放应设置为 100%。');" } ], "challengeType": 0, @@ -382,16 +378,16 @@ "id": "bad87fee1348bd9aede08807", "title": "Set the Font Family of an Element", "description": [ - "You can set which font an element should use, by using the font-family property.", - "For example, if you wanted to set your h2 element's font to sans-serif, you would use the following CSS:", + "通过font-family属性,可以设置元素里面的字体样式。", + "例如,如果你想设置h2元素的字体为sans-serif,你可以用以下的 CSS 规则:", "
h2 {
  font-family: sans-serif;
}
", "
", - "Make all of your p elements use the monospace font." + "确保你所有的p元素使用monospace字体。" ], "tests": [ { - "text": "Your p elements should use the font monospace.", - "testString": "assert($(\"p\").not(\".red-text\").css(\"font-family\").match(/monospace/i), 'Your p elements should use the font monospace.');" + "text": "你的p元素应该使用monospace字体。", + "testString": "assert($(\"p\").not(\".red-text\").css(\"font-family\").match(/monospace/i), '你的p元素应该使用monospace字体。');" } ], "challengeType": 0, @@ -4399,4 +4395,4 @@ } } ] -} \ No newline at end of file +} diff --git a/01-responsive-web-design/basic-css.md b/01-responsive-web-design/basic-css.md index 9b27984..c3c039c 100644 --- a/01-responsive-web-design/basic-css.md +++ b/01-responsive-web-design/basic-css.md @@ -16,90 +16,3 @@ There are three main ways to apply CSS styling. You can apply inline styles dire In this section, you'll see how adding CSS styles to the elements of your CatPhotoApp can change it from simple text to something more. -# Upcoming Lessons # - -Change the Color of Text - -Use CSS Selectors to Style Elements - -Use a CSS Class to Style an Element - -Style Multiple Elements with a CSS Class - -Change the Font Size of an Element - -Set the Font Family of an Element - -Import a Google Font - -Specify How Fonts Should Degrade - -Size Your Images - -Add Borders Around Your Elements - -Add Rounded Corners with border-radius - -Make Circular Images with a border-radius - -Give a Background Color to a div Element - -Set the id of an Element - -Use an id Attribute to Style an Element - -Adjust the Padding of an Element - -Adjust the Margin of an Element - -Add a Negative Margin to an Element - -Add Different Padding to Each Side of an Element - -Add Different Margins to Each Side of an Element - -Use Clockwise Notation to Specify the Padding of an Element - -Use Clockwise Notation to Specify the Margin of an Element - -Use Attribute Selectors to Style Elements - -Understand Absolute versus Relative Units - -Style the HTML Body Element - -Inherit Styles from the Body Element - -Prioritize One Style Over Another - -Override Styles in Subsequent CSS - -Override Class Declarations by Styling ID Attributes - -Override Class Declarations with Inline Styles - -Override All Other Styles by using Important - -Use Hex Code for Specific Colors - -Use Hex Code to Mix Colors - -Use Abbreviated Hex Code - -Use RGB values to Color Elements - -Use RGB to Mix Colors - -Use CSS Variables to change several elements at once - -Create a custom CSS Variable - -Use a custom CSS Variable - -Attach a Fallback value to a CSS Variable - -Cascading CSS variables - -Change a variable for a specific area - -Use a media query to change a variable \ No newline at end of file diff --git a/01-responsive-web-design/basic-html-and-html5.md b/01-responsive-web-design/basic-html-and-html5.md index 216faeb..6693e7e 100644 --- a/01-responsive-web-design/basic-html-and-html5.md +++ b/01-responsive-web-design/basic-html-and-html5.md @@ -31,60 +31,4 @@ The HyperText part of HTML comes from the early days of the web and its original As web pages and web applications grow more complex, the W3 Consortium updates the HTML specification to ensure that a webpage can be shown reliably on any browser. The latest version of HTML is HTML5. -This section introduces how to use HTML elements to give structure and meaning to your web content. - -# Upcoming Lessons # - -Say Hello to HTML Elements - -Headline with the h2 Element - -Inform with the Paragraph Element - -Fill in the Blank with Placeholder Text - -Uncomment HTML - -Comment out HTML - -Delete HTML Elements - -Introduction to HTML5 Elements - -Add Images to Your Website - -Link to External Pages with Anchor Elements - -Link to Internal Sections of a Page with Anchor Elements - -Nest an Anchor Element within a Paragraph - -Make Dead Links Using the Hash Symbol - -Turn an Image into a Link - -Create a Bulleted Unordered List - -Create an Ordered List - -Create a Text Field - -Add Placeholder Text to a Text Field - -Create a Form Element - -Add a Submit Button to a Form - -Use HTML5 to Require a Field - -Create a Set of Radio Buttons - -Create a Set of Checkboxes - -Check Radio Buttons and Checkboxes by Default - -Nest Many Elements within a Single div Element - -Declare the Doctype of an HTML Document - -Define the Head and Body of an HTML Document \ No newline at end of file +This section introduces how to use HTML elements to give structure and meaning to your web content. \ No newline at end of file diff --git a/01-responsive-web-design/css-flexbox.md b/01-responsive-web-design/css-flexbox.md index da12c5f..e38623e 100644 --- a/01-responsive-web-design/css-flexbox.md +++ b/01-responsive-web-design/css-flexbox.md @@ -3,39 +3,3 @@ A website's User Interface ("UI") has two components. First, there are the visual elements, such as colors, fonts, and images. Second, there is the placement or positioning of those elements. In Responsive Web Design, a UI layout must accommodate many different browsers and devices accessing the content. CSS3 introduced Flexible Boxes, or flexbox, to create page layouts for a dynamic UI. It is a layout mode that arranges elements in a predictable way for different screen sizes and browsers. While somewhat new, all popular modern browsers support flexbox. This section covers how to use flexbox and the different layout options it offers. - -# Upcoming Lessons # - -Use display: flex to Position Two Boxes - -Add Flex Superpowers to the Tweet Embed - -Use the flex-direction Property to Make a Row - -Apply the flex-direction Property to Create Rows in the Tweet Embed - -Use the flex-direction Property to Make a Column - -Apply the flex-direction Property to Create a Column in the Tweet Embed - -Align Elements Using the justify-content Property - -Use the justify-content Property in the Tweet Embed - -Align Elements Using the align-items Property - -Use the align-items Property in the Tweet Embed - -Use the flex-wrap Property to Wrap a Row or Column - -Use the flex-shrink Property to Shrink Items - -Use the flex-grow Property to Expand Items - -Use the flex-basis Property to Set the Initial Size of an Item - -Use the flex Shorthand Property - -Use the order Property to Rearrange Items - -Use the align-self Property \ No newline at end of file diff --git a/01-responsive-web-design/css-grid.json b/01-responsive-web-design/css-grid.json index 159f623..e3d7d90 100644 --- a/01-responsive-web-design/css-grid.json +++ b/01-responsive-web-design/css-grid.json @@ -1,1492 +1,1492 @@ { - "name": "CSS Grid", - "order": 6, - "time": "5 hours", - "helpRoom": "Help", - "challenges": [ - { - "id": "5a858944d96184f06fd60d61", - "title": "Create Your First CSS Grid", - "description": [ - "Turn any HTML element into a grid container by setting its display property to grid. This gives you the ability to use all the other properties associated with CSS Grid.", - "Note
In CSS Grid, the parent element is referred to as the container and its children are called items.", - "
", - "Change the display of the div with the container class to grid." - ], - "tests": [ - { - "text": "container class should have a display property with a value of grid.", - "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*display\\s*?:\\s*?grid\\s*?;[\\s\\S]*}/gi), 'container class should have a display property with a value of grid.');" + "name": "CSS Grid", + "order": 6, + "time": "5 hours", + "helpRoom": "Help", + "challenges": [ + { + "id": "5a858944d96184f06fd60d61", + "title": "Create Your First CSS Grid", + "description": [ + "通过将属性display的值设为grid,使 HTML 元素变为网格容器。通过前面的操作,你可以对该容器使用与 CSS 网格(CSS Grid)相关的属性。", + "注意:
在 CSS 网格中,父元素称为容器(container),它的子元素称为项(items)。", + "
", + "将类为container的 div 的display属性改为grid。" + ], + "tests": [ + { + "text": "container类应该有display属性且值为grid。", + "testString": "assert(code.match(/.container\\s*?{[\\s\\S]*display\\s*?:\\s*?grid\\s*?;[\\s\\S]*}/gi), 'container类应该有display属性且值为grid。');" + } + ], + "solutions": [], + "hints": [], + "releasedOn": "Feb 15, 2018", + "challengeType": 0, + "files": { + "indexhtml": { + "key": "indexhtml", + "ext": "html", + "name": "index", + "contents": [ + "", + " ", + "
", + "
1
", + "
2
", + "
3
", + "
4
", + "
5
", + "
" + ], + "head": [], + "tail": [] + } } - ], - "solutions": [], - "hints": [], - "releasedOn": "Feb 15, 2018", - "challengeType": 0, - "files": { - "indexhtml": { - "key": "indexhtml", - "ext": "html", - "name": "index", - "contents": [ - "", - " ", - "
", - "
1
", - "
2
", - "
3
", - "
4
", - "
5
", - "
" - ], - "head": [], - "tail": [] + }, + { + "id": "5a9036d038fddaf9a66b5d32", + "title": "Add Columns with grid-template-columns", + "description": [ + "简单地添加一个网格元素并不能取得很大的进展。你还需要明确网格的结构。在一个网格容器中使用grid-template-columns属性可以添加一些列,示例如下:", + "
.container {
  display: grid;
  grid-template-columns: 50px 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": [ + "", + " ", + "
", + "
1
", + "
2
", + "
3
", + "
4
", + "
5
", + "
" + ], + "head": [], + "tail": [] + } } - } - }, - { - "id": "5a9036d038fddaf9a66b5d32", - "title": "Add Columns with grid-template-columns", - "description": [ - "Simply creating a grid element doesn't get you very far. You need to define the structure of the grid as well. To add some columns to the grid, use the grid-template-columns property on a grid container as demonstrated below:", - "
.container {
  display: grid;
  grid-template-columns: 50px 50px;
}
", - "This will give your grid two columns that are 50px wide each.", - "The number of parameters given to the grid-template-columns property indicates the number of columns in the grid, and the value of each parameter indicates the width of each column.", - "
", - "Give the grid container three columns that are 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": [ - "", - " ", - "
", - "
1
", - "
2
", - "
3
", - "
4
", - "
5
", - "
" - ], - "head": [], - "tail": [] - } - } - }, - { - "id": "5a9036e138fddaf9a66b5d33", - "title": "Add Rows with grid-template-rows", - "description": [ - "The grid you created in the last challenge will set the number of rows automatically. To adjust the rows manually, use the grid-template-rows property in the same way you used grid-template-columns in previous challenge.", - "
", - "Add two rows to the grid that are 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": [ - "", - " ", - "
", - "
1
", - "
2
", - "
3
", - "
4
", - "
5
", - "
" - ], - "head": [], - "tail": [] - } - } - }, - { - "id": "5a9036ee38fddaf9a66b5d34", - "title": "Use CSS Grid units to Change the Size of Columns and Rows", - "description": [ - "You can use absolute and relative units like 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.", - "
", - "Make a grid with three columns whose widths are as follows: 1fr, 100px, and 2fr." - ], - "tests": [ - { - "text": "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": [ - "", - " ", - "
", - "
1
", - "
2
", - "
3
", - "
4
", - "
5
", - "
" - ], - "head": [], - "tail": [] - } - } - }, - { - "id": "5a9036ee38fddaf9a66b5d35", - "title": "Create a Column Gap Using grid-column-gap", - "description": [ - "So far in the grids you have created, the columns have all been tight up against each other. Sometimes you want a gap in between the columns. To add a gap between the columns, use the grid-column-gap property like this:", - "
grid-column-gap: 10px;
", - "This creates 10px of empty space between all of our columns.", - "
", - "Give the columns in the grid a 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": [ - "", - " ", - "
", - "
1
", - "
2
", - "
3
", - "
4
", - "
5
", - "
" - ], - "head": [], - "tail": [] + }, + { + "id": "5a9036e138fddaf9a66b5d33", + "title": "Add Rows with grid-template-rows", + "description": [ + "在上次挑战中,你创建的网格会自动设置行数。你可以像用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": [ + "", + " ", + "
", + "
1
", + "
2
", + "
3
", + "
4
", + "
5
", + "
" + ], + "head": [], + "tail": [] + } } - } - }, - { - "id": "5a9036ee38fddaf9a66b5d36", - "title": "Create a Row Gap using grid-row-gap", - "description": [ - "You can add a gap in between the rows of a grid using grid-row-gap in the same way that you added a gap in between columns in the previous challenge.", - "
", - "Create a gap for the rows that is 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 网格中,可以使用绝对定位和相对定位单位如pxem来确定行或列的大小。下面的单位也可以使用:", + "fr:设置列或行占剩余空间的一个比例,", + "auto:设置列宽或行高自动等于它的内容的宽度或高度,", + "%:将列或行调整为它的容器宽度或高度的百分比,", + "最右侧的预览区中的效果通过下面的代码实现:", + "
grid-template-columns: auto 50px 10% 2fr 1fr;
", + "这段代添加了五个列。第一列的宽与它的内容宽度相等;第二列宽 50px;第三列宽是它容器的 10%;最后两列,将剩余的宽度平均分成三份,第四列占两份,第五列占一份。", + "
", + "生成一个包含三列的网格,每列宽度分别为:1fr,100px,和 2fr。" + ], + "tests": [ + { + "text": "container类应该有grid-template-columns属性,且生成宽为1fr, 100px2fr的三列。", + "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, 100px2fr的三列。');" + } + ], + "solutions": [], + "hints": [], + "releasedOn": "", + "challengeType": 0, + "files": { + "indexhtml": { + "key": "indexhtml", + "ext": "html", + "name": "index", + "contents": [ + "", + " ", + "
", + "
1
", + "
2
", + "
3
", + "
4
", + "
5
", + "
" + ], + "head": [], + "tail": [] + } } - ], - "solutions": [], - "hints": [], - "releasedOn": "", - "challengeType": 0, - "files": { - "indexhtml": { - "key": "indexhtml", - "ext": "html", - "name": "index", - "contents": [ - "", - " ", - "
", - "
1
", - "
2
", - "
3
", - "
4
", - "
5
", - "
" - ], - "head": [], - "tail": [] + }, + { + "id": "5a9036ee38fddaf9a66b5d35", + "title": "Create a Column Gap Using grid-column-gap", + "description": [ + "到目前为止,在你所建立的网格中列都相互紧挨着。如果需要在列与列之间添加一些间隙,我们可以使用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": [ + "", + " ", + "
", + "
1
", + "
2
", + "
3
", + "
4
", + "
5
", + "
" + ], + "head": [], + "tail": [] + } } - } - }, - { - "id": "5a9036ee38fddaf9a66b5d37", - "title": "Add Gaps Faster with grid-gap", - "description": [ - "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.", - "
", - "Use 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": [ + "", + " ", + "
", + "
1
", + "
2
", + "
3
", + "
4
", + "
5
", + "
" + ], + "head": [], + "tail": [] + } } - ], - "solutions": [], - "hints": [], - "releasedOn": "", - "challengeType": 0, - "files": { - "indexhtml": { - "key": "indexhtml", - "ext": "html", - "name": "index", - "contents": [ - "", - "
", - "
1
", - "
2
", - "
3
", - "
4
", - "
5
", - "
" - ], - "head": [], - "tail": [] + }, + { + "id": "5a9036ee38fddaf9a66b5d37", + "title": "Add Gaps Faster with grid-gap", + "description": [ + "grid-gapgrid-row-gapgrid-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": [ + "", + "
", + "
1
", + "
2
", + "
3
", + "
4
", + "
5
", + "
" + ], + "head": [], + "tail": [] + } } - } - }, - { - "id": "5a90372638fddaf9a66b5d38", - "title": "Use grid-column to Control Spacing", - "description": [ - "Up to this point, all the properties that have been discussed are for grid containers. The 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

", - "To control the amount of columns an item will consume, you can use the 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.", - "
", - "Make the item with the class 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": [ + "", + " ", + "
", + "
1
", + "
2
", + "
3
", + "
4
", + "
5
", + "
" + ], + "head": [], + "tail": [] + } } - ], - "solutions": [], - "hints": [], - "releasedOn": "", - "challengeType": 0, - "files": { - "indexhtml": { - "key": "indexhtml", - "ext": "html", - "name": "index", - "contents": [ - "", - " ", - "
", - "
1
", - "
2
", - "
3
", - "
4
", - "
5
", - "
" - ], - "head": [], - "tail": [] + }, + { + "id": "5a90373638fddaf9a66b5d39", + "title": "Use grid-row to Control Spacing", + "description": [ + "当然,你可以像列一样使网格项跨越多行。对于一个网格项,你可以用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": [ + "", + " ", + "
", + "
1
", + "
2
", + "
3
", + "
4
", + "
5
", + "
" + ], + "head": [], + "tail": [] + } } - } - }, - { - "id": "5a90373638fddaf9a66b5d39", - "title": "Use grid-row to Control Spacing", - "description": [ - "Of course, you can make items consume multiple rows just like you can with columns. You define the horizontal lines you want an item to start and stop at using the grid-row property on a grid item.", - "
", - "Make the element with the 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": [ + "", + " ", + "
", + "
1
", + "
2
", + "
3
", + "
4
", + "
5
", + "
" + ], + "head": [], + "tail": [] + } } - ], - "solutions": [], - "hints": [], - "releasedOn": "", - "challengeType": 0, - "files": { - "indexhtml": { - "key": "indexhtml", - "ext": "html", - "name": "index", - "contents": [ - "", - " ", - "
", - "
1
", - "
2
", - "
3
", - "
4
", - "
5
", - "
" - ], - "head": [], - "tail": [] + }, + { + "id": "5a90375238fddaf9a66b5d3b", + "title": "Align an Item Vertically using align-self", + "description": [ + "正如能设置网格项沿行轴对齐方式一样,也可以设置网格项沿列轴对齐方式:你可以对网格项使用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": [ + "", + " ", + "
", + "
1
", + "
2
", + "
3
", + "
4
", + "
5
", + "
" + ], + "head": [], + "tail": [] + } } - } - }, - { - "id": "5a90374338fddaf9a66b5d3a", - "title": "Align an Item Horizontally using justify-self", - "description": [ - "In CSS Grid, the content of each item is located in a box which is referred to as a cell. You can align the content's position within its cell horizontally using the 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.", - "
", - "Use the 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使它们一次性沿行轴对齐。对于这个属性你能使用在之前的两个挑战中学到的所有值,与之前不同的是,它将使网格中所有的网格项按所设置的方式对齐。", + "
", + "使用本次挑战所学的属性设置所有网格项水平居中。" + ], + "tests": [ + { + "text": "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": [ + "", + " ", + "
", + "
1
", + "
2
", + "
3
", + "
4
", + "
5
", + "
" + ], + "head": [], + "tail": [] + } } - ], - "solutions": [], - "hints": [], - "releasedOn": "", - "challengeType": 0, - "files": { - "indexhtml": { - "key": "indexhtml", - "ext": "html", - "name": "index", - "contents": [ - "", - " ", - "
", - "
1
", - "
2
", - "
3
", - "
4
", - "
5
", - "
" - ], - "head": [], - "tail": [] + }, + { + "id": "5a94fdf869fb03452672e45b", + "title": "Align All Items Vertically using align-items", + "description": [ + "对网格容器使用align-items属性可以给网格中所有的网格项设置沿列轴对齐的方式。", + "
", + "请使用它让所有网格项移动到单元格的末尾。" + ], + "tests": [ + { + "text": "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": [ + "", + " ", + "
", + "
1
", + "
2
", + "
3
", + "
4
", + "
5
", + "
" + ], + "head": [], + "tail": [] + } } - } - }, - { - "id": "5a90375238fddaf9a66b5d3b", - "title": "Align an Item Vertically using align-self", - "description": [ - "Just as you can align an item horizontally, there's a way to align an item vertically as well. To do this, you use the align-self property on an item. This property accepts all of the same values as justify-self from the last challenge.", - "
", - "Align the item with the class 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的区域,并在中间行生成两个区域————advertcontent。", + "注意:
在代码中,每个单词代表一个网格单元格,每对引号代表一行。", + "除了自定义标签,你还能使用句点(.)来表示一个空单元格", + "
", + "请放置区域模板,让名为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": [ + "", + " ", + "
", + "
1
", + "
2
", + "
3
", + "
4
", + "
5
", + "
" + ], + "head": [], + "tail": [] + } } - ], - "solutions": [], - "hints": [], - "releasedOn": "", - "challengeType": 0, - "files": { - "indexhtml": { - "key": "indexhtml", - "ext": "html", - "name": "index", - "contents": [ - "", - " ", - "
", - "
1
", - "
2
", - "
3
", - "
4
", - "
5
", - "
" - ], - "head": [], - "tail": [] + }, + { + "id": "5a94fe1369fb03452672e45d", + "title": "Place Items in Grid Areas Using the grid-area Property", + "description": [ + "像上一个挑战那样,在为网格容添加区域模板后,你可以通过添加你定义的名称将网格项放入自定义区域。为此,你需要对网格项使用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": [ + "", + " ", + "
", + "
1
", + "
2
", + "
3
", + "
4
", + "
5
", + "
" + ], + "head": [], + "tail": [] + } } - } - }, - { - "id": "5a90376038fddaf9a66b5d3c", - "title": "Align All Items Horizontally using justify-items", - "description": [ - "Sometimes you want all the items in your CSS Grid to share the same alignment. You can use the previously learned properties and align them individually, or you can align them all at once horizontally by using 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.", - "
", - "Use this property to center all our items horizontally." - ], - "tests": [ - { - "text": "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": [ + "", + " ", + "
", + "
1
", + "
2
", + "
3
", + "
4
", + "
5
", + "
" + ], + "head": [], + "tail": [] + } } - ], - "solutions": [], - "hints": [], - "releasedOn": "", - "challengeType": 0, - "files": { - "indexhtml": { - "key": "indexhtml", - "ext": "html", - "name": "index", - "contents": [ - "", - " ", - "
", - "
1
", - "
2
", - "
3
", - "
4
", - "
5
", - "
" - ], - "head": [], - "tail": [] + }, + { + "id": "5a94fe3669fb03452672e45f", + "title": "Reduce Repetition Using the repeat Function", + "description": [ + "当使用grid-template-columnsgrid-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": [ + "", + " ", + "
", + "
1
", + "
2
", + "
3
", + "
4
", + "
5
", + "
" + ], + "head": [], + "tail": [] + } } - } - }, - { - "id": "5a94fdf869fb03452672e45b", - "title": "Align All Items Vertically using align-items", - "description": [ - "Using the align-items property on a grid container will set the vertical alignment for all the items in our grid.", - "
", - "Use it now to move all the items to the end of each cell." - ], - "tests": [ - { - "text": "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-columnsgrid-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": [ + "", + " ", + "
", + "
1
", + "
2
", + "
3
", + "
4
", + "
5
", + "
" + ], + "head": [], + "tail": [] + } } - ], - "solutions": [], - "hints": [], - "releasedOn": "", - "challengeType": 0, - "files": { - "indexhtml": { - "key": "indexhtml", - "ext": "html", - "name": "index", - "contents": [ - "", - " ", - "
", - "
1
", - "
2
", - "
3
", - "
4
", - "
5
", - "
" - ], - "head": [], - "tail": [] + }, + { + "id": "5a94fe5469fb03452672e461", + "title": "Create Flexible Layouts Using auto-fill", + "description": [ + "重复方法带有一个名为自动填充(auto-fill)的功能。它的功能是根据容器的大小,尽可能多地放入指定大小的行或列。你可以通过结合auto-fillminmax来更灵活地布局。", + "在最右侧的预览区中,grid-template-columns被设置为:", + "
repeat(auto-fill, minmax(60px, 1fr));
", + "上面的代码效果:列的宽度会随容器大小改变,在可以插入一个 60px 宽的列之前,当前行的所有列会一直拉伸。(译者注:动手试试你将更明白。)", + "注意:
如果容器无法使所有网格项放在同一行,余下的网格项将移至新的一行。", + "
", + "在第一个网格中,用auto-fillrepeat来填充网格,其中列宽的最小值为60px,最大值为1fr。你可以调整最右侧的预览区大小,查看自动填充效果。" + ], + "tests": [ + { + "text": "container类应该有grid-template-columns属性且使用repeatauto-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属性且使用repeatauto-fill,以便将最小宽度为60px,最大宽度为1fr的列填充至网格。');" + } + ], + "solutions": [], + "hints": [], + "releasedOn": "", + "challengeType": 0, + "files": { + "indexhtml": { + "key": "indexhtml", + "ext": "html", + "name": "index", + "contents": [ + "", + "
", + "
1
", + "
2
", + "
3
", + "
4
", + "
5
", + "
", + "
", + "
1
", + "
2
", + "
3
", + "
4
", + "
5
", + "
" + ], + "head": [], + "tail": [] + } } - } - }, - { - "id": "5a94fe0569fb03452672e45c", - "title": "Divide the Grid Into an Area Template", - "description": [ - "You can group cells of your grid together into an area and give the area a custom name. Do this by using grid-template-areas on the container like this:", - "
grid-template-areas:
  \"header header header\"
  \"advert content content\"
  \"footer footer footer\";
", - "The code above merges the top three cells together into an area named header, the bottom three cells into a footer area, and it makes two areas in the middle row; advert and content.", - "Note
Every word in the code represents a cell and every pair of quotation marks represent a row.", - "In addition to custom labels, you can use a period (.) to designate an empty cell in the grid.", - "
", - "Place the area template so that the cell labeled 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-fitrepeat来填充网格,其中列宽的最小值为60px,最大值为1fr。你可以调整最右侧的预览区以查看差异。" + ], + "tests": [ + { + "text": "container2类应该有grid-template-columns属性,且使用repeatauto-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属性,且使用repeatauto-fit以便将最小宽度为60px,最大宽度为1fr的列放入网格。');" + } + ], + "solutions": [], + "hints": [], + "releasedOn": "", + "challengeType": 0, + "files": { + "indexhtml": { + "key": "indexhtml", + "ext": "html", + "name": "index", + "contents": [ + "", + " ", + "
", + "
1
", + "
2
", + "
3
", + "
4
", + "
5
", + "
", + "
", + "
1
", + "
2
", + "
3
", + "
4
", + "
5
", + "
" + ], + "head": [], + "tail": [] + } } - ], - "solutions": [], - "hints": [], - "releasedOn": "", - "challengeType": 0, - "files": { - "indexhtml": { - "key": "indexhtml", - "ext": "html", - "name": "index", - "contents": [ - "", - " ", - "
", - "
1
", - "
2
", - "
3
", - "
4
", - "
5
", - "
" - ], - "head": [], - "tail": [] - } - } - }, - { - "id": "5a94fe1369fb03452672e45d", - "title": "Place Items in Grid Areas Using the grid-area Property", - "description": [ - "After creating an areas template for your grid container, as shown in the previous challenge, you can place an item in your custom area by referencing the name you gave it. To do this, you use the 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.", - "
", - "Place an element with the 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": [ - "", - " ", - "
", - "
1
", - "
2
", - "
3
", - "
4
", - "
5
", - "
" - ], - "head": [], - "tail": [] - } - } - }, - { - "id": "5a94fe2669fb03452672e45e", - "title": "Use grid-area Without Creating an Areas Template", - "description": [ - "The 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.", - "
", - "Using the 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": [ - "", - " ", - "
", - "
1
", - "
2
", - "
3
", - "
4
", - "
5
", - "
" - ], - "head": [], - "tail": [] - } - } - }, - { - "id": "5a94fe3669fb03452672e45f", - "title": "Reduce Repetition Using the repeat Function", - "description": [ - "When you used 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.", - "
", - "Use 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": [ - "", - " ", - "
", - "
1
", - "
2
", - "
3
", - "
4
", - "
5
", - "
" - ], - "head": [], - "tail": [] - } - } - }, - { - "id": "5a94fe4469fb03452672e460", - "title": "Limit Item Size Using the minmax Function", - "description": [ - "There's another built-in function to use with 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.", - "
", - "Using the 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": [ - "", - " ", - "
", - "
1
", - "
2
", - "
3
", - "
4
", - "
5
", - "
" - ], - "head": [], - "tail": [] - } - } - }, - { - "id": "5a94fe5469fb03452672e461", - "title": "Create Flexible Layouts Using auto-fill", - "description": [ - "The repeat function comes with a option called auto-fill. This allows you to automatically insert as many rows or columns of your desired size as possible depending on the size of the container. You can create flexible layouts when combining 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
If your container can't fit all your items on one row, it will move them down to a new one.", - "
", - "In the first grid, use 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": [ - "", - "
", - "
1
", - "
2
", - "
3
", - "
4
", - "
5
", - "
", - "
", - "
1
", - "
2
", - "
3
", - "
4
", - "
5
", - "
" - ], - "head": [], - "tail": [] - } - } - }, - { - "id": "5a94fe6269fb03452672e462", - "title": "Create Flexible Layouts Using auto-fit", - "description": [ - "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.", - "Note
If your container can't fit all your items on one row, it will move them down to a new one.", - "
", - "In the second grid, use auto-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": [ - "", - " ", - "
", - "
1
", - "
2
", - "
3
", - "
4
", - "
5
", - "
", - "
", - "
1
", - "
2
", - "
3
", - "
4
", - "
5
", - "
" - ], - "head": [], - "tail": [] - } - } - }, - { - "id": "5a94fe7769fb03452672e463", - "title": "Use Media Queries to Create Responsive Layouts", - "description": [ - "CSS Grid can be an easy way to make your site more responsive by using media queries to rearrange grid areas, change dimensions of a grid, and rearrange the placement of items.", - "In the preview, when the viewport width is 300px or more, the number of columns changes from 1 to 2. The advertisement area then occupies the left column completely.", - "
", - "When the viewport width is 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": [ - "", - " ", - "
", - "
header
", - "
advert
", - "
content
", - "
footer
", - "
" - ], - "head": [], - "tail": [] - } - } - }, - { - "id": "5a94fe8569fb03452672e464", - "title": "Create Grids within Grids", - "description": [ - "Turning an element into a grid only affects the behavior of its direct descendants. So by turning a direct descendant into a grid, you have a grid within a grid.", - "For example, by setting the display and grid-template-columns properties of the element with the item3 class, you create a grid within your grid.", - "
", - "Turn the element with the 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": [ + "", + " ", + "
", + "
header
", + "
advert
", + "
content
", + "
footer
", + "
" + ], + "head": [], + "tail": [] + } } - ], - "solutions": [], - "hints": [], - "releasedOn": "", - "challengeType": 0, - "files": { - "indexhtml": { - "key": "indexhtml", - "ext": "html", - "name": "index", - "contents": [ - "", - " ", - "
", - "
header
", - "
advert
", - "
", - "
paragraph1
", - "
paragraph2
", - "
", - "
footer
", - "
" - ], - "head": [], - "tail": [] + }, + { + "id": "5a94fe8569fb03452672e464", + "title": "Create Grids within Grids", + "description": [ + "将元素转换为网格只会影响其子代元素。因此,在把某个子代元素设置为网格后,就会得到一个嵌套的网格。", + "例如,设置类为item3的元素的displaygrid-template-columns属性,就会得到一个嵌套的网格。", + "
", + "用displaygrid-template-columns,使类为item3元素转换为有两列且宽度为auto1fr的网格。" + ], + "tests": [ + { + "text": "item3类应该有grid-template-columns属性且值为auto1fr。", + "testString": "assert(code.match(/.item3\\s*?{[\\s\\S]*grid-template-columns\\s*?:\\s*?auto\\s*?1fr\\s*?;[\\s\\S]*}/gi), 'item3类应该有grid-template-columns属性且将auto1fr作为值。');" + }, + { + "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": [ + "", + " ", + "
", + "
header
", + "
advert
", + "
", + "
paragraph1
", + "
paragraph2
", + "
", + "
footer
", + "
" + ], + "head": [], + "tail": [] + } } } - } - ] -} \ No newline at end of file + ] + } \ No newline at end of file diff --git a/01-responsive-web-design/css-grid.md b/01-responsive-web-design/css-grid.md index 21185fc..6c9e035 100644 --- a/01-responsive-web-design/css-grid.md +++ b/01-responsive-web-design/css-grid.md @@ -1,49 +1,3 @@ -# Introduction to the CSS Grid Challenges # +# CSS 网格简介 # -CSS Grid helps you easily build complex web designs. It works by turning an HTML element into a grid container with rows and columns for you to place children elements where you want within the grid. - -# Upcoming Lessons # - -Create Your First CSS Grid - -Add Columns with grid-template-columns - -Add Rows with grid-template-rows - -Use CSS Grid units to Change the Size of Columns and Rows - -Create a Column Gap Using grid-column-gap - -Create a Row Gap using grid-row-gap - -Add Gaps Faster with grid-gap - -Use grid-column to Control Spacing - -Use grid-row to Control Spacing - -Align an Item Horizontally using justify-self - -Align an Item Vertically using align-self - -Align All Items Horizontally using justify-items - -Align All Items Vertically using align-items - -Divide the Grid Into an Area Template - -Place Items in Grid Areas Using the grid-area Property - -Use grid-area Without Creating an Areas Template - -Reduce Repetition Using the repeat Function - -Limit Item Size Using the minmax Function - -Create Flexible Layouts Using auto-fill - -Create Flexible Layouts Using auto-fit - -Use Media Queries to Create Responsive Layouts - -Create Grids within Grids \ No newline at end of file +CSS 网格帮助你轻松实现复杂的 Web 设计。它通过把 HTML 元素转换为具有行和列的网格容器,以便将子元素放置在所需要的位置。 \ No newline at end of file diff --git a/01-responsive-web-design/responsive-web-design-principles.json b/01-responsive-web-design/responsive-web-design-principles.json index 9f2ecf0..a8a76b8 100644 --- a/01-responsive-web-design/responsive-web-design-principles.json +++ b/01-responsive-web-design/responsive-web-design-principles.json @@ -8,24 +8,24 @@ "id": "587d78b0367417b2b2512b08", "title": "Create a Media Query", "description": [ - "Media Queries are a new technique introduced in CSS3 that change the presentation of content based on different viewport sizes. The viewport is a user's visible area of a web page, and is different depending on the device used to access the site.", - "Media Queries consist of a media type, and if that media type matches the type of device the document is displayed on, the styles are applied. You can have as many selectors and styles inside your media query as you want.", - "Here's an example of a media query that returns the content when the device's width is less than or equal to 100px:", + "媒体查询是 CSS3 中引入的一项新技术,它可以根据不同的可视窗口大小显示不同的布局。可视窗口是用户在网页上的可见区域,根据访问网站的设备不同而不同。", + "媒体查询由媒体类型组成,如果媒体类型与展示网页的设备类型匹配,则应用对应的样式。你可以在媒体查询中用上你想用的选择器和样式。", + "下面是一个媒体查询的例子,当设备宽度小于或等于 100px 时返回内容:", "@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。", "
", - "Add a media query, so that the 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": "使用 @mediaheight 小于或等于 800px 的设备添加一个媒体查询。", + "testString": "assert(code.match(/@media\\s?\\(max-height:\\s*?800px\\)/g), '使用 @mediaheight 小于或等于 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 {
  max-width: 100%;
  display: block;
  height: auto;
}
", - "The 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 保持图片的原始宽高比。", "
", - "Add style rules for the 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">
", + "为优化图片在高分辨率设备下的显示效果,最简单的方式是定义它们的 widthheight 值为源文件宽高的一半。", + "这是一个图片宽高设置为源文件一半的例子:", + "
<style>
  img { height: 250px; width: 250px; }
</style>
<img src="coolPic500x500" alt="一张高质量的图片">
", "
", - "Set the 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 标签的 widthheight 为它们原始宽高的一半。在这个例子中,原始 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).
", + "除了用 empx 去设置文本大小, 你还可以用视窗单位来做响应式排版。视窗单位还有百分比,它们都是相对单位,但却基于不同的参照物。视窗单位相对于设备的视窗尺寸 (宽度或高度) ,百分比是相对于父级元素的大小。", + "四个不同的视窗单位分别是:", + "
  • vw:如 10vw 的意思是视窗宽度的 10%。
  • vh:3vh 的意思是视窗高度的 3%。
  • vmin:70vmin 的意思是视窗中较小尺寸的 70% (高度 VS 宽度)。
  • vmax:100vmax 的意思是视窗中较大尺寸的 100% (高度 VS 宽度)。
", "
", - "Set the 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:如果我输入的数字超出了范围(使用 minmax 属性定义),我将会看见验证错误信息。", + "用户故事 #10:对于表单中的名称,邮箱和数字输入框应该使用对应 id 为:id=\"name-label\", id=\"email-label\", 和 id=\"number-label\" 的描述标签", + "用户故事 #11:在表单中的名称,邮箱和数字输入框中,我能看到各自的描述文字作为占位符。", + "用户故事 #12:在表单元素内,我可以在 id=\"dropdown\" 的下拉列表中选择一个选项。", + "用户故事 #13:在表单元素内,我可以从一组或多组单选按钮中选择一个字段。每组使用 name 属性进行分组。", + "用户故事 #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 &​amp; Gabbana.", - "testString": "assert.match(convertHTML(\"Dolce & Gabbana\"), /Dolce & Gabbana/, 'convertHTML(\"Dolce & Gabbana\") should return Dolce &​amp; Gabbana.');" + "text": "convertHTML(\"Dolce & Gabbana\") 应该返回 Dolce &​amp; Gabbana。", + "testString": "assert.match(convertHTML(\"Dolce & Gabbana\"), /Dolce & Gabbana/, 'convertHTML(\"Dolce & Gabbana\") 应该返回 Dolce &​amp; Gabbana。');" }, { - "text": "convertHTML(\"Hamburgers < Pizza < Tacos\") should return Hamburgers &​lt; Pizza &​lt; Tacos.", - "testString": "assert.match(convertHTML(\"Hamburgers < Pizza < Tacos\"), /Hamburgers < Pizza < Tacos/, 'convertHTML(\"Hamburgers < Pizza < Tacos\") should return Hamburgers &​lt; Pizza &​lt; Tacos.');" + "text": "convertHTML(\"Hamburgers < Pizza < Tacos\") 应该返回 Hamburgers &​lt; Pizza &​lt; Tacos。", + "testString": "assert.match(convertHTML(\"Hamburgers < Pizza < Tacos\"), /Hamburgers < Pizza < Tacos/, 'convertHTML(\"Hamburgers < Pizza < Tacos\") 应该返回 Hamburgers &​lt; Pizza &​lt; Tacos。');" }, { - "text": "convertHTML(\"Sixty > twelve\") should return Sixty &​gt; twelve.", - "testString": "assert.match(convertHTML(\"Sixty > twelve\"), /Sixty > twelve/, 'convertHTML(\"Sixty > twelve\") should return Sixty &​gt; twelve.');" + "text": "convertHTML(\"Sixty > twelve\") 应该返回 Sixty &​gt; twelve。", + "testString": "assert.match(convertHTML(\"Sixty > twelve\"), /Sixty > twelve/, 'convertHTML(\"Sixty > twelve\") 应该返回 Sixty &​gt; twelve。');" }, { - "text": "convertHTML('Stuff in \"quotation marks\"') should return Stuff in &​quot;quotation marks&​quot;.", - "testString": "assert.match(convertHTML('Stuff in \"quotation marks\"'), /Stuff in "quotation marks"/, 'convertHTML('Stuff in \"quotation marks\"') should return Stuff in &​quot;quotation marks&​quot;.');" + "text": "convertHTML('Stuff in \"quotation marks\"') 应该返回 Stuff in &​quot;quotation marks&​quot;。", + "testString": "assert.match(convertHTML('Stuff in \"quotation marks\"'), /Stuff in "quotation marks"/, 'convertHTML('Stuff in \"quotation marks\"') 应该返回 Stuff in &​quot;quotation marks&​quot;。');" }, { - "text": "convertHTML(\"Schindler's List\") should return Schindler&​apos;s List.", - "testString": "assert.match(convertHTML(\"Schindler's List\"), /Schindler's List/, 'convertHTML(\"Schindler's List\") should return Schindler&​apos;s List.');" + "text": "convertHTML(\"Schindler's List\") 应该返回 Schindler&​apos;s List。", + "testString": "assert.match(convertHTML(\"Schindler's List\"), /Schindler's List/, 'convertHTML(\"Schindler's List\") 应该返回 Schindler&​apos;s List。');" }, { - "text": "convertHTML(\"<>\") should return &​lt;&​gt;.", - "testString": "assert.match(convertHTML('<>'), /<>/, 'convertHTML(\"<>\") should return &​lt;&​gt;.');" + "text": "convertHTML(\"<>\") 应该返回 &​lt;&​gt;。", + "testString": "assert.match(convertHTML('<>'), /<>/, 'convertHTML(\"<>\") 应该返回 &​lt;&​gt;。');" }, { - "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 UnitAmount
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)
" ], "solutions": [ "var denom = [\n\t{ name: 'ONE HUNDRED', val: 100},\n\t{ name: 'TWENTY', val: 20},\n\t{ name: 'TEN', val: 10},\n\t{ name: 'FIVE', val: 5},\n\t{ name: 'ONE', val: 1},\n\t{ name: 'QUARTER', val: 0.25},\n\t{ name: 'DIME', val: 0.1},\n\t{ name: 'NICKEL', val: 0.05},\n\t{ name: 'PENNY', val: 0.01}\n];\n\nfunction checkCashRegister(price, cash, cid) {\n var output = {status: null, change: []};\n var change = cash - price;\n var register = cid.reduce(function(acc, curr) {\n acc.total += curr[1];\n acc[curr[0]] = curr[1];\n return acc;\n }, {total: 0});\n if(register.total === change) {\n output.status = 'CLOSED';\n output.change = cid;\n return output;\n }\n if(register.total < change) {\n output.status = 'INSUFFICIENT_FUNDS';\n return output;\n }\n var change_arr = denom.reduce(function(acc, curr) {\n var value = 0;\n while(register[curr.name] > 0 && change >= curr.val) {\n change -= curr.val;\n register[curr.name] -= curr.val;\n value += curr.val;\n change = Math.round(change * 100) / 100;\n }\n if(value > 0) {\n acc.push([ curr.name, value ]);\n }\n return acc;\n }, []);\n if(change_arr.length < 1 || change > 0) {\n output.status = 'INSUFFICIENT_FUNDS';\n return output;\n }\n output.status = 'OPEN';\n output.change = change_arr;\n return output;\n}" ], "tests": [ { - "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 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 = {
  name: \"Aflac\",
  numLegs: 2
};
", - "This duck object has two property/value pairs: a name of \"Aflac\" and a numLegs of 2.", + "这个duck 对象 有两组键值对:一个是name属性,它的值是 \"Aflac\";另一个是numLegs属性,它的值是 2。", "
", - "Create a dog object with name and numLegs properties, and set them to a string and a number, respectively." + "创建一个dog 对象,并给这个对象添加两个属性:namenumLegs,同时把这两个属性的值分别设为字符串和数字。" ], "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对象,其属性namecolornumLegs的值分别被设置为Albertblue和 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。给其添加namecolornumLegs属性并分别给它们设置为:字符串,字符串和数字。" ], "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:", + "上一个挑战中BirdDog构造函数运行得不错。但是,注意到没有:所有通过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构造函数。这一次,给它设置两个参数:namecolor,同时给numLegs赋值为 4。然后创建一个新Dog实例保存为变量名:terrier,再将两个字符串通过参数的形式传入namecolor属性。" ], "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构造函数定义了两个属性:namenumLegs:", "
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:", + "namenumLegs被叫做自身属性,因为他们是直接在实例对象上定义的。这就意味着duckcanary这两个对象分别拥有这些属性的独立副本。", + "事实上,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
", + "由于所有的实例都可以继承原型上的属性,所以可以把原型看作是创建对象的 \"配方\"。", + "请注意:duckcanary原型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:", + "在上一个挑战中创建的实例对象duckbeagle都有一个特殊的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": "如果candidateDog的一个对象实例,则joinDogFraternity函数应该返回true。", + "testString": "assert(joinDogFraternity(new Dog(\"\")) === true, '如果candidateDog的一个对象实例,则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