javascript关键字
by Cynthia Lee
辛西娅·李(Cynthia Lee)
让我们揭开JavaScript的“ new”关键字的神秘面纱 (Let’s demystify JavaScript’s ‘new’ keyword)
Over the weekend, I completed Will Sentance’s JavaScript: The Hard Parts. It might not sound like the most glorious way to spend a weekend, but I actually found it pretty fun and relaxing to complete the course. It touched on functional programming, higher-order functions, closures, and asynchronous JavaScript.
上周末,我完成了Will Sentance的JavaScript:The Hard Parts 。 听起来可能不是周末度过的最光荣的方式,但实际上,我觉得这很有趣且轻松,可以完成课程。 它涉及函数式编程,高阶函数,闭包和异步JavaScript。
For me, the highlight of the course was how he expanded on the JavaScript approaches to Object-Oriented Programming (OOP) and demystified the magic behind the new operator. I now have a well-rounded understanding of what goes on under the hood when the new operator is used.
对我而言,本课程的重点是他如何扩展JavaScript面向对象编程(OOP)的方法,并揭开了新操作符背后的神秘面纱。 现在,我对使用新操作员时幕后情况有了全面的了解。
JavaScript中的面向对象编程 (Object-Oriented Programming in JavaScript)
Object-Oriented Programming (OOP) is a programming paradigm based on the concept of “objects.” Data and functions (attributes and methods) are bundled within an object.
面向对象编程(OOP)是基于“对象”概念的编程范例。 数据和功能(属性和方法)捆绑在一个对象中。
An object in JavaScript is a collection of key-value pairs. These key-value pairs are properties of the object. A property can be an array, a function, an object itself or any primitive data type such as strings or integers.
JavaScript中的对象是键值对的集合。 这些键值对是对象的属性。 属性可以是数组,函数,对象本身或任何原始数据类型,例如字符串或整数。
What techniques do we have in our JavaScript toolbox for object creation?
我们JavaScript工具箱中有哪些技术可用于对象创建?
Let’s assume that we are creating users in a game that we just designed. How would we store user details such as their names, points, and implement methods such as an increment in points? Here are two options for basic object creation.
假设我们在刚刚设计的游戏中创建用户。 我们将如何存储用户详细信息(例如他们的姓名,积分)以及实现方法(例如增加积分)? 这是用于基本对象创建的两个选项。
选项1-对象文字表示法 (Option 1 — Object Literal Notation)
let user1 = {
name: "Taylor",
points: 5,
increment: function() {
user1.points++;
}
};
A JavaScript object literal is a list of name-value pairs wrapped in curly braces. In the example above, the object ‘user1’ is created, and the associated data is stored within it.
JavaScript对象文字是用花括号括起来的名称-值对的列表。 在上面的示例中,创建了对象“ user1”,并将关联的数据存储在其中。
选项2 — Object.create() (Option 2 — Object.create())
Object.create(proto, [ propertiesObject ])
Object.create(proto, [ propertiesObject ])
Object.create
methods accept two arguments:
Object.create
方法接受两个参数:
- proto: the object which should be the prototype of the newly-created object. It has to be an object or null. proto:应该是新创建对象的原型的对象。 它必须是一个对象或null。
- propertiesObject: properties of the new object. This argument is optional. propertiesObject:新对象的属性。 此参数是可选的。
Basically, you pass into Object.create
an object that you want to inherit from, and it returns a new object that inherits from the object you passed into it.
基本上,您将传递给Object.create
一个想要继承的对象,然后返回一个新对象,该对象继承Object.create
递给它的对象。
let user2 = Object.create(null);
user2.name = "Cam";
user2.points = 8;
user2.increment = function() {
user2.points++;
}
The basic object creation options above are repetitive. It requires each one to be manually created.
上面的基本对象创建选项是重复的。 它要求每个手动创建。
How do we overcome this?
我们如何克服这个问题?
解决方案 (Solutions)
解决方案1 —使用函数生成对象 (Solution 1 — Generate objects using a function)
A simple solution is to write a function to create new users.
一个简单的解决方案是编写一个函数来创建新用户。
function createUser(name, points) {
let newUser = {};
newUser.name = name;
newUser.points = points;
newUser.increment = function() {
newUser.points++;
};
return newUser;
}
To create a user, you would now enter the information in parameters of the function.
要创建用户,您现在将在功能参数中输入信息。
let user1 = createUser("Bob", 5);
user1.increment();
However, the increment function in the example above is just a copy of the original increment function. This is not a good way to write your code, as any potential changes to the function will need to be done manually for each object.
但是,上面示例中的增量函数只是原始增量函数的副本。 这不是编写代码的好方法,因为对该功能的任何潜在更改都需要针对每个对象手动进行。
解决方案2-使用JavaScript的原型性质 (Solution 2 — Use the prototypal nature of JavaScript)
Unlike object-oriented languages such as Python and Java, JavaScript does not have classes. It uses the concept of prototypes and prototype chaining for inheritance.
与Python和Java等面向对象的语言不同,JavaScript没有类。 它使用原型和原型链的概念进行继承。
When you create a new array, you automatically have access to built-in methods such as Array.join
, Array.sort
, and Array.filter
. This is due to the fact that array objects inherit properties from Array.prototype.
创建新数组时,可以自动访问内置方法,例如Array.join
, Array.sort
和Array.filter
。 这是由于数组对象继承了Array.prototype的属性。
Every JavaScript function has a prototype property, which is empty by default. You can add functions to this prototype property, and in this form, it is known as a method. When an inherited function is executed, the value of this points to the inheriting object.
每个JavaScript函数都有一个prototype属性,默认情况下为空。 您可以向该原型属性添加函数,并且以这种形式将其称为方法。 当执行继承的函数时,此值指向继承的对象。
function createUser(name, points) {
let newUser = Object.create(userFunction);
newUser.name = name;
newUser.points = points;
return newUser;
}
let userFunction = {
increment: function() {this.points++};
login: function() {console.log("Please login.")};
}
let user1 = createUser("Bob", 5);
user1.increment();
When the user1
object was created, a prototype chain bond with userFunction was formed.
创建user1
对象时,形成了带有userFunction的原型链键。
When user1.increment()
is in the call stack, the interpreter will look for user1 in the global memory. Next, it will look for the increment function, but will not find it. The interpreter will look at the next object up the prototype chain and will find the increment function there.
当user1.increment()
位于调用堆栈中时,解释器将在全局内存中查找user1。 接下来,它将查找增量函数,但找不到它。 解释器将查看原型链中的下一个对象,并在其中找到增量函数。
解决方案3- 新关键字和此关键字 (Solution 3 — new and this keywords)
The new operator is used to create an instance of an object which has a constructor function.
的 new运算符用于创建具有构造函数的对象的实例。
When we call the constructor function with new, we automate the following actions:
当我们使用new调用构造函数时,我们将自动执行以下操作:
- A new object is created 创建一个新对象
It binds
this
to the object它结合
this
对象- The constructor function’s prototype object becomes the __proto__ property of the new object 构造函数的原型对象成为新对象的__proto__属性。
- It returns the object from the function 它从函数返回对象
This is fantastic, because the automation results in less repetitive code!
这太棒了,因为自动化可以减少重复代码!
function User(name, points) {
this.name = name;
this.points = points;
}
User.prototype.increment = function(){
this.points++;
}
User.prototype.login = function() {
console.log(“Please login.”)
}
let user1 = new User(“Dylan”, 6);
user1.increment();
By using the prototype pattern, each method and property is added directly on the object’s prototype.
通过使用原型模式,每个方法和属性都直接添加到对象的原型上。
The interpreter will go up the prototypal chain and find the increment function under the prototype property of User, which itself is also an object with the information inside it. Remember — All functions in JavaScript are also objects. Now that the interpreter has found what it needs, it can create a new local execution context to run user1.increment()
.
解释器将沿着原型链向上移动,并在User的prototype属性下找到增量函数,该属性本身也是一个内部包含信息的对象。 请记住,JavaScript中的所有函数也是对象 。 现在,解释器已经找到了所需的内容,它可以创建一个新的本地执行上下文来运行user1.increment()
。
Side note: Difference between __proto__ and prototype
旁注:__ proto__和原型之间的区别
If you are already getting confused about __proto__ and prototype, don’t worry! You are far from the only one to be confused about this.
如果您已经对__proto__和原型感到困惑,请放心! 您远非唯一对此感到困惑的人。
Prototype is a property of the constructor function that determines what will become the __proto__ property on the constructed object.
原型是构造函数的属性,该函数确定在构造对象上将成为__proto__属性的内容。
So, __proto__ is the reference created, and that reference is known as the prototype chain bond.
因此,__ proto__是创建的引用,该引用称为原型链键。
解决方案4-ES6“语法糖” (Solution 4 — ES6 ‘syntactic sugar’)
Other languages allow us to write our shared methods within the object “constructor” itself. ECMAScript6 introduced the class keyword, which allows us to write classes that resemble normal classes of other classical languages. In reality, it is syntactic sugar over JavaScript’s prototypal behavior.
其他语言允许我们在对象“构造函数”本身内编写共享方法。 ECMAScript6引入了class关键字,该关键字使我们能够编写类似于其他古典语言的普通类的类。 实际上,它是JavaScript原型行为的语法糖。
class User {
constructor(name, points) {
this.name = name;
this.points = points;
}
increment () {
this.points++;
}
login () {
console.log("Please login.")
}
}
let user1 = new User("John", 12);
user1.increment();
In solution 3, the associated methods were precisely implemented using User.prototype.functionName
. In this solution, the same results are achieved but the syntax looks cleaner.
在解决方案3中,使用User.prototype.functionName
精确实现了相关方法。 在此解决方案中,可以达到相同的结果,但是语法看起来更简洁。
结论 (Conclusion)
We have now learned more about the different options we have in JavaScript to create objects. While class declarations and the new operator are relatively easy to use, it is important to understand what is automated.
现在,我们已经了解了更多有关JavaScript创建对象的不同选项的信息。 虽然类声明和 新操作员相对易于使用,重要的是要了解什么是自动化的。
To recap, the following actions are automated when the constructor function is called with new:
概括地说,当用new调用构造函数时,以下动作是自动的:
- A new object is created 创建一个新对象
It binds
this
to the object它结合
this
对象- The constructor function’s prototype object becomes the __proto__ property of the new object 构造函数的原型对象成为新对象的__proto__属性。
- It returns the object from the function 它从函数返回对象
Thanks for reading my article, and clap if you liked it! Check out my other articles like How I built my Pomodoro Clock app, and the lessons I learned along the way.
感谢您阅读我的文章,如果喜欢您也可以鼓掌! 查阅其他文章,例如“我如何构建Pomodoro Clock应用程序”,以及我在此过程中学到的课程 。
翻译自: https://www.freecodecamp.org/news/demystifying-javascripts-new-keyword-874df126184c/
javascript关键字