New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
1 js/04 object basics/06 constructor new #124
Changes from 11 commits
19bed5e
60a6fbe
f378f24
93a3caa
6fd7d1d
24176e3
cc2ec59
cfa370b
a60cdb7
47602e1
22d601f
11c1315
b9818a1
cbbcc53
bfd9027
9752253
a9e7c67
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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` 方法中完成。将来它可能会扩展到支持更复杂的表达式。 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) { | ||
|
@@ -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 = { | ||
|
@@ -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`, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 『以明确表示一个函数将被运行 |
||
|
||
````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 ); // 哇哦,得到了 object ^^ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 『哇哦,得到了 object ^^』=>『哇哦,得到了对象,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 | ||
|
||
// ... | ||
|
||
|
@@ -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 添加到属性中,而且还添加到方法中。 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 『我们不仅可以将 this 添加到属性中,而且还添加到方法中。』=>『我们不仅可以将属性添加到 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) { | ||
|
@@ -203,17 +203,18 @@ 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. | ||
- 构造函数或简言之,就是常规函数,但构造函数有个共同的约定,命名它们首字母要大写。 | ||
|
||
We can use constructor functions to make multiple similar objects. | ||
- 构造函数只能使用 `new` 来调用。这样的调用意味着在开始时创建空的 `this`,并在最后返回填充的。 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 『填充的』=>『填充的对象』 |
||
|
||
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. | ||
在本章中,我们只介绍关于对象和构造函数的基础知识。它们对于在下一章中更多地了解数据类型和功能非常重要。 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 『数据类型和功能』=>『数据类型和函数』 |
||
|
||
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> 我们返回到对象并深入其中,包括继承和类。 | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
『比每次使用文字要短得多』=>『比每次使用字面量创建要短得多』