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 e55e814..62e880f 100644
--- a/02-javascript-algorithms-and-data-structures/object-oriented-programming.json
+++ b/02-javascript-algorithms-and-data-structures/object-oriented-programming.json
@@ -566,7 +566,7 @@
"description": [
"在上一个挑战中创建的实例对象duck
和beagle
都有一个特殊的constructor
属性:",
"
let duck = new Bird();", - "需要注意到的是这个
let beagle = new Dog();
console.log(duck.constructor === Bird); //输出 true
console.log(beagle.constructor === Dog); //输出 true
constructor
属性是对创建这个实例的构造函数的一个引用。",
+ "需要注意的是这个constructor
属性是对创建这个实例的构造函数的一个引用。",
"constructor
属性存在的一个优势是,我们可以通过检查这个属性来找出它是一个什么样的对象。下面是一个例子,来看看是怎么使用的:",
"function joinBirdFraternity(candidate) {", "注意:
if (candidate.constructor === Bird) {
return true;
} else {
return false;
}
}
constructor
属性可以被重写(在下面两节挑战中将会遇到),所以使用instanceof
方法来检查对象的类型会更好。",
@@ -675,17 +675,17 @@
"id": "587d7daf367417b2b2512b80",
"title": "Remember to Set the Constructor Property when Changing the Prototype",
"description": [
- "There is one crucial side effect of manually setting the prototype
to a new object. It erased the constructor
property! The code in the previous challenge would print the following for duck
:",
- "console.log(duck.constructor)", - "To fix this, whenever a prototype is manually set to a new object, remember to define the
// prints ‘undefined’ - Oops!
constructor
property:",
- "Bird.prototype = {", + "手动给新对象重新设置
constructor: Bird, // define the constructor property
numLegs: 2,
eat: function() {
console.log(\"nom nom nom\");
},
describe: function() {
console.log(\"My name is \" + this.name);
}
};
原型
对象,会产生一个重要的副作用:删除了constructor
属性!我们来看一下,上一个挑战中duck
的constructor
属性输出到控制台的结果:",
+ "console.log(duck.constructor)", + "为了解决这个问题,凡是手动给新对象重新设置过原型对象的,都别忘记在原型对象中定义一个
// 哎呀,控制台中输出了 ‘undefined’!
constructor
属性:",
+ "Bird.prototype = {", "
constructor: Bird, // 定义 constructor 属性
numLegs: 2,
eat: function() {
console.log(\"nom nom nom\");
},
describe: function() {
console.log(\"My name is \" + this.name);
}
};
constructor
property on the Dog
prototype
."
+ "给Dog 的原型
对象定义一个constructor
属性。"
],
"tests": [
{
- "text": "Dog.prototype
should set the constructor
property.",
- "testString": "assert(Dog.prototype.constructor === Dog, 'Dog.prototype
should set the constructor
property.');"
+ "text": "Dog.prototype
应该定义一个constructor
属性。",
+ "testString": "assert(Dog.prototype.constructor === Dog, 'Dog.prototype
应该定义一个constructor
属性。');"
}
],
"solutions": [
@@ -704,7 +704,7 @@
" this.name = name; ",
"}",
"",
- "// Modify the code below this line",
+ "// 请只修改这条注释以下的代码",
"Dog.prototype = {",
" ",
" numLegs: 2, ",
@@ -725,17 +725,17 @@
"id": "587d7db0367417b2b2512b81",
"title": "Understand Where an Object’s Prototype Comes From",
"description": [
- "Just like people inherit genes from their parents, an object inherits its prototype
directly from the constructor function that created it. For example, here the Bird
constructor creates the duck
object:",
+ "就像人们从父母那里继承基因一样,对象也可直接从创建它的构造函数那里继承其prototype
。请看下面的例子:Bird
构造函数创建了一个duck
对象:",
"function Bird(name) {", - "
this.name = name;
}
let duck = new Bird(\"Donald\");
duck
inherits its prototype
from the Bird
constructor function. You can show this relationship with the isPrototypeOf
method:",
- "Bird.prototype.isPrototypeOf(duck);", + "
// returns true
duck
从Bird
构造函数那里继承了它的prototype
,你可以使用isPrototypeOf
方法来验证他们之间的关系:",
+ "Bird.prototype.isPrototypeOf(duck);", "
// 返回 true
isPrototypeOf
to check the prototype
of beagle
."
+ "使用isPrototypeOf
方法验证beagle
是否继承了Bird
构造函数的prototype
。"
],
"tests": [
{
- "text": "Show that Dog.prototype
is the prototype
of beagle
",
- "testString": "assert(/Dog\\.prototype\\.isPrototypeOf\\(beagle\\)/.test(code), 'Show that Dog.prototype
is the prototype
of beagle
');"
+ "text": "验证Dog.prototype
应该是beagle
的原型
。",
+ "testString": "assert(/Dog\\.prototype\\.isPrototypeOf\\(beagle\\)/.test(code), '验证Dog.prototype
应该是beagle
的原型
。');"
}
],
"solutions": [
@@ -756,7 +756,7 @@
"",
"let beagle = new Dog(\"Snoopy\");",
"",
- "// Add your code below this line",
+ "// 请把你的代码写在这条注释以下",
"",
""
],
@@ -769,22 +769,22 @@
"id": "587d7db0367417b2b2512b82",
"title": "Understand the Prototype Chain",
"description": [
- "All objects in JavaScript (with a few exceptions) have a prototype
. Also, an object’s prototype
itself is an object.",
+ "JavaScript 中所有的对象(除了少数例外)都有自己的原型
。而且,对象的原型
本身也是一个对象。",
"function Bird(name) {", - "Because a
this.name = name;
}
typeof Bird.prototype; // => object
prototype
is an object, a prototype
can have its own prototype
! In this case, the prototype
of Bird.prototype
is Object.prototype
:",
- "Object.prototype.isPrototypeOf(Bird.prototype);", - "How is this useful? You may recall the
// returns true
hasOwnProperty
method from a previous challenge:",
+ "正因为原型
是一个对象,所以原型
对象也有它自己的原型
!这样看来的话,Bird.prototype
的原型
就是Object.prototype
:",
+ "Object.prototype.isPrototypeOf(Bird.prototype);", + "这有什么作用呢?你可能还记得我们在上一个挑战中学到的
// 返回 true
hasOwnProperty
方法:",
"let duck = new Bird(\"Donald\");", - "The
duck.hasOwnProperty(\"name\"); // => true
hasOwnProperty
method is defined in Object.prototype
, which can be accessed by Bird.prototype
, which can then be accessed by duck
. This is an example of the prototype
chain.",
- "In this prototype
chain, Bird
is the supertype
for duck
, while duck
is the subtype
. Object
is a supertype
for both Bird
and duck
.",
- "Object
is a supertype
for all objects in JavaScript. Therefore, any object can use the hasOwnProperty
method.",
+ "hasOwnProperty
是定义在Object.prototype
上的一个方法,但是我们可以同时在Bird.prototype
和duck
对象上访问到这个方法,尽管这两个对象上并没有定义该方法。这就是一个原型
链。",
+ "在这个原型
链中,Bird
构造函数是父级
,duck
是子级
。Object
则是Bird
构造函数和duck
实例共同的父级
。",
+ "Object
是 JavaScript 中所有对象的父级
,也就是原型链的最顶层。因此,所有对象都可以访问hasOwnProperty
方法。",
"Object.prototype
is the prototype of Dog.prototype
\")",
- "testString": "assert(/Object\\.prototype\\.isPrototypeOf/.test(code), \"Your code should show that Object.prototype
is the prototype of Dog.prototype
\");"
+ "text": "你的代码应该展示Object.prototype
是Dog.prototype
的原型。",
+ "testString": "assert(/Object\\.prototype\\.isPrototypeOf/.test(code), \"你的代码应该展示Object.prototype
是Dog.prototype
的原型。\");"
}
],
"solutions": [
@@ -807,7 +807,7 @@
"",
"Dog.prototype.isPrototypeOf(beagle); // => true",
"",
- "// Fix the code below so that it evaluates to true",
+ "// 修改以下代码使其结果返回 true",
"???.isPrototypeOf(Dog.prototype);",
""
],
@@ -820,28 +820,28 @@
"id": "587d7db0367417b2b2512b83",
"title": "Use Inheritance So You Don't Repeat Yourself",
"description": [
- "There's a principle in programming called Don't Repeat Yourself (DRY)
. The reason repeated code is a problem is because any change requires fixing code in multiple places. This usually means more work for programmers and more room for errors.",
- "Notice in the example below that the describe
method is shared by Bird
and Dog
:",
+ "编程中有一条原则叫做:不要重复你自己(简称:DRY )
。编写重复代码会产生的问题是:任何改变都需要去多个地方修复所有重复的代码。这通常意味着我们需要做更多的工作,会产生更高的出错率。",
+ "请观察下面的示例,Bird
和Dog
共享describe
方法:",
"Bird.prototype = {", - "The
constructor: Bird,
describe: function() {
console.log(\"My name is \" + this.name);
}
};
Dog.prototype = {
constructor: Dog,
describe: function() {
console.log(\"My name is \" + this.name);
}
};
describe
method is repeated in two places. The code can be edited to follow the DRY
principle by creating a supertype
(or parent) called Animal
:",
+ "我们可以看到describe
方法在两个地方重复定义了。根据以上所说的DRY
原则,我们可以通过创建一个Animal 超类
(或者父类)来重写这段代码:",
"function Animal() { };", - "Since
Animal.prototype = {
constructor: Animal,
describe: function() {
console.log(\"My name is \" + this.name);
}
};
Animal
includes the describe
method, you can remove it from Bird
and Dog
:",
+ "Animal
构造函数中定义了describe
方法,可将Bird
和Dog
这两个构造函数的方法删除掉:",
"Bird.prototype = {", "
constructor: Bird
};
Dog.prototype = {
constructor: Dog
};
eat
method is repeated in both Cat
and Bear
. Edit the code in the spirit of DRY
by moving the eat
method to the Animal
supertype
."
+ "Cat
和Bear
重复定义了eat
方法。本着DRY
的原则,通过将eat
方法移动到Animal 超类
中来重写你的代码。"
],
"tests": [
{
- "text": "Animal.prototype
should have the eat
property.",
- "testString": "assert(Animal.prototype.hasOwnProperty('eat'), 'Animal.prototype
should have the eat
property.');"
+ "text": "Animal.prototype
应该有eat
属性。",
+ "testString": "assert(Animal.prototype.hasOwnProperty('eat'), 'Animal.prototype
应该有eat
属性。');"
},
{
- "text": "Bear.prototype
should not have the eat
property.",
- "testString": "assert(!(Bear.prototype.hasOwnProperty('eat')), 'Bear.prototype
should not have the eat
property.');"
+ "text": "Bear.prototype
不应该有eat
属性。",
+ "testString": "assert(!(Bear.prototype.hasOwnProperty('eat')), 'Bear.prototype
不应该有eat
属性。');"
},
{
- "text": "Cat.prototype
should not have the eat
property.",
- "testString": "assert(!(Cat.prototype.hasOwnProperty('eat')), 'Cat.prototype
should not have the eat
property.');"
+ "text": "Cat.prototype
不应该有eat
属性。",
+ "testString": "assert(!(Cat.prototype.hasOwnProperty('eat')), 'Cat.prototype
不应该有eat
属性。');"
}
],
"solutions": [
@@ -894,35 +894,35 @@
"id": "587d7db0367417b2b2512b84",
"title": "Inherit Behaviors from a Supertype",
"description": [
- "In the previous challenge, you created a supertype
called Animal
that defined behaviors shared by all animals:",
+ "在上一个挑战中,我们创建了一个Animal 超类
,用来定义所有动物共有的行为:",
"function Animal() { }", - "This and the next challenge will cover how to reuse
Animal.prototype.eat = function() {
console.log(\"nom nom nom\");
};
Animal's
methods inside Bird
and Dog
without defining them again. It uses a technique called inheritance
.",
- "This challenge covers the first step: make an instance of the supertype
(or parent).",
- "You already know one way to create an instance of Animal
using the new
operator:",
+ "在这一节以及下一节挑战中我们将学习如何给Bird
、Dog
重写Animal
中的方法,而无需重新定义它们。这里我们会用到构造函数的继承
特性。",
+ "这一节挑战中我们学习第一步:创建一个超类
(或者叫父类)的实例。",
+ "你已经学会了一种创建Animal
实例的方法,即使用new
操作符:",
"let animal = new Animal();", - "There are some disadvantages when using this syntax for
inheritance
, which are too complex for the scope of this challenge. Instead, here's an alternative approach without those disadvantages:",
+ "此语法用于继承
时会存在一些缺点,这些缺点对于当前我们这个挑战来说太复杂了。相反,我们学习另外一种没有这些缺点的方法来替代new
操作:",
"let animal = Object.create(Animal.prototype);", - "
Object.create(obj)
creates a new object, and sets obj
as the new object's prototype
. Recall that the prototype
is like the \"recipe\" for creating an object. By setting the prototype
of animal
to be Animal's
prototype
, you are effectively giving the animal
instance the same \"recipe\" as any other instance of Animal
.",
- "animal.eat(); // prints \"nom nom nom\"", + "
animal instanceof Animal; // => true
Object.create(obj)
创建了一个新对象,并指定了obj
作为新对象的原型
。回忆一下,我们之前说过原型
就像是创建对象的 \"配方\"。通过给animal
的原型
设置为Animal
构造函数的原型
,就可以有效的给animal
对象一个 \"配方\",与Animal
的其他实例一样。",
+ "animal.eat(); // 输出 \"nom nom nom\"", "
animal instanceof Animal; // => true
Object.create
to make two instances of Animal
named duck
and beagle
."
+ "使用Object.create
方法给Animal
创建两个实例:duck
和beagle
。"
],
"tests": [
{
- "text": "The duck
variable should be defined.",
- "testString": "assert(typeof duck !== \"undefined\", 'The duck
variable should be defined.');"
+ "text": "应该定义一个duck
变量。",
+ "testString": "assert(typeof duck !== \"undefined\", '应该定义一个duck
变量。');"
},
{
- "text": "The beagle
variable should be defined.",
- "testString": "assert(typeof beagle !== \"undefined\", 'The beagle
variable should be defined.');"
+ "text": "应该定义一个beagle
变量。",
+ "testString": "assert(typeof beagle !== \"undefined\", '应该定义一个beagle
变量。');"
},
{
- "text": "duck
should have a prototype
of Animal
.",
- "testString": "assert(duck instanceof Animal, 'duck
should have a prototype
of Animal
.');"
+ "text": "duck
的原型应该被设置为Animal
构造函数的原型
。",
+ "testString": "assert(duck instanceof Animal, 'duck
的原型应该被设置为Animal
构造函数的原型
。');"
},
{
- "text": "beagle
should have a prototype
of Animal
.",
- "testString": "assert(beagle instanceof Animal, 'beagle
should have a prototype
of Animal
.');"
+ "text": "beagle
的原型应该被设置为Animal
构造函数的原型
。",
+ "testString": "assert(beagle instanceof Animal, 'beagle
的原型应该被设置为Animal
构造函数的原型
。');"
}
],
"solutions": [
@@ -946,13 +946,13 @@
" }",
"};",
"",
- "// Add your code below this line",
+ "// 请把你的代码写在这条注释以下",
"",
- "let duck; // Change this line",
- "let beagle; // Change this line",
+ "let duck; // 修改这一行代码",
+ "let beagle; // 修改这一行代码",
"",
- "duck.eat(); // Should print \"nom nom nom\"",
- "beagle.eat(); // Should print \"nom nom nom\" "
+ "duck.eat(); // 应该输出 \"nom nom nom\"",
+ "beagle.eat(); // 应该输出 \"nom nom nom\" "
],
"head": [],
"tail": []
@@ -963,19 +963,19 @@
"id": "587d7db1367417b2b2512b85",
"title": "Set the Child's Prototype to an Instance of the Parent",
"description": [
- "In the previous challenge you saw the first step for inheriting behavior from the supertype
(or parent) Animal
: making a new instance of Animal
.",
- "This challenge covers the next step: set the prototype
of the subtype
(or child)—in this case, Bird
—to be an instance of Animal
.",
+ "在上一个挑战中,我们学习了从超类 Animal
(或者叫父类)继承其行为的第一个步骤:创建一个Animal
的实例。",
+ "这一节挑战我们将学习第二个步骤:给子类型
(或者子类)设置原型
。这样一来,Bird
就是Animal
的一个实例了。",
"Bird.prototype = Object.create(Animal.prototype);", - "Remember that the
prototype
is like the \"recipe\" for creating an object. In a way, the recipe for Bird
now includes all the key \"ingredients\" from Animal
.",
- "let duck = new Bird(\"Donald\");", - "
duck.eat(); // prints \"nom nom nom\"
duck
inherits all of Animal
's properties, including the eat
method.",
+ "请记住,原型
类似于创建对象的 \"配方\"。从某种意义上来说,Bird
对象的配方包含了Animal
构造函数的所有关键 \"成分\"。",
+ "let duck = new Bird(\"Donald\");", + "
duck.eat(); // 输出 \"nom nom nom\"
duck
继承了Animal
构造函数的所有属性,其中包括了eat
方法。",
"Dog
inherit from Animal
."
+ "修改你的代码,以实现Dog
继承了Animal
构造函数。"
],
"tests": [
{
- "text": "Dog.prototype
should be an instance of Animal
.",
- "testString": "assert(Animal.prototype.isPrototypeOf(Dog.prototype), 'Dog.prototype
should be an instance of Animal
.');"
+ "text": "Dog.prototype
应该是Animal
的一个实例。",
+ "testString": "assert(Animal.prototype.isPrototypeOf(Dog.prototype), 'Dog.prototype
应该是Animal
的一个实例。');"
}
],
"solutions": [
@@ -1001,11 +1001,11 @@
"",
"function Dog() { }",
"",
- "// Add your code below this line",
+ "// 请把你的代码写在这条注释以下",
"",
"",
"let beagle = new Dog();",
- "beagle.eat(); // Should print \"nom nom nom\""
+ "beagle.eat(); // 应该输出 \"nom nom nom\""
],
"head": [],
"tail": []
@@ -1016,30 +1016,30 @@
"id": "587d7db1367417b2b2512b86",
"title": "Reset an Inherited Constructor Property",
"description": [
- "When an object inherits its prototype
from another object, it also inherits the supertype
's constructor property.",
- "Here's an example:",
+ "当一个对象从另一个对象那里继承了其原型
,那它也继承了父类
的 constructor 属性。",
+ "请看下面的举例:",
"function Bird() { }", - "But
Bird.prototype = Object.create(Animal.prototype);
let duck = new Bird();
duck.constructor // function Animal(){...}
duck
and all instances of Bird
should show that they were constructed by Bird
and not Animal
. To do so, you can manually set Bird's
constructor property to the Bird
object:",
+ "但是duck
和其他所有Bird
的实例都应该表明它们是由Bird
创建的,而不是由Animal
创建的。为此,你可以手动把Bird
的 constructor 属性设置为Bird
对象:",
"Bird.prototype.constructor = Bird;", "
duck.constructor // function Bird(){...}
duck.constructor
and beagle.constructor
return their respective constructors."
+ "修改你的代码,使得duck.constructor
和beagle.constructor
返回各自的构造函数。"
],
"tests": [
{
- "text": "Bird.prototype
should be an instance of Animal
.",
- "testString": "assert(Animal.prototype.isPrototypeOf(Bird.prototype), 'Bird.prototype
should be an instance of Animal
.');"
+ "text": "Bird.prototype
应该是Animal
的一个实例。",
+ "testString": "assert(Animal.prototype.isPrototypeOf(Bird.prototype), 'Bird.prototype
应该是Animal
的一个实例。');"
},
{
- "text": "duck.constructor
should return Bird
.",
- "testString": "assert(duck.constructor === Bird, 'duck.constructor
should return Bird
.');"
+ "text": "duck.constructor
应该返回Bird
。",
+ "testString": "assert(duck.constructor === Bird, 'duck.constructor
应该返回Bird
。');"
},
{
- "text": "Dog.prototype
should be an instance of Animal
.",
- "testString": "assert(Animal.prototype.isPrototypeOf(Dog.prototype), 'Dog.prototype
should be an instance of Animal
.');"
+ "text": "Dog.prototype
应该是Animal
的一个实例。",
+ "testString": "assert(Animal.prototype.isPrototypeOf(Dog.prototype), 'Dog.prototype
应该是Animal
的一个实例。');"
},
{
- "text": "beagle.constructor
should return Dog
.",
- "testString": "assert(beagle.constructor === Dog, 'beagle.constructor
should return Dog
.');"
+ "text": "beagle.constructor
应该返回Dog
。",
+ "testString": "assert(beagle.constructor === Dog, 'beagle.constructor
应该返回Dog
。');"
}
],
"solutions": [
@@ -1061,7 +1061,7 @@
"Bird.prototype = Object.create(Animal.prototype);",
"Dog.prototype = Object.create(Animal.prototype);",
"",
- "// Add your code below this line",
+ "// 请把你的代码写在这条注释以下",
"",
"",
"",
@@ -1077,36 +1077,36 @@
"id": "587d7db1367417b2b2512b87",
"title": "Add Methods After Inheritance",
"description": [
- "A constructor function that inherits its prototype
object from a supertype
constructor function can still have its own methods in addition to inherited methods.",
- "For example, Bird
is a constructor that inherits its prototype
from Animal
:",
+ "从父类
继承其原型
对象的构造函数除了继承的方法之外,还可以有自己的方法。",
+ "请看举例:Bird
是一个构造函数,它继承了Animal
构造函数的原型
:",
"function Animal() { }", - "In addition to what is inherited from
Animal.prototype.eat = function() {
console.log(\"nom nom nom\");
};
function Bird() { }
Bird.prototype = Object.create(Animal.prototype);
Bird.prototype.constructor = Bird;
Animal
, you want to add behavior that is unique to Bird
objects. Here, Bird
will get a fly()
function. Functions are added to Bird's
prototype
the same way as any constructor function:",
+ "除了从Animal
构造函数继承的行为之外,还需要给Bird
对象添加能表示其唯一的行为。这里,我们给Bird
对象添加一个fly()
函数。函数会以一种与其他构造函数相同的方式添加到Bird
的原型
中:",
"Bird.prototype.fly = function() {", - "Now instances of
console.log(\"I'm flying!\");
};
Bird
will have both eat()
and fly()
methods:",
- "let duck = new Bird();", + "现在
duck.eat(); // prints \"nom nom nom\"
duck.fly(); // prints \"I'm flying!\"
Bird
的实例中就有了eat()
和fly()
这两个方法:",
+ "let duck = new Bird();", "
duck.eat(); // 输出 \"nom nom nom\"
duck.fly(); // 输出 \"I'm flying!\"
Dog
object inherits from Animal
and the Dog's
prototype
constructor is set to Dog. Then add a bark()
method to the Dog
object so that beagle
can both eat()
and bark()
. The bark()
method should print \"Woof!\" to the console."
+ "添加必要的代码,使得Dog
对象继承Animal
构造函数,并且把Dog 原型
上的 constructor 属性设置为 Dog。然后给Dog
对象添加一个bark()
方法,这样的话,beagle
将同时拥有eat()
和bark()
这两个方法。bark()
方法中应该输出 \"Woof!\" 到控制台。"
],
"tests": [
{
- "text": "Animal
should not respond to the bark()
method.",
- "testString": "assert(typeof Animal.prototype.bark == \"undefined\", 'Animal
should not respond to the bark()
method.');"
+ "text": "Animal
应该没有bark()
方法。",
+ "testString": "assert(typeof Animal.prototype.bark == \"undefined\", 'Animal
应该没有bark()
方法。');"
},
{
- "text": "Dog
should inherit the eat()
method from Animal
.",
- "testString": "assert(typeof Dog.prototype.eat == \"function\", 'Dog
should inherit the eat()
method from Animal
.');"
+ "text": "Dog
应该继承了Animal
构造函数的eat()
方法。",
+ "testString": "assert(typeof Dog.prototype.eat == \"function\", 'Dog
应该继承了Animal
构造函数的eat()
方法。');"
},
{
- "text": "Dog
should have the bark()
method as an own
property.",
- "testString": "assert(Dog.prototype.hasOwnProperty('bark'), 'Dog
should have the bark()
method as an own
property.');"
+ "text": "Dog
应该有一个bark()
方法作为自身
属性。",
+ "testString": "assert(Dog.prototype.hasOwnProperty('bark'), 'Dog
应该有一个bark()
方法作为自身
属性。');"
},
{
- "text": "beagle
should be an instanceof
Animal
.",
- "testString": "assert(beagle instanceof Animal, 'beagle
should be an instanceof
Animal
.');"
+ "text": "beagle
应该是Animal
的一个instanceof
。",
+ "testString": "assert(beagle instanceof Animal, 'beagle
应该是Animal
的一个instanceof
。');"
},
{
- "text": "The constructor for beagle
should be set to Dog
.",
- "testString": "assert(beagle.constructor === Dog, 'The constructor for beagle
should be set to Dog
.');"
+ "text": "beagle
的 constructor 属性应该被设置为Dog
。",
+ "testString": "assert(beagle.constructor === Dog, 'beagle
的 constructor 属性应该被设置为Dog
。');"
}
],
"solutions": [
@@ -1128,17 +1128,17 @@
"",
"function Dog() { }",
"",
- "// Add your code below this line",
+ "// 请把你的代码写在这条注释以下 ",
"",
"",
"",
"",
- "// Add your code above this line",
+ "// 请把你的代码写在这条注释以下 ",
"",
"let beagle = new Dog();",
"",
- "beagle.eat(); // Should print \"nom nom nom\"",
- "beagle.bark(); // Should print \"Woof!\""
+ "beagle.eat(); // 应该输出 \"nom nom nom\"",
+ "beagle.bark(); // 应该输出 \"Woof!\""
],
"head": [],
"tail": []
@@ -1149,29 +1149,29 @@
"id": "587d7db1367417b2b2512b88",
"title": "Override Inherited Methods",
"description": [
- "In previous lessons, you learned that an object can inherit its behavior (methods) from another object by cloning its prototype
object:",
+ "在上一个挑战中,我们学习了一个对象可以通过复制另一个对象的原型
来继承其属性和行为(或方法):",
"ChildObject.prototype = Object.create(ParentObject.prototype);", - "Then the
ChildObject
received its own methods by chaining them onto its prototype
:",
+ "然后,ChildObject
将自己的方法链接到它的原型
中,这样就可以访问了:",
"ChildObject.prototype.methodName = function() {...};", - "It's possible to override an inherited method. It's done the same way - by adding a method to
ChildObject.prototype
using the same method name as the one to override.",
- "Here's an example of Bird
overriding the eat()
method inherited from Animal
:",
- "function Animal() { }", - "If you have an instance
Animal.prototype.eat = function() {
return \"nom nom nom\";
};
function Bird() { }
// Inherit all methods from Animal
Bird.prototype = Object.create(Animal.prototype);
// Bird.eat() overrides Animal.eat()
Bird.prototype.eat = function() {
return \"peck peck peck\";
};
let duck = new Bird();
and you call duck.eat()
, this is how JavaScript looks for the method on duck’s
prototype
chain:",
- "1. duck => Is eat() defined here? No.",
- "2. Bird => Is eat() defined here? => Yes. Execute it and stop searching.",
- "3. Animal => eat() is also defined, but JavaScript stopped searching before reaching this level.",
- "4. Object => JavaScript stopped searching before reaching this level.",
+ "我们还可以重写继承的方法。以同样的方式——通过使用一个与需要重写的方法相同的方法名,向ChildObject.prototype
中添加方法。",
+ "请看下面的举例:Bird
重写了从Animal
继承来的eat()
方法:",
+ "function Animal() { }", + "如果你有一个实例:
Animal.prototype.eat = function() {
return \"nom nom nom\";
};
function Bird() { }
// 继承了 Animal 的所有方法
Bird.prototype = Object.create(Animal.prototype);
// Bird.eat() 重写了 Animal.eat() 方法
Bird.prototype.eat = function() {
return \"peck peck peck\";
};
let duck = new Bird();
,然后你调用了duck.eat()
,以下就是 JavaScript 在duck
的原型
链上寻找方法的过程:",
+ "1. duck => 这里定义了 eat() 方法吗?没有。",
+ "2. Bird => 这里定义了 eat() 方法吗?=> 是的。执行它并停止往上搜索。",
+ "3. Animal => 这里也定义了 eat() 方法,但是 JavaScript 在到达这层原型链之前已停止了搜索。",
+ "4. Object => JavaScript 在到达这层原型链之前也已经停止了搜索。",
"fly()
method for Penguin
so that it returns \"Alas, this is a flightless bird.\""
+ "重写Penguin
的fly()
方法,使其返回 \"Alas, this is a flightless bird.\""
],
"tests": [
{
- "text": "penguin.fly()
should return the string \"Alas, this is a flightless bird.\"",
- "testString": "assert(penguin.fly() === \"Alas, this is a flightless bird.\", 'penguin.fly()
should return the string \"Alas, this is a flightless bird.\"');"
+ "text": "penguin.fly()
方法应该返回字符串:\"Alas, this is a flightless bird.\"",
+ "testString": "assert(penguin.fly() === \"Alas, this is a flightless bird.\", 'penguin.fly()
方法应该返回字符串:\"Alas, this is a flightless bird.\"');"
},
{
- "text": "The bird.fly()
method should return \"I am flying!\"",
- "testString": "assert((new Bird()).fly() === \"I am flying!\", 'The bird.fly()
method should return \"I am flying!\"');"
+ "text": "The bird.fly()
方法应该返回 \"I am flying!\"",
+ "testString": "assert((new Bird()).fly() === \"I am flying!\", 'The bird.fly()
方法应该返回 \"I am flying!\"');"
}
],
"solutions": [
@@ -1194,11 +1194,11 @@
"Penguin.prototype = Object.create(Bird.prototype);",
"Penguin.prototype.constructor = Penguin;",
"",
- "// Add your code below this line",
+ "// 请把你的代码写在这条注释以下",
"",
"",
"",
- "// Add your code above this line",
+ "// 请把你的代码写在这条注释以下",
"",
"let penguin = new Penguin();",
"console.log(penguin.fly());"
@@ -1212,29 +1212,29 @@
"id": "587d7db2367417b2b2512b89",
"title": "Use a Mixin to Add Common Behavior Between Unrelated Objects",
"description": [
- "As you have seen, behavior is shared through inheritance. However, there are cases when inheritance is not the best solution. Inheritance does not work well for unrelated objects like Bird
and Airplane
. They can both fly, but a Bird
is not a type of Airplane
and vice versa.",
- "For unrelated objects, it's better to use mixins
. A mixin
allows other objects to use a collection of functions.",
+ "正如你所见,通过继承可以共享行为。然而,在有些情况下,继承不是最好的解决方案。它不适用于那些不相关的对象,比如Bird
和Airplane
。虽然它们都可以飞行,但是一只Bird
并不是一架Airplane
,反之亦然。",
+ "对于不相关的对象,最好使用mixins
类。一个mixin
类允许其他对象使用函数集合。",
"let flyMixin = function(obj) {", - "The
obj.fly = function() {
console.log(\"Flying, wooosh!\");
}
};
flyMixin
takes any object and gives it the fly
method.",
+ "flyMixin
构造器能接受任何对象,并为其提供fly
方法。",
"let bird = {", - "Here
name: \"Donald\",
numLegs: 2
};
let plane = {
model: \"777\",
numPassengers: 524
};
flyMixin(bird);
flyMixin(plane);
bird
and plane
are passed into flyMixin
, which then assigns the fly
function to each object. Now bird
and plane
can both fly:",
- "bird.fly(); // prints \"Flying, wooosh!\"", - "Note how the
plane.fly(); // prints \"Flying, wooosh!\"
mixin
allows for the same fly
method to be reused by unrelated objects bird
and plane
.",
+ "这里的flyMixin
接收了bird
和code>plane对象,然后将fly
方法分配给了每一个对象。现在bird
和plane
都可以飞行了:",
+ "bird.fly(); // 输出 \"Flying, wooosh!\"", + "注意观察
plane.fly(); // 输出 \"Flying, wooosh!\"
mixin
是如何允许相同的fly
方法被不相关的对象bird
和plane
重用的。",
"mixin
named glideMixin
that defines a method named glide
. Then use the glideMixin
to give both bird
and boat
the ability to glide."
+ "创建一个名为glideMixin
的mixin
类,并定义一个glide
方法。然后使用glideMixin
来给bird
和boat
赋予滑行的能力。"
],
"tests": [
{
- "text": "Your code should declare a glideMixin
variable that is a function.",
- "testString": "assert(typeof glideMixin === \"function\", 'Your code should declare a glideMixin
variable that is a function.');"
+ "text": "你应该声明一个变量名为glideMixin
的函数。",
+ "testString": "assert(typeof glideMixin === \"function\", '你应该声明一个变量名为glideMixin
的函数。');"
},
{
- "text": "Your code should use the glideMixin
on the bird
object to give it the glide
method.",
- "testString": "assert(typeof bird.glide === \"function\", 'Your code should use the glideMixin
on the bird
object to give it the glide
method.');"
+ "text": "你应该在bird
上使用glideMixin
,以提供glide
方法。",
+ "testString": "assert(typeof bird.glide === \"function\", '你应该在bird
上使用glideMixin
,以提供glide
方法。');"
},
{
- "text": "Your code should use the glideMixin
on the boat
object to give it the glide
method.",
- "testString": "assert(typeof boat.glide === \"function\", 'Your code should use the glideMixin
on the boat
object to give it the glide
method.');"
+ "text": "你应该在boat
上使用glideMixin
,以提供glide
方法。",
+ "testString": "assert(typeof boat.glide === \"function\", '你应该在boat
上使用glideMixin
,以提供glide
方法。');"
}
],
"solutions": [
@@ -1259,7 +1259,7 @@
" type: \"race-boat\"",
"};",
"",
- "// Add your code below this line",
+ "// 请把你的代码写在这条注释以下",
"",
"",
"",
@@ -1276,23 +1276,23 @@
"id": "587d7db2367417b2b2512b8a",
"title": "Use Closure to Protect Properties Within an Object from Being Modified Externally",
"description": [
- "In the previous challenge, bird
had a public property name
. It is considered public because it can be accessed and changed outside of bird
's definition.",
+ "在上一次挑战中,bird
有一个公共属性name
。公共属性的定义就是:它可以在bird
的定义范围之外被访问和更改。",
"bird.name = \"Duffy\";", - "Therefore, any part of your code can easily change the name of
bird
to any value. Think about things like passwords and bank accounts being easily changeable by any part of your codebase. That could cause a lot of issues.",
- "The simplest way to make properties private is by creating a variable within the constructor function. This changes the scope of that variable to be within the constructor function versus available globally. This way, the property can only be accessed and changed by methods also within the constructor function.",
- "function Bird() {", - "Here
let hatchedEgg = 10; // private property
this.getHatchedEggCount = function() { // publicly available method that a bird object can use
return hatchedEgg;
};
}
let ducky = new Bird();
ducky.getHatchedEggCount(); // returns 10
getHachedEggCount
is a privileged method, because it has access to the private variable hatchedEgg
. This is possible because hatchedEgg
is declared in the same context as getHachedEggCount
. In JavaScript, a function always has access to the context in which it was created. This is called closure
.",
+ "因此,代码的任何地方都可以轻松地将bird
的 name 属性更改为任意值。想想密码和银行账户之类的东西,如果代码库的任何部分都可以轻易改变,那么将会引起很多问题。",
+ "使属性私有化最简单的方法就是在构造函数中创建变量。可以将该变量范围限定在构造函数中,而不是全局可用。这样,属性只能由构造函数中的方法访问和更改。",
+ "function Bird() {", + "这里的
let hatchedEgg = 10; // 私有属性
this.getHatchedEggCount = function() { // bird 对象可以是使用的公有方法
return hatchedEgg;
};
}
let ducky = new Bird();
ducky.getHatchedEggCount(); // 返回 10
getHachedEggCount
是一种特权方法,因为它可以访问私有属性hatchedEgg
。这是可能的,因为hatchedEgg
是在与getHachedEggCount
相同的上下文中声明的。在 JavaScript 中,函数总是可以访问创建它的上下文。这就叫做闭包
。",
"weight
is declared in the Bird
function so it is a private variable. Then, create a method getWeight
that returns the value of weight
."
+ "更改在Bird
函数中声明的weight
方法,使其成为私有变量。然后,创建一个返回weight
值的getWeight
方法。"
],
"tests": [
{
- "text": "The weight
property should be a private variable.",
- "testString": "assert(!code.match(/this\\.weight/g), 'The weight
property should be a private variable.');"
+ "text": "weight
属性应该是一个私有变量。",
+ "testString": "assert(!code.match(/this\\.weight/g), 'The weight
属性应该是一个私有变量。');"
},
{
- "text": "Your code should create a method in Bird
called getWeight
that returns the weight
.",
- "testString": "assert((new Bird()).getWeight() === 15, 'Your code should create a method in Bird
called getWeight
that returns the weight
.');"
+ "text": "你的代码应该在Bird
中创建一个名为getWeight
方法,该方法返回weight
值。",
+ "testString": "assert((new Bird()).getWeight() === 15, '你的代码应该在Bird
中创建一个名为getWeight
方法,该方法返回weight
值。');"
}
],
"solutions": [
@@ -1323,20 +1323,20 @@
"id": "587d7db2367417b2b2512b8b",
"title": "Understand the Immediately Invoked Function Expression (IIFE)",
"description": [
- "A common pattern in JavaScript is to execute a function as soon as it is declared:",
- "(function () {", - "Note that the function has no name and is not stored in a variable. The two parentheses () at the end of the function expression cause it to be immediately executed or invoked. This pattern is known as an
console.log(\"Chirp, chirp!\");
})(); // this is an anonymous function expression that executes right away
// Outputs \"Chirp, chirp!\" immediately
immediately invoked function expression
or IIFE
.",
+ "JavaScript 中的一个常见模式就是,函数一被声明就执行:",
+ "(function () {", + "请注意,函数没有名称,也不存储在变量中。函数表达式末尾的两个括号()导致它被立即执行或调用。这种模式被叫做
console.log(\"Chirp, chirp!\");
})(); // 这是一个立即执行的匿名函数表达式
// 立即输出 \"Chirp, chirp!\"
自执行函数表达式
或者IIFE
。",
"makeNest
and remove its call so instead it's an anonymous immediately invoked function expression
(IIFE
)."
+ "重写函数makeNest
,并删除它的调用,取而代之是一个匿名的自执行函数表达式
(IIFE
)。"
],
"tests": [
{
- "text": "The function should be anonymous.",
- "testString": "assert(/\\(\\s*?function\\s*?\\(\\s*?\\)\\s*?{/.test(code), 'The function should be anonymous.');"
+ "text": "该函数应该是匿名的。",
+ "testString": "assert(/\\(\\s*?function\\s*?\\(\\s*?\\)\\s*?{/.test(code), '该函数应该是匿名的。');"
},
{
- "text": "Your function should have parentheses at the end of the expression to call it immediately.",
- "testString": "assert(/}\\s*?\\)\\s*?\\(\\s*?\\)/.test(code), 'Your function should have parentheses at the end of the expression to call it immediately.');"
+ "text": "函数应该在表达式的末尾有括号,以便立即调用它。",
+ "testString": "assert(/}\\s*?\\)\\s*?\\(\\s*?\\)/.test(code), '函数应该在表达式的末尾有括号,以便立即调用它。');"
}
],
"solutions": [
@@ -1366,28 +1366,28 @@
"id": "587d7db2367417b2b2512b8c",
"title": "Use an IIFE to Create a Module",
"description": [
- "An immediately invoked function expression
(IIFE
) is often used to group related functionality into a single object or module
. For example, an earlier challenge defined two mixins:",
+ "一个自执行函数表达式
(IIFE
)通常用于将相关功能分组到单个对象或者是模块
中。例如,先前的挑战中定义了一个混合类:",
"function glideMixin(obj) {", - "We can group these
obj.glide = function() {
console.log(\"Gliding on the water\");
};
}
function flyMixin(obj) {
obj.fly = function() {
console.log(\"Flying, wooosh!\");
};
}
mixins
into a module as follows:",
- "let motionModule = (function () {", - "Note that you have an
return {
glideMixin: function (obj) {
obj.glide = function() {
console.log(\"Gliding on the water\");
};
},
flyMixin: function(obj) {
obj.fly = function() {
console.log(\"Flying, wooosh!\");
};
}
}
}) (); // The two parentheses cause the function to be immediately invoked
immediately invoked function expression
(IIFE
) that returns an object motionModule
. This returned object contains all of the mixin
behaviors as properties of the object.",
- "The advantage of the module
pattern is that all of the motion behaviors can be packaged into a single object that can then be used by other parts of your code. Here is an example using it:",
+ "我们可以将这些mixins
分成以下模块:",
+ "let motionModule = (function () {", + "注意:一个
return {
glideMixin: function (obj) {
obj.glide = function() {
console.log(\"Gliding on the water\");
};
},
flyMixin: function(obj) {
obj.fly = function() {
console.log(\"Flying, wooosh!\");
};
}
}
}) (); // 末尾的两个括号导致函数被立即调用
自执行函数表达式
(IIFE
)返回了一个motionModule
对象。返回的这个对象包含了作为对象属性的所有mixin
行为。",
+ "模块
模式的优点是,所有的运动行为都可以打包成一个对象,然后由代码的其他部分使用。下面是一个使用它的例子:",
"motionModule.glideMixin(duck);", "
duck.glide();
module
named funModule
to wrap the two mixins
isCuteMixin
and singMixin
. funModule
should return an object."
+ "创建一个名为funModule
的模块
,将这两个mixins
:isCuteMixin
和singMixin
包装起来。funModule
应该返回一个对象。"
],
"tests": [
{
- "text": "funModule
should be defined and return an object.",
- "testString": "assert(typeof funModule === \"object\", 'funModule
should be defined and return an object.');"
+ "text": "funModule
应该被定义并返回一个对象。",
+ "testString": "assert(typeof funModule === \"object\", 'funModule
应该被定义并返回一个对象。');"
},
{
- "text": "funModule.isCuteMixin
should access a function.",
- "testString": "assert(typeof funModule.isCuteMixin === \"function\", 'funModule.isCuteMixin
should access a function.');"
+ "text": "funModule.isCuteMixin
应该访问一个函数。",
+ "testString": "assert(typeof funModule.isCuteMixin === \"function\", 'funModule.isCuteMixin
应该访问一个函数。');"
},
{
- "text": "funModule.singMixin
should access a function.",
- "testString": "assert(typeof funModule.singMixin === \"function\", 'funModule.singMixin
should access a function.');"
+ "text": "funModule.singMixin
应该访问一个函数。",
+ "testString": "assert(typeof funModule.singMixin === \"function\", 'funModule.singMixin
应该访问一个函数。');"
}
],
"solutions": [
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 4918604..33bd5a8 100644
--- a/02-javascript-algorithms-and-data-structures/object-oriented-programming.md
+++ b/02-javascript-algorithms-and-data-structures/object-oriented-programming.md
@@ -1,9 +1,9 @@
-# Introduction to the Object Oriented Programming Challenges #
+# 面向对象编程挑战简介 #
-At its core, software development solves a problem or achieves a result with computation. The software development process first defines a problem, then presents a solution. Object oriented programming is one of several major approaches to the software development process.
+软件开发的核心是解决问题或通过计算获得结果。软件开发过程首先定义一个问题,然后提出一个解决方案。面向对象编程是软件开发过程的几种主要方法之一。
-As its name implies, object oriented programming organizes code into object definitions. These are sometimes called classes, and they group together data with related behavior. The data is an object's attributes, and the behavior (or functions) are methods.
+顾名思义,面向对象编程将代码组织成对象定义。这些有时被称为类,它们将数据和相关行为组合在一起。数据是对象的属性,行为(或函数)是方法。
-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.
+对于编程方法的选择取决于几个因素,其中包括问题的类型、如何构造数据以及算法等。本节将介绍 JavaScript 中面向对象的编程原则。