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關鍵字