diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/add-methods-after-inheritance.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/add-methods-after-inheritance.chinese.md index 0efa00ce96..d2bf9e7975 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/add-methods-after-inheritance.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/add-methods-after-inheritance.chinese.md @@ -2,30 +2,62 @@ id: 587d7db1367417b2b2512b87 title: Add Methods After Inheritance challengeType: 1 -videoUrl: '' +forumTopicId: 301315 localeTitle: 继承后添加方法 --- ## Description -
除了继承的方法之外,从supertype构造函数继承其prototype对象的构造函数仍然可以拥有自己的方法。例如, Bird是一个从Animal继承其prototype的构造函数:
function Animal(){}
Animal.prototype.eat = function(){
console.log(“nom nom nom”);
};
函数Bird(){}
Bird.prototype = Object.create(Animal.prototype);
Bird.prototype.constructor = Bird;
除了从Animal继承的内容之外,您还希望添加Bird对象独有的行为。在这里, Bird将获得一个fly()函数。函数以与任何构造函数相同的方式添加到Bird's prototype
Bird.prototype.fly = function(){
console.log(“我在飞!”);
};
现在Bird实例将同时使用eat()fly()方法:
let duck = new Bird();
duck.eat(); //打印“nom nom nom”
duck.fly(); //打印“我在飞!”
+
+从父类继承其原型对象的构造函数除了继承的方法之外,还可以有自己的方法。 +请看举例:Bird是一个构造函数,它继承了Animal构造函数的原型: + +```js +function Animal() { } +Animal.prototype.eat = function() { + console.log("nom nom nom"); +}; +function Bird() { } +Bird.prototype = Object.create(Animal.prototype); +Bird.prototype.constructor = Bird; +``` + +除了从Animal构造函数继承的行为之外,还需要给Bird对象添加它独有的行为。这里,我们给Bird对象添加一个fly()函数。函数会以一种与其他构造函数相同的方式添加到Bird原型中: + +```js +Bird.prototype.fly = function() { + console.log("I'm flying!"); +}; +``` + +现在Bird的实例中就有了eat()fly()这两个方法: + +```js +let duck = new Bird(); +duck.eat(); // prints "nom nom nom" +duck.fly(); // prints "I'm flying!" +``` + +
## Instructions -
添加所有必需的代码,以便Dog对象继承自AnimalDog's prototype构造函数设置为Dog。然后将一个bark()方法添加到Dog对象,以便beagle可以eat()bark()bark()方法应该打印“Woof!”到控制台。
+
+添加必要的代码,使得Dog对象继承Animal构造函数,并且把Dog 原型上的 constructor 属性设置为 Dog。然后给Dog对象添加一个bark()方法,这样的话,beagle将同时拥有eat()bark()这两个方法。bark()方法中应该输出 "Woof!" 到控制台。 +
## Tests
```yml tests: - - text: Animal不应该响应bark()方法。 + - text: Animal应该没有bark()方法。 testString: assert(typeof Animal.prototype.bark == "undefined"); - - text: Dog应该继承Animaleat()方法。 + - text: Dog应该继承了Animal构造函数的eat()方法。 testString: assert(typeof Dog.prototype.eat == "function"); - - text: Dog应该将bark()方法作为own属性。 + - text: Dog应该有一个bark()方法作为自身属性。 testString: assert(Dog.prototype.hasOwnProperty('bark')); - - text: beagle应该是Animal一个instanceof 。 + - text: beagle应该是Animal的一个instanceof。 testString: assert(beagle instanceof Animal); - - text: beagle的构造函数应该设置为Dog 。 + - text: beagle的 constructor 属性应该被设置为Dog。 testString: assert(beagle.constructor === Dog); ``` @@ -54,7 +86,6 @@ let beagle = new Dog(); beagle.eat(); // Should print "nom nom nom" beagle.bark(); // Should print "Woof!" - ``` @@ -66,7 +97,21 @@ beagle.bark(); // Should print "Woof!" ## Solution
+ ```js -// solution required +function Animal() { } +Animal.prototype.eat = function() { console.log("nom nom nom"); }; + +function Dog() { } +Dog.prototype = Object.create(Animal.prototype); +Dog.prototype.constructor = Dog; +Dog.prototype.bark = function () { + console.log('Woof!'); +}; +let beagle = new Dog(); + +beagle.eat(); +beagle.bark(); ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/change-the-prototype-to-a-new-object.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/change-the-prototype-to-a-new-object.chinese.md index 637a01f0d8..2825c3cf4a 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/change-the-prototype-to-a-new-object.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/change-the-prototype-to-a-new-object.chinese.md @@ -2,28 +2,63 @@ id: 587d7daf367417b2b2512b7f title: Change the Prototype to a New Object challengeType: 1 -videoUrl: '' -localeTitle: 将Prototype更改为新对象 +forumTopicId: 301316 +localeTitle: 将原型更改为新对象 --- ## Description -
到目前为止,您一直在为prototype添加属性:
Bird.prototype.numLegs = 2;
经过多个属性后,这变得乏味。
Bird.prototype.eat = function(){
console.log(“nom nom nom”);
}

Bird.prototype.describe = function(){
console.log(“我的名字是”+ this.name);
}
更有效的方法是将prototype设置为已包含属性的新对象。这样,一次性添加属性:
Bird.prototype = {
numLegs:2,
吃:function(){
console.log(“nom nom nom”);
},
describe:function(){
console.log(“我的名字是”+ this.name);
}
};
+
+到目前为止,你已经可以单独给prototype添加属性了: + +```js +Bird.prototype.numLegs = 2; +``` + +这将在添加许多属性的时候变得单调乏味。 + +```js +Bird.prototype.eat = function() { + console.log("nom nom nom"); +} + +Bird.prototype.describe = function() { + console.log("My name is " + this.name); +} +``` + +一种更有效的方法就是给对象的prototype设置为一个已经包含了属性的新对象。这样一来,所有属性都可以一次性添加进来: + +```js +Bird.prototype = { + numLegs: 2, + eat: function() { + console.log("nom nom nom"); + }, + describe: function() { + console.log("My name is " + this.name); + } +}; +``` + +
## Instructions -
添加属性numLegs和两种方法eat()describe()prototypeDog被设置prototype到一个新的对象。
+
+通过给prototype设置为新对象的方法,在Dog构造函数的原型上添加一个属性numLegs以及两个方法:eat()describe()。 +
## Tests
```yml tests: - - text: Dog.prototype应该设置为一个新对象。 + - text: Dog.prototype应该被设置为一个新对象。 testString: assert((/Dog\.prototype\s*?=\s*?{/).test(code)); - - text: Dog.prototype应该具有属性numLegs 。 + - text: Dog.prototype应该拥有属性numLegs。 testString: assert(Dog.prototype.numLegs !== undefined); - - text: Dog.prototype应该有方法eat() 。 + - text: Dog.prototype应该拥有方法eat()。 testString: assert(typeof Dog.prototype.eat === 'function'); - - text: Dog.prototype应该有方法describe() 。 + - text: Dog.prototype应该拥有方法describe()。 testString: assert(typeof Dog.prototype.describe === 'function'); ``` @@ -44,7 +79,6 @@ Dog.prototype = { // Add your code below this line }; - ``` @@ -56,7 +90,20 @@ Dog.prototype = { ## Solution
+ ```js -// solution required +function Dog(name) { + this.name = name; +} +Dog.prototype = { +numLegs: 4, + eat () { + console.log('nom nom nom'); + }, + describe () { + console.log('My name is ' + this.name); + } +}; ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/create-a-basic-javascript-object.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/create-a-basic-javascript-object.chinese.md index 91e0f8d62d..809ad90fcf 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/create-a-basic-javascript-object.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/create-a-basic-javascript-object.chinese.md @@ -2,26 +2,42 @@ id: 587d7dac367417b2b2512b73 title: Create a Basic JavaScript Object challengeType: 1 -videoUrl: '' -localeTitle: 创建一个基本的JavaScript对象 +forumTopicId: 301317 +localeTitle: 创建一个基本的 JavaScript 对象 --- ## Description -
想想人们每天看到的东西,比如汽车,商店和鸟类。这些都是objects :人们可以观察和互动的有形事物。这些objects一些特质是什么?一辆车有轮子。商店出售物品。鸟有翅膀。这些品质或properties定义了构成object 。请注意,类似objects共享相同的properties ,但这些properties可能具有不同的值。例如,所有汽车都有轮子,但并非所有汽车都有相同数量的轮子。 JavaScript中的Objects用于模拟现实世界的对象,为它们提供properties和行为,就像它们的真实对象一样。这是使用这些概念创建duck object的示例:
让duck = {
名称:“Aflac”,
numLegs:2
};
这个duck object有两个属性/值对: name “Aflac”和numLegs为2。
+
+想想我们在生活中每天都可见到的事物:比如汽车、商店以及小鸟等。它们都是物体:即人们可以观察和与之互动的实体事物。 +那么这些物体都有哪些特征呢?比如汽车的特征是有轮子,商店是用来出售商品的,而小鸟的特征是有翅膀。 +这些特征,或者说是属性定义了一个物体由什么构成的。需要注意的是:那些相似的物体可以拥有相同的属性,但是这些属性可能会有不同的值。举个例子:所有的汽车都有轮子,但并不是所有汽车的轮子个数都是一样的。 +JavaScript 中的对象可以用来描述现实世界中的物体,并赋予他们属性和行为,就像它们在现实世界中的对应物一样。下面是使用这些概念来创建一个duck 对象的示例: + +```js +let duck = { + name: "Aflac", + numLegs: 2 +}; +``` + +这个duck 对象 有两组键值对:一个是name属性,它的值是 "Aflac";另一个是numLegs属性,它的值是 2。 +
## Instructions -
使用namenumLegs属性创建一个dog object ,并将它们分别设置为字符串和数字。
+
+创建一个dog 对象,并给这个对象添加两个属性:namenumLegs,同时把这两个属性的值分别设为字符串和数字。 +
## Tests
```yml tests: - - text: dog应该是一个object 。 + - text: dog应该是一个object。 testString: assert(typeof(dog) === 'object'); - - text: dog应该将name属性设置为string 。 + - text: dog应该有一个name属性,且它的值是一个字符串。 testString: assert(typeof(dog.name) === 'string'); - - text: dog应该将numLegs属性设置为number 。 + - text: dog应该有一个numLegs属性,且它的值是一个数字。 testString: assert(typeof(dog.numLegs) === 'number'); ``` @@ -37,7 +53,6 @@ tests: let dog = { }; - ``` @@ -49,7 +64,12 @@ let dog = { ## Solution
+ ```js -// solution required +let dog = { + name: '', + numLegs: 4 +}; ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/create-a-method-on-an-object.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/create-a-method-on-an-object.chinese.md index 73b64fab0f..ae6f4b7603 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/create-a-method-on-an-object.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/create-a-method-on-an-object.chinese.md @@ -2,15 +2,33 @@ id: 587d7dad367417b2b2512b75 title: Create a Method on an Object challengeType: 1 -videoUrl: '' +forumTopicId: 301318 localeTitle: 在对象上创建方法 --- ## Description -
Objects可以具有特殊类型的property ,称为methodMethods是作为函数的properties 。这会为object添加不同的行为。这是一个方法的duck示例:
让duck = {
名称:“Aflac”,
numLegs:2,
sayName:function(){return“这个鸭子的名字是”+ duck.name +“。”;}
};
duck.sayName();
//返回“这个鸭子的名字是Aflac。”
该示例添加了sayName method ,该method是一个返回给出duck名称的句子的函数。请注意,该method使用duck.name访问return语句中的name属性。下一个挑战将包括另一种方法。
+
+对象可以有一个叫做方法的特殊属性。 +方法其实是一个值为函数的属性,它可以为一个对象添加不同的行为。以下就是一个带有方法属性的duck示例: + +```js +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." +``` + +这个例子给duck对象添加了一个sayName 方法,这个方法返回一个包含duck名字的句子。 +注意:这个方法在返回语句中使用duck.name的方式来获取name的属性值。在下一个挑战中我们将会使用另外一种方法来实现。 +
## Instructions -
使用dog object ,给它一个名为sayLegs的方法。该方法应该返回句子“这条狗有4条腿”。
+
+给dog 对象设置一个名为sayLegs的方法,并让它返回 "This dog has 4 legs." 这句话。 +
## Tests
@@ -19,7 +37,7 @@ localeTitle: 在对象上创建方法 tests: - text: dog.sayLegs()应该是一个函数。 testString: assert(typeof(dog.sayLegs) === 'function'); - - text: dog.sayLegs()应返回给定的字符串 - 请注意标点符号和间距很重要。 + - text: dog.sayLegs()应该返回给定的字符串,需要注意标点和间距的问题。 testString: assert(dog.sayLegs() === 'This dog has 4 legs.'); ``` @@ -39,7 +57,6 @@ let dog = { }; dog.sayLegs(); - ``` @@ -51,7 +68,17 @@ dog.sayLegs(); ## Solution
+ ```js -// solution required +let dog = { + name: "Spot", + numLegs: 4, + sayLegs () { + return 'This dog has ' + this.numLegs + ' legs.'; + } +}; + +dog.sayLegs(); ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/define-a-constructor-function.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/define-a-constructor-function.chinese.md index 5e168cfb0d..12f34e5654 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/define-a-constructor-function.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/define-a-constructor-function.chinese.md @@ -2,26 +2,43 @@ id: 587d7dad367417b2b2512b77 title: Define a Constructor Function challengeType: 1 -videoUrl: '' +forumTopicId: 16804 localeTitle: 定义构造函数 --- ## Description -
Constructors函数是创建新对象的函数。它们定义属于新对象的属性和行为。将它们视为创建新对象的蓝图。以下是constructor的示例:
function Bird(){
this.name =“阿尔伯特”;
this.color =“blue”;
this.numLegs = 2;
}
constructor定义一个Bird对象,其属性namecolornumLegs设置为Albert,blue和2。 Constructors遵循一些约定:
  • Constructors函数使用大写名称定义,以区别于非constructors函数的其他函数。
  • Constructors使用关键字this来设置它们将创建的对象的属性。在constructorthis指的是它将创建的新对象。
  • Constructors定义属性和行为,而不是像其他函数那样返回值。
+
+构造函数用以创建一个新对象,并给这个新对象定义属性和行为。因此这是创建新对象的一个最基本的方式。 +以下就是一个构造函数的示例: + +```js +function Bird() { + this.name = "Albert"; + this.color = "blue"; + this.numLegs = 2; +} +``` + +这个构造函数定义了一个Bird对象,其属性namecolornumLegs的值分别被设置为Albertblue和 2。 +构造函数遵循一些惯例规则: +
  • 构造函数函数名的首字母最好大写,这是为了方便我们区分构造函数和其他非构造函数。
  • 构造函数使用this关键字来给它将创建的这个对象设置新的属性。在构造函数里面,this指向的就是它新创建的这个对象。
  • 构造函数定义了属性和行为就可创建对象,而不是像其他函数一样需要设置返回值。
+
## Instructions -
创建一个constructor Dog ,其属性namecolornumLegs分别设置为字符串,字符串和数字。
+
+创建一个构造函数Dog。给其添加namecolornumLegs属性并分别给它们设置为:字符串,字符串和数字。 +
## Tests
```yml tests: - - text: Dog应该将name属性设置为字符串。 + - text: Dog应该有一个name属性且它的值是一个字符串。 testString: assert(typeof (new Dog()).name === 'string'); - - text: Dog应该将color属性设置为字符串。 + - text: Dog应该有一个color属性且它的值是一个字符串。 testString: assert(typeof (new Dog()).color === 'string'); - - text: Dog应该将numLegs属性设置为数字。 + - text: Dog应该有一个numLegs属性且它的值是一个数字。 testString: assert(typeof (new Dog()).numLegs === 'number'); ``` @@ -46,7 +63,13 @@ tests: ## Solution
+ ```js -// solution required +function Dog (name, color, numLegs) { + this.name = 'name'; + this.color = 'color'; + this.numLegs = 4; +} ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/extend-constructors-to-receive-arguments.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/extend-constructors-to-receive-arguments.chinese.md index 6c8816dcbc..d1307c7a42 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/extend-constructors-to-receive-arguments.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/extend-constructors-to-receive-arguments.chinese.md @@ -2,28 +2,62 @@ id: 587d7dae367417b2b2512b79 title: Extend Constructors to Receive Arguments challengeType: 1 -videoUrl: '' +forumTopicId: 18235 localeTitle: 扩展构造函数以接收参数 --- ## Description -
最后一次挑战的BirdDog建设者运作良好。但是,请注意,所有的Birds与该创建Bird构造自动命名伟业,颜色为蓝色,有两条腿。如果您希望鸟类的名称和颜色具有不同的值,该怎么办?可以手动更改每只鸟的属性,但这将是很多工作:
让swan = new Bird();
swan.name =“卡洛斯”;
swan.color =“white”;
假设您正在编写一个程序来跟踪鸟舍中数百甚至数千种不同的鸟类。创建所有鸟类需要花费大量时间,然后将每个属性的属性更改为不同的值。为了更轻松地创建不同的Bird对象,您可以设计Bird构造函数来接受参数:
function Bird(名称,颜色){
this.name = name;
this.color = color;
this.numLegs = 2;
}
然后传入值作为参数,将每个独特的鸟定义到Bird构造函数中: let cardinal = new Bird("Bruce", "red");这给出了一个Bird的新实例,其名称和颜色属性分别设置为Bruce和red。 numLegs属性仍设置为2. cardinal具有以下属性:
cardinal.name // =>布鲁斯
cardinal.color // =>红色
cardinal.numLegs // => 2
构造函数更灵活。现在可以在创建时为每个Bird定义属性,这是JavaScript构造函数如此有用的一种方式。他们根据共享的特征和行为将对象组合在一起,并定义一个自动创建的蓝图。
+
+上一个挑战中BirdDog构造函数运行得不错。但是,注意到没有:所有通过Bird构造函数创建出来的实例Birds都自动的取名为 Albert,颜色都是蓝色,还都有两条腿。如果你想要新创建出来的小鸟们拥有不同的名字和颜色要怎么办呢?当然,手动的去修改每一个小鸟实例自己的属性也是可以实现的,只是会增加很多无谓的工作量: + +```js +let swan = new Bird(); +swan.name = "Carlos"; +swan.color = "white"; +``` + +假如你写了一个程序来追踪一个鸟舍里面的几百只甚至几千只不同的小鸟,你将会花费很多时间去创建所有的小鸟实例并给它们的属性一一修改为不同的值。 +为了减轻创建不同Bird对象的工作量,你可以给你的Bird设置为可以接收参数的构造函数: + +```js +function Bird(name, color) { + this.name = name; + this.color = color; + this.numLegs = 2; +} +``` + +然后将值通过参数的方式传递给Bird构造函数来定义每一个唯一的小鸟实例: +let cardinal = new Bird("Bruce", "red"); +这给Bird的名字和颜色属性分别赋值为 Bruce 和红色提供了另外一种方法。但numLegs属性被默认赋值为 2。 +cardinal有以下这些属性: + +```js +cardinal.name // => Bruce +cardinal.color // => red +cardinal.numLegs // => 2 +``` + +这样一来构造函数就变得很灵活了。现在可以直接定义每个Bird实例在创建时的属性,这是 JavaScript 构造函数非常实用的用法之一。它们根据共同或相似的属性和行为将对象归纳为一组,并能够自动的创建各自实例。 +
## Instructions -
创建另一个Dog构造函数。这次,将其设置为采用参数namecolor ,并将属性numLegs固定为4.然后创建一个保存在变量terrier的新Dog 。将两个字符串作为namecolor属性的参数传递给它。
+
+创建另一个Dog构造函数。这一次,给它设置两个参数:namecolor,同时给numLegs赋值为 4。然后创建一个新Dog实例保存为变量名:terrier,再将两个字符串通过参数的形式传入namecolor属性。 +
## Tests
```yml tests: - - text: Dog应该收到name的论据。 + - text: Dog应该接收一个name参数。 testString: assert((new Dog('Clifford')).name === 'Clifford'); - - text: Dog应该收到color的论据。 + - text: Dog应该接收一个color参数。 testString: assert((new Dog('Clifford', 'yellow')).color === 'yellow'); - - text: Dog应该将属性numLegs设置为4。 + - text: Dog应该有一个numLegs属性且值为 4。 testString: assert((new Dog('Clifford')).numLegs === 4); - - text: 应该使用Dog构造函数创建terrier 。 + - text: terrier应该是通过Dog构造函数创建的。 testString: assert(terrier instanceof Dog); ``` @@ -40,6 +74,7 @@ function Dog() { } + ``` @@ -51,7 +86,15 @@ function Dog() { ## Solution
+ ```js -// solution required +function Dog (name, color) { + this.numLegs = 4; + this.name = name; + this.color = color; +} + +const terrier = new Dog(); ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/inherit-behaviors-from-a-supertype.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/inherit-behaviors-from-a-supertype.chinese.md index b9df394803..efccae04ba 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/inherit-behaviors-from-a-supertype.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/inherit-behaviors-from-a-supertype.chinese.md @@ -2,29 +2,66 @@ id: 587d7db0367417b2b2512b84 title: Inherit Behaviors from a Supertype challengeType: 1 -videoUrl: '' -localeTitle: 从超类型继承行为 +forumTopicId: 301319 +localeTitle: 从超类继承行为 --- ## Description -
在之前的挑战中,您创建了一个名为Animalsupertype ,它定义了所有动物共享的行为:
function Animal(){}
Animal.prototype.eat = function(){
console.log(“nom nom nom”);
};
这个和下一个挑战将涵盖如何在Bird and Dog重用Animal's方法而不再重新定义它们。它使用一种称为inheritance的技术。这个挑战包括第一步:创建supertype (或父类)的实例。您已经知道使用new运算符创建Animal实例的一种方法:
让animal = new Animal();
使用此语法进行inheritance时存在一些缺点,这对于此挑战的范围来说过于复杂。相反,这是一种没有这些缺点的替代方法:
let animal = Object.create(Animal.prototype);
Object.create(obj)创建一个新对象,并将obj设置为新对象的prototype 。回想一下prototype就像创建对象的“配方”。通过设置prototypeanimalAnimal's prototype ,你实际上给animal例如相同的“配方”为任何其他实例Animal
animal.eat(); //打印“nom nom nom”
动物动物; // =>是的
+
+在上一个挑战中,我们创建了一个Animal 超类,用来定义所有动物共有的行为: + +```js +function Animal() { } +Animal.prototype.eat = function() { + console.log("nom nom nom"); +}; +``` + +在这一节以及下一节挑战中我们将学习如何给BirdDog重写Animal中的方法,而无需重新定义它们。这里我们会用到构造函数的继承特性。 +这一节挑战中我们学习第一步:创建一个超类(或者叫父类)的实例。 +你已经学会了一种创建Animal实例的方法,即使用new操作符: + +```js +let animal = new Animal(); +``` + +此语法用于继承时会存在一些缺点,这些缺点对于当前我们这个挑战来说太复杂了。相反,我们学习另外一种没有这些缺点的方法来替代new操作: + +```js +let animal = Object.create(Animal.prototype); +``` + +Object.create(obj)创建了一个新对象,并指定了obj作为新对象的原型。回忆一下,我们之前说过原型就像是创建对象的“配方”。如果我们把animal原型设置为与Animal构造函数的原型一样,那么就相当于让animal这个实例的配方与Animal其他实例的配方一样了。 + +```js +animal.eat(); // prints "nom nom nom" +animal instanceof Animal; // => true +``` + +
## Instructions -
使用Object.create创建名为duckbeagleAnimal两个实例。
+
+使用Object.create方法给Animal创建两个实例:duckbeagle。 +
## Tests
```yml tests: - - text: 应该定义duck变量。 - testString: 'assert(typeof duck !== "undefined", "The duck variable should be defined.");' - - text: 应该定义beagle变量。 - testString: 'assert(typeof beagle !== "undefined", "The beagle variable should be defined.");' - - text: duck应该有Animalprototype 。 - testString: 'assert(duck instanceof Animal, "duck should have a prototype of Animal.");' - - text: beagle应该有Animalprototype 。 - testString: 'assert(beagle instanceof Animal, "beagle should have a prototype of Animal.");' + - text: 应该定义一个duck变量。 + testString: assert(typeof duck !== "undefined"); + - text: 应该定义一个beagle变量。 + testString: assert(typeof beagle !== "undefined"); + - text: duck 变量应该通过 Object.create 初始化。 + testString: assert(/(let|const|var)\s{1,}duck\s*=\s*Object\.create\s*\(\s*Animal\.prototype\s*\)\s*/.test(code)); + - text: beagle 变量应该通过 Object.create 初始化。 + testString: assert(/(let|const|var)\s{1,}beagle\s*=\s*Object\.create\s*\(\s*Animal\.prototype\s*\)\s*/.test(code)); + - text: duck的原型应该被设置为Animal构造函数的原型。 + testString: assert(duck instanceof Animal); + - text: beagle的原型应该被设置为Animal构造函数的原型。 + testString: assert(beagle instanceof Animal); ``` @@ -52,7 +89,6 @@ let beagle; // Change this line duck.eat(); // Should print "nom nom nom" beagle.eat(); // Should print "nom nom nom" - ``` @@ -64,7 +100,21 @@ beagle.eat(); // Should print "nom nom nom" ## Solution
+ ```js -// solution required +function Animal() { } + +Animal.prototype = { + constructor: Animal, + eat: function() { + console.log("nom nom nom"); + } +}; +let duck = Object.create(Animal.prototype); +let beagle = Object.create(Animal.prototype); + +duck.eat(); +beagle.eat(); ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/iterate-over-all-properties.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/iterate-over-all-properties.chinese.md index 0e16259640..6bd4ac5312 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/iterate-over-all-properties.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/iterate-over-all-properties.chinese.md @@ -2,26 +2,59 @@ id: 587d7daf367417b2b2512b7d title: Iterate Over All Properties challengeType: 1 -videoUrl: '' +forumTopicId: 301320 localeTitle: 迭代所有属性 --- ## Description -
您现在已经看到了两种属性: own属性和prototype属性。 Own属性直接在对象实例本身上定义。和prototype属性所定义的prototype
function Bird(name){
this.name = name; //拥有财产
}

Bird.prototype.numLegs = 2; //原型属性

让鸭子=新鸟(“唐纳德”);
以下是如何将duck own属性添加到数组ownPropsprototype属性到数组prototypeProps
让ownProps = [];
让prototypeProps = [];

for(let duck in duck){
if(duck.hasOwnProperty(property)){
ownProps.push(属性);
} else {
prototypeProps.push(属性);
}
}

的console.log(ownProps); //打印[“名称”]
的console.log(prototypeProps); //打印[“numLegs”]
+
+现在你已经了解了两种属性: 自身属性和原型属性。自身属性是直接在对象上定义的。而原型属性是定义在prototype上的: + +```js +function Bird(name) { + this.name = name; // 自身属性 +} + +Bird.prototype.numLegs = 2; // 原型属性 + +let duck = new Bird("Donald"); +``` + +这个示例会告诉你如何将duck自身属性和原型属性分别添加到ownProps数组和prototypeProps数组里面: + +```js +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"] +``` + +
## Instructions -
所有添加own的属性beagle到数组ownProps 。将Dog所有prototype属性添加到数组prototypeProps
+
+将beagle的自身属性都添加到ownProps数组里面去。将Dog的所有原型属性添加到prototypeProps数组中。 +
## Tests
```yml tests: - - text: ownProps数组应包含"name" 。 + - text: "这个ownProps数组应该包含'name'这个值。" testString: assert(ownProps.indexOf('name') !== -1); - - text: prototypeProps数组应该包含"numLegs" 。 + - text: "这个prototypeProps数组应该包含'numLegs'这个值。" testString: assert(prototypeProps.indexOf('numLegs') !== -1); - - text: 无需使用内置方法Object.keys()即可解决此挑战。 + - text: 在不使用内置方法Object.keys()的情况下完成这个挑战。 testString: assert(!/\Object.keys/.test(code)); ``` @@ -47,6 +80,8 @@ let prototypeProps = []; // Add your code below this line + + ``` @@ -58,7 +93,25 @@ let prototypeProps = []; ## Solution
+ ```js -// solution required +function Dog(name) { + this.name = name; +} + +Dog.prototype.numLegs = 4; + +let beagle = new Dog("Snoopy"); + +let ownProps = []; +let prototypeProps = []; +for (let prop in beagle) { + if (beagle.hasOwnProperty(prop)) { + ownProps.push(prop); + } else { + prototypeProps.push(prop); + } +} ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/make-code-more-reusable-with-the-this-keyword.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/make-code-more-reusable-with-the-this-keyword.chinese.md index ca72cba2e9..2134ae558e 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/make-code-more-reusable-with-the-this-keyword.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/make-code-more-reusable-with-the-this-keyword.chinese.md @@ -2,24 +2,42 @@ id: 587d7dad367417b2b2512b76 title: Make Code More Reusable with the this Keyword challengeType: 1 -videoUrl: '' -localeTitle: 使用此关键字使代码更可重用 +forumTopicId: 301321 +localeTitle: 使用 this 关键字使代码更加可重用 --- ## Description -
最后一个挑战为duck对象引入了一个method 。它使用duck.name点表示法来访问return语句中name属性的值: sayName: function() {return "The name of this duck is " + duck.name + ".";}虽然这是有效的访问对象属性的方法,这里有一个陷阱。如果变量名称更改,则还需要更新引用原始名称的任何代码。在简短的对象定义中,它不是问题,但如果一个对象有很多对其属性的引用,则错误的可能性更大。避免这些问题的方法是使用this关键字:
让duck = {
名称:“Aflac”,
numLegs:2,
sayName:function(){return“这个鸭子的名字是”+ this.name +“。”;}
};
this是一个深刻的话题,上面的例子只是一种使用它的方法。在当前上下文中, this指的是与该方法相关联的对象: duck 。如果对象的名称更改为mallard ,则无需在代码中找到duck所有引用。它使代码可重用且易于阅读。
+
+在上一个挑战中我们了解了该如何给duck对象设置一个方法属性。然后在 return 语句里,我们通过使用 “点号表示法” duck.name来获取name的属性值: +sayName: function() {return "The name of this duck is " + duck.name + ".";} +虽然这是访问对象属性的有效方法,但是这里有一个陷阱。如果变量名发生了改变,那么引用了原始名称的任何代码都需要更新。在一个简短的对象定义中这并不是问题,但是如果对象有很多对其属性的引用,那么发生错误的可能性就更大了。 +我们可以使用this关键字这个方法来避免这一问题: + +```js +let duck = { + name: "Aflac", + numLegs: 2, + sayName: function() {return "The name of this duck is " + this.name + ".";} +}; +``` + +this是一个很复杂的知识点,而上面那个例子也只是使用this的一种方法而已。在当前的上下文环境中,this指向的就是与这个方法有关联的duck对象。 +如果把对象的变量名改为mallard,那使用this就没有必要在代码中找到所有指向duck的部分,这样可以使得代码更具有可读性和复用性。 +
## Instructions -
修改dog.sayLegs方法以删除对dog任何引用。使用duck示例进行指导。
+
+修改dog.sayLegs方法以将所有直接对dog的引用删除。可以参考上面的例子。 +
## Tests
```yml tests: - - text: dog.sayLegs()应该返回给定的字符串。 + - text: dog.sayLegs()应该返回一个指定的字符串。 testString: assert(dog.sayLegs() === 'This dog has 4 legs.'); - - text: 您的代码应使用this关键字来访问dognumLegs属性。 + - text: 你的代码应该使用this关键字来访问dog对象的numLegs属性值。 testString: assert(code.match(/this\.numLegs/g)); ``` @@ -39,7 +57,6 @@ let dog = { }; dog.sayLegs(); - ``` @@ -51,7 +68,17 @@ dog.sayLegs(); ## Solution
+ ```js -// solution required +let dog = { + name: "Spot", + numLegs: 4, + sayLegs () { + return 'This dog has ' + this.numLegs + ' legs.'; + } +}; + +dog.sayLegs(); ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/override-inherited-methods.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/override-inherited-methods.chinese.md index 55508fac41..5205b462da 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/override-inherited-methods.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/override-inherited-methods.chinese.md @@ -2,24 +2,67 @@ id: 587d7db1367417b2b2512b88 title: Override Inherited Methods challengeType: 1 -videoUrl: '' +forumTopicId: 301322 localeTitle: 重写继承的方法 --- ## Description -
在前面的课程中,您了解到一个对象可以通过克隆其prototype对象从另一个对象继承其行为(方法):
ChildObject.prototype = Object.create(ParentObject.prototype);
然后, ChildObject通过将它们链接到其prototype ChildObject获得自己的方法:
ChildObject.prototype.methodName = function(){...};
可以覆盖继承的方法。它以相同的方式完成 - 通过使用与要覆盖的方法名称相同的方法名称向ChildObject.prototype添加方法。以下是Bird重写从Animal继承的eat()方法的示例:
function Animal(){}
Animal.prototype.eat = function(){
返回“nom nom nom”;
};
函数Bird(){}

//继承Animal的所有方法
Bird.prototype = Object.create(Animal.prototype);

// Bird.eat()重写Animal.eat()
Bird.prototype.eat = function(){
返回“peck peck peck”;
};
如果你有一个实例,请let duck = new Bird();你调用duck.eat() ,这就是JavaScript在duck's prototype链上寻找方法的方法: duck.eat() =>这里定义了eat()吗? No. 2. Bird =>这里定义了eat()吗? =>是的。执行它并停止搜索。 3. Animal => eat()也被定义,但JavaScript在达到此级别之前停止搜索。 4. Object => JavaScript在达到此级别之前停止搜索。
+
+ +在上一个挑战中,我们学习了一个对象可以通过复制另一个对象的原型来继承其属性和行为(或方法): + +```js +ChildObject.prototype = Object.create(ParentObject.prototype); +``` + +然后,ChildObject将自己的方法链接到它的原型中: + +```js +ChildObject.prototype.methodName = function() {...}; +``` + +我们还可以重写继承的方法。以同样的方式——通过使用一个与需要重写的方法相同的方法名,向ChildObject.prototype中添加方法。 +请看下面的举例:Bird重写了从Animal继承来的eat()方法: + +```js +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 在到达这层原型链之前也已经停止了搜索。 + +
## Instructions -
覆盖Penguinfly()方法,使其返回“唉,这是一只不会飞的鸟”。
+
+ +重写Penguinfly()方法,使其返回 "Alas, this is a flightless bird." +
## Tests
```yml tests: - - text: penguin.fly()应该返回字符串“唉,这是一只不会飞的鸟”。 + - text: "penguin.fly()方法应该返回字符串:'Alas, this is a flightless bird.'" testString: assert(penguin.fly() === "Alas, this is a flightless bird."); - - text: bird.fly()方法应该返回“我正在飞行!” + - text: "The bird.fly()方法应该返回 'I am flying!'" testString: assert((new Bird()).fly() === "I am flying!"); ``` @@ -48,7 +91,6 @@ Penguin.prototype.constructor = Penguin; let penguin = new Penguin(); console.log(penguin.fly()); - ``` @@ -60,7 +102,18 @@ console.log(penguin.fly()); ## Solution
+ ```js -// solution required +function Bird() { } + +Bird.prototype.fly = function() { return "I am flying!"; }; + +function Penguin() { } +Penguin.prototype = Object.create(Bird.prototype); +Penguin.prototype.constructor = Penguin; +Penguin.prototype.fly = () => 'Alas, this is a flightless bird.'; +let penguin = new Penguin(); +console.log(penguin.fly()); ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/remember-to-set-the-constructor-property-when-changing-the-prototype.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/remember-to-set-the-constructor-property-when-changing-the-prototype.chinese.md index 83415bfaa8..fc42342b55 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/remember-to-set-the-constructor-property-when-changing-the-prototype.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/remember-to-set-the-constructor-property-when-changing-the-prototype.chinese.md @@ -2,22 +2,48 @@ id: 587d7daf367417b2b2512b80 title: Remember to Set the Constructor Property when Changing the Prototype challengeType: 1 -videoUrl: '' -localeTitle: 请记住在更改原型时设置构造函数属性 +forumTopicId: 301323 +localeTitle: 更改原型时,记得设置构造函数属性 --- ## Description -
prototype手动设置为新对象有一个至关重要的副作用。它擦除了constructor属性!上一个挑战中的代码将为duck打印以下内容:
执行console.log(duck.constructor)
//打印'undefined' - 哎呀!
要解决此问题,每当手动将原型设置为新对象时,请记住定义constructor属性:
Bird.prototype = {
构造函数:Bird,//定义构造函数属性
numLegs:2,
吃:function(){
console.log(“nom nom nom”);
},
describe:function(){
console.log(“我的名字是”+ this.name);
}
};
+
+手动给新对象重新设置原型对象,会产生一个重要的副作用:删除了constructor属性!我们来看一下,上一个挑战中duckconstructor属性输出到控制台的结果: + +```js +duck.constructor === Bird; // false -- 啊哦 +duck.constructor === Object; // true, 所有的对象都继承自 Object.prototype +duck instanceof Bird; // true, 依然生效 +``` + +为了解决这个问题,凡是手动给新对象重新设置过原型对象的,都别忘记在原型对象中定义一个constructor属性: + +```js +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); + } +}; +``` + +
## Instructions -
Dog prototype上定义constructor属性。
+
+给Dog 的原型对象定义一个constructor属性。 +
## Tests
```yml tests: - - text: Dog.prototype应该设置constructor属性。 + - text: Dog.prototype应该定义一个constructor属性。 testString: assert(Dog.prototype.constructor === Dog); ``` @@ -37,7 +63,7 @@ function Dog(name) { // Modify the code below this line Dog.prototype = { - numLegs: 2, + numLegs: 4, eat: function() { console.log("nom nom nom"); }, @@ -45,7 +71,6 @@ Dog.prototype = { console.log("My name is " + this.name); } }; - ``` @@ -57,7 +82,21 @@ Dog.prototype = { ## Solution
+ ```js -// solution required +function Dog(name) { + this.name = name; +} +Dog.prototype = { + constructor: Dog, + numLegs: 4, + eat: function() { + console.log("nom nom nom"); + }, + describe: function() { + console.log("My name is " + this.name); + } +}; ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/reset-an-inherited-constructor-property.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/reset-an-inherited-constructor-property.chinese.md index 41997a4cfa..f727044ed2 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/reset-an-inherited-constructor-property.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/reset-an-inherited-constructor-property.chinese.md @@ -2,28 +2,48 @@ id: 587d7db1367417b2b2512b86 title: Reset an Inherited Constructor Property challengeType: 1 -videoUrl: '' -localeTitle: 重置继承的构造函数属性 +forumTopicId: 301324 +localeTitle: 重置一个继承的构造函数属性 --- ## Description -
当一个对象从另一个对象继承它的prototype ,它也继承了supertype的构造函数属性。这是一个例子:
函数Bird(){}
Bird.prototype = Object.create(Animal.prototype);
let duck = new Bird();
duck.constructor // function Animal(){...}
duck和所有Bird实例都应该表明它们是由Bird而不是Animal建造的。为此,您可以手动将Bird's构造函数属性设置为Bird对象:
Bird.prototype.constructor = Bird;
duck.constructor // function Bird(){...}
+
+当一个对象从另一个对象那里继承了其原型,那它也继承了父类的 constructor 属性。 +请看下面的举例: + +```js +function Bird() { } +Bird.prototype = Object.create(Animal.prototype); +let duck = new Bird(); +duck.constructor // function Animal(){...} +``` + +但是duck和其他所有Bird的实例都应该表明它们是由Bird创建的,而不是由Animal创建的。为此,你可以手动把Bird的 constructor 属性设置为Bird对象: + +```js +Bird.prototype.constructor = Bird; +duck.constructor // function Bird(){...} +``` + +
## Instructions -
修复代码,使duck.constructorbeagle.constructor返回各自的构造函数。
+
+修改你的代码,使得duck.constructorbeagle.constructor返回各自的构造函数。 +
## Tests
```yml tests: - - text: Bird.prototype应该是Animal一个实例。 + - text: Bird.prototype应该是Animal的一个实例。 testString: assert(Animal.prototype.isPrototypeOf(Bird.prototype)); - - text: duck.constructor应该返回Bird 。 + - text: duck.constructor应该返回Bird。 testString: assert(duck.constructor === Bird); - - text: Dog.prototype应该是Animal一个实例。 + - text: Dog.prototype应该是Animal的一个实例。 testString: assert(Animal.prototype.isPrototypeOf(Dog.prototype)); - - text: beagle.constructor应该返回Dog 。 + - text: beagle.constructor应该返回Dog。 testString: assert(beagle.constructor === Dog); ``` @@ -49,7 +69,6 @@ Dog.prototype = Object.create(Animal.prototype); let duck = new Bird(); let beagle = new Dog(); - ``` @@ -61,7 +80,17 @@ let beagle = new Dog(); ## Solution
+ ```js -// solution required +function Animal() { } +function Bird() { } +function Dog() { } +Bird.prototype = Object.create(Animal.prototype); +Dog.prototype = Object.create(Animal.prototype); +Dog.prototype.constructor = Dog; +Bird.prototype.constructor = Bird; +let duck = new Bird(); +let beagle = new Dog(); ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/set-the-childs-prototype-to-an-instance-of-the-parent.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/set-the-childs-prototype-to-an-instance-of-the-parent.chinese.md index c7fadea698..e534eac930 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/set-the-childs-prototype-to-an-instance-of-the-parent.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/set-the-childs-prototype-to-an-instance-of-the-parent.chinese.md @@ -2,22 +2,40 @@ id: 587d7db1367417b2b2512b85 title: Set the Child's Prototype to an Instance of the Parent challengeType: 1 -videoUrl: '' -localeTitle: 将Child的Prototype设置为Parent的实例 +forumTopicId: 301325 +localeTitle: 将子辈的原型设置为父辈的实例 --- ## Description -
在之前的挑战中,您看到了从supertype (或父级) Animal继承行为的第一步:创建一个新的Animal实例。这个挑战包括下一步:设置subtype (或子)的prototype - 在这种情况下, Bird - 是Animal一个实例。
Bird.prototype = Object.create(Animal.prototype);
请记住, prototype就像创建对象的“配方”。在某种程度上, Bird的配方现在包括Animal所有关键“成分”。
让鸭子=新鸟(“唐纳德”);
duck.eat(); //打印“nom nom nom”
duck继承了Animal的所有属性,包括eat方法。
+
+在上一个挑战中,我们学习了从超类(或者叫父类) Animal继承其行为的第一个步骤:创建一个Animal的实例。 +这一节挑战我们将学习第二个步骤:给子类型(或者子类)设置原型。这样一来,Bird就是Animal的一个实例了。 + +```js +Bird.prototype = Object.create(Animal.prototype); +``` + +请记住,原型类似于创建对象的“配方”。从某种意义上来说,Bird对象的配方包含了Animal构造函数的所有关键“成分”。 + +```js +let duck = new Bird("Donald"); +duck.eat(); // prints "nom nom nom" +``` + +duck继承了Animal构造函数的所有属性,其中包括了eat方法。 +
## Instructions -
修改代码,以便Dog实例继承自Animal
+
+修改你的代码,实现一个继承自AnimalDog构造函数。 +
## Tests
```yml tests: - - text: Dog.prototype应该是Animal一个实例。 + - text: Dog.prototype应该是Animal的一个实例。 testString: assert(Animal.prototype.isPrototypeOf(Dog.prototype)); ``` @@ -46,7 +64,6 @@ function Dog() { } let beagle = new Dog(); beagle.eat(); // Should print "nom nom nom" - ``` @@ -58,7 +75,22 @@ beagle.eat(); // Should print "nom nom nom" ## Solution
+ ```js -// solution required +function Animal() { } + +Animal.prototype = { + constructor: Animal, + eat: function() { + console.log("nom nom nom"); + } +}; + +function Dog() { } +Dog.prototype = Object.create(Animal.prototype); + +let beagle = new Dog(); +beagle.eat(); ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-own-properties.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-own-properties.chinese.md index 1b57ebcb6e..d0418a415b 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-own-properties.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-own-properties.chinese.md @@ -2,25 +2,58 @@ id: 587d7dae367417b2b2512b7b title: Understand Own Properties challengeType: 1 -videoUrl: '' +forumTopicId: 301326 localeTitle: 了解自己的属性 --- ## Description -
在以下示例中, Bird构造函数定义了两个属性: namenumLegs
function Bird(name){
this.name = name;
this.numLegs = 2;
}

让鸭子=新鸟(“唐纳德”);
让金丝雀=新鸟(“特威蒂”);
namenumLegs称为own属性,因为它们直接在实例对象上定义。这意味着duckcanary每个都有自己独立的这些属性的副本。事实上, Bird每个实例都有自己的这些属性的副本。下面的代码将所有的own的性质duck到阵列ownProps
让ownProps = [];

for(let duck in duck){
if(duck.hasOwnProperty(property)){
ownProps.push(属性);
}
}

的console.log(ownProps); //打印[“name”,“numLegs”]
+
+请看下面的实例,Bird构造函数定义了两个属性:namenumLegs: + +```js +function Bird(name) { + this.name = name; + this.numLegs = 2; +} + +let duck = new Bird("Donald"); +let canary = new Bird("Tweety"); +``` + +namenumLegs被叫做自身属性,因为他们是直接在实例对象上定义的。这就意味着duckcanary这两个对象分别拥有这些属性的独立副本。 +事实上,Bird的这些实例都将拥有这些属性的独立副本。 +以下的代码将duck里面所有的自身属性都存到一个叫ownProps的数组里面: + +```js +let ownProps = []; + +for (let property in duck) { + if(duck.hasOwnProperty(property)) { + ownProps.push(property); + } +} + +console.log(ownProps); // prints [ "name", "numLegs" ] +``` + +
## Instructions -
canary own属性添加到数组ownProps
+
+将canary对象里面的自身属性添加到ownProps数组里面。 +
## Tests
```yml tests: - - text: ownProps应包含值"numLegs""name" 。 - testString: assert(ownProps.indexOf("name") !== -1 && ownProps.indexOf("numLegs") !== -1); - - text: 无需使用内置方法Object.keys()即可解决此挑战。 - testString: assert(!/\Object.keys/.test(code)); + - text: "ownProps应该包含'numLegs''name'两个属性的值。" + testString: assert(ownProps.indexOf('name') !== -1 && ownProps.indexOf('numLegs') !== -1); + - text: 在不使用内置方法Object.keys()的情况下完成这个挑战。 + testString: assert(!/Object(\.keys|\[(['"`])keys\2\])/.test(code)); + - text: You should solve this challenge without hardcoding the ownProps array. + testString: assert(!/\[\s*(?:'|")(?:name|numLegs)|(?:push|concat)\(\s*(?:'|")(?:name|numLegs)/.test(code)); ``` @@ -41,6 +74,8 @@ let canary = new Bird("Tweety"); let ownProps = []; // Add your code below this line + + ``` @@ -52,7 +87,27 @@ let ownProps = []; ## Solution
+ ```js -// solution required +function Bird(name) { + this.name = name; + this.numLegs = 2; +} + +let canary = new Bird("Tweety"); +function getOwnProps (obj) { + const props = []; + + for (let prop in obj) { + if (obj.hasOwnProperty(prop)) { + props.push(prop); + } + } + + return props; +} + +const ownProps = getOwnProps(canary); ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-the-constructor-property.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-the-constructor-property.chinese.md index a3ca4ddb1d..4262cd0b8a 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-the-constructor-property.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-the-constructor-property.chinese.md @@ -2,15 +2,42 @@ id: 587d7daf367417b2b2512b7e title: Understand the Constructor Property challengeType: 1 -videoUrl: '' -localeTitle: 理解构造函数属性 +forumTopicId: 301327 +localeTitle: 了解构造函数属性 --- ## Description -
在以前的挑战中创建的对象实例duckbeagle上有一个特殊的constructor属性:
let duck = new Bird();
让beagle = new Dog();

console.log(duck.constructor === Bird); //打印为true
console.log(beagle.constructor === Dog); //打印为true
请注意, constructor属性是对创建实例的构造函数的引用。 constructor属性的优点是可以检查此属性以找出它是什么类型的对象。以下是如何使用它的示例:
function joinBirdFraternity(candidate){
if(candidate.constructor === Bird){
返回true;
} else {
返回虚假;
}
}
注意
由于constructor属性可以被覆盖(将在接下来的两个挑战中讨论),因此通常最好使用instanceof方法来检查对象的类型。
+
+在上一个挑战中创建的实例对象duckbeagle都有一个特殊的constructor属性: + +```js +let duck = new Bird(); +let beagle = new Dog(); + +console.log(duck.constructor === Bird); //prints true +console.log(beagle.constructor === Dog); //prints true +``` + +需要注意到的是这个constructor属性是对创建这个实例的构造函数的一个引用。 +constructor属性存在的一个优势是,我们可以通过检查这个属性来找出它是一个什么样的对象。下面是一个例子,来看看是怎么使用的: + +```js +function joinBirdFraternity(candidate) { + if (candidate.constructor === Bird) { + return true; + } else { + return false; + } +} +``` + +注意:
由于constructor属性可以被重写(在下面两节挑战中将会遇到),所以使用instanceof方法来检查对象的类型会更好。 +
## Instructions -
编写一个joinDogFraternity函数,该函数接受candidate参数,并且如果候选者是Dog ,则使用constructor属性返回true ,否则返回false
+
+写一个joinDogFraternity函数,传入一个candidate参数并使用constructor属性来判断传入的 candidate 是不是Dog创建的对象实例,如果是,就返回true,否则返回false。 +
## Tests
@@ -19,9 +46,9 @@ localeTitle: 理解构造函数属性 tests: - text: joinDogFraternity应该被定义为一个函数。 testString: assert(typeof(joinDogFraternity) === 'function'); - - text: 如果candidateDog一个实例, joinDogFraternity应该返回true。 + - text: 如果candidateDog的一个对象实例,则joinDogFraternity函数应该返回true。 testString: assert(joinDogFraternity(new Dog("")) === true); - - text: joinDogFraternity应该使用constructor属性。 + - text: joinDogFraternity中应该用到constructor属性。 testString: assert(/\.constructor/.test(code) && !/instanceof/.test(code)); ``` @@ -54,7 +81,14 @@ function joinDogFraternity(candidate) { ## Solution
+ ```js -// solution required +function Dog(name) { + this.name = name; +} +function joinDogFraternity(candidate) { + return candidate.constructor === Dog; +} ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-the-immediately-invoked-function-expression-iife.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-the-immediately-invoked-function-expression-iife.chinese.md index 543d98695e..57a786d779 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-the-immediately-invoked-function-expression-iife.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-the-immediately-invoked-function-expression-iife.chinese.md @@ -2,24 +2,37 @@ id: 587d7db2367417b2b2512b8b title: Understand the Immediately Invoked Function Expression (IIFE) challengeType: 1 -videoUrl: '' -localeTitle: 理解立即调用的函数表达式(IIFE) +forumTopicId: 301328 +localeTitle: 了解立即调用函数表达(IIFE) --- ## Description -
JavaScript中的一个常见模式是在声明函数后立即执行:
(function(){
console.log(“Chirp,chirp!”);
})(); //这是一个立即执行的匿名函数表达式
//输出“Chirp,chirp!”立即
请注意,该函数没有名称,也没有存储在变量中。函数表达式末尾的两个括号()会立即执行或调用它。此模式称为immediately invoked function expressionIIFE
+
+JavaScript 中的一个常见模式就是,函数在声明后立刻执行: + +```js +(function () { + console.log("Chirp, chirp!"); +})(); // 这是一个立即执行的匿名函数表达式 +// 立即输出 "Chirp, chirp!" +``` + +请注意,函数没有名称,也不存储在变量中。函数表达式末尾的两个括号()导致它被立即执行或调用。这种模式被叫做自执行函数表达式或者IIFE。 +
## Instructions -
重写函数makeNest并删除它的调用,所以它是一个匿名的immediately invoked function expressionIIFE )。
+
+重写函数makeNest,并删除它的调用,取而代之是一个匿名的自执行函数表达式IIFE)。 +
## Tests
```yml tests: - - text: 该功能应该是匿名的。 + - text: 该函数应该是匿名的。 testString: assert(/\((function|\(\))(=>|\(\)){/.test(code.replace(/\s/g, ""))); - - text: 您的函数应在表达式的末尾加上括号以立即调用它。 + - text: 函数应该在表达式的末尾有括号,以便立即调用它。 testString: assert(/}\)\(\)/.test(code.replace(/\s/g, ""))); ``` @@ -37,7 +50,6 @@ function makeNest() { } makeNest(); - ``` @@ -49,7 +61,11 @@ makeNest(); ## Solution
+ ```js -// solution required +(function () { + console.log("A cozy nest is ready"); +})(); ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-the-prototype-chain.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-the-prototype-chain.chinese.md index db43b508f1..3488f96f08 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-the-prototype-chain.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-the-prototype-chain.chinese.md @@ -2,22 +2,52 @@ id: 587d7db0367417b2b2512b82 title: Understand the Prototype Chain challengeType: 1 -videoUrl: '' -localeTitle: 理解原型链 +forumTopicId: 301329 +localeTitle: 了解原型链 --- ## Description -
JavaScript中的所有对象(除少数例外)都有prototype 。此外,对象的prototype本身就是一个对象。
function Bird(name){
this.name = name;
}

typeof Bird.prototype; // =>对象
因为prototype是一个对象, prototype可以拥有自己的prototype !在这种情况下, Bird.prototypeprototypeObject.prototype
Object.prototype.isPrototypeOf(Bird.prototype);
//返回true
这有用吗?您可以回想一下之前挑战中的hasOwnProperty方法:
让鸭子=新鸟(“唐纳德”);
duck.hasOwnProperty( “名称”); // =>是的
hasOwnProperty方法在Object.prototype定义,可以通过Bird.prototype访问,然后可以通过duck访问它。这是prototype链的一个例子。在这个prototype链中, Birdducksupertype ,而ducksubtypeObjectBirdducksupertypeObject是JavaScript中所有对象的supertype 。因此,任何对象都可以使用hasOwnProperty方法。
+
+JavaScript 中所有的对象(除了少数例外)都有自己的原型。而且,对象的原型本身也是一个对象。 + +```js +function Bird(name) { + this.name = name; +} + +typeof Bird.prototype; // => object +``` + +正因为原型是一个对象,所以原型对象也有它自己的原型!这样看来的话,Bird.prototype原型就是Object.prototype: + +```js +Object.prototype.isPrototypeOf(Bird.prototype); +// 返回 true +``` + +这有什么作用呢?你可能还记得我们在上一个挑战中学到的hasOwnProperty方法: + +```js +let duck = new Bird("Donald"); +duck.hasOwnProperty("name"); // => true +``` + +hasOwnProperty是定义在Object.prototype上的一个方法,尽管在Bird.prototypeduck上并没有定义该方法,但是我们依然可以在这两个对象上访问到。这就是一个原型链。 +在这个原型链中,Bird构造函数是父级duck子级Object则是Bird构造函数和duck实例共同的父级。 +Object是 JavaScript 中所有对象的父级,也就是原型链的最顶层。因此,所有对象都可以访问hasOwnProperty方法。 +
## Instructions -
修改代码以显示正确的原型链。
+
+修改以下代码使其展示出正确的原型链。 +
## Tests
```yml tests: - - text: 您的代码应该显示Object.prototype是原型Dog.prototype “) + - text: 你的代码应该展示Object.prototypeDog.prototype的原型。 testString: assert(/Object\.prototype\.isPrototypeOf/.test(code)); ``` @@ -52,7 +82,14 @@ Dog.prototype.isPrototypeOf(beagle); // => true ## Solution
+ ```js -// solution required +function Dog(name) { + this.name = name; +} +let beagle = new Dog("Snoopy"); +Dog.prototype.isPrototypeOf(beagle); +Object.prototype.isPrototypeOf(Dog.prototype); ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-where-an-objects-prototype-comes-from.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-where-an-objects-prototype-comes-from.chinese.md index 7112052c43..4f13f7a262 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-where-an-objects-prototype-comes-from.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/understand-where-an-objects-prototype-comes-from.chinese.md @@ -2,22 +2,42 @@ id: 587d7db0367417b2b2512b81 title: Understand Where an Object’s Prototype Comes From challengeType: 1 -videoUrl: '' -localeTitle: 了解对象原型的来源 +forumTopicId: 301330 +localeTitle: 了解对象的原型来自哪里 --- ## Description -
就像人们从父母那里继承基因一样,一个对象直接从创建它的构造函数继承它的prototype 。例如, Bird构造函数在这里创建duck对象:
function Bird(name){
this.name = name;
}

让鸭子=新鸟(“唐纳德”);
duckBird构造函数继承了它的prototype 。您可以使用isPrototypeOf方法显示此关系:
Bird.prototype.isPrototypeOf(鸭);
//返回true
+
+就像人们从父母那里继承基因一样,对象也可直接从创建它的构造函数那里继承其原型。请看下面的例子:Bird构造函数创建了一个duck对象: + +```js +function Bird(name) { + this.name = name; +} + +let duck = new Bird("Donald"); +``` + +duckBird构造函数那里继承了它的原型,你可以使用isPrototypeOf方法来验证他们之间的关系: + +```js +Bird.prototype.isPrototypeOf(duck); +// 返回 true +``` + +
## Instructions -
使用isPrototypeOf检查prototypebeagle
+
+使用isPrototypeOf方法验证beagle是否继承了Dog构造函数的原型。 +
## Tests
```yml tests: - - text: 证明Dog.prototypebeagleprototype + - text: Dog.prototype应该是beagle原型。 testString: assert(/Dog\.prototype\.isPrototypeOf\(beagle\)/.test(code)); ``` @@ -38,6 +58,7 @@ let beagle = new Dog("Snoopy"); // Add your code below this line + ``` @@ -49,7 +70,13 @@ let beagle = new Dog("Snoopy"); ## Solution
+ ```js -// solution required +function Dog(name) { + this.name = name; +} +let beagle = new Dog("Snoopy"); +Dog.prototype.isPrototypeOf(beagle); ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-a-constructor-to-create-objects.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-a-constructor-to-create-objects.chinese.md index 200a071511..296c1abeed 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-a-constructor-to-create-objects.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-a-constructor-to-create-objects.chinese.md @@ -2,24 +2,56 @@ id: 587d7dad367417b2b2512b78 title: Use a Constructor to Create Objects challengeType: 1 -videoUrl: '' +forumTopicId: 18233 localeTitle: 使用构造函数创建对象 --- ## Description -
这是上一次挑战中的Bird构造函数:
function Bird(){
this.name =“阿尔伯特”;
this.color =“blue”;
this.numLegs = 2;
//构造函数中的“this”始终引用正在创建的对象
}

让blueBird = new Bird();
请注意,在调用构造函数时使用new运算符。这告诉JavaScript创建一个名为blueBirdBirdinstance 。如果没有new运营商, this在构造函数中不会指向新创建的对象,给人意想不到的效果。现在, blueBird具有在Bird构造函数中定义的所有属性:
blueBird.name; // =>艾伯特
blueBird.color; // =>蓝色
blueBird.numLegs; // => 2
就像任何其他对象一样,可以访问和修改其属性:
blueBird.name ='Elvira';
blueBird.name; // =>埃尔维拉
+
+在上一个挑战中,我们用所学到的知识创建了一个Bird构造函数: + +```js +function Bird() { + this.name = "Albert"; + this.color = "blue"; + this.numLegs = 2; + // 构造器内的 "this" 一直指向创建的对象 +} + +let blueBird = new Bird(); +``` + +注意:通过构造函数创建对象的时候要使用new操作符。因为只有这样,JavaScript 才知道要给Bird这个构造函数创建一个新的实例blueBird。如果不使用new操作符来新建对象,那么构造函数里面的this就无法指向新创建的这个对象实例,从而产生不可预见的错误。 +现在blueBird这个实例就继承了Bird这个构造函数的所有属性,如下: + +```js +blueBird.name; // => Albert +blueBird.color; // => blue +blueBird.numLegs; // => 2 +``` + +由构造函数创建的实例也和其他对象一样,它的属性可以被访问和修改: + +```js +blueBird.name = 'Elvira'; +blueBird.name; // => Elvira +``` + +
## Instructions -
使用上一课中的Dog构造函数创建Dog的新实例,将其分配给变量hound
+
+使用上一个课时中的Dog构造函数创建一个Dog的新实例,并把它赋值给变量hound。 +
## Tests
```yml tests: - - text: 应该使用Dog构造函数创建hound 。 + - text: hound应该是通过Dog构造函数来创建的。 testString: assert(hound instanceof Dog); - - text: 您的代码应该使用new运算符来创建Doginstance 。 + - text: 你的代码中应该使用new操作符来创建Dog构造函数的新实例。 testString: assert(code.match(/new/g)); ``` @@ -39,6 +71,7 @@ function Dog() { } // Add your code below this line + ``` @@ -50,7 +83,14 @@ function Dog() { ## Solution
+ ```js -// solution required +function Dog() { + this.name = "Rupert"; + this.color = "brown"; + this.numLegs = 4; +} +const hound = new Dog(); ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-a-mixin-to-add-common-behavior-between-unrelated-objects.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-a-mixin-to-add-common-behavior-between-unrelated-objects.chinese.md index bb1cdb3716..d8377a795e 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-a-mixin-to-add-common-behavior-between-unrelated-objects.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-a-mixin-to-add-common-behavior-between-unrelated-objects.chinese.md @@ -2,26 +2,65 @@ id: 587d7db2367417b2b2512b89 title: Use a Mixin to Add Common Behavior Between Unrelated Objects challengeType: 1 -videoUrl: '' -localeTitle: 使用Mixin在不相关的对象之间添加常见行为 +forumTopicId: 301331 +localeTitle: 使用 Mixin 在不相关对象之间添加共同行为 --- ## Description -
如您所见,行为通过继承来共享。但是,有些情况下继承不是最佳解决方案。对于像BirdAirplane这样的无关对象,继承不起作用。它们都可以飞行,但是Bird不是一种Airplane ,反之亦然。对于不相关的对象,最好使用mixinsmixin允许其他对象使用一组函数。
让flyMixin = function(obj){
obj.fly = function(){
console.log(“Flying,wooosh!”);
}
};
flyMixin接受任何对象并为其提供fly方法。
让bird = {
名称:“唐纳德”,
numLegs:2
};

让plane = {
型号:“777”,
numPassengers:524
};

flyMixin(鸟);
flyMixin(平面);
这里将birdplane传递给flyMixin ,然后将fly函数分配给每个对象。现在birdplane都可以飞行:
bird.fly(); //打印“飞行,嗖!”
plane.fly(); //打印“飞行,嗖!”
注意mixin如何允许相同的fly方法被不相关的对象birdplane重用。
+
+正如你所见,行为是可以通过继承来共享的。然而,在有些情况下,继承不是最好的解决方案。继承不适用于不相关的对象,比如BirdAirplane。虽然它们都可以飞行,但是Bird并不是一种Airplane,反之亦然。 +对于不相关的对象,更好的方法是使用mixinsmixin允许其他对象使用函数集合。 + +```js +let flyMixin = function(obj) { + obj.fly = function() { + console.log("Flying, wooosh!"); + } +}; +``` + +flyMixin能接受任何对象,并为其提供fly方法。 + +```js +let bird = { + name: "Donald", + numLegs: 2 +}; + +let plane = { + model: "777", + numPassengers: 524 +}; + +flyMixin(bird); +flyMixin(plane); +``` + +这里的flyMixin接收了birdplane对象,然后将fly方法分配给了每一个对象。现在birdplane都可以飞行了: + +```js +bird.fly(); // prints "Flying, wooosh!" +plane.fly(); // prints "Flying, wooosh!" +``` + +注意观察mixin是如何允许相同的fly方法被不相关的对象birdplane重用的。 +
## Instructions -
创建一个名为glideMixinmixin ,它定义了一个名为glide的方法。然后使用glideMixinbirdboat都能够滑行。
+
+创建一个名为glideMixinmixin,并定义一个glide方法。然后使用glideMixin来给birdboat赋予滑行(glide)的能力。 +
## Tests
```yml tests: - - text: 您的代码应该声明一个glideMixin变量,它是一个函数。 + - text: 你应该声明一个变量名为glideMixin的函数。 testString: assert(typeof glideMixin === "function"); - - text: 你的代码应该使用bird对象上的glideMixin来为它提供glide方法。 + - text: 你应该在bird上使用glideMixin,以提供glide方法。 testString: assert(typeof bird.glide === "function"); - - text: 你的代码应该使用boat对象上的glideMixin来为它提供glide方法。 + - text: 你应该在boat上使用glideMixin,以提供glide方法。 testString: assert(typeof boat.glide === "function"); ``` @@ -46,6 +85,11 @@ let boat = { // Add your code below this line + + + + + ``` @@ -57,7 +101,23 @@ let boat = { ## Solution
+ ```js -// solution required +let bird = { + name: "Donald", + numLegs: 2 +}; + +let boat = { + name: "Warrior", + type: "race-boat" +}; +function glideMixin (obj) { + obj.glide = () => 'Gliding!'; +} + +glideMixin(bird); +glideMixin(boat); ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-an-iife-to-create-a-module.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-an-iife-to-create-a-module.chinese.md index 331441490f..76ad50b027 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-an-iife-to-create-a-module.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-an-iife-to-create-a-module.chinese.md @@ -2,22 +2,67 @@ id: 587d7db2367417b2b2512b8c title: Use an IIFE to Create a Module challengeType: 1 -videoUrl: '' -localeTitle: 使用IIFE创建模块 +forumTopicId: 301332 +localeTitle: 使用 IIFE 创建一个模块 --- ## Description -
immediately invoked function expressionIIFE )通常用于将相关功能分组到单个对象或module 。例如,早期的挑战定义了两个mixins:
function glideMixin(obj){
obj.glide = function(){
console.log(“在水面上滑行”);
};
}
function flyMixin(obj){
obj.fly = function(){
console.log(“Flying,wooosh!”);
};
}
我们可以将这些mixins分组到一个模块中,如下所示:
让motionModule =(function(){
返回{
glideMixin:function(obj){
obj.glide = function(){
console.log(“在水面上滑行”);
};
},
flyMixin:function(obj){
obj.fly = function(){
console.log(“Flying,wooosh!”);
};
}
}
})(); //两个括号使得函数立即被调用
请注意,您有一个immediately invoked function expressionIIFE ),它返回一个对象motionModule 。此返回对象包含作为对象属性的所有mixin行为。 module模式的优点是可以将所有运动行为打包到单个对象中,然后可以由代码的其他部分使用。以下是使用它的示例:
motionModule.glideMixin(鸭);
duck.glide();
+
+一个自执行函数表达式IIFE)通常用于将相关功能分组到单个对象或者是模块中。例如,先前的挑战中定义了一个混合类: + +```js +function glideMixin(obj) { + obj.glide = function() { + console.log("Gliding on the water"); + }; +} +function flyMixin(obj) { + obj.fly = function() { + console.log("Flying, wooosh!"); + }; +} +``` + +我们可以将这些mixins分成以下模块: + +```js +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行为。 +模块模式的优点是,所有的运动行为都可以打包成一个对象,然后由代码的其他部分使用。下面是一个使用它的例子: + +```js +motionModule.glideMixin(duck); +duck.glide(); +``` + +
## Instructions -
创建一个名为funModulemodule来包装两个mixins isCuteMixinsingMixinfunModule应该返回一个对象。
+
+创建一个名为funModule模块,将这两个mixinsisCuteMixinsingMixin包装起来。funModule应该返回一个对象。 +
## Tests
```yml tests: - - text: 应该定义funModule并返回一个对象。 + - text: funModule应该被定义并返回一个对象。 testString: assert(typeof funModule === "object"); - text: funModule.isCuteMixin应该访问一个函数。 testString: assert(typeof funModule.isCuteMixin === "function"); @@ -44,7 +89,6 @@ let singMixin = function(obj) { console.log("Singing to an awesome tune"); }; }; - ``` @@ -56,7 +100,18 @@ let singMixin = function(obj) { ## Solution
+ ```js -// solution required +const funModule = (function () { + return { + isCuteMixin: obj => { + obj.isCute = () => true; + }, + singMixin: obj => { + obj.sing = () => console.log("Singing to an awesome tune"); + } + }; +})(); ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-closure-to-protect-properties-within-an-object-from-being-modified-externally.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-closure-to-protect-properties-within-an-object-from-being-modified-externally.chinese.md index beb903d612..a2345abfdb 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-closure-to-protect-properties-within-an-object-from-being-modified-externally.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-closure-to-protect-properties-within-an-object-from-being-modified-externally.chinese.md @@ -2,25 +2,58 @@ id: 587d7db2367417b2b2512b8a title: Use Closure to Protect Properties Within an Object from Being Modified Externally challengeType: 1 -videoUrl: '' +forumTopicId: 18234 localeTitle: 使用闭包保护对象内的属性不被外部修改 --- ## Description -
在之前的挑战中, bird有一个公共财产name 。它被认为是公开的,因为它可以在bird的定义之外进行访问和更改。
bird.name =“达菲”;
因此,代码的任何部分都可以轻松地将bird的名称更改为任何值。考虑一下代码库的任何部分都可以轻松更改密码和银行帐户等内容。这可能会导致很多问题。使属性私有的最简单方法是在构造函数中创建一个变量。这会将该变量的范围更改为构造函数,而不是全局可用。这样,只能通过构造函数中的方法访问和更改属性。
function Bird(){
让hatchedEgg = 10; // 私人财产

this.getHatchedEggCount = function(){//鸟类对象可以使用的公共可用方法
返回hatchedEgg;
};
}
让ducky = new Bird();
ducky.getHatchedEggCount(); //返回10
这里getHachedEggCount是一种特权方法,因为它可以访问私有变量hatchedEgg 。这是可能的,因为hatchedEgg在与getHachedEggCount相同的上下文中getHachedEggCount 。在JavaScript中,函数始终可以访问创建它的上下文。这叫做closure
+
+ +在上一次挑战中,bird有一个公共属性name。公共属性的定义就是:它可以在bird的定义范围之外被访问和更改。 + + +```js +bird.name = "Duffy"; +``` + + +因此,代码的任何地方都可以轻松地将bird的 name 属性更改为任意值。想想密码和银行账户之类的东西,如果代码库的任何部分都可以轻易改变,那么将会引起很多问题。 + +使属性私有化最简单的方法就是在构造函数中创建变量。可以将该变量范围限定在构造函数中,而不是全局可用。这样,属性只能由构造函数中的方法访问和更改。 + +```js +function Bird() { + let hatchedEgg = 10; // 私有变量 + + /* bird 对象可用的公共方法 */ + this.getHatchedEggCount = function() { + return hatchedEgg; + }; +} +let ducky = new Bird(); +ducky.getHatchedEggCount(); // 返回 10 +``` + +这里的getHachedEggCount是一种特权方法,因为它可以访问私有属性hatchedEgg。这是因为hatchedEgg是在与getHachedEggCount相同的上下文中声明的。在 JavaScript 中,函数总是可以访问创建它的上下文。这就叫做闭包。 + +
## Instructions -
更改Bird函数中声明weight方式,使其成为私有变量。然后,创建一个返回weight值的方法getWeight
+
+更改在Bird函数中声明的weight方法,使其成为私有变量。然后,创建一个返回weight值的getWeight方法。 +
## Tests
```yml tests: - - text: weight属性应该是私有变量。 - testString: 'assert(!code.match(/this\.weight/g), "The weight property should be a private variable.");' - - text: 你的代码应该在Bird创建一个名为getWeight的方法来返回weight 。 - testString: 'assert((new Bird()).getWeight() === 15, "Your code should create a method in Bird called getWeight that returns the weight.");' + - text: weight属性应该是一个私有变量,值应该是 15。 + testString: assert(code.match(/(var|let|const)\s+weight\s*\=\s*15\;?/g)); + - text: 你的代码应该在Bird中创建一个名为getWeight方法,该方法返回weight值。 + testString: assert((new Bird()).getWeight() === 15, '你的代码应该在Bird中创建一个名为getWeight方法,该方法返回weight值。'); + - text: Your getWeight function should return the private variable weight. + testString: assert(code.match(/((return\s+)|(\(\s*\)\s*\=\>\s*))weight\;?/g)); ``` @@ -49,7 +82,13 @@ function Bird() { ## Solution
+ ```js -// solution required +function Bird() { + let weight = 15; + + this.getWeight = () => weight; +} ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-dot-notation-to-access-the-properties-of-an-object.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-dot-notation-to-access-the-properties-of-an-object.chinese.md index d74f325c07..5abf6ad9c0 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-dot-notation-to-access-the-properties-of-an-object.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-dot-notation-to-access-the-properties-of-an-object.chinese.md @@ -2,24 +2,39 @@ id: 587d7dac367417b2b2512b74 title: Use Dot Notation to Access the Properties of an Object challengeType: 1 -videoUrl: '' -localeTitle: 使用点表示法访问对象的属性 +forumTopicId: 301333 +localeTitle: 使用点符号来访问对象的属性 --- ## Description -
最后一个挑战创建了一个具有各种propertiesobject ,现在您将看到如何访问这些properties的值。这是一个例子:
让duck = {
名称:“Aflac”,
numLegs:2
};
的console.log(duck.name);
//这会将“Aflac”打印到控制台
点符号用于object名称duck ,后跟property name ,以访问“Aflac”的值。
+
+在上一个挑战中,我们创建了一个拥有不同属性对象,现在我们来看看该如何访问这些属性: + +```js +let duck = { + name: "Aflac", + numLegs: 2 +}; +console.log(duck.name); +// 这段代码会在控制台中输出 "Aflac" +``` + +我们可以用“点号表示法”来访问对象的属性,只需要在对象名称后面加上.以及属性名即可。比如,duck.name就可以访问到 "Aflac"。 +
## Instructions -
将以下dog对象的两个properties打印到控制台。
+
+请在控制台里面输出dog对象中两个属性对应的值。 +
## Tests
```yml tests: - - text: 您应该使用console.log来打印dog对象的name属性的值。 + - text: 你应该使用console.log来将dog对象的name属性值输出到控制台。 testString: assert(/console.log\(.*dog\.name.*\)/g.test(code)); - - text: 您应该使用console.log来打印dog对象的numLegs属性的值。 + - text: 你应该使用console.log来将dog对象的numLegs属性值输出到控制台。 testString: assert(/console.log\(.*dog\.numLegs.*\)/g.test(code)); ``` @@ -38,6 +53,7 @@ let dog = { }; // Add your code below this line + ``` @@ -49,7 +65,14 @@ let dog = { ## Solution
+ ```js -// solution required +let dog = { + name: "Spot", + numLegs: 4 +}; +console.log(dog.name); +console.log(dog.numLegs); ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-inheritance-so-you-dont-repeat-yourself.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-inheritance-so-you-dont-repeat-yourself.chinese.md index abc82f4202..05f1a6cde0 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-inheritance-so-you-dont-repeat-yourself.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-inheritance-so-you-dont-repeat-yourself.chinese.md @@ -2,15 +2,62 @@ id: 587d7db0367417b2b2512b83 title: Use Inheritance So You Don't Repeat Yourself challengeType: 1 -videoUrl: '' -localeTitle: 使用继承,所以你不要重复自己 +forumTopicId: 301334 +localeTitle: 使用继承避免重复 --- ## Description -
编程中有一个原则叫做“ Don't Repeat Yourself (DRY) 。重复代码是一个问题的原因是因为任何更改都需要在多个位置修复代码。这通常意味着为程序员提供更多工作,并且有更多错误空间。请注意,在下面的示例中, describe方法由BirdDog共享:
Bird.prototype = {
构造函数:Bird,
describe:function(){
console.log(“我的名字是”+ this.name);
}
};

Dog.prototype = {
构造函数:狗,
describe:function(){
console.log(“我的名字是”+ this.name);
}
};
describe方法在两个地方重复。可以通过创建名为Animalsupertype (或父级)来编辑代码以遵循DRY原则:
function Animal(){};

Animal.prototype = {
构造函数:Animal,
describe:function(){
console.log(“我的名字是”+ this.name);
}
};
由于Animal包含describe方法,您可以从BirdDog删除它:
Bird.prototype = {
构造函数:Bird
};

Dog.prototype = {
构造函数:狗
};
+
+有一条原则叫做:Don't Repeat Yourself,常以缩写形式DRY出现,意思是“不要自己重复”。编写重复代码会产生的问题是:任何改变都需要去多个地方修复所有重复的代码。这通常意味着我们需要做更多的工作,会产生更高的出错率。 +请观察下面的示例,BirdDog共享describe方法: + +```js +Bird.prototype = { + 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方法在两个地方重复定义了。根据以上所说的DRY原则,我们可以通过创建一个Animal 超类(或者父类)来重写这段代码: + +```js +function Animal() { }; + +Animal.prototype = { + constructor: Animal, + describe: function() { + console.log("My name is " + this.name); + } +}; +``` + +Animal构造函数中定义了describe方法,可将BirdDog这两个构造函数的方法删除掉: + +```js +Bird.prototype = { + constructor: Bird +}; + +Dog.prototype = { + constructor: Dog +}; +``` + +
## Instructions -
CatBear都重复eat 。通过将eat方法移动到Animal supertypeDRY的精神编辑代码。
+
+CatBear重复定义了eat方法。本着DRY的原则,通过将eat方法移动到Animal 超类中来重写你的代码。 +
## Tests
@@ -62,7 +109,6 @@ Animal.prototype = { constructor: Animal, }; - ``` @@ -74,7 +120,32 @@ Animal.prototype = { ## Solution
+ ```js -// solution required +function Cat(name) { + this.name = name; +} + +Cat.prototype = { + constructor: Cat +}; + +function Bear(name) { + this.name = name; +} + +Bear.prototype = { + constructor: Bear +}; + +function Animal() { } + +Animal.prototype = { + constructor: Animal, + eat: function() { + console.log("nom nom nom"); + } +}; ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-prototype-properties-to-reduce-duplicate-code.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-prototype-properties-to-reduce-duplicate-code.chinese.md index 64e4235084..657bd1c50a 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-prototype-properties-to-reduce-duplicate-code.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/use-prototype-properties-to-reduce-duplicate-code.chinese.md @@ -2,26 +2,47 @@ id: 587d7dae367417b2b2512b7c title: Use Prototype Properties to Reduce Duplicate Code challengeType: 1 -videoUrl: '' +forumTopicId: 301336 localeTitle: 使用原型属性来减少重复代码 --- ## Description -
由于numLegs对于Bird所有实例可能具有相同的值, numLegs在每个Bird实例中基本上都有一个重复的变量numLegs 。当只有两个实例时,这可能不是问题,但想象一下,如果有数百万个实例。这将是许多重复的变量。更好的方法是使用Bird's prototypeprototype是一个在Bird所有实例之间共享的对象。以下是如何将numLegs添加到Bird prototype
Bird.prototype.numLegs = 2;
现在Bird所有实例都具有numLegs属性。
的console.log(duck.numLegs); //打印2
的console.log(canary.numLegs); //打印2
由于所有实例都自动拥有prototype上的属性,因此将prototype视为创建对象的“配方”。请注意, duckcanaryprototypeBird构造函数的一部分,如Bird.prototype 。 JavaScript中几乎每个对象都有一个prototype属性,它是创建它的构造函数的一部分。
+
+所有Bird实例可能会有相同的numLegs值,所以在每一个Bird的实例中本质上都有一个重复的变量numLegs。 +当只有两个实例时可能并不是什么问题,但想象一下如果有数百万个实例,这将会产生许许多多重复的变量。 +这里有一个更好的方法可以解决上述问题,那就是使用Bird原型原型是一个可以在所有Bird实例之间共享的对象。以下是一个在Bird prototype中添加numLegs属性的示例: + +```js +Bird.prototype.numLegs = 2; +``` + +现在所有的Bird实例都拥有了共同的numLegs属性值。 + +```js +console.log(duck.numLegs); // prints 2 +console.log(canary.numLegs); // prints 2 +``` + +由于所有的实例都可以继承原型上的属性,所以可以把原型看作是创建对象的 "配方"。 +请注意:duckcanary原型属于Bird的构造函数,即 Bird 的原型 Bird.prototype。JavaScript 中几乎所有的对象都有一个原型属性,这个属性是属于它所在的构造函数。 +
+ ## Instructions -
numLegs属性添加到Dogprototype
+
+给Dog原型添加一个numLegs属性。 +
## Tests
```yml tests: - - text: beagle应该有一个numLegs财产。 + - text: beagle应该有一个numLegs属性。 testString: assert(beagle.numLegs !== undefined); - text: beagle.numLegs应该是一个数字。 testString: assert(typeof(beagle.numLegs) === 'number' ); - - text: numLegs应该是prototype属性而不是own属性。 + - text: numLegs应该是一个原型属性而不是一个自身属性。 testString: assert(beagle.hasOwnProperty('numLegs') === false); ``` @@ -42,7 +63,6 @@ function Dog(name) { // Add your code above this line let beagle = new Dog("Snoopy"); - ``` @@ -54,7 +74,13 @@ let beagle = new Dog("Snoopy"); ## Solution
+ ```js -// solution required +function Dog (name) { + this.name = name; +} +Dog.prototype.numLegs = 4; +let beagle = new Dog("Snoopy"); ``` +
diff --git a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/verify-an-objects-constructor-with-instanceof.chinese.md b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/verify-an-objects-constructor-with-instanceof.chinese.md index 1f3efa83c9..67c4f0277c 100644 --- a/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/verify-an-objects-constructor-with-instanceof.chinese.md +++ b/curriculum/challenges/chinese/02-javascript-algorithms-and-data-structures/object-oriented-programming/verify-an-objects-constructor-with-instanceof.chinese.md @@ -2,24 +2,53 @@ id: 587d7dae367417b2b2512b7a title: Verify an Object's Constructor with instanceof challengeType: 1 -videoUrl: '' -localeTitle: 使用instanceof验证Object的构造函数 +forumTopicId: 301337 +localeTitle: 使用 instance of 验证对象的构造函数 --- ## Description -
无论何时构造函数创建一个新对象,该对象都被称为其构造函数的一个instance 。 JavaScript提供了一种使用instanceof运算符验证这一点的便捷方法。 instanceof允许您将对象与构造函数进行比较,根据是否使用构造函数创建该对象,返回truefalse 。这是一个例子:
让Bird = function(名称,颜色){
this.name = name;
this.color = color;
this.numLegs = 2;
}

让乌鸦=新鸟(“亚历克西斯”,“黑色”);

鸟的鸟; // =>是的
如果在不使用构造函数的instanceof创建对象, instanceof将验证它不是该构造函数的实例:
让金丝雀= {
名称:“Mildred”,
颜色:“黄色”,
numLegs:2
};

鸟类的金丝雀; // => false
+
+凡是通过构造函数创建出的新对象,都叫做这个构造函数的实例。JavaScript 提供了一种很简便的方法来验证这个事实,那就是通过instanceof操作符。instanceof允许你将对象与构造函数之间进行比较,根据对象是否由这个构造函数创建的返回true或者false。以下是一个示例: + +```js +let Bird = function(name, color) { + this.name = name; + this.color = color; + this.numLegs = 2; +} + +let crow = new Bird("Alexis", "black"); + +crow instanceof Bird; // => true +``` + +如果一个对象不是使用构造函数创建的,那么instanceof将会验证这个对象不是构造函数的实例: + +```js +let canary = { + name: "Mildred", + color: "Yellow", + numLegs: 2 +}; + +canary instanceof Bird; // => false +``` + +
## Instructions -
创建House构造函数的新实例,将其myHouse并传递多个卧室。然后,使用instanceof验证它是House的实例。
+
+给House构造函数创建一个新实例,取名为myHouse并且传递一个数字给bedrooms参数。然后使用instanceof操作符验证这个对象是否为House的实例。 +
## Tests
```yml tests: - - text: myHouse应该将numBedrooms属性设置为数字。 + - text: myHouse应该有一个numBedrooms属性被赋值为一个数字。 testString: assert(typeof myHouse.numBedrooms === 'number'); - - text: 请务必使用instanceof运算符验证myHouseHouseinstanceof 。 + - text: 请务必使用instanceof操作符验证myHouse这个对象是House构造函数的一个实例。 testString: assert(/myHouse\s*instanceof\s*House/.test(code)); ``` @@ -40,6 +69,8 @@ function House(numBedrooms) { // Add your code below this line + + ``` @@ -51,7 +82,13 @@ function House(numBedrooms) { ## Solution
+ ```js -// solution required +function House(numBedrooms) { + this.numBedrooms = numBedrooms; +} +const myHouse = new House(4); +console.log(myHouse instanceof House); ``` +