The regular {...}
syntax allows creation of an object. But we often need to create many similar objects, such as multiple users or menu items, etc.
This can be achieved using constructors and the "new"
operator.
Constructor is technically a regular function. But there are two conventions:
"new"
operator. For example:
function User(name) { this.name = name; this.isAdmin = false; }let user = new User("Jack"); alert(user.name); // Jackalert(user.isAdmin); // false复制代码
When a function is executed using the new
operator, it follows the following steps:
this
. this
, adding new properties to it. this
. In other words, new User(...)
does something like:
function User(name) { // this = {};(隐式创建) // 添加属性到 this this.name = name; this.isAdmin = false; // return this;(隐式返回)}复制代码
So new User("Jack" )
results in the same object:
let user = { name: "Jack", isAdmin: false};复制代码
Now, if we want to create other users, we can call new User("Ann")
,new User( "Alice")
etc. Much shorter and easier to read than using literal creation every time.
This is the main purpose of the constructor - to implement reusable object creation code.
Let us stress it again - technically any function can be used as a constructor. That is: any function can be run through new
, which will execute the above algorithm. "Capitalization" is a common convention to make it clear that a function will be run using new
.
If we have many lines of code that create a single complex object, we can encapsulate them in a constructor, like this:
let user = new function() { this.name = "John"; this.isAdmin = false; // ……用于用户创建的其他代码 // 也许是复杂的逻辑和语句 // 局部变量等};复制代码
The constructor cannot be called again because it is not saved anywhere, just created and called. Therefore, this tip is intended to encapsulate the code that builds a single object without needing to reuse it in the future.
Advanced content:
The syntax content involved in this section is rarely used unless You want to understand everything, otherwise you can just skip the syntax.
Inside a function, we can use the new.target
property to check whether it has been called using new
.
For regular calls, it is empty. For calls using new
, it is equal to the function:
function User() { alert(new.target); }// 不带 "new":User(); // undefined// 带 "new":new User(); // function User { ... }复制代码
It can be used inside the function to determine the function Is it the "constructor mode" that is called through new
, or the "regular mode" that is not called through new
.
We can also make the new
call do the same job as a regular call, like this:
function User(name) { if (!new.target) { // 如果你没有通过 new 运行我 return new User(name); // ……我会给你添加 new } this.name = name; }let john = User("John"); // 将调用重定向到新用户alert(john.name); // John复制代码
This approach is sometimes used in libraries to make the syntax more flexible . In this way, when people call the function, the program will work regardless of whether new
is used.
It's not a good thing to use it everywhere, though, because omitting new
makes it difficult to observe what's going on in the code. And through new
we can all know that this creates a new object.
Normally, a constructor does not have a return
statement. Their job is to write all the necessary stuff into this
and automatically convert it into the result.
However, if there is a return
statement, then the rule is simple:
return
returns an object, Then return this object instead of this
. return
returns a primitive type, it is ignored. In other words, return
with an object returns that object, in all other cases this
is returned.
For example, here return
overrides this
by returning an object:
function BigUser() { this.name = "John"; return { name: "Godzilla" }; // <-- 返回这个对象} alert( new BigUser().name ); // Godzilla,得到了那个对象复制代码
Here is an example where return
is empty (Or we could put a primitive type after it, no effect):
function SmallUser() { this.name = "John"; return; // <-- 返回 this} alert( new SmallUser().name ); // John复制代码
Normally constructors don't have a return
statement. Here we mention the special behavior of returned objects mainly for completeness.
By the way, if there are no parameters, we can omit the brackets after new
:
let user = new User; // <-- 没有参数// 等同于let user = new User();复制代码
Omitting brackets here is not considered A "good style", but the syntax is allowed by the specification.
Using constructors to create objects brings great flexibility. A constructor may have parameters that define how the object is constructed and what to put in it.
当然,我们不仅可以将属性添加到 this
中,还可以添加方法。
例如,下面的 new User(name)
用给定的 name
和方法 sayHi
创建了一个对象:
function User(name) { this.name = name; this.sayHi = function() { alert( "My name is: " + this.name ); }; }let john = new User("John"); john.sayHi(); // My name is: John/* john = { name: "John", sayHi: function() { ... } } */复制代码
类 是用于创建复杂对象的一个更高级的语法,我们稍后会讲到。
new
来调用。这样的调用意味着在开始时创建了空的 this
,并在最后返回填充了值的 this
。我们可以使用构造函数来创建多个类似的对象。
JavaScript 为许多内置的对象提供了构造函数:比如日期 Date
、集合 Set
以及其他我们计划学习的内容。
对象,我们还会回来哒!
在本章中,我们只介绍了关于对象和构造器的基础知识。它们对于我们在下一章中,学习更多关于数据类型和函数的相关知识非常重要。
在我们学习了那些之后,我们将回到对象,在 info:prototypes 和 info:classes 章节中深入介绍它们。
先自己做题目再看答案。
重要程度:⭐️⭐️
是否可以创建像 new A()==new B()
这样的函数 A
和 B
?
function A() { ... }function B() { ... }let a = new A;let b = new B; alert( a == b ); // true复制代码
如果可以,请提供一个它们的代码示例。
重要程度:⭐️⭐️⭐️⭐️⭐️
创建一个构造函数 Calculator
,它创建的对象中有三个方法:
read()
使用 prompt
请求两个值并把它们记录在对象的属性中。sum()
返回这些属性的总和。mul()
返回这些属性的乘积。例如:
let calculator = new Calculator(); calculator.read(); alert( "Sum=" + calculator.sum() ); alert( "Mul=" + calculator.mul() );复制代码
重要程度:⭐️⭐️⭐️⭐️⭐️
创建一个构造函数 Accumulator(startingValue)
。
它创建的对象应该:
value
中。起始值被设置到构造器 startingValue
的参数。read()
方法应该使用 prompt
来读取一个新的数字,并将其添加到 value
中。换句话说,value
属性是所有用户输入值与初始值 startingValue
的总和。
下面是示例代码:
let accumulator = new Accumulator(1); // 初始值 1accumulator.read(); // 添加用户输入的 valueaccumulator.read(); // 添加用户输入的 valuealert(accumulator.value); // 显示这些值的总和复制代码
相关免费学习推荐:JavaScript(视频)
The above is the detailed content of Detailed explanation of JavaScript constructor and 'new' operator. For more information, please follow other related articles on the PHP Chinese website!