Skip to content

Commit

Permalink
1 js/04 object basics/06 constructor new (#124)
Browse files Browse the repository at this point in the history
* Update article.md

* Update article.md

* Update task.md

* Update solution.md

* Update task.md

* Update task.md

* Update solution.md

* Update task.md

* Update task.md

* Update task.md

* Update article.md

感谢校对

* Update task.md

* Update article.md

* Update task.md

* Update task.md

* Update article.md
  • Loading branch information
sunhaokk authored and leviding committed Jul 13, 2018
1 parent c8b28bb commit 78676fa
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 94 deletions.
@@ -1,8 +1,8 @@
Yes, it's possible.
是的,这是可以的。

If a function returns an object then `new` returns it instead of `this`.
如果一个函数返回一个对象,那么 `new` 返回那个对象而不是 `this`

So thay can, for instance, return the same externally defined object `obj`:
所以他们可以,例如,返回相同的外部定义的对象 `obj`

```js run no-beautify
let obj = {};
Expand Down
Expand Up @@ -4,7 +4,7 @@ importance: 2

# Two functions – one object

Is it possible to create functions `A` and `B` such as `new A()==new B()`?
是否可以创建函数 `A` `B`,如 `new A()==new B()`

```js no-beautify
function A() { ... }
Expand All @@ -16,4 +16,4 @@ let b = new B;
alert( a == b ); // true
```

If it is, then provide an example of their code.
如果可以,请提供他们的代码示例。
Expand Up @@ -2,15 +2,15 @@ importance: 5

---

# Create new Calculator
# 创建 new Calculator

Create a constructor function `Calculator` that creates objects with 3 methods:
创建一个构造函数使用3种方法创建对象的 `Calculator`

- `read()` asks for two values using `prompt` and remembers them in object properties.
- `sum()` returns the sum of these properties.
- `mul()` returns the multiplication product of these properties.
- `read()` 使用 `prompt` 请求两个值并在对象属性中记住它们。
- `sum()` 返回这些属性的总和。
- `mul()` 返回这些属性的乘积。

For instance:
例如:

```js
let calculator = new Calculator();
Expand Down
22 changes: 11 additions & 11 deletions 1-js/04-object-basics/06-constructor-new/3-accumulator/task.md
Expand Up @@ -2,24 +2,24 @@ importance: 5

---

# Create new Accumulator
# 创建 new Accumulator

Create a constructor function `Accumulator(startingValue)`.
创建一个构造函数 `Accumulator(startingValue)`

Object that it creates should:
它创建的对象应该:

- Store the "current value" in the property `value`. The starting value is set to the argument of the constructor `startingValue`.
- The `read()` method should use `prompt` to read a new number and add it to `value`.
- 将“当前 value”存储在属性 `value` 中。起始值被设置为构造函数 `startingValue` 的参数。
- `read()` 方法应该使用 `prompt` 来读取一个新的数字并将其添加到 `value` 中。

In other words, the `value` property is the sum of all user-entered values with the initial value `startingValue`.
换句话说,`value` 属性是所有用户输入值与初始值 `startingValue` 的总和。

Here's the demo of the code:
这里是代码的演示:

```js
let accumulator = new Accumulator(1); // initial value 1
accumulator.read(); // adds the user-entered value
accumulator.read(); // adds the user-entered value
alert(accumulator.value); // shows the sum of these values
let accumulator = new Accumulator(1); // 初始 value 1
accumulator.read(); // 添加用户输入 value
accumulator.read(); // 添加用户输入 value
alert(accumulator.value); // 显示这些值的总和
```

[demo]
@@ -1,3 +1,3 @@

- Please note how methods are stored. They are simply added to the internal object.
- All tests and numeric conversions are done in the `calculate` method. In future it may be extended to support more complex expressions.
- 请注意如何存储方法。它们只是添加到内部对象。
- 所有测试和数值转换都在 `calculate` 方法中完成。将来它可能会扩展到支持更复杂的表达式。
Expand Up @@ -2,24 +2,24 @@ importance: 5

---

# Create an extendable calculator
# 创建一个可扩展的 calculator

Create a constructor function `Calculator` that creates "extendable" calculator objects.
创建一个构造函数 `Calculator` 创建可扩展的 calculator 对象。

The task consists of two parts.
该任务由两部分组成。

1. First, implement the method `calculate(str)` that takes a string like `"1 + 2"` in the format "NUMBER operator NUMBER" (space-delimited) and returns the result. Should understand plus `+` and minus `-`.
1. 首先,实现 `calculate(str)` 方法,“NUMBER operator NUMBER”(空格分隔),其格式为“1 + 2”,并返回结果。所以要实现加`+`和减`-`

Usage example:
用法示例:

```js
let calc = new Calculator;

alert( calc.calculate("3 + 7") ); // 10
```
2. Then add the method `addOperator(name, func)` that teaches the calculator a new operation. It takes the operator `name` and the two-argument function `func(a,b)` that implements it.
2. 然后添加 calculate 新操作的方法 `addOperator(name, func)`。它需要运算符 `name` 和实现它的双参数函数 `func(a,b)`

For instance, let's add the multiplication `*`, division `/` and power `**`:
例如,我们添加乘法`*`,除法`/`和求幂`**`

```js
let powerCalc = new Calculator;
Expand All @@ -31,6 +31,6 @@ The task consists of two parts.
alert( result ); // 8
```

- No brackets or complex expressions in this task.
- The numbers and the operator are delimited with exactly one space.
- There may be error handling if you'd like to add it.
- 此任务中没有括号或复杂的表达式。
- 数字和运算符用一个空格分隔。
- 添加错误处理。
120 changes: 60 additions & 60 deletions 1-js/04-object-basics/06-constructor-new/article.md
@@ -1,17 +1,17 @@
# Constructor, operator "new"
# 构造函数和操作符 "new"

The regular `{...}` syntax allows to create one object. But often we need to create many similar objects, like multiple users or menu items and so on.
常规的 `{...}` 语法允许创建一个对象。但是我们经常需要创建许多类似的对象,例如多个用户或菜单项等等。

That can be done using constructor functions and the `"new"` operator.
这可以使用构造函数和 `"new"` 操作符。

## Constructor function
## 构造函数

Constructor functions technically are regular functions. There are two conventions though:
构造函数在技术上是常规函数。不过有两个约定:

1. They are named with capital letter first.
2. They should be executed only with `"new"` operator.
1. 他们首先用大写字母命名。
2. 它们只能用 `"new"` 操作符来执行。

For instance:
例如:

```js run
function User(name) {
Expand All @@ -27,31 +27,31 @@ alert(user.name); // Jack
alert(user.isAdmin); // false
```

When a function is executed as `new User(...)`, it does the following steps:
当一个函数作为 `new User(...)`执行时,它执行以下步骤:

1. A new empty object is created and assigned to `this`.
2. The function body executes. Usually it modifies `this`, adds new properties to it.
3. The value of `this` is returned.
1. 一个新的空对象被创建并分配给 `this`
2. 函数体执行。通常它会修改 `this`,为其添加新的属性。
3. 返回 `this` 的值。

In other words, `new User(...)` does something like:
换句话说,`new User(...)` 做类似的事情:

```js
function User(name) {
*!*
// this = {}; (implicitly)
// this = {};(隐式创建)
*/!*

// add properties to this
// 添加属性到 this
this.name = name;
this.isAdmin = false;

*!*
// return this; (implicitly)
// return this;(隐式返回)
*/!*
}
```

So the result of `new User("Jack")` is the same object as:
所以 `new User("Jack")` 的结果是相同的对象:

```js
let user = {
Expand All @@ -60,96 +60,96 @@ let user = {
};
```

Now if we want to create other users, we can call `new User("Ann")`, `new User("Alice")` and so on. Much shorter than using literals every time, and also easy to read.
现在,如果我们想创建其他用户,我们可以调用 `new User("Ann")``new User("Alice")` 等等。比每次使用字面量创建要短得多,而且易于阅读。

That's the main purpose of constructors -- to implement reusable object creation code.
这是构造函数的主要目的 — 实现可重用的对象创建代码

Let's note once again -- technically, any function can be used as a constructor. That is: any function can be run with `new`, and it will execute the algorithm above. The "capital letter first" is a common agreement, to make it clear that a function is to be run with `new`.
让我们再次注意 — 从技术上讲,任何函数都可以用作构造函数。即:任何函数都可以运行 `new`,它会执行上面的算法。 “首字母大写”是一个共同的约定,以明确表示一个函数将被使用 `new` 运行。

````smart header="new function() { ... }"
If we have many lines of code all about creation of a single complex object, we can wrap them in constructor function, like this:
如果我们有许多关于创建单个复杂对象的代码行,我们可以将它们封装在构造函数中,如下所示:
```js
let user = new function() {
this.name = "John";
this.isAdmin = false;
// ...other code for user creation
// maybe complex logic and statements
// local variables etc
// ...用户创建的其他代码
// 也许是复杂的逻辑和陈述
// 局部变量等
};
```
The constructor can't be called again, because it is not saved anywhere, just created and called. So this trick aims to encapsulate the code that constructs the single object, without future reuse.
构造函数不能被再次调用,因为它不保存在任何地方,只是被创建和调用。所以这个技巧的目的是封装构建单个对象的代码,而不是将来重用。
````

## Dual-syntax constructors: new.target
## 双语法构造函数:new.target

Inside a function, we can check whether it was called with `new` or without it, using a special `new.target` property.
在一个函数内部,我们可以使用 `new.target` 属性来检查它是用 `new` 还是不用它来调用。

It is empty for regular calls and equals the function if called with `new`:
常规调用为空,如果通过 `new` 调用,则等于函数:

```js run
function User() {
alert(new.target);
}

// without new:
// 不带 new
User(); // undefined

// with new:
// new
new User(); // function User { ... }
```

That can be used to allow both `new` and regular syntax to work the same:
这可以使 `new` 和常规语法的工作原理相同:

```js run
function User(name) {
if (!new.target) { // if you run me without new
return new User(name); // ...I will add new for you
if (!new.target) { // 如果你没有运行 new
return new User(name); // ...会为你添加 new
}

this.name = name;
}

let john = User("John"); // redirects call to new User
let john = User("John"); // 重新调用 new User
alert(john.name); // John
```

This approach is sometimes used in libraries to make the syntax more flexible. Probably not a good thing to use everywhere though, because omitting `new` makes it a bit less obvious what's going on. With `new` we all know that the new object is being created, that's a good thing.
这种方法有时用在库中以使语法更加灵活。但因为省略 `new` 使得它不易阅读,这可不是一件好事。 而通过 `new` 我们可以都知道这个新对象正在创建。

## Return from constructors
## 构造函数 Return

Usually, constructors do not have a `return` statement. Their task is to write all necessary stuff into `this`, and it automatically becomes the result.
通常,构造函数没有 `return` 语句。他们的任务是将所有必要的东西写入 `this`,并自动转换。

But if there is a `return` statement, then the rule is simple:
但是,如果有 `return` 语句,那么规则很简单:

- If `return` is called with object, then it is returned instead of `this`.
- If `return` is called with a primitive, it's ignored.
- 如果 `return` 对象,则返回它,而不是 `this`
- 如果 `return` 一个原函数,则忽略。

In other words, `return` with an object returns that object, in all other cases `this` is returned.
换一种说法,带有对象的 `return` 返回该对象,在所有其他情况下返回 `this`

For instance, here `return` overrides `this` by returning an object:
例如,这里 `return` 通过返回一个对象覆盖 `this`

```js run
function BigUser() {

this.name = "John";

return { name: "Godzilla" }; // <-- returns an object
return { name: "Godzilla" }; // <-- returns 一个 object
}

alert( new BigUser().name ); // Godzilla, got that object ^^
alert( new BigUser().name ); // 哇哦,得到了对象,name 属性值为 Godzilla ^^
```

And here's an example with an empty `return` (or we could place a primitive after it, doesn't matter):
这里有一个 `return` 空的例子(或者我们可以在它之后放置一个原函数):

```js run
function SmallUser() {

this.name = "John";

return; // finishes the execution, returns this
return; // 完成执行,returns this

// ...

Expand All @@ -158,27 +158,27 @@ function SmallUser() {
alert( new SmallUser().name ); // John
```

Usually constructors don't have a `return` statement. Here we mention the special behavior with returning objects mainly for the sake of completeness.
通常构造函数没有 `return` 语句。这里我们主要为了完整性而提及返回对象的特殊行为。

````smart header="Omitting parentheses"
By the way, we can omit parentheses after `new`, if it has no arguments:
顺便说一下,如果没有参数我们 `new` 可以省略括号:
```js
let user = new User; // <-- no parentheses
// same as
let user = new User();
```
Omitting parentheses here is not considered a "good style", but the syntax is permitted by specification.
这里省略括号不被认为是一种“好风格”,但是规范允许使用该语法。
````

## Methods in constructor
## 构造函数中的方法

Using constructor functions to create objects gives a great deal of flexibility. The constructor function may have parameters that define how to construct the object, and what to put in it.
使用构造函数来创建对象会带来很大的灵活性。通过构造函数的参数传递定义构造对象。

Of course, we can add to `this` not only properties, but methods as well.
当然,我们不仅可以将属性添加到 this 中,而且还可以添加方法。

For instance, `new User(name)` below creates an object with the given `name` and the method `sayHi`:
例如,`new User(name)` 下面用给定的 `name` 和方法 `sayHi` 创建一个对象:

```js run
function User(name) {
Expand All @@ -203,17 +203,17 @@ john = {
*/
```

## Summary
## 总结

- Constructor functions or, briefly, constructors, are regular functions, but there's a common agreement to name them with capital letter first.
- Constructor functions should only be called using `new`. Such a call implies a creation of empty `this` at the start and returning the populated one at the end.
- 构造函数或简言之,就是常规函数,但构造函数有个共同的约定,命名它们首字母要大写。
- 构造函数只能使用 `new` 来调用。这样的调用意味着在开始时创建空的 `this`,并在最后返回填充的对象。

We can use constructor functions to make multiple similar objects.
我们可以使用构造函数来创建多个类似的对象。

JavaScript provides constructor functions for many built-in language objects: like `Date` for dates, `Set` for sets and others that we plan to study.
JavaScript 为许多内置的对象提供了构造函数:比如日期 Date,设置集合 Set 以及其他我们计划学习的内容。

```smart header="Objects, we'll be back!"
In this chapter we only cover the basics about objects and constructors. They are essential for learning more about data types and functions in the next chapters.
在本章中,我们只介绍关于对象和构造函数的基础知识。它们对于在下一章中更多地了解数据类型和函数非常重要。
After we learn that, in the chapter <info:object-oriented-programming> we return to objects and cover them in-depth, including inheritance and classes.
在我们了解了这一章之后 <info:object-oriented-programming> 我们返回到对象并深入其中,包括继承和类。
```

0 comments on commit 78676fa

Please sign in to comment.