fix(i18n): update Chinese i18n of object oriented programming (#38055)
Co-authored-by: Zhicheng Chen <chenzhicheng@dayuwuxian.com>
This commit is contained in:
@ -2,30 +2,62 @@
|
||||
id: 587d7db1367417b2b2512b87
|
||||
title: Add Methods After Inheritance
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
forumTopicId: 301315
|
||||
localeTitle: 继承后添加方法
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">除了继承的方法之外,从<code>supertype</code>构造函数继承其<code>prototype</code>对象的构造函数仍然可以拥有自己的方法。例如, <code>Bird</code>是一个从<code>Animal</code>继承其<code>prototype</code>的构造函数: <blockquote> function Animal(){} <br> Animal.prototype.eat = function(){ <br> console.log(“nom nom nom”); <br> }; <br>函数Bird(){} <br> Bird.prototype = Object.create(Animal.prototype); <br> Bird.prototype.constructor = Bird; </blockquote>除了从<code>Animal</code>继承的内容之外,您还希望添加<code>Bird</code>对象独有的行为。在这里, <code>Bird</code>将获得一个<code>fly()</code>函数。函数以与任何构造函数相同的方式添加到<code>Bird's</code> <code>prototype</code> : <blockquote> Bird.prototype.fly = function(){ <br> console.log(“我在飞!”); <br> }; </blockquote>现在<code>Bird</code>实例将同时使用<code>eat()</code>和<code>fly()</code>方法: <blockquote> let duck = new Bird(); <br> duck.eat(); //打印“nom nom nom” <br> duck.fly(); //打印“我在飞!” </blockquote></section>
|
||||
<section id='description'>
|
||||
从<code>父类</code>继承其<code>原型</code>对象的构造函数除了继承的方法之外,还可以有自己的方法。
|
||||
请看举例:<code>Bird</code>是一个构造函数,它继承了<code>Animal</code>构造函数的<code>原型</code>:
|
||||
|
||||
```js
|
||||
function Animal() { }
|
||||
Animal.prototype.eat = function() {
|
||||
console.log("nom nom nom");
|
||||
};
|
||||
function Bird() { }
|
||||
Bird.prototype = Object.create(Animal.prototype);
|
||||
Bird.prototype.constructor = Bird;
|
||||
```
|
||||
|
||||
除了从<code>Animal</code>构造函数继承的行为之外,还需要给<code>Bird</code>对象添加它独有的行为。这里,我们给<code>Bird</code>对象添加一个<code>fly()</code>函数。函数会以一种与其他构造函数相同的方式添加到<code>Bird</code>的<code>原型</code>中:
|
||||
|
||||
```js
|
||||
Bird.prototype.fly = function() {
|
||||
console.log("I'm flying!");
|
||||
};
|
||||
```
|
||||
|
||||
现在<code>Bird</code>的实例中就有了<code>eat()</code>和<code>fly()</code>这两个方法:
|
||||
|
||||
```js
|
||||
let duck = new Bird();
|
||||
duck.eat(); // prints "nom nom nom"
|
||||
duck.fly(); // prints "I'm flying!"
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">添加所有必需的代码,以便<code>Dog</code>对象继承自<code>Animal</code> , <code>Dog's</code> <code>prototype</code>构造函数设置为Dog。然后将一个<code>bark()</code>方法添加到<code>Dog</code>对象,以便<code>beagle</code>可以<code>eat()</code>和<code>bark()</code> 。 <code>bark()</code>方法应该打印“Woof!”到控制台。 </section>
|
||||
<section id='instructions'>
|
||||
添加必要的代码,使得<code>Dog</code>对象继承<code>Animal</code>构造函数,并且把<code>Dog 原型</code>上的 constructor 属性设置为 Dog。然后给<code>Dog</code>对象添加一个<code>bark()</code>方法,这样的话,<code>beagle</code>将同时拥有<code>eat()</code>和<code>bark()</code>这两个方法。<code>bark()</code>方法中应该输出 "Woof!" 到控制台。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>Animal</code>不应该响应<code>bark()</code>方法。
|
||||
- text: <code>Animal</code>应该没有<code>bark()</code>方法。
|
||||
testString: assert(typeof Animal.prototype.bark == "undefined");
|
||||
- text: <code>Dog</code>应该继承<code>Animal</code>的<code>eat()</code>方法。
|
||||
- text: <code>Dog</code>应该继承了<code>Animal</code>构造函数的<code>eat()</code>方法。
|
||||
testString: assert(typeof Dog.prototype.eat == "function");
|
||||
- text: <code>Dog</code>应该将<code>bark()</code>方法作为<code>own</code>属性。
|
||||
- text: <code>Dog</code>应该有一个<code>bark()</code>方法作为<code>自身</code>属性。
|
||||
testString: assert(Dog.prototype.hasOwnProperty('bark'));
|
||||
- text: <code>beagle</code>应该是<code>Animal</code>一个<code>instanceof</code> 。
|
||||
- text: <code>beagle</code>应该是<code>Animal</code>的一个<code>instanceof</code>。
|
||||
testString: assert(beagle instanceof Animal);
|
||||
- text: <code>beagle</code>的构造函数应该设置为<code>Dog</code> 。
|
||||
- text: <code>beagle</code>的 constructor 属性应该被设置为<code>Dog</code>。
|
||||
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!"
|
||||
|
||||
```
|
||||
|
||||
</div>
|
||||
@ -66,7 +97,21 @@ beagle.bark(); // Should print "Woof!"
|
||||
## Solution
|
||||
<section id='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();
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -2,28 +2,63 @@
|
||||
id: 587d7daf367417b2b2512b7f
|
||||
title: Change the Prototype to a New Object
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
localeTitle: 将Prototype更改为新对象
|
||||
forumTopicId: 301316
|
||||
localeTitle: 将原型更改为新对象
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">到目前为止,您一直在为<code>prototype</code>添加属性: <blockquote> Bird.prototype.numLegs = 2; </blockquote>经过多个属性后,这变得乏味。 <blockquote> Bird.prototype.eat = function(){ <br> console.log(“nom nom nom”); <br> } <br><br> Bird.prototype.describe = function(){ <br> console.log(“我的名字是”+ this.name); <br> } </blockquote>更有效的方法是将<code>prototype</code>设置为已包含属性的新对象。这样,一次性添加属性: <blockquote> Bird.prototype = { <br> numLegs:2, <br>吃:function(){ <br> console.log(“nom nom nom”); <br> }, <br> describe:function(){ <br> console.log(“我的名字是”+ this.name); <br> } <br> }; </blockquote></section>
|
||||
<section id='description'>
|
||||
到目前为止,你已经可以单独给<code>prototype</code>添加属性了:
|
||||
|
||||
```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);
|
||||
}
|
||||
```
|
||||
|
||||
一种更有效的方法就是给对象的<code>prototype</code>设置为一个已经包含了属性的新对象。这样一来,所有属性都可以一次性添加进来:
|
||||
|
||||
```js
|
||||
Bird.prototype = {
|
||||
numLegs: 2,
|
||||
eat: function() {
|
||||
console.log("nom nom nom");
|
||||
},
|
||||
describe: function() {
|
||||
console.log("My name is " + this.name);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">添加属性<code>numLegs</code>和两种方法<code>eat()</code>和<code>describe()</code>的<code>prototype</code>的<code>Dog</code>被设置<code>prototype</code>到一个新的对象。 </section>
|
||||
<section id='instructions'>
|
||||
通过给<code>prototype</code>设置为新对象的方法,在<code>Dog</code>构造函数的<code>原型</code>上添加一个属性<code>numLegs</code>以及两个方法:<code>eat()</code>和<code>describe()</code>。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>Dog.prototype</code>应该设置为一个新对象。
|
||||
- text: <code>Dog.prototype</code>应该被设置为一个新对象。
|
||||
testString: assert((/Dog\.prototype\s*?=\s*?{/).test(code));
|
||||
- text: <code>Dog.prototype</code>应该具有属性<code>numLegs</code> 。
|
||||
- text: <code>Dog.prototype</code>应该拥有属性<code>numLegs</code>。
|
||||
testString: assert(Dog.prototype.numLegs !== undefined);
|
||||
- text: <code>Dog.prototype</code>应该有方法<code>eat()</code> 。
|
||||
- text: <code>Dog.prototype</code>应该拥有方法<code>eat()</code>。
|
||||
testString: assert(typeof Dog.prototype.eat === 'function');
|
||||
- text: <code>Dog.prototype</code>应该有方法<code>describe()</code> 。
|
||||
- text: <code>Dog.prototype</code>应该拥有方法<code>describe()</code>。
|
||||
testString: assert(typeof Dog.prototype.describe === 'function');
|
||||
|
||||
```
|
||||
@ -44,7 +79,6 @@ Dog.prototype = {
|
||||
// Add your code below this line
|
||||
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
</div>
|
||||
@ -56,7 +90,20 @@ Dog.prototype = {
|
||||
## Solution
|
||||
<section id='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);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -2,26 +2,42 @@
|
||||
id: 587d7dac367417b2b2512b73
|
||||
title: Create a Basic JavaScript Object
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
localeTitle: 创建一个基本的JavaScript对象
|
||||
forumTopicId: 301317
|
||||
localeTitle: 创建一个基本的 JavaScript 对象
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">想想人们每天看到的东西,比如汽车,商店和鸟类。这些都是<code>objects</code> :人们可以观察和互动的有形事物。这些<code>objects</code>一些特质是什么?一辆车有轮子。商店出售物品。鸟有翅膀。这些品质或<code>properties</code>定义了构成<code>object</code> 。请注意,类似<code>objects</code>共享相同的<code>properties</code> ,但这些<code>properties</code>可能具有不同的值。例如,所有汽车都有轮子,但并非所有汽车都有相同数量的轮子。 JavaScript中的<code>Objects</code>用于模拟现实世界的对象,为它们提供<code>properties</code>和行为,就像它们的真实对象一样。这是使用这些概念创建<code>duck</code> <code>object</code>的示例: <blockquote>让duck = { <br>名称:“Aflac”, <br> numLegs:2 <br> }; </blockquote>这个<code>duck</code> <code>object</code>有两个属性/值对: <code>name</code> “Aflac”和<code>numLegs</code>为2。 </section>
|
||||
<section id='description'>
|
||||
想想我们在生活中每天都可见到的事物:比如汽车、商店以及小鸟等。它们都是<code>物体</code>:即人们可以观察和与之互动的实体事物。
|
||||
那么这些<code>物体</code>都有哪些特征呢?比如汽车的特征是有轮子,商店是用来出售商品的,而小鸟的特征是有翅膀。
|
||||
这些特征,或者说是<code>属性</code>定义了一个<code>物体</code>由什么构成的。需要注意的是:那些相似的<code>物体</code>可以拥有相同的<code>属性</code>,但是这些<code>属性</code>可能会有不同的值。举个例子:所有的汽车都有轮子,但并不是所有汽车的轮子个数都是一样的。
|
||||
JavaScript 中的<code>对象</code>可以用来描述现实世界中的物体,并赋予他们<code>属性</code>和行为,就像它们在现实世界中的对应物一样。下面是使用这些概念来创建一个<code>duck 对象</code>的示例:
|
||||
|
||||
```js
|
||||
let duck = {
|
||||
name: "Aflac",
|
||||
numLegs: 2
|
||||
};
|
||||
```
|
||||
|
||||
这个<code>duck 对象</code> 有两组键值对:一个是<code>name</code>属性,它的值是 "Aflac";另一个是<code>numLegs</code>属性,它的值是 2。
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">使用<code>name</code>和<code>numLegs</code>属性创建一个<code>dog</code> <code>object</code> ,并将它们分别设置为字符串和数字。 </section>
|
||||
<section id='instructions'>
|
||||
创建一个<code>dog 对象</code>,并给这个对象添加两个属性:<code>name</code>和<code>numLegs</code>,同时把这两个属性的值分别设为字符串和数字。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>dog</code>应该是一个<code>object</code> 。
|
||||
- text: <code>dog</code>应该是一个<code>object</code>。
|
||||
testString: assert(typeof(dog) === 'object');
|
||||
- text: <code>dog</code>应该将<code>name</code>属性设置为<code>string</code> 。
|
||||
- text: <code>dog</code>应该有一个<code>name</code>属性,且它的值是一个<code>字符串<code>。
|
||||
testString: assert(typeof(dog.name) === 'string');
|
||||
- text: <code>dog</code>应该将<code>numLegs</code>属性设置为<code>number</code> 。
|
||||
- text: <code>dog</code>应该有一个<code>numLegs</code>属性,且它的值是一个<code>数字</code>。
|
||||
testString: assert(typeof(dog.numLegs) === 'number');
|
||||
|
||||
```
|
||||
@ -37,7 +53,6 @@ tests:
|
||||
let dog = {
|
||||
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
</div>
|
||||
@ -49,7 +64,12 @@ let dog = {
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
|
||||
|
||||
```js
|
||||
// solution required
|
||||
let dog = {
|
||||
name: '',
|
||||
numLegs: 4
|
||||
};
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -2,15 +2,33 @@
|
||||
id: 587d7dad367417b2b2512b75
|
||||
title: Create a Method on an Object
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
forumTopicId: 301318
|
||||
localeTitle: 在对象上创建方法
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description"> <code>Objects</code>可以具有特殊类型的<code>property</code> ,称为<code>method</code> 。 <code>Methods</code>是作为函数的<code>properties</code> 。这会为<code>object</code>添加不同的行为。这是一个方法的<code>duck</code>示例: <blockquote>让duck = { <br>名称:“Aflac”, <br> numLegs:2, <br> sayName:function(){return“这个鸭子的名字是”+ duck.name +“。”;} <br> }; <br> duck.sayName(); <br> //返回“这个鸭子的名字是Aflac。” </blockquote>该示例添加了<code>sayName</code> <code>method</code> ,该<code>method</code>是一个返回给出<code>duck</code>名称的句子的函数。请注意,该<code>method</code>使用<code>duck.name</code>访问return语句中的<code>name</code>属性。下一个挑战将包括另一种方法。 </section>
|
||||
<section id='description'>
|
||||
<code>对象</code>可以有一个叫做<code>方法</code>的特殊<code>属性</code>。
|
||||
<code>方法</code>其实是一个值为函数的<code>属性</code>,它可以为一个<code>对象</code>添加不同的行为。以下就是一个带有方法属性的<code>duck</code>示例:
|
||||
|
||||
```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."
|
||||
```
|
||||
|
||||
这个例子给<code>duck</code>对象添加了一个<code>sayName 方法</code>,这个方法返回一个包含<code>duck</code>名字的句子。
|
||||
注意:这个<code>方法</code>在返回语句中使用<code>duck.name</code>的方式来获取<code>name</code>的属性值。在下一个挑战中我们将会使用另外一种方法来实现。
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">使用<code>dog</code> <code>object</code> ,给它一个名为<code>sayLegs</code>的方法。该方法应该返回句子“这条狗有4条腿”。 </section>
|
||||
<section id='instructions'>
|
||||
给<code>dog 对象</code>设置一个名为<code>sayLegs</code>的方法,并让它返回 "This dog has 4 legs." 这句话。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
@ -19,7 +37,7 @@ localeTitle: 在对象上创建方法
|
||||
tests:
|
||||
- text: <code>dog.sayLegs()</code>应该是一个函数。
|
||||
testString: assert(typeof(dog.sayLegs) === 'function');
|
||||
- text: <code>dog.sayLegs()</code>应返回给定的字符串 - 请注意标点符号和间距很重要。
|
||||
- text: <code>dog.sayLegs()</code>应该返回给定的字符串,需要注意标点和间距的问题。
|
||||
testString: assert(dog.sayLegs() === 'This dog has 4 legs.');
|
||||
|
||||
```
|
||||
@ -39,7 +57,6 @@ let dog = {
|
||||
};
|
||||
|
||||
dog.sayLegs();
|
||||
|
||||
```
|
||||
|
||||
</div>
|
||||
@ -51,7 +68,17 @@ dog.sayLegs();
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
|
||||
|
||||
```js
|
||||
// solution required
|
||||
let dog = {
|
||||
name: "Spot",
|
||||
numLegs: 4,
|
||||
sayLegs () {
|
||||
return 'This dog has ' + this.numLegs + ' legs.';
|
||||
}
|
||||
};
|
||||
|
||||
dog.sayLegs();
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -2,26 +2,43 @@
|
||||
id: 587d7dad367417b2b2512b77
|
||||
title: Define a Constructor Function
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
forumTopicId: 16804
|
||||
localeTitle: 定义构造函数
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description"> <code>Constructors</code>函数是创建新对象的函数。它们定义属于新对象的属性和行为。将它们视为创建新对象的蓝图。以下是<code>constructor</code>的示例: <blockquote> function Bird(){ <br> this.name =“阿尔伯特”; <br> this.color =“blue”; <br> this.numLegs = 2; <br> } </blockquote>此<code>constructor</code>定义一个<code>Bird</code>对象,其属性<code>name</code> , <code>color</code>和<code>numLegs</code>设置为Albert,blue和2。 <code>Constructors</code>遵循一些约定: <ul><li> <code>Constructors</code>函数使用大写名称定义,以区别于非<code>constructors</code>函数的其他函数。 </li><li> <code>Constructors</code>使用关键字<code>this</code>来设置它们将创建的对象的属性。在<code>constructor</code> , <code>this</code>指的是它将创建的新对象。 </li><li> <code>Constructors</code>定义属性和行为,而不是像其他函数那样返回值。 </li></ul></section>
|
||||
<section id='description'>
|
||||
<code>构造函数</code>用以创建一个新对象,并给这个新对象定义属性和行为。因此这是创建新对象的一个最基本的方式。
|
||||
以下就是一个<code>构造函数</code>的示例:
|
||||
|
||||
```js
|
||||
function Bird() {
|
||||
this.name = "Albert";
|
||||
this.color = "blue";
|
||||
this.numLegs = 2;
|
||||
}
|
||||
```
|
||||
|
||||
这个<code>构造函数</code>定义了一个<code>Bird</code>对象,其属性<code>name</code>、<code>color</code>和<code>numLegs</code>的值分别被设置为<code>Albert</code>、<code>blue</code>和 2。
|
||||
<code>构造函数</code>遵循一些惯例规则:
|
||||
<ul><li><code>构造函数</code>函数名的首字母最好大写,这是为了方便我们区分<code>构造函数</code>和其他非构造函数。</li><li><code>构造函数</code>使用<code>this</code>关键字来给它将创建的这个对象设置新的属性。在<code>构造函数</code>里面,<code>this</code>指向的就是它新创建的这个对象。</li><li><code>构造函数</code>定义了属性和行为就可创建对象,而不是像其他函数一样需要设置返回值。</li></ul>
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">创建一个<code>constructor</code> <code>Dog</code> ,其属性<code>name</code> , <code>color</code>和<code>numLegs</code>分别设置为字符串,字符串和数字。 </section>
|
||||
<section id='instructions'>
|
||||
创建一个<code>构造函数</code>:<code>Dog</code>。给其添加<code>name</code>,<code>color</code>和<code>numLegs</code>属性并分别给它们设置为:字符串,字符串和数字。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>Dog</code>应该将<code>name</code>属性设置为字符串。
|
||||
- text: <code>Dog</code>应该有一个<code>name</code>属性且它的值是一个字符串。
|
||||
testString: assert(typeof (new Dog()).name === 'string');
|
||||
- text: <code>Dog</code>应该将<code>color</code>属性设置为字符串。
|
||||
- text: <code>Dog</code>应该有一个<code>color</code>属性且它的值是一个字符串。
|
||||
testString: assert(typeof (new Dog()).color === 'string');
|
||||
- text: <code>Dog</code>应该将<code>numLegs</code>属性设置为数字。
|
||||
- text: <code>Dog</code>应该有一个<code>numLegs</code>属性且它的值是一个数字。
|
||||
testString: assert(typeof (new Dog()).numLegs === 'number');
|
||||
|
||||
```
|
||||
@ -46,7 +63,13 @@ tests:
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
|
||||
|
||||
```js
|
||||
// solution required
|
||||
function Dog (name, color, numLegs) {
|
||||
this.name = 'name';
|
||||
this.color = 'color';
|
||||
this.numLegs = 4;
|
||||
}
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -2,28 +2,62 @@
|
||||
id: 587d7dae367417b2b2512b79
|
||||
title: Extend Constructors to Receive Arguments
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
forumTopicId: 18235
|
||||
localeTitle: 扩展构造函数以接收参数
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">最后一次挑战的<code>Bird</code>和<code>Dog</code>建设者运作良好。但是,请注意,所有的<code>Birds</code>与该创建<code>Bird</code>构造自动命名伟业,颜色为蓝色,有两条腿。如果您希望鸟类的名称和颜色具有不同的值,该怎么办?可以手动更改每只鸟的属性,但这将是很多工作: <blockquote>让swan = new Bird(); <br> swan.name =“卡洛斯”; <br> swan.color =“white”; </blockquote>假设您正在编写一个程序来跟踪鸟舍中数百甚至数千种不同的鸟类。创建所有鸟类需要花费大量时间,然后将每个属性的属性更改为不同的值。为了更轻松地创建不同的<code>Bird</code>对象,您可以设计Bird构造函数来接受参数: <blockquote> function Bird(名称,颜色){ <br> this.name = name; <br> this.color = color; <br> this.numLegs = 2; <br> } </blockquote>然后传入值作为参数,将每个独特的鸟定义到<code>Bird</code>构造函数中: <code>let cardinal = new Bird("Bruce", "red");</code>这给出了一个<code>Bird</code>的新实例,其名称和颜色属性分别设置为Bruce和red。 <code>numLegs</code>属性仍设置为2. <code>cardinal</code>具有以下属性: <blockquote> cardinal.name // =>布鲁斯<br> cardinal.color // =>红色<br> cardinal.numLegs // => 2 </blockquote>构造函数更灵活。现在可以在创建时为每个<code>Bird</code>定义属性,这是JavaScript构造函数如此有用的一种方式。他们根据共享的特征和行为将对象组合在一起,并定义一个自动创建的蓝图。 </section>
|
||||
<section id='description'>
|
||||
上一个挑战中<code>Bird</code>和<code>Dog</code>构造函数运行得不错。但是,注意到没有:所有通过<code>Bird</code>构造函数创建出来的实例<code>Birds</code>都自动的取名为 Albert,颜色都是蓝色,还都有两条腿。如果你想要新创建出来的小鸟们拥有不同的名字和颜色要怎么办呢?当然,手动的去修改每一个小鸟实例自己的属性也是可以实现的,只是会增加很多无谓的工作量:
|
||||
|
||||
```js
|
||||
let swan = new Bird();
|
||||
swan.name = "Carlos";
|
||||
swan.color = "white";
|
||||
```
|
||||
|
||||
假如你写了一个程序来追踪一个鸟舍里面的几百只甚至几千只不同的小鸟,你将会花费很多时间去创建所有的小鸟实例并给它们的属性一一修改为不同的值。
|
||||
为了减轻创建不同<code>Bird</code>对象的工作量,你可以给你的<code>Bird</code>设置为可以接收参数的构造函数:
|
||||
|
||||
```js
|
||||
function Bird(name, color) {
|
||||
this.name = name;
|
||||
this.color = color;
|
||||
this.numLegs = 2;
|
||||
}
|
||||
```
|
||||
|
||||
然后将值通过参数的方式传递给<code>Bird</code>构造函数来定义每一个唯一的小鸟实例:
|
||||
<code>let cardinal = new Bird("Bruce", "red");</code>
|
||||
这给<code>Bird</code>的名字和颜色属性分别赋值为 Bruce 和红色提供了另外一种方法。但<code>numLegs</code>属性被默认赋值为 2。
|
||||
<code>cardinal</code>有以下这些属性:
|
||||
|
||||
```js
|
||||
cardinal.name // => Bruce
|
||||
cardinal.color // => red
|
||||
cardinal.numLegs // => 2
|
||||
```
|
||||
|
||||
这样一来构造函数就变得很灵活了。现在可以直接定义每个<code>Bird</code>实例在创建时的属性,这是 JavaScript 构造函数非常实用的用法之一。它们根据共同或相似的属性和行为将对象归纳为一组,并能够自动的创建各自实例。
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">创建另一个<code>Dog</code>构造函数。这次,将其设置为采用参数<code>name</code>和<code>color</code> ,并将属性<code>numLegs</code>固定为4.然后创建一个保存在变量<code>terrier</code>的新<code>Dog</code> 。将两个字符串作为<code>name</code>和<code>color</code>属性的参数传递给它。 </section>
|
||||
<section id='instructions'>
|
||||
创建另一个<code>Dog</code>构造函数。这一次,给它设置两个参数:<code>name</code>和<code>color</code>,同时给<code>numLegs</code>赋值为 4。然后创建一个新<code>Dog</code>实例保存为变量名:<code>terrier</code>,再将两个字符串通过参数的形式传入<code>name</code>和<code>color</code>属性。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>Dog</code>应该收到<code>name</code>的论据。
|
||||
- text: <code>Dog</code>应该接收一个<code>name</code>参数。
|
||||
testString: assert((new Dog('Clifford')).name === 'Clifford');
|
||||
- text: <code>Dog</code>应该收到<code>color</code>的论据。
|
||||
- text: <code>Dog</code>应该接收一个<code>color</code>参数。
|
||||
testString: assert((new Dog('Clifford', 'yellow')).color === 'yellow');
|
||||
- text: <code>Dog</code>应该将属性<code>numLegs</code>设置为4。
|
||||
- text: <code>Dog</code>应该有一个<code>numLegs</code>属性且值为 4。
|
||||
testString: assert((new Dog('Clifford')).numLegs === 4);
|
||||
- text: 应该使用<code>Dog</code>构造函数创建<code>terrier</code> 。
|
||||
- text: <code>terrier</code>应该是通过<code>Dog</code>构造函数创建的。
|
||||
testString: assert(terrier instanceof Dog);
|
||||
|
||||
```
|
||||
@ -40,6 +74,7 @@ function Dog() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
</div>
|
||||
@ -51,7 +86,15 @@ function Dog() {
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
|
||||
|
||||
```js
|
||||
// solution required
|
||||
function Dog (name, color) {
|
||||
this.numLegs = 4;
|
||||
this.name = name;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
const terrier = new Dog();
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -2,29 +2,66 @@
|
||||
id: 587d7db0367417b2b2512b84
|
||||
title: Inherit Behaviors from a Supertype
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
localeTitle: 从超类型继承行为
|
||||
forumTopicId: 301319
|
||||
localeTitle: 从超类继承行为
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">在之前的挑战中,您创建了一个名为<code>Animal</code>的<code>supertype</code> ,它定义了所有动物共享的行为: <blockquote> function Animal(){} <br> Animal.prototype.eat = function(){ <br> console.log(“nom nom nom”); <br> }; </blockquote>这个和下一个挑战将涵盖如何在<code>Bird</code> and <code>Dog</code>重用<code>Animal's</code>方法而不再重新定义它们。它使用一种称为<code>inheritance</code>的技术。这个挑战包括第一步:创建<code>supertype</code> (或父类)的实例。您已经知道使用<code>new</code>运算符创建<code>Animal</code>实例的一种方法: <blockquote>让animal = new Animal(); </blockquote>使用此语法进行<code>inheritance</code>时存在一些缺点,这对于此挑战的范围来说过于复杂。相反,这是一种没有这些缺点的替代方法: <blockquote> let animal = Object.create(Animal.prototype); </blockquote> <code>Object.create(obj)</code>创建一个新对象,并将<code>obj</code>设置为新对象的<code>prototype</code> 。回想一下<code>prototype</code>就像创建对象的“配方”。通过设置<code>prototype</code>的<code>animal</code>是<code>Animal's</code> <code>prototype</code> ,你实际上给<code>animal</code>例如相同的“配方”为任何其他实例<code>Animal</code> 。 <blockquote> animal.eat(); //打印“nom nom nom” <br>动物动物; // =>是的</blockquote></section>
|
||||
<section id='description'>
|
||||
在上一个挑战中,我们创建了一个<code>Animal 超类</code>,用来定义所有动物共有的行为:
|
||||
|
||||
```js
|
||||
function Animal() { }
|
||||
Animal.prototype.eat = function() {
|
||||
console.log("nom nom nom");
|
||||
};
|
||||
```
|
||||
|
||||
在这一节以及下一节挑战中我们将学习如何给<code>Bird</code>、<code>Dog</code>重写<code>Animal</code>中的方法,而无需重新定义它们。这里我们会用到构造函数的<code>继承</code>特性。
|
||||
这一节挑战中我们学习第一步:创建一个<code>超类</code>(或者叫父类)的实例。
|
||||
你已经学会了一种创建<code>Animal</code>实例的方法,即使用<code>new</code>操作符:
|
||||
|
||||
```js
|
||||
let animal = new Animal();
|
||||
```
|
||||
|
||||
此语法用于<code>继承</code>时会存在一些缺点,这些缺点对于当前我们这个挑战来说太复杂了。相反,我们学习另外一种没有这些缺点的方法来替代<code>new</code>操作:
|
||||
|
||||
```js
|
||||
let animal = Object.create(Animal.prototype);
|
||||
```
|
||||
|
||||
<code>Object.create(obj)</code>创建了一个新对象,并指定了<code>obj</code>作为新对象的<code>原型</code>。回忆一下,我们之前说过<code>原型</code>就像是创建对象的“配方”。如果我们把<code>animal</code>的<code>原型</code>设置为与<code>Animal</code>构造函数的<code>原型</code>一样,那么就相当于让<code>animal</code>这个实例的配方与<code>Animal</code>其他实例的配方一样了。
|
||||
|
||||
```js
|
||||
animal.eat(); // prints "nom nom nom"
|
||||
animal instanceof Animal; // => true
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">使用<code>Object.create</code>创建名为<code>duck</code>和<code>beagle</code>的<code>Animal</code>两个实例。 </section>
|
||||
<section id='instructions'>
|
||||
使用<code>Object.create</code>方法给<code>Animal</code>创建两个实例:<code>duck</code>和<code>beagle</code>。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 应该定义<code>duck</code>变量。
|
||||
testString: 'assert(typeof duck !== "undefined", "The <code>duck</code> variable should be defined.");'
|
||||
- text: 应该定义<code>beagle</code>变量。
|
||||
testString: 'assert(typeof beagle !== "undefined", "The <code>beagle</code> variable should be defined.");'
|
||||
- text: <code>duck</code>应该有<code>Animal</code>的<code>prototype</code> 。
|
||||
testString: 'assert(duck instanceof Animal, "<code>duck</code> should have a <code>prototype</code> of <code>Animal</code>.");'
|
||||
- text: <code>beagle</code>应该有<code>Animal</code>的<code>prototype</code> 。
|
||||
testString: 'assert(beagle instanceof Animal, "<code>beagle</code> should have a <code>prototype</code> of <code>Animal</code>.");'
|
||||
- text: 应该定义一个<code>duck</code>变量。
|
||||
testString: assert(typeof duck !== "undefined");
|
||||
- text: 应该定义一个<code>beagle</code>变量。
|
||||
testString: assert(typeof beagle !== "undefined");
|
||||
- text: <code>duck</code> 变量应该通过 <code>Object.create</code> 初始化。
|
||||
testString: assert(/(let|const|var)\s{1,}duck\s*=\s*Object\.create\s*\(\s*Animal\.prototype\s*\)\s*/.test(code));
|
||||
- text: <code>beagle</code> 变量应该通过 <code>Object.create</code> 初始化。
|
||||
testString: assert(/(let|const|var)\s{1,}beagle\s*=\s*Object\.create\s*\(\s*Animal\.prototype\s*\)\s*/.test(code));
|
||||
- text: <code>duck</code>的原型应该被设置为<code>Animal</code>构造函数的<code>原型</code>。
|
||||
testString: assert(duck instanceof Animal);
|
||||
- text: <code>beagle</code>的原型应该被设置为<code>Animal</code>构造函数的<code>原型</code>。
|
||||
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"
|
||||
|
||||
```
|
||||
|
||||
</div>
|
||||
@ -64,7 +100,21 @@ beagle.eat(); // Should print "nom nom nom"
|
||||
## Solution
|
||||
<section id='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();
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -2,26 +2,59 @@
|
||||
id: 587d7daf367417b2b2512b7d
|
||||
title: Iterate Over All Properties
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
forumTopicId: 301320
|
||||
localeTitle: 迭代所有属性
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">您现在已经看到了两种属性: <code>own</code>属性和<code>prototype</code>属性。 <code>Own</code>属性直接在对象实例本身上定义。和<code>prototype</code>属性所定义的<code>prototype</code> 。 <blockquote> function Bird(name){ <br> this.name = name; //拥有财产<br> } <br><br> Bird.prototype.numLegs = 2; //原型属性<br><br>让鸭子=新鸟(“唐纳德”); </blockquote>以下是如何将<code>duck</code> <code>own</code>属性添加到数组<code>ownProps</code>和<code>prototype</code>属性到数组<code>prototypeProps</code> : <blockquote>让ownProps = []; <br>让prototypeProps = []; <br><br> for(let duck in duck){ <br> if(duck.hasOwnProperty(property)){ <br> ownProps.push(属性); <br> } else { <br> prototypeProps.push(属性); <br> } <br> } <br><br>的console.log(ownProps); //打印[“名称”] <br>的console.log(prototypeProps); //打印[“numLegs”] </blockquote></section>
|
||||
<section id='description'>
|
||||
现在你已经了解了两种属性: <code>自身</code>属性和<code>原型</code>属性。<code>自身</code>属性是直接在对象上定义的。而<code>原型</code>属性是定义在<code>prototype</code>上的:
|
||||
|
||||
```js
|
||||
function Bird(name) {
|
||||
this.name = name; // 自身属性
|
||||
}
|
||||
|
||||
Bird.prototype.numLegs = 2; // 原型属性
|
||||
|
||||
let duck = new Bird("Donald");
|
||||
```
|
||||
|
||||
这个示例会告诉你如何将<code>duck</code>的<code>自身</code>属性和<code>原型</code>属性分别添加到<code>ownProps</code>数组和<code>prototypeProps</code>数组里面:
|
||||
|
||||
```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"]
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">所有添加<code>own</code>的属性<code>beagle</code>到数组<code>ownProps</code> 。将<code>Dog</code>所有<code>prototype</code>属性添加到数组<code>prototypeProps</code> 。 </section>
|
||||
<section id='instructions'>
|
||||
将<code>beagle</code>的自身属性都添加到<code>ownProps</code>数组里面去。将<code>Dog</code>的所有<code>原型</code>属性添加到<code>prototypeProps</code>数组中。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>ownProps</code>数组应包含<code>"name"</code> 。
|
||||
- text: "这个<code>ownProps</code>数组应该包含<code>'name'</code>这个值。"
|
||||
testString: assert(ownProps.indexOf('name') !== -1);
|
||||
- text: <code>prototypeProps</code>数组应该包含<code>"numLegs"</code> 。
|
||||
- text: "这个<code>prototypeProps</code>数组应该包含<code>'numLegs'</code>这个值。"
|
||||
testString: assert(prototypeProps.indexOf('numLegs') !== -1);
|
||||
- text: 无需使用内置方法<code>Object.keys()</code>即可解决此挑战。
|
||||
- text: 在不使用内置方法<code>Object.keys()</code>的情况下完成这个挑战。
|
||||
testString: assert(!/\Object.keys/.test(code));
|
||||
|
||||
```
|
||||
@ -47,6 +80,8 @@ let prototypeProps = [];
|
||||
|
||||
// Add your code below this line
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
</div>
|
||||
@ -58,7 +93,25 @@ let prototypeProps = [];
|
||||
## Solution
|
||||
<section id='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);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -2,24 +2,42 @@
|
||||
id: 587d7dad367417b2b2512b76
|
||||
title: Make Code More Reusable with the this Keyword
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
localeTitle: 使用此关键字使代码更可重用
|
||||
forumTopicId: 301321
|
||||
localeTitle: 使用 this 关键字使代码更加可重用
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">最后一个挑战为<code>duck</code>对象引入了一个<code>method</code> 。它使用<code>duck.name</code>点表示法来访问return语句中<code>name</code>属性的值: <code>sayName: function() {return "The name of this duck is " + duck.name + ".";}</code>虽然这是有效的访问对象属性的方法,这里有一个陷阱。如果变量名称更改,则还需要更新引用原始名称的任何代码。在简短的对象定义中,它不是问题,但如果一个对象有很多对其属性的引用,则错误的可能性更大。避免这些问题的方法是使用<code>this</code>关键字: <blockquote>让duck = { <br>名称:“Aflac”, <br> numLegs:2, <br> sayName:function(){return“这个鸭子的名字是”+ this.name +“。”;} <br> }; </blockquote> <code>this</code>是一个深刻的话题,上面的例子只是一种使用它的方法。在当前上下文中, <code>this</code>指的是与该方法相关联的对象: <code>duck</code> 。如果对象的名称更改为<code>mallard</code> ,则无需在代码中找到<code>duck</code>所有引用。它使代码可重用且易于阅读。 </section>
|
||||
<section id='description'>
|
||||
在上一个挑战中我们了解了该如何给<code>duck</code>对象设置一个<code>方法</code>属性。然后在 <code>return</code> 语句里,我们通过使用 “点号表示法” <code>duck.name</code>来获取<code>name</code>的属性值:
|
||||
<code>sayName: function() {return "The name of this duck is " + duck.name + ".";}</code>
|
||||
虽然这是访问对象属性的有效方法,但是这里有一个陷阱。如果变量名发生了改变,那么引用了原始名称的任何代码都需要更新。在一个简短的对象定义中这并不是问题,但是如果对象有很多对其属性的引用,那么发生错误的可能性就更大了。
|
||||
我们可以使用<code>this</code>关键字这个方法来避免这一问题:
|
||||
|
||||
```js
|
||||
let duck = {
|
||||
name: "Aflac",
|
||||
numLegs: 2,
|
||||
sayName: function() {return "The name of this duck is " + this.name + ".";}
|
||||
};
|
||||
```
|
||||
|
||||
<code>this</code>是一个很复杂的知识点,而上面那个例子也只是使用<code>this</code>的一种方法而已。在当前的上下文环境中,<code>this</code>指向的就是与这个方法有关联的<code>duck</code>对象。
|
||||
如果把对象的变量名改为<code>mallard</code>,那使用<code>this</code>就没有必要在代码中找到所有指向<code>duck</code>的部分,这样可以使得代码更具有可读性和复用性。
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">修改<code>dog.sayLegs</code>方法以删除对<code>dog</code>任何引用。使用<code>duck</code>示例进行指导。 </section>
|
||||
<section id='instructions'>
|
||||
修改<code>dog.sayLegs</code>方法以将所有直接对<code>dog</code>的引用删除。可以参考上面的例子。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>dog.sayLegs()</code>应该返回给定的字符串。
|
||||
- text: <code>dog.sayLegs()</code>应该返回一个指定的字符串。
|
||||
testString: assert(dog.sayLegs() === 'This dog has 4 legs.');
|
||||
- text: 您的代码应使用<code>this</code>关键字来访问<code>dog</code>的<code>numLegs</code>属性。
|
||||
- text: 你的代码应该使用<code>this</code>关键字来访问<code>dog</code>对象的<code>numLegs</code>属性值。
|
||||
testString: assert(code.match(/this\.numLegs/g));
|
||||
|
||||
```
|
||||
@ -39,7 +57,6 @@ let dog = {
|
||||
};
|
||||
|
||||
dog.sayLegs();
|
||||
|
||||
```
|
||||
|
||||
</div>
|
||||
@ -51,7 +68,17 @@ dog.sayLegs();
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
|
||||
|
||||
```js
|
||||
// solution required
|
||||
let dog = {
|
||||
name: "Spot",
|
||||
numLegs: 4,
|
||||
sayLegs () {
|
||||
return 'This dog has ' + this.numLegs + ' legs.';
|
||||
}
|
||||
};
|
||||
|
||||
dog.sayLegs();
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -2,24 +2,67 @@
|
||||
id: 587d7db1367417b2b2512b88
|
||||
title: Override Inherited Methods
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
forumTopicId: 301322
|
||||
localeTitle: 重写继承的方法
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">在前面的课程中,您了解到一个对象可以通过克隆其<code>prototype</code>对象从另一个对象继承其行为(方法): <blockquote> ChildObject.prototype = Object.create(ParentObject.prototype); </blockquote>然后, <code>ChildObject</code>通过将它们链接到其<code>prototype</code> <code>ChildObject</code>获得自己的方法: <blockquote> ChildObject.prototype.methodName = function(){...}; </blockquote>可以覆盖继承的方法。它以相同的方式完成 - 通过使用与要覆盖的方法名称相同的方法名称向<code>ChildObject.prototype</code>添加方法。以下是<code>Bird</code>重写从<code>Animal</code>继承的<code>eat()</code>方法的示例: <blockquote> function Animal(){} <br> Animal.prototype.eat = function(){ <br>返回“nom nom nom”; <br> }; <br>函数Bird(){} <br><br> //继承Animal的所有方法<br> Bird.prototype = Object.create(Animal.prototype); <br><br> // Bird.eat()重写Animal.eat() <br> Bird.prototype.eat = function(){ <br>返回“peck peck peck”; <br> }; </blockquote>如果你有一个实例,请<code>let duck = new Bird();</code>你调用<code>duck.eat()</code> ,这就是JavaScript在<code>duck's</code> <code>prototype</code>链上寻找方法的方法: <code>duck.eat()</code> =>这里定义了eat()吗? No. 2. Bird =>这里定义了eat()吗? =>是的。执行它并停止搜索。 3. Animal => eat()也被定义,但JavaScript在达到此级别之前停止搜索。 4. Object => JavaScript在达到此级别之前停止搜索。 </section>
|
||||
<section id='description'>
|
||||
|
||||
在上一个挑战中,我们学习了一个对象可以通过复制另一个对象的<code>原型</code>来继承其属性和行为(或方法):
|
||||
|
||||
```js
|
||||
ChildObject.prototype = Object.create(ParentObject.prototype);
|
||||
```
|
||||
|
||||
然后,<code>ChildObject</code>将自己的方法链接到它的<code>原型</code>中:
|
||||
|
||||
```js
|
||||
ChildObject.prototype.methodName = function() {...};
|
||||
```
|
||||
|
||||
我们还可以重写继承的方法。以同样的方式——通过使用一个与需要重写的方法相同的方法名,向<code>ChildObject.prototype</code>中添加方法。
|
||||
请看下面的举例:<code>Bird</code>重写了从<code>Animal</code>继承来的<code>eat()</code>方法:
|
||||
|
||||
```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";
|
||||
};
|
||||
```
|
||||
|
||||
如果你有一个实例:<code>let duck = new Bird();</code>,然后你调用了<code>duck.eat()</code>,以下就是 JavaScript 在<code>duck</code>的<code>原型</code>链上寻找方法的过程:
|
||||
|
||||
1. duck => 这里定义了 eat() 方法吗?没有。
|
||||
2. Bird => 这里定义了 eat() 方法吗?=> 是的。执行它并停止往上搜索。
|
||||
3. Animal => 这里也定义了 eat() 方法,但是 JavaScript 在到达这层原型链之前已停止了搜索。
|
||||
4. Object => JavaScript 在到达这层原型链之前也已经停止了搜索。
|
||||
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">覆盖<code>Penguin</code>的<code>fly()</code>方法,使其返回“唉,这是一只不会飞的鸟”。 </section>
|
||||
<section id='instructions'>
|
||||
|
||||
重写<code>Penguin</code>的<code>fly()</code>方法,使其返回 "Alas, this is a flightless bird."
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>penguin.fly()</code>应该返回字符串“唉,这是一只不会飞的鸟”。
|
||||
- text: "<code>penguin.fly()</code>方法应该返回字符串:'Alas, this is a flightless bird.'"
|
||||
testString: assert(penguin.fly() === "Alas, this is a flightless bird.");
|
||||
- text: <code>bird.fly()</code>方法应该返回“我正在飞行!”
|
||||
- text: "The <code>bird.fly()</code>方法应该返回 '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());
|
||||
|
||||
```
|
||||
|
||||
</div>
|
||||
@ -60,7 +102,18 @@ console.log(penguin.fly());
|
||||
## Solution
|
||||
<section id='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());
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -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
|
||||
<section id="description">将<code>prototype</code>手动设置为新对象有一个至关重要的副作用。它擦除了<code>constructor</code>属性!上一个挑战中的代码将为<code>duck</code>打印以下内容: <blockquote>执行console.log(duck.constructor) <br> //打印'undefined' - 哎呀! </blockquote>要解决此问题,每当手动将原型设置为新对象时,请记住定义<code>constructor</code>属性: <blockquote> Bird.prototype = { <br>构造函数:Bird,//定义构造函数属性<br> numLegs:2, <br>吃:function(){ <br> console.log(“nom nom nom”); <br> }, <br> describe:function(){ <br> console.log(“我的名字是”+ this.name); <br> } <br> }; </blockquote></section>
|
||||
<section id='description'>
|
||||
手动给新对象重新设置<code>原型</code>对象,会产生一个重要的副作用:删除了<code>constructor</code>属性!我们来看一下,上一个挑战中<code>duck</code>的<code>constructor</code>属性输出到控制台的结果:
|
||||
|
||||
```js
|
||||
duck.constructor === Bird; // false -- 啊哦
|
||||
duck.constructor === Object; // true, 所有的对象都继承自 Object.prototype
|
||||
duck instanceof Bird; // true, 依然生效
|
||||
```
|
||||
|
||||
为了解决这个问题,凡是手动给新对象重新设置过原型对象的,都别忘记在原型对象中定义一个<code>constructor</code>属性:
|
||||
|
||||
```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);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">在<code>Dog</code> <code>prototype</code>上定义<code>constructor</code>属性。 </section>
|
||||
<section id='instructions'>
|
||||
给<code>Dog 的原型</code>对象定义一个<code>constructor</code>属性。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>Dog.prototype</code>应该设置<code>constructor</code>属性。
|
||||
- text: <code>Dog.prototype</code>应该定义一个<code>constructor</code>属性。
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
</div>
|
||||
@ -57,7 +82,21 @@ Dog.prototype = {
|
||||
## Solution
|
||||
<section id='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);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -2,28 +2,48 @@
|
||||
id: 587d7db1367417b2b2512b86
|
||||
title: Reset an Inherited Constructor Property
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
localeTitle: 重置继承的构造函数属性
|
||||
forumTopicId: 301324
|
||||
localeTitle: 重置一个继承的构造函数属性
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">当一个对象从另一个对象继承它的<code>prototype</code> ,它也继承了<code>supertype</code>的构造函数属性。这是一个例子: <blockquote>函数Bird(){} <br> Bird.prototype = Object.create(Animal.prototype); <br> let duck = new Bird(); <br> duck.constructor // function Animal(){...} </blockquote>但<code>duck</code>和所有<code>Bird</code>实例都应该表明它们是由<code>Bird</code>而不是<code>Animal</code>建造的。为此,您可以手动将<code>Bird's</code>构造函数属性设置为<code>Bird</code>对象: <blockquote> Bird.prototype.constructor = Bird; <br> duck.constructor // function Bird(){...} </blockquote></section>
|
||||
<section id='description'>
|
||||
当一个对象从另一个对象那里继承了其<code>原型</code>,那它也继承了<code>父类</code>的 constructor 属性。
|
||||
请看下面的举例:
|
||||
|
||||
```js
|
||||
function Bird() { }
|
||||
Bird.prototype = Object.create(Animal.prototype);
|
||||
let duck = new Bird();
|
||||
duck.constructor // function Animal(){...}
|
||||
```
|
||||
|
||||
但是<code>duck</code>和其他所有<code>Bird</code>的实例都应该表明它们是由<code>Bird</code>创建的,而不是由<code>Animal</code>创建的。为此,你可以手动把<code>Bird</code>的 constructor 属性设置为<code>Bird</code>对象:
|
||||
|
||||
```js
|
||||
Bird.prototype.constructor = Bird;
|
||||
duck.constructor // function Bird(){...}
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">修复代码,使<code>duck.constructor</code>和<code>beagle.constructor</code>返回各自的构造函数。 </section>
|
||||
<section id='instructions'>
|
||||
修改你的代码,使得<code>duck.constructor</code>和<code>beagle.constructor</code>返回各自的构造函数。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>Bird.prototype</code>应该是<code>Animal</code>一个实例。
|
||||
- text: <code>Bird.prototype</code>应该是<code>Animal</code>的一个实例。
|
||||
testString: assert(Animal.prototype.isPrototypeOf(Bird.prototype));
|
||||
- text: <code>duck.constructor</code>应该返回<code>Bird</code> 。
|
||||
- text: <code>duck.constructor</code>应该返回<code>Bird</code>。
|
||||
testString: assert(duck.constructor === Bird);
|
||||
- text: <code>Dog.prototype</code>应该是<code>Animal</code>一个实例。
|
||||
- text: <code>Dog.prototype</code>应该是<code>Animal</code>的一个实例。
|
||||
testString: assert(Animal.prototype.isPrototypeOf(Dog.prototype));
|
||||
- text: <code>beagle.constructor</code>应该返回<code>Dog</code> 。
|
||||
- text: <code>beagle.constructor</code>应该返回<code>Dog</code>。
|
||||
testString: assert(beagle.constructor === Dog);
|
||||
|
||||
```
|
||||
@ -49,7 +69,6 @@ Dog.prototype = Object.create(Animal.prototype);
|
||||
|
||||
let duck = new Bird();
|
||||
let beagle = new Dog();
|
||||
|
||||
```
|
||||
|
||||
</div>
|
||||
@ -61,7 +80,17 @@ let beagle = new Dog();
|
||||
## Solution
|
||||
<section id='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();
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -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
|
||||
<section id="description">在之前的挑战中,您看到了从<code>supertype</code> (或父级) <code>Animal</code>继承行为的第一步:创建一个新的<code>Animal</code>实例。这个挑战包括下一步:设置<code>subtype</code> (或子)的<code>prototype</code> - 在这种情况下, <code>Bird</code> - 是<code>Animal</code>一个实例。 <blockquote> Bird.prototype = Object.create(Animal.prototype); </blockquote>请记住, <code>prototype</code>就像创建对象的“配方”。在某种程度上, <code>Bird</code>的配方现在包括<code>Animal</code>所有关键“成分”。 <blockquote>让鸭子=新鸟(“唐纳德”); <br> duck.eat(); //打印“nom nom nom” </blockquote> <code>duck</code>继承了<code>Animal</code>的所有属性,包括<code>eat</code>方法。 </section>
|
||||
<section id='description'>
|
||||
在上一个挑战中,我们学习了从<code>超类(或者叫父类) Animal</code>继承其行为的第一个步骤:创建一个<code>Animal</code>的实例。
|
||||
这一节挑战我们将学习第二个步骤:给<code>子类型(或者子类)</code>设置<code>原型</code>。这样一来,<code>Bird</code>就是<code>Animal</code>的一个实例了。
|
||||
|
||||
```js
|
||||
Bird.prototype = Object.create(Animal.prototype);
|
||||
```
|
||||
|
||||
请记住,<code>原型</code>类似于创建对象的“配方”。从某种意义上来说,<code>Bird</code>对象的配方包含了<code>Animal</code>构造函数的所有关键“成分”。
|
||||
|
||||
```js
|
||||
let duck = new Bird("Donald");
|
||||
duck.eat(); // prints "nom nom nom"
|
||||
```
|
||||
|
||||
<code>duck</code>继承了<code>Animal</code>构造函数的所有属性,其中包括了<code>eat</code>方法。
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">修改代码,以便<code>Dog</code>实例继承自<code>Animal</code> 。 </section>
|
||||
<section id='instructions'>
|
||||
修改你的代码,实现一个继承自<code>Animal</code>的<code>Dog</code>构造函数。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>Dog.prototype</code>应该是<code>Animal</code>一个实例。
|
||||
- text: <code>Dog.prototype</code>应该是<code>Animal</code>的一个实例。
|
||||
testString: assert(Animal.prototype.isPrototypeOf(Dog.prototype));
|
||||
|
||||
```
|
||||
@ -46,7 +64,6 @@ function Dog() { }
|
||||
|
||||
let beagle = new Dog();
|
||||
beagle.eat(); // Should print "nom nom nom"
|
||||
|
||||
```
|
||||
|
||||
</div>
|
||||
@ -58,7 +75,22 @@ beagle.eat(); // Should print "nom nom nom"
|
||||
## Solution
|
||||
<section id='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();
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -2,25 +2,58 @@
|
||||
id: 587d7dae367417b2b2512b7b
|
||||
title: Understand Own Properties
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
forumTopicId: 301326
|
||||
localeTitle: 了解自己的属性
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">在以下示例中, <code>Bird</code>构造函数定义了两个属性: <code>name</code>和<code>numLegs</code> : <blockquote> function Bird(name){ <br> this.name = name; <br> this.numLegs = 2; <br> } <br><br>让鸭子=新鸟(“唐纳德”); <br>让金丝雀=新鸟(“特威蒂”); </blockquote> <code>name</code>和<code>numLegs</code>称为<code>own</code>属性,因为它们直接在实例对象上定义。这意味着<code>duck</code>和<code>canary</code>每个都有自己独立的这些属性的副本。事实上, <code>Bird</code>每个实例都有自己的这些属性的副本。下面的代码将所有的<code>own</code>的性质<code>duck</code>到阵列<code>ownProps</code> : <blockquote>让ownProps = []; <br><br> for(let duck in duck){ <br> if(duck.hasOwnProperty(property)){ <br> ownProps.push(属性); <br> } <br> } <br><br>的console.log(ownProps); //打印[“name”,“numLegs”] </blockquote></section>
|
||||
<section id='description'>
|
||||
请看下面的实例,<code>Bird</code>构造函数定义了两个属性:<code>name</code>和<code>numLegs</code>:
|
||||
|
||||
```js
|
||||
function Bird(name) {
|
||||
this.name = name;
|
||||
this.numLegs = 2;
|
||||
}
|
||||
|
||||
let duck = new Bird("Donald");
|
||||
let canary = new Bird("Tweety");
|
||||
```
|
||||
|
||||
<code>name</code>和<code>numLegs</code>被叫做<code>自身</code>属性,因为他们是直接在实例对象上定义的。这就意味着<code>duck</code>和<code>canary</code>这两个对象分别拥有这些属性的独立副本。
|
||||
事实上,<code>Bird</code>的这些实例都将拥有这些属性的独立副本。
|
||||
以下的代码将<code>duck</code>里面所有的<code>自身</code>属性都存到一个叫<code>ownProps</code>的数组里面:
|
||||
|
||||
```js
|
||||
let ownProps = [];
|
||||
|
||||
for (let property in duck) {
|
||||
if(duck.hasOwnProperty(property)) {
|
||||
ownProps.push(property);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(ownProps); // prints [ "name", "numLegs" ]
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">将<code>canary</code> <code>own</code>属性添加到数组<code>ownProps</code> 。 </section>
|
||||
<section id='instructions'>
|
||||
将<code>canary</code>对象里面的<code>自身</code>属性添加到<code>ownProps</code>数组里面。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>ownProps</code>应包含值<code>"numLegs"</code>和<code>"name"</code> 。
|
||||
testString: assert(ownProps.indexOf("name") !== -1 && ownProps.indexOf("numLegs") !== -1);
|
||||
- text: 无需使用内置方法<code>Object.keys()</code>即可解决此挑战。
|
||||
testString: assert(!/\Object.keys/.test(code));
|
||||
- text: "<code>ownProps</code>应该包含<code>'numLegs'</code>和<code>'name'</code>两个属性的值。"
|
||||
testString: assert(ownProps.indexOf('name') !== -1 && ownProps.indexOf('numLegs') !== -1);
|
||||
- text: 在不使用内置方法<code>Object.keys()</code>的情况下完成这个挑战。
|
||||
testString: assert(!/Object(\.keys|\[(['"`])keys\2\])/.test(code));
|
||||
- text: You should solve this challenge without hardcoding the <code>ownProps</code> 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
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
</div>
|
||||
@ -52,7 +87,27 @@ let ownProps = [];
|
||||
## Solution
|
||||
<section id='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);
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -2,15 +2,42 @@
|
||||
id: 587d7daf367417b2b2512b7e
|
||||
title: Understand the Constructor Property
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
localeTitle: 理解构造函数属性
|
||||
forumTopicId: 301327
|
||||
localeTitle: 了解构造函数属性
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">在以前的挑战中创建的对象实例<code>duck</code>和<code>beagle</code>上有一个特殊的<code>constructor</code>属性: <blockquote> let duck = new Bird(); <br>让beagle = new Dog(); <br><br> console.log(duck.constructor === Bird); //打印为true <br> console.log(beagle.constructor === Dog); //打印为true </blockquote>请注意, <code>constructor</code>属性是对创建实例的构造函数的引用。 <code>constructor</code>属性的优点是可以检查此属性以找出它是什么类型的对象。以下是如何使用它的示例: <blockquote> function joinBirdFraternity(candidate){ <br> if(candidate.constructor === Bird){ <br>返回true; <br> } else { <br>返回虚假; <br> } <br> } </blockquote> <strong>注意</strong> <br>由于<code>constructor</code>属性可以被覆盖(将在接下来的两个挑战中讨论),因此通常最好使用<code>instanceof</code>方法来检查对象的类型。 </section>
|
||||
<section id='description'>
|
||||
在上一个挑战中创建的实例对象<code>duck</code>和<code>beagle</code>都有一个特殊的<code>constructor</code>属性:
|
||||
|
||||
```js
|
||||
let duck = new Bird();
|
||||
let beagle = new Dog();
|
||||
|
||||
console.log(duck.constructor === Bird); //prints true
|
||||
console.log(beagle.constructor === Dog); //prints true
|
||||
```
|
||||
|
||||
需要注意到的是这个<code>constructor</code>属性是对创建这个实例的构造函数的一个引用。
|
||||
<code>constructor</code>属性存在的一个优势是,我们可以通过检查这个属性来找出它是一个什么样的对象。下面是一个例子,来看看是怎么使用的:
|
||||
|
||||
```js
|
||||
function joinBirdFraternity(candidate) {
|
||||
if (candidate.constructor === Bird) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<strong>注意:</strong><br>由于<code>constructor</code>属性可以被重写(在下面两节挑战中将会遇到),所以使用<code>instanceof</code>方法来检查对象的类型会更好。
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">编写一个<code>joinDogFraternity</code>函数,该函数接受<code>candidate</code>参数,并且如果候选者是<code>Dog</code> ,则使用<code>constructor</code>属性返回<code>true</code> ,否则返回<code>false</code> 。 </section>
|
||||
<section id='instructions'>
|
||||
写一个<code>joinDogFraternity</code>函数,传入一个<code>candidate</code>参数并使用<code>constructor</code>属性来判断传入的 candidate 是不是<code>Dog</code>创建的对象实例,如果是,就返回<code>true</code>,否则返回<code>false</code>。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
@ -19,9 +46,9 @@ localeTitle: 理解构造函数属性
|
||||
tests:
|
||||
- text: <code>joinDogFraternity</code>应该被定义为一个函数。
|
||||
testString: assert(typeof(joinDogFraternity) === 'function');
|
||||
- text: 如果<code>candidate</code>是<code>Dog</code>一个实例, <code>joinDogFraternity</code>应该返回true。
|
||||
- text: 如果<code>candidate</code>是<code>Dog</code>的一个对象实例,则<code>joinDogFraternity</code>函数应该返回<code>true</code>。
|
||||
testString: assert(joinDogFraternity(new Dog("")) === true);
|
||||
- text: <code>joinDogFraternity</code>应该使用<code>constructor</code>属性。
|
||||
- text: <code>joinDogFraternity</code>中应该用到<code>constructor</code>属性。
|
||||
testString: assert(/\.constructor/.test(code) && !/instanceof/.test(code));
|
||||
|
||||
```
|
||||
@ -54,7 +81,14 @@ function joinDogFraternity(candidate) {
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
|
||||
|
||||
```js
|
||||
// solution required
|
||||
function Dog(name) {
|
||||
this.name = name;
|
||||
}
|
||||
function joinDogFraternity(candidate) {
|
||||
return candidate.constructor === Dog;
|
||||
}
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -2,24 +2,37 @@
|
||||
id: 587d7db2367417b2b2512b8b
|
||||
title: Understand the Immediately Invoked Function Expression (IIFE)
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
localeTitle: 理解立即调用的函数表达式(IIFE)
|
||||
forumTopicId: 301328
|
||||
localeTitle: 了解立即调用函数表达(IIFE)
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description"> JavaScript中的一个常见模式是在声明函数后立即执行: <blockquote> (function(){ <br> console.log(“Chirp,chirp!”); <br> })(); //这是一个立即执行的匿名函数表达式<br> //输出“Chirp,chirp!”立即</blockquote>请注意,该函数没有名称,也没有存储在变量中。函数表达式末尾的两个括号()会立即执行或调用它。此模式称为<code>immediately invoked function expression</code>或<code>IIFE</code> 。 </section>
|
||||
<section id='description'>
|
||||
JavaScript 中的一个常见模式就是,函数在声明后立刻执行:
|
||||
|
||||
```js
|
||||
(function () {
|
||||
console.log("Chirp, chirp!");
|
||||
})(); // 这是一个立即执行的匿名函数表达式
|
||||
// 立即输出 "Chirp, chirp!"
|
||||
```
|
||||
|
||||
请注意,函数没有名称,也不存储在变量中。函数表达式末尾的两个括号()导致它被立即执行或调用。这种模式被叫做<code>自执行函数表达式</code>或者<code>IIFE</code>。
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">重写函数<code>makeNest</code>并删除它的调用,所以它是一个匿名的<code>immediately invoked function expression</code> ( <code>IIFE</code> )。 </section>
|
||||
<section id='instructions'>
|
||||
重写函数<code>makeNest</code>,并删除它的调用,取而代之是一个匿名的<code>自执行函数表达式</code>(<code>IIFE</code>)。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='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();
|
||||
|
||||
```
|
||||
|
||||
</div>
|
||||
@ -49,7 +61,11 @@ makeNest();
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
|
||||
|
||||
```js
|
||||
// solution required
|
||||
(function () {
|
||||
console.log("A cozy nest is ready");
|
||||
})();
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -2,22 +2,52 @@
|
||||
id: 587d7db0367417b2b2512b82
|
||||
title: Understand the Prototype Chain
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
localeTitle: 理解原型链
|
||||
forumTopicId: 301329
|
||||
localeTitle: 了解原型链
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description"> JavaScript中的所有对象(除少数例外)都有<code>prototype</code> 。此外,对象的<code>prototype</code>本身就是一个对象。 <blockquote> function Bird(name){ <br> this.name = name; <br> } <br><br> typeof Bird.prototype; // =>对象</blockquote>因为<code>prototype</code>是一个对象, <code>prototype</code>可以拥有自己的<code>prototype</code> !在这种情况下, <code>Bird.prototype</code>的<code>prototype</code>是<code>Object.prototype</code> : <blockquote> Object.prototype.isPrototypeOf(Bird.prototype); <br> //返回true </blockquote>这有用吗?您可以回想一下之前挑战中的<code>hasOwnProperty</code>方法: <blockquote>让鸭子=新鸟(“唐纳德”); <br> duck.hasOwnProperty( “名称”); // =>是的</blockquote> <code>hasOwnProperty</code>方法在<code>Object.prototype</code>定义,可以通过<code>Bird.prototype</code>访问,然后可以通过<code>duck</code>访问它。这是<code>prototype</code>链的一个例子。在这个<code>prototype</code>链中, <code>Bird</code>是<code>duck</code>的<code>supertype</code> ,而<code>duck</code>是<code>subtype</code> 。 <code>Object</code>是<code>Bird</code>和<code>duck</code>的<code>supertype</code> 。 <code>Object</code>是JavaScript中所有对象的<code>supertype</code> 。因此,任何对象都可以使用<code>hasOwnProperty</code>方法。 </section>
|
||||
<section id='description'>
|
||||
JavaScript 中所有的对象(除了少数例外)都有自己的<code>原型</code>。而且,对象的<code>原型</code>本身也是一个对象。
|
||||
|
||||
```js
|
||||
function Bird(name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
typeof Bird.prototype; // => object
|
||||
```
|
||||
|
||||
正因为<code>原型</code>是一个对象,所以<code>原型</code>对象也有它自己的<code>原型</code>!这样看来的话,<code>Bird.prototype</code>的<code>原型</code>就是<code>Object.prototype</code>:
|
||||
|
||||
```js
|
||||
Object.prototype.isPrototypeOf(Bird.prototype);
|
||||
// 返回 true
|
||||
```
|
||||
|
||||
这有什么作用呢?你可能还记得我们在上一个挑战中学到的<code>hasOwnProperty</code>方法:
|
||||
|
||||
```js
|
||||
let duck = new Bird("Donald");
|
||||
duck.hasOwnProperty("name"); // => true
|
||||
```
|
||||
|
||||
<code>hasOwnProperty</code>是定义在<code>Object.prototype</code>上的一个方法,尽管在<code>Bird.prototype</code>和<code>duck</code>上并没有定义该方法,但是我们依然可以在这两个对象上访问到。这就是一个<code>原型</code>链。
|
||||
在这个<code>原型</code>链中,<code>Bird</code>构造函数是<code>父级</code>,<code>duck</code>是<code>子级</code>。<code>Object</code>则是<code>Bird</code>构造函数和<code>duck</code>实例共同的<code>父级</code>。
|
||||
<code>Object</code>是 JavaScript 中所有对象的<code>父级</code>,也就是原型链的最顶层。因此,所有对象都可以访问<code>hasOwnProperty</code>方法。
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">修改代码以显示正确的原型链。 </section>
|
||||
<section id='instructions'>
|
||||
修改以下代码使其展示出正确的原型链。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 您的代码应该显示<code>Object.prototype</code>是原型<code>Dog.prototype</code> “)
|
||||
- text: 你的代码应该展示<code>Object.prototype</code>是<code>Dog.prototype</code>的原型。
|
||||
testString: assert(/Object\.prototype\.isPrototypeOf/.test(code));
|
||||
|
||||
```
|
||||
@ -52,7 +82,14 @@ Dog.prototype.isPrototypeOf(beagle); // => true
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
|
||||
|
||||
```js
|
||||
// solution required
|
||||
function Dog(name) {
|
||||
this.name = name;
|
||||
}
|
||||
let beagle = new Dog("Snoopy");
|
||||
Dog.prototype.isPrototypeOf(beagle);
|
||||
Object.prototype.isPrototypeOf(Dog.prototype);
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -2,22 +2,42 @@
|
||||
id: 587d7db0367417b2b2512b81
|
||||
title: Understand Where an Object’s Prototype Comes From
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
localeTitle: 了解对象原型的来源
|
||||
forumTopicId: 301330
|
||||
localeTitle: 了解对象的原型来自哪里
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">就像人们从父母那里继承基因一样,一个对象直接从创建它的构造函数继承它的<code>prototype</code> 。例如, <code>Bird</code>构造函数在这里创建<code>duck</code>对象: <blockquote> function Bird(name){ <br> this.name = name; <br> } <br><br>让鸭子=新鸟(“唐纳德”); </blockquote> <code>duck</code>从<code>Bird</code>构造函数继承了它的<code>prototype</code> 。您可以使用<code>isPrototypeOf</code>方法显示此关系: <blockquote> Bird.prototype.isPrototypeOf(鸭); <br> //返回true </blockquote></section>
|
||||
<section id='description'>
|
||||
就像人们从父母那里继承基因一样,对象也可直接从创建它的构造函数那里继承其<code>原型</code>。请看下面的例子:<code>Bird</code>构造函数创建了一个<code>duck</code>对象:
|
||||
|
||||
```js
|
||||
function Bird(name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
let duck = new Bird("Donald");
|
||||
```
|
||||
|
||||
<code>duck</code>从<code>Bird</code>构造函数那里继承了它的<code>原型</code>,你可以使用<code>isPrototypeOf</code>方法来验证他们之间的关系:
|
||||
|
||||
```js
|
||||
Bird.prototype.isPrototypeOf(duck);
|
||||
// 返回 true
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">使用<code>isPrototypeOf</code>检查<code>prototype</code>的<code>beagle</code> 。 </section>
|
||||
<section id='instructions'>
|
||||
使用<code>isPrototypeOf</code>方法验证<code>beagle</code>是否继承了<code>Dog</code>构造函数的<code>原型</code>。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 证明<code>Dog.prototype</code>是<code>beagle</code>的<code>prototype</code>
|
||||
- text: <code>Dog.prototype</code>应该是<code>beagle</code>的<code>原型</code>。
|
||||
testString: assert(/Dog\.prototype\.isPrototypeOf\(beagle\)/.test(code));
|
||||
|
||||
```
|
||||
@ -38,6 +58,7 @@ let beagle = new Dog("Snoopy");
|
||||
|
||||
// Add your code below this line
|
||||
|
||||
|
||||
```
|
||||
|
||||
</div>
|
||||
@ -49,7 +70,13 @@ let beagle = new Dog("Snoopy");
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
|
||||
|
||||
```js
|
||||
// solution required
|
||||
function Dog(name) {
|
||||
this.name = name;
|
||||
}
|
||||
let beagle = new Dog("Snoopy");
|
||||
Dog.prototype.isPrototypeOf(beagle);
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -2,24 +2,56 @@
|
||||
id: 587d7dad367417b2b2512b78
|
||||
title: Use a Constructor to Create Objects
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
forumTopicId: 18233
|
||||
localeTitle: 使用构造函数创建对象
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">这是上一次挑战中的<code>Bird</code>构造函数: <blockquote> function Bird(){ <br> this.name =“阿尔伯特”; <br> this.color =“blue”; <br> this.numLegs = 2; <br> //构造函数中的“this”始终引用正在创建的对象<br> } <br><br>让blueBird = new Bird(); </blockquote>请注意,在调用构造函数时使用<code>new</code>运算符。这告诉JavaScript创建一个名为<code>blueBird</code>的<code>Bird</code>新<code>instance</code> 。如果没有<code>new</code>运营商, <code>this</code>在构造函数中不会指向新创建的对象,给人意想不到的效果。现在, <code>blueBird</code>具有在<code>Bird</code>构造函数中定义的所有属性: <blockquote> blueBird.name; // =>艾伯特<br> blueBird.color; // =>蓝色<br> blueBird.numLegs; // => 2 </blockquote>就像任何其他对象一样,可以访问和修改其属性: <blockquote> blueBird.name ='Elvira'; <br> blueBird.name; // =>埃尔维拉</blockquote></section>
|
||||
<section id='description'>
|
||||
在上一个挑战中,我们用所学到的知识创建了一个<code>Bird</code>构造函数:
|
||||
|
||||
```js
|
||||
function Bird() {
|
||||
this.name = "Albert";
|
||||
this.color = "blue";
|
||||
this.numLegs = 2;
|
||||
// 构造器内的 "this" 一直指向创建的对象
|
||||
}
|
||||
|
||||
let blueBird = new Bird();
|
||||
```
|
||||
|
||||
注意:通过构造函数创建对象的时候要使用<code>new</code>操作符。因为只有这样,JavaScript 才知道要给<code>Bird</code>这个构造函数创建一个新的<code>实例</code>:<code>blueBird</code>。如果不使用<code>new</code>操作符来新建对象,那么构造函数里面的<code>this</code>就无法指向新创建的这个对象实例,从而产生不可预见的错误。
|
||||
现在<code>blueBird</code>这个实例就继承了<code>Bird</code>这个构造函数的所有属性,如下:
|
||||
|
||||
```js
|
||||
blueBird.name; // => Albert
|
||||
blueBird.color; // => blue
|
||||
blueBird.numLegs; // => 2
|
||||
```
|
||||
|
||||
由构造函数创建的实例也和其他对象一样,它的属性可以被访问和修改:
|
||||
|
||||
```js
|
||||
blueBird.name = 'Elvira';
|
||||
blueBird.name; // => Elvira
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">使用上一课中的<code>Dog</code>构造函数创建<code>Dog</code>的新实例,将其分配给变量<code>hound</code> 。 </section>
|
||||
<section id='instructions'>
|
||||
使用上一个课时中的<code>Dog</code>构造函数创建一个<code>Dog</code>的新实例,并把它赋值给变量<code>hound</code>。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 应该使用<code>Dog</code>构造函数创建<code>hound</code> 。
|
||||
- text: <code>hound</code>应该是通过<code>Dog</code>构造函数来创建的。
|
||||
testString: assert(hound instanceof Dog);
|
||||
- text: 您的代码应该使用<code>new</code>运算符来创建<code>Dog</code>的<code>instance</code> 。
|
||||
- text: 你的代码中应该使用<code>new</code>操作符来创建<code>Dog</code>构造函数的新<code>实例</code>。
|
||||
testString: assert(code.match(/new/g));
|
||||
|
||||
```
|
||||
@ -39,6 +71,7 @@ function Dog() {
|
||||
}
|
||||
// Add your code below this line
|
||||
|
||||
|
||||
```
|
||||
|
||||
</div>
|
||||
@ -50,7 +83,14 @@ function Dog() {
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
|
||||
|
||||
```js
|
||||
// solution required
|
||||
function Dog() {
|
||||
this.name = "Rupert";
|
||||
this.color = "brown";
|
||||
this.numLegs = 4;
|
||||
}
|
||||
const hound = new Dog();
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -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
|
||||
<section id="description">如您所见,行为通过继承来共享。但是,有些情况下继承不是最佳解决方案。对于像<code>Bird</code>和<code>Airplane</code>这样的无关对象,继承不起作用。它们都可以飞行,但是<code>Bird</code>不是一种<code>Airplane</code> ,反之亦然。对于不相关的对象,最好使用<code>mixins</code> 。 <code>mixin</code>允许其他对象使用一组函数。 <blockquote>让flyMixin = function(obj){ <br> obj.fly = function(){ <br> console.log(“Flying,wooosh!”); <br> } <br> }; </blockquote> <code>flyMixin</code>接受任何对象并为其提供<code>fly</code>方法。 <blockquote>让bird = { <br>名称:“唐纳德”, <br> numLegs:2 <br> }; <br><br>让plane = { <br>型号:“777”, <br> numPassengers:524 <br> }; <br><br> flyMixin(鸟); <br> flyMixin(平面); </blockquote>这里将<code>bird</code>和<code>plane</code>传递给<code>flyMixin</code> ,然后将<code>fly</code>函数分配给每个对象。现在<code>bird</code>和<code>plane</code>都可以飞行: <blockquote> bird.fly(); //打印“飞行,嗖!” <br> plane.fly(); //打印“飞行,嗖!” </blockquote>注意<code>mixin</code>如何允许相同的<code>fly</code>方法被不相关的对象<code>bird</code>和<code>plane</code>重用。 </section>
|
||||
<section id='description'>
|
||||
正如你所见,行为是可以通过继承来共享的。然而,在有些情况下,继承不是最好的解决方案。继承不适用于不相关的对象,比如<code>Bird</code>和<code>Airplane</code>。虽然它们都可以飞行,但是<code>Bird</code>并不是一种<code>Airplane</code>,反之亦然。
|
||||
对于不相关的对象,更好的方法是使用<code>mixins</code>。<code>mixin</code>允许其他对象使用函数集合。
|
||||
|
||||
```js
|
||||
let flyMixin = function(obj) {
|
||||
obj.fly = function() {
|
||||
console.log("Flying, wooosh!");
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
<code>flyMixin</code>能接受任何对象,并为其提供<code>fly</code>方法。
|
||||
|
||||
```js
|
||||
let bird = {
|
||||
name: "Donald",
|
||||
numLegs: 2
|
||||
};
|
||||
|
||||
let plane = {
|
||||
model: "777",
|
||||
numPassengers: 524
|
||||
};
|
||||
|
||||
flyMixin(bird);
|
||||
flyMixin(plane);
|
||||
```
|
||||
|
||||
这里的<code>flyMixin</code>接收了<code>bird</code>和<code>plane</code>对象,然后将<code>fly</code>方法分配给了每一个对象。现在<code>bird</code>和<code>plane</code>都可以飞行了:
|
||||
|
||||
```js
|
||||
bird.fly(); // prints "Flying, wooosh!"
|
||||
plane.fly(); // prints "Flying, wooosh!"
|
||||
```
|
||||
|
||||
注意观察<code>mixin</code>是如何允许相同的<code>fly</code>方法被不相关的对象<code>bird</code>和<code>plane</code>重用的。
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">创建一个名为<code>glideMixin</code>的<code>mixin</code> ,它定义了一个名为<code>glide</code>的方法。然后使用<code>glideMixin</code>让<code>bird</code>和<code>boat</code>都能够滑行。 </section>
|
||||
<section id='instructions'>
|
||||
创建一个名为<code>glideMixin</code>的<code>mixin</code>,并定义一个<code>glide</code>方法。然后使用<code>glideMixin</code>来给<code>bird</code>和<code>boat</code>赋予滑行(glide)的能力。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 您的代码应该声明一个<code>glideMixin</code>变量,它是一个函数。
|
||||
- text: 你应该声明一个变量名为<code>glideMixin</code>的函数。
|
||||
testString: assert(typeof glideMixin === "function");
|
||||
- text: 你的代码应该使用<code>bird</code>对象上的<code>glideMixin</code>来为它提供<code>glide</code>方法。
|
||||
- text: 你应该在<code>bird</code>上使用<code>glideMixin</code>,以提供<code>glide</code>方法。
|
||||
testString: assert(typeof bird.glide === "function");
|
||||
- text: 你的代码应该使用<code>boat</code>对象上的<code>glideMixin</code>来为它提供<code>glide</code>方法。
|
||||
- text: 你应该在<code>boat</code>上使用<code>glideMixin</code>,以提供<code>glide</code>方法。
|
||||
testString: assert(typeof boat.glide === "function");
|
||||
|
||||
```
|
||||
@ -46,6 +85,11 @@ let boat = {
|
||||
|
||||
// Add your code below this line
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
</div>
|
||||
@ -57,7 +101,23 @@ let boat = {
|
||||
## Solution
|
||||
<section id='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);
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -2,22 +2,67 @@
|
||||
id: 587d7db2367417b2b2512b8c
|
||||
title: Use an IIFE to Create a Module
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
localeTitle: 使用IIFE创建模块
|
||||
forumTopicId: 301332
|
||||
localeTitle: 使用 IIFE 创建一个模块
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description"> <code>immediately invoked function expression</code> ( <code>IIFE</code> )通常用于将相关功能分组到单个对象或<code>module</code> 。例如,早期的挑战定义了两个mixins: <blockquote> function glideMixin(obj){ <br> obj.glide = function(){ <br> console.log(“在水面上滑行”); <br> }; <br> } <br> function flyMixin(obj){ <br> obj.fly = function(){ <br> console.log(“Flying,wooosh!”); <br> }; <br> } </blockquote>我们可以将这些<code>mixins</code>分组到一个模块中,如下所示: <blockquote>让motionModule =(function(){ <br>返回{ <br> glideMixin:function(obj){ <br> obj.glide = function(){ <br> console.log(“在水面上滑行”); <br> }; <br> }, <br> flyMixin:function(obj){ <br> obj.fly = function(){ <br> console.log(“Flying,wooosh!”); <br> }; <br> } <br> } <br> })(); //两个括号使得函数立即被调用</blockquote>请注意,您有一个<code>immediately invoked function expression</code> ( <code>IIFE</code> ),它返回一个对象<code>motionModule</code> 。此返回对象包含作为对象属性的所有<code>mixin</code>行为。 <code>module</code>模式的优点是可以将所有运动行为打包到单个对象中,然后可以由代码的其他部分使用。以下是使用它的示例: <blockquote> motionModule.glideMixin(鸭); <br> duck.glide(); </blockquote></section>
|
||||
<section id='description'>
|
||||
一个<code>自执行函数表达式</code>(<code>IIFE</code>)通常用于将相关功能分组到单个对象或者是<code>模块</code>中。例如,先前的挑战中定义了一个混合类:
|
||||
|
||||
```js
|
||||
function glideMixin(obj) {
|
||||
obj.glide = function() {
|
||||
console.log("Gliding on the water");
|
||||
};
|
||||
}
|
||||
function flyMixin(obj) {
|
||||
obj.fly = function() {
|
||||
console.log("Flying, wooosh!");
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
我们可以将这些<code>mixins</code>分成以下模块:
|
||||
|
||||
```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!");
|
||||
};
|
||||
}
|
||||
}
|
||||
})(); // 末尾的两个括号导致函数被立即调用
|
||||
```
|
||||
|
||||
注意:一个<code>自执行函数表达式</code>(<code>IIFE</code>)返回了一个<code>motionModule</code>对象。返回的这个对象包含了作为对象属性的所有<code>mixin</code>行为。
|
||||
<code>模块</code>模式的优点是,所有的运动行为都可以打包成一个对象,然后由代码的其他部分使用。下面是一个使用它的例子:
|
||||
|
||||
```js
|
||||
motionModule.glideMixin(duck);
|
||||
duck.glide();
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">创建一个名为<code>funModule</code>的<code>module</code>来包装两个<code>mixins</code> <code>isCuteMixin</code>和<code>singMixin</code> 。 <code>funModule</code>应该返回一个对象。 </section>
|
||||
<section id='instructions'>
|
||||
创建一个名为<code>funModule</code>的<code>模块</code>,将这两个<code>mixins</code>:<code>isCuteMixin</code>和<code>singMixin</code>包装起来。<code>funModule</code>应该返回一个对象。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 应该定义<code>funModule</code>并返回一个对象。
|
||||
- text: <code>funModule</code>应该被定义并返回一个对象。
|
||||
testString: assert(typeof funModule === "object");
|
||||
- text: <code>funModule.isCuteMixin</code>应该访问一个函数。
|
||||
testString: assert(typeof funModule.isCuteMixin === "function");
|
||||
@ -44,7 +89,6 @@ let singMixin = function(obj) {
|
||||
console.log("Singing to an awesome tune");
|
||||
};
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
</div>
|
||||
@ -56,7 +100,18 @@ let singMixin = function(obj) {
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
|
||||
|
||||
```js
|
||||
// solution required
|
||||
const funModule = (function () {
|
||||
return {
|
||||
isCuteMixin: obj => {
|
||||
obj.isCute = () => true;
|
||||
},
|
||||
singMixin: obj => {
|
||||
obj.sing = () => console.log("Singing to an awesome tune");
|
||||
}
|
||||
};
|
||||
})();
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -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
|
||||
<section id="description">在之前的挑战中, <code>bird</code>有一个公共财产<code>name</code> 。它被认为是公开的,因为它可以在<code>bird</code>的定义之外进行访问和更改。 <blockquote> bird.name =“达菲”; </blockquote>因此,代码的任何部分都可以轻松地将<code>bird</code>的名称更改为任何值。考虑一下代码库的任何部分都可以轻松更改密码和银行帐户等内容。这可能会导致很多问题。使属性私有的最简单方法是在构造函数中创建一个变量。这会将该变量的范围更改为构造函数,而不是全局可用。这样,只能通过构造函数中的方法访问和更改属性。 <blockquote> function Bird(){ <br>让hatchedEgg = 10; // 私人财产<br><br> this.getHatchedEggCount = function(){//鸟类对象可以使用的公共可用方法<br>返回hatchedEgg; <br> }; <br> } <br>让ducky = new Bird(); <br> ducky.getHatchedEggCount(); //返回10 </blockquote>这里<code>getHachedEggCount</code>是一种特权方法,因为它可以访问私有变量<code>hatchedEgg</code> 。这是可能的,因为<code>hatchedEgg</code>在与<code>getHachedEggCount</code>相同的上下文中<code>getHachedEggCount</code> 。在JavaScript中,函数始终可以访问创建它的上下文。这叫做<code>closure</code> 。 </section>
|
||||
<section id='description'>
|
||||
|
||||
在上一次挑战中,<code>bird</code>有一个公共属性<code>name</code>。公共属性的定义就是:它可以在<code>bird</code>的定义范围之外被访问和更改。
|
||||
|
||||
|
||||
```js
|
||||
bird.name = "Duffy";
|
||||
```
|
||||
|
||||
|
||||
因此,代码的任何地方都可以轻松地将<code>bird</code>的 name 属性更改为任意值。想想密码和银行账户之类的东西,如果代码库的任何部分都可以轻易改变,那么将会引起很多问题。
|
||||
|
||||
使属性私有化最简单的方法就是在构造函数中创建变量。可以将该变量范围限定在构造函数中,而不是全局可用。这样,属性只能由构造函数中的方法访问和更改。
|
||||
|
||||
```js
|
||||
function Bird() {
|
||||
let hatchedEgg = 10; // 私有变量
|
||||
|
||||
/* bird 对象可用的公共方法 */
|
||||
this.getHatchedEggCount = function() {
|
||||
return hatchedEgg;
|
||||
};
|
||||
}
|
||||
let ducky = new Bird();
|
||||
ducky.getHatchedEggCount(); // 返回 10
|
||||
```
|
||||
|
||||
这里的<code>getHachedEggCount</code>是一种特权方法,因为它可以访问私有属性<code>hatchedEgg</code>。这是因为<code>hatchedEgg</code>是在与<code>getHachedEggCount</code>相同的上下文中声明的。在 JavaScript 中,函数总是可以访问创建它的上下文。这就叫做<code>闭包</code>。
|
||||
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">更改<code>Bird</code>函数中声明<code>weight</code>方式,使其成为私有变量。然后,创建一个返回<code>weight</code>值的方法<code>getWeight</code> 。 </section>
|
||||
<section id='instructions'>
|
||||
更改在<code>Bird</code>函数中声明的<code>weight</code>方法,使其成为私有变量。然后,创建一个返回<code>weight</code>值的<code>getWeight</code>方法。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>weight</code>属性应该是私有变量。
|
||||
testString: 'assert(!code.match(/this\.weight/g), "The <code>weight</code> property should be a private variable.");'
|
||||
- text: 你的代码应该在<code>Bird</code>创建一个名为<code>getWeight</code>的方法来返回<code>weight</code> 。
|
||||
testString: 'assert((new Bird()).getWeight() === 15, "Your code should create a method in <code>Bird</code> called <code>getWeight</code> that returns the <code>weight</code>.");'
|
||||
- text: <code>weight</code>属性应该是一个私有变量,值应该是 <code>15</code>。
|
||||
testString: assert(code.match(/(var|let|const)\s+weight\s*\=\s*15\;?/g));
|
||||
- text: 你的代码应该在<code>Bird</code>中创建一个名为<code>getWeight</code>方法,该方法返回<code>weight</code>值。
|
||||
testString: assert((new Bird()).getWeight() === 15, '你的代码应该在<code>Bird</code>中创建一个名为<code>getWeight</code>方法,该方法返回<code>weight</code>值。');
|
||||
- text: Your <code>getWeight</code> function should return the private variable <code>weight</code>.
|
||||
testString: assert(code.match(/((return\s+)|(\(\s*\)\s*\=\>\s*))weight\;?/g));
|
||||
|
||||
```
|
||||
|
||||
@ -49,7 +82,13 @@ function Bird() {
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
|
||||
|
||||
```js
|
||||
// solution required
|
||||
function Bird() {
|
||||
let weight = 15;
|
||||
|
||||
this.getWeight = () => weight;
|
||||
}
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -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
|
||||
<section id="description">最后一个挑战创建了一个具有各种<code>properties</code>的<code>object</code> ,现在您将看到如何访问这些<code>properties</code>的值。这是一个例子: <blockquote>让duck = { <br>名称:“Aflac”, <br> numLegs:2 <br> }; <br>的console.log(duck.name); <br> //这会将“Aflac”打印到控制台</blockquote>点符号用于<code>object</code>名称<code>duck</code> ,后跟<code>property</code> <code>name</code> ,以访问“Aflac”的值。 </section>
|
||||
<section id='description'>
|
||||
在上一个挑战中,我们创建了一个拥有不同<code>属性</code>的<code>对象</code>,现在我们来看看该如何访问这些<code>属性</code>:
|
||||
|
||||
```js
|
||||
let duck = {
|
||||
name: "Aflac",
|
||||
numLegs: 2
|
||||
};
|
||||
console.log(duck.name);
|
||||
// 这段代码会在控制台中输出 "Aflac"
|
||||
```
|
||||
|
||||
我们可以用“点号表示法”来访问对象的属性,只需要在<code>对象</code>名称后面加上<code>.</code>以及<code>属性</code>名即可。比如,<code>duck.name</code>就可以访问到 "Aflac"。
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">将以下<code>dog</code>对象的两个<code>properties</code>打印到控制台。 </section>
|
||||
<section id='instructions'>
|
||||
请在控制台里面输出<code>dog</code>对象中两个<code>属性</code>对应的值。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: 您应该使用<code>console.log</code>来打印<code>dog</code>对象的<code>name</code>属性的值。
|
||||
- text: 你应该使用<code>console.log</code>来将<code>dog</code>对象的<code>name</code>属性值输出到控制台。
|
||||
testString: assert(/console.log\(.*dog\.name.*\)/g.test(code));
|
||||
- text: 您应该使用<code>console.log</code>来打印<code>dog</code>对象的<code>numLegs</code>属性的值。
|
||||
- text: 你应该使用<code>console.log</code>来将<code>dog</code>对象的<code>numLegs</code>属性值输出到控制台。
|
||||
testString: assert(/console.log\(.*dog\.numLegs.*\)/g.test(code));
|
||||
|
||||
```
|
||||
@ -38,6 +53,7 @@ let dog = {
|
||||
};
|
||||
// Add your code below this line
|
||||
|
||||
|
||||
```
|
||||
|
||||
</div>
|
||||
@ -49,7 +65,14 @@ let dog = {
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
|
||||
|
||||
```js
|
||||
// solution required
|
||||
let dog = {
|
||||
name: "Spot",
|
||||
numLegs: 4
|
||||
};
|
||||
console.log(dog.name);
|
||||
console.log(dog.numLegs);
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -2,15 +2,62 @@
|
||||
id: 587d7db0367417b2b2512b83
|
||||
title: Use Inheritance So You Don't Repeat Yourself
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
localeTitle: 使用继承,所以你不要重复自己
|
||||
forumTopicId: 301334
|
||||
localeTitle: 使用继承避免重复
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">编程中有一个原则叫做“ <code>Don't Repeat Yourself (DRY)</code> 。重复代码是一个问题的原因是因为任何更改都需要在多个位置修复代码。这通常意味着为程序员提供更多工作,并且有更多错误空间。请注意,在下面的示例中, <code>describe</code>方法由<code>Bird</code>和<code>Dog</code>共享: <blockquote> Bird.prototype = { <br>构造函数:Bird, <br> describe:function(){ <br> console.log(“我的名字是”+ this.name); <br> } <br> }; <br><br> Dog.prototype = { <br>构造函数:狗, <br> describe:function(){ <br> console.log(“我的名字是”+ this.name); <br> } <br> }; </blockquote> <code>describe</code>方法在两个地方重复。可以通过创建名为<code>Animal</code>的<code>supertype</code> (或父级)来编辑代码以遵循<code>DRY</code>原则: <blockquote> function Animal(){}; <br><br> Animal.prototype = { <br>构造函数:Animal, <br> describe:function(){ <br> console.log(“我的名字是”+ this.name); <br> } <br> }; </blockquote>由于<code>Animal</code>包含<code>describe</code>方法,您可以从<code>Bird</code>和<code>Dog</code>删除它: <blockquote> Bird.prototype = { <br>构造函数:Bird <br> }; <br><br> Dog.prototype = { <br>构造函数:狗<br> }; </blockquote></section>
|
||||
<section id='description'>
|
||||
有一条原则叫做:<code>Don't Repeat Yourself</code>,常以缩写形式<code>DRY</code>出现,意思是“不要自己重复”。编写重复代码会产生的问题是:任何改变都需要去多个地方修复所有重复的代码。这通常意味着我们需要做更多的工作,会产生更高的出错率。
|
||||
请观察下面的示例,<code>Bird</code>和<code>Dog</code>共享<code>describe</code>方法:
|
||||
|
||||
```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);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
我们可以看到<code>describe</code>方法在两个地方重复定义了。根据以上所说的<code>DRY</code>原则,我们可以通过创建一个<code>Animal 超类(或者父类)</code>来重写这段代码:
|
||||
|
||||
```js
|
||||
function Animal() { };
|
||||
|
||||
Animal.prototype = {
|
||||
constructor: Animal,
|
||||
describe: function() {
|
||||
console.log("My name is " + this.name);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
<code>Animal</code>构造函数中定义了<code>describe</code>方法,可将<code>Bird</code>和<code>Dog</code>这两个构造函数的方法删除掉:
|
||||
|
||||
```js
|
||||
Bird.prototype = {
|
||||
constructor: Bird
|
||||
};
|
||||
|
||||
Dog.prototype = {
|
||||
constructor: Dog
|
||||
};
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions"> <code>Cat</code>和<code>Bear</code>都重复<code>eat</code> 。通过将<code>eat</code>方法移动到<code>Animal</code> <code>supertype</code>以<code>DRY</code>的精神编辑代码。 </section>
|
||||
<section id='instructions'>
|
||||
<code>Cat</code>和<code>Bear</code>重复定义了<code>eat</code>方法。本着<code>DRY</code>的原则,通过将<code>eat</code>方法移动到<code>Animal 超类</code>中来重写你的代码。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
@ -62,7 +109,6 @@ Animal.prototype = {
|
||||
constructor: Animal,
|
||||
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
</div>
|
||||
@ -74,7 +120,32 @@ Animal.prototype = {
|
||||
## Solution
|
||||
<section id='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");
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -2,26 +2,47 @@
|
||||
id: 587d7dae367417b2b2512b7c
|
||||
title: Use Prototype Properties to Reduce Duplicate Code
|
||||
challengeType: 1
|
||||
videoUrl: ''
|
||||
forumTopicId: 301336
|
||||
localeTitle: 使用原型属性来减少重复代码
|
||||
---
|
||||
|
||||
## Description
|
||||
<section id="description">由于<code>numLegs</code>对于<code>Bird</code>所有实例可能具有相同的值, <code>numLegs</code>在每个<code>Bird</code>实例中基本上都有一个重复的变量<code>numLegs</code> 。当只有两个实例时,这可能不是问题,但想象一下,如果有数百万个实例。这将是许多重复的变量。更好的方法是使用<code>Bird's</code> <code>prototype</code> 。 <code>prototype</code>是一个在<code>Bird</code>所有实例之间共享的对象。以下是如何将<code>numLegs</code>添加到<code>Bird prototype</code> : <blockquote> Bird.prototype.numLegs = 2; </blockquote>现在<code>Bird</code>所有实例都具有<code>numLegs</code>属性。 <blockquote>的console.log(duck.numLegs); //打印2 <br>的console.log(canary.numLegs); //打印2 </blockquote>由于所有实例都自动拥有<code>prototype</code>上的属性,因此将<code>prototype</code>视为创建对象的“配方”。请注意, <code>duck</code>和<code>canary</code>的<code>prototype</code>是<code>Bird</code>构造函数的一部分,如<code>Bird.prototype</code> 。 JavaScript中几乎每个对象都有一个<code>prototype</code>属性,它是创建它的构造函数的一部分。 </section>
|
||||
<section id='description'>
|
||||
所有<code>Bird</code>实例可能会有相同的<code>numLegs</code>值,所以在每一个<code>Bird</code>的实例中本质上都有一个重复的变量<code>numLegs</code>。
|
||||
当只有两个实例时可能并不是什么问题,但想象一下如果有数百万个实例,这将会产生许许多多重复的变量。
|
||||
这里有一个更好的方法可以解决上述问题,那就是使用<code>Bird</code>的<code>原型</code>。<code>原型</code>是一个可以在所有<code>Bird</code>实例之间共享的对象。以下是一个在<code>Bird prototype</code>中添加<code>numLegs</code>属性的示例:
|
||||
|
||||
```js
|
||||
Bird.prototype.numLegs = 2;
|
||||
```
|
||||
|
||||
现在所有的<code>Bird</code>实例都拥有了共同的<code>numLegs</code>属性值。
|
||||
|
||||
```js
|
||||
console.log(duck.numLegs); // prints 2
|
||||
console.log(canary.numLegs); // prints 2
|
||||
```
|
||||
|
||||
由于所有的实例都可以继承<code>原型</code>上的属性,所以可以把<code>原型</code>看作是创建对象的 "配方"。
|
||||
请注意:<code>duck</code>和<code>canary</code>的<code>原型</code>属于<code>Bird</code>的构造函数,即 Bird 的原型 <code>Bird.prototype</code>。JavaScript 中几乎所有的对象都有一个<code>原型</code>属性,这个属性是属于它所在的构造函数。
|
||||
</section>
|
||||
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">将<code>numLegs</code>属性添加到<code>Dog</code>的<code>prototype</code>中</section>
|
||||
<section id='instructions'>
|
||||
给<code>Dog</code>的<code>原型</code>添加一个<code>numLegs</code>属性。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>beagle</code>应该有一个<code>numLegs</code>财产。
|
||||
- text: <code>beagle</code>应该有一个<code>numLegs</code>属性。
|
||||
testString: assert(beagle.numLegs !== undefined);
|
||||
- text: <code>beagle.numLegs</code>应该是一个数字。
|
||||
testString: assert(typeof(beagle.numLegs) === 'number' );
|
||||
- text: <code>numLegs</code>应该是<code>prototype</code>属性而不是<code>own</code>属性。
|
||||
- text: <code>numLegs</code>应该是一个<code>原型</code>属性而不是一个<code>自身</code>属性。
|
||||
testString: assert(beagle.hasOwnProperty('numLegs') === false);
|
||||
|
||||
```
|
||||
@ -42,7 +63,6 @@ function Dog(name) {
|
||||
|
||||
// Add your code above this line
|
||||
let beagle = new Dog("Snoopy");
|
||||
|
||||
```
|
||||
|
||||
</div>
|
||||
@ -54,7 +74,13 @@ let beagle = new Dog("Snoopy");
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
|
||||
|
||||
```js
|
||||
// solution required
|
||||
function Dog (name) {
|
||||
this.name = name;
|
||||
}
|
||||
Dog.prototype.numLegs = 4;
|
||||
let beagle = new Dog("Snoopy");
|
||||
```
|
||||
|
||||
</section>
|
||||
|
@ -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
|
||||
<section id="description">无论何时构造函数创建一个新对象,该对象都被称为其构造函数的一个<code>instance</code> 。 JavaScript提供了一种使用<code>instanceof</code>运算符验证这一点的便捷方法。 <code>instanceof</code>允许您将对象与构造函数进行比较,根据是否使用构造函数创建该对象,返回<code>true</code>或<code>false</code> 。这是一个例子: <blockquote>让Bird = function(名称,颜色){ <br> this.name = name; <br> this.color = color; <br> this.numLegs = 2; <br> } <br><br>让乌鸦=新鸟(“亚历克西斯”,“黑色”); <br><br>鸟的鸟; // =>是的</blockquote>如果在不使用构造函数的<code>instanceof</code>创建对象, <code>instanceof</code>将验证它不是该构造函数的实例: <blockquote>让金丝雀= { <br>名称:“Mildred”, <br>颜色:“黄色”, <br> numLegs:2 <br> }; <br><br>鸟类的金丝雀; // => false </blockquote></section>
|
||||
<section id='description'>
|
||||
凡是通过构造函数创建出的新对象,都叫做这个构造函数的<code>实例</code>。JavaScript 提供了一种很简便的方法来验证这个事实,那就是通过<code>instanceof</code>操作符。<code>instanceof</code>允许你将对象与构造函数之间进行比较,根据对象是否由这个构造函数创建的返回<code>true</code>或者<code>false</code>。以下是一个示例:
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
如果一个对象不是使用构造函数创建的,那么<code>instanceof</code>将会验证这个对象不是构造函数的实例:
|
||||
|
||||
```js
|
||||
let canary = {
|
||||
name: "Mildred",
|
||||
color: "Yellow",
|
||||
numLegs: 2
|
||||
};
|
||||
|
||||
canary instanceof Bird; // => false
|
||||
```
|
||||
|
||||
</section>
|
||||
|
||||
## Instructions
|
||||
<section id="instructions">创建<code>House</code>构造函数的新实例,将其<code>myHouse</code>并传递多个卧室。然后,使用<code>instanceof</code>验证它是<code>House</code>的实例。 </section>
|
||||
<section id='instructions'>
|
||||
给<code>House</code>构造函数创建一个新实例,取名为<code>myHouse</code>并且传递一个数字给<code>bedrooms</code>参数。然后使用<code>instanceof</code>操作符验证这个对象是否为<code>House</code>的实例。
|
||||
</section>
|
||||
|
||||
## Tests
|
||||
<section id='tests'>
|
||||
|
||||
```yml
|
||||
tests:
|
||||
- text: <code>myHouse</code>应该将<code>numBedrooms</code>属性设置为数字。
|
||||
- text: <code>myHouse</code>应该有一个<code>numBedrooms</code>属性被赋值为一个数字。
|
||||
testString: assert(typeof myHouse.numBedrooms === 'number');
|
||||
- text: 请务必使用<code>instanceof</code>运算符验证<code>myHouse</code>是<code>House</code>的<code>instanceof</code> 。
|
||||
- text: 请务必使用<code>instanceof</code>操作符验证<code>myHouse</code>这个对象是<code>House</code>构造函数的一个实例。
|
||||
testString: assert(/myHouse\s*instanceof\s*House/.test(code));
|
||||
|
||||
```
|
||||
@ -40,6 +69,8 @@ function House(numBedrooms) {
|
||||
|
||||
// Add your code below this line
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
</div>
|
||||
@ -51,7 +82,13 @@ function House(numBedrooms) {
|
||||
## Solution
|
||||
<section id='solution'>
|
||||
|
||||
|
||||
```js
|
||||
// solution required
|
||||
function House(numBedrooms) {
|
||||
this.numBedrooms = numBedrooms;
|
||||
}
|
||||
const myHouse = new House(4);
|
||||
console.log(myHouse instanceof House);
|
||||
```
|
||||
|
||||
</section>
|
||||
|
Reference in New Issue
Block a user