Tìm hiểu ES6 The Dope Way Phần II: Các hàm mũi tên và từ khóa 'this'

Chào mừng bạn đến với Phần II của Learn ES6 The Dope Way, một loạt bài được tạo ra để giúp bạn dễ dàng hiểu ES6 (ECMAScript 6)!

Thế là cái quái gì => ; ?

Bạn có thể đã nhìn thấy những biểu tượng chữ tượng hình kỳ lạ trông giống như Ai Cập này ở đây và ở đó, đặc biệt là trong mã của người khác, nơi bạn hiện đang gỡ lỗi vấn đề từ khóa 'này' . Sau một giờ mày mò, bây giờ bạn đang chuyển vùng thanh tìm kiếm của Google và rình rập Stack Overflow. Nghe có vẻ quen?

Cùng nhau, chúng ta hãy bao gồm ba chủ đề trong Học ES6 Con đường Dope Phần II:

  • Từ khóa ' this ' có liên quan như thế nào với => .
  • Cách chuyển các chức năng từ ES5 sang ES6.
  • Những câu hỏi quan trọng cần lưu ý khi sử dụng => .

Hàm mũi tên

Các hàm mũi tên được tạo ra để đơn giản hóa phạm vi hàm và làm cho việc sử dụng từ khóa ' this ' trở nên đơn giản hơn nhiều. Họ sử dụng = & gt; cú pháp, trông giống như một mũi tên. Mặc dù tôi không nghĩ rằng nó cần phải ăn kiêng, nhưng mọi người gọi tôi là “the fat arr ow” (và những người đam mê Ruby có thể biết rõ hơn là “hash rock et”) - một điều cần lưu ý.

Làm thế nào từ khóa 'this' liên quan đến Hàm mũi tên

Trước khi chúng ta đi sâu hơn vào các hàm mũi tên của ES6, điều quan trọng trước tiên là phải có một bức tranh rõ ràng về những gì ' cái này ' liên kết với mã ES5.

Nếu từ khóa ' this ' nằm trong phương thức của một đối tượng (một hàm thuộc về một đối tượng), thì nó sẽ tham chiếu đến điều gì?

// Test it here: //jsfiddle.net/maasha/x7wz1686/ var bunny = { name: 'Usagi', showName: function() { alert(this.name); } }; bunny.showName(); // Usagi

Chính xác! Nó sẽ tham chiếu đến đối tượng. Chúng ta sẽ tìm hiểu lý do tại sao sau.

Bây giờ điều gì xảy ra nếu từ khóa ' this ' nằm trong hàm của method?

// Test it here: //jsfiddle.net/maasha/z65c1znn/ var bunny = { name: 'Usagi', tasks: ['transform', 'eat cake', 'blow kisses'], showTasks: function() { this.tasks.forEach(function(task) { alert(this.name + " wants to " + task); }); } }; bunny.showTasks(); // [object Window] wants to transform // [object Window] wants to eat cake // [object Window] wants to blow kisses // please note, in jsfiddle the [object Window] is named 'result' within inner functions of methods. 

Bạn đã nhận được gì? Chờ đã, chuyện gì đã xảy ra với chú thỏ của chúng ta…?

À, bạn có nghĩ ' this ' ám chỉ đến hàm bên trong của phương thức không?

Có lẽ đối tượng chính nó?

Bạn thật khôn ngoan khi nghĩ như vậy, nhưng thực tế không phải như vậy. Cho phép tôi dạy cho bạn những gì mà những người lớn tuổi lập trình đã từng dạy tôi:

Mã hóa Elder :À đúng rồi, t ông đang mạnh mẽ với thế này. Thực tế là thực tế khi nghĩ rằng từ khóa 'this' liên kết với hàm nhưng sự thật là, 'cái này' giờ đã không còn nằm trong phạm vi… Nó giờ thuộc về… ”, anh dừng lại như thể trải qua sự xáo trộn bên trong ,“ đối tượng cửa sổ .

Đúng rồi. Đó chính xác là cách nó đã xảy ra.

Tại sao ' this ' liên kết với đối tượng window? Bởi vì ' this ', luôn tham chiếu đến chủ sở hữu của hàm mà nó có, đối với trường hợp này - vì nó hiện nằm ngoài phạm vi - đối tượng window / global.

Khi nó nằm bên trong phương thức của một đối tượng - chủ sở hữu của hàm là đối tượng. Vì vậy , từ khóa ' this ' được liên kết với đối tượng. Tuy nhiên, khi nó nằm bên trong một hàm, đứng một mình hoặc trong một phương thức khác, nó sẽ luôn tham chiếu đến đối tượng window / global.

// Test it here: //jsfiddle.net/maasha/g278gjtn/ var standAloneFunc = function(){ alert(this); } standAloneFunc(); // [object Window]

Nhưng tại sao…?

Điều này được biết đến như là một câu đố JavaScript, có nghĩa là một cái gì đó xảy ra trong JavaScript không chính xác và nó không hoạt động theo cách bạn nghĩ. Điều này cũng được các nhà phát triển coi là một lựa chọn thiết kế kém, mà họ hiện đang khắc phục bằng các chức năng mũi tên của ES6.

Trước khi chúng ta tiếp tục, điều quan trọng là phải biết hai cách thông minh mà các lập trình viên giải quyết vấn đề ' này ' trong mã ES5, đặc biệt là vì bạn sẽ tiếp tục chạy vào ES5 trong một thời gian (không phải mọi trình duyệt đều đã chuyển hoàn toàn sang ES6):

# 1 Tạo một biến bên ngoài hàm bên trong của phương thức. Bây giờ phương thức 'forEach' có quyền truy cập vào ' this ' và do đó các thuộc tính của đối tượng và giá trị của chúng. Điều này là do ' this ' đang được lưu trữ trong một biến trong khi nó vẫn nằm trong phạm vi của phương thức trực tiếp của đối tượng 'showTasks'.

// Test it here: //jsfiddle.net/maasha/3mu5r6vg/ var bunny = { name: 'Usagi', tasks: ['transform', 'eat cake', 'blow kisses'], showTasks: function() { var _this = this; this.tasks.forEach(function(task) { alert(_this.name + " wants to " + task); }); } }; bunny.showTasks(); // Usagi wants to transform // Usagi wants to eat cake // Usagi wants to blow kisses

# 2 Sử dụng bind để đính kèm từ khóa ' this ' tham chiếu đến phương thức với hàm bên trong của phương thức.

// Test it here: //jsfiddle.net/maasha/u8ybgwd5/ var bunny = { name: 'Usagi', tasks: ['transform', 'eat cake', 'blow kisses'], showTasks: function() { this.tasks.forEach(function(task) { alert(this.name + " wants to " + task); }.bind(this)); } }; bunny.showTasks(); // Usagi wants to transform // Usagi wants to eat cake // Usagi wants to blow kisses

Và bây giờ giới thiệu… Các hàm mũi tên! Đối phó với vấn đề ' này ' chưa bao giờ dễ dàng và đơn giản hơn! Giải pháp ES6 đơn giản:

// Test it here: //jsfiddle.net/maasha/che8m4c1/ var bunny = { name: 'Usagi', tasks: ['transform', 'eat cake', 'blow kisses'], showTasks() { this.tasks.forEach((task) => { alert(this.name + " wants to " + task); }); } }; bunny.showTasks(); // Usagi wants to transform // Usagi wants to eat cake // Usagi wants to blow kisses

Trong khi trong ES5, ' this ' đề cập đến hàm cha của hàm, trong ES6, các hàm mũi tên sử dụng phạm vi từ vựng - ' this ' đề cập đến phạm vi xung quanh hiện tại của nó và không xa hơn. Vì vậy, hàm bên trong chỉ biết liên kết với hàm bên trong, chứ không phải với phương thức của đối tượng hoặc chính đối tượng.

Cách chuyển các chức năng từ ES5 sang ES6.

// Before let bunny = function(name) { console.log("Usagi"); } // After let bunny = (name) => console.log("Usagi") // Step 1: Remove the word ‘function’. let bunny = (name) { console.log("Usagi"); } // Step 2: If your code is less than a line, remove brackets and place on one line. let bunny = (name) console.log("Usagi"); // Step 3. Add the hash rocket. let bunny = (name) => console.log("Usagi");

Bạn làm được rồi! Bạn đã làm rất tốt! Đủ đơn giản phải không? Dưới đây là một vài ví dụ khác về việc sử dụng mũi tên béo - gầy để làm quen với mắt của bạn:

// #1 ES6: if passing one argument you don't need to include parenthesis around parameter. var kitty = name => name; // same as ES5: var kitty = function(name) { return name; }; // #2 ES6: no parameters example. var add = () => 3 + 2; // same as ES5: var add = function() { return 3 + 2; }; // #3 ES6: if function consists of more than one line or is an object, include braces. var objLiteral = age => ({ name: "Usagi", age: age }); // same as ES5: var objLiteral = function(age) { return { name: "Usagi", age: age }; }; // #4 ES6: promises and callbacks. asyncfn1().then(() => asyncfn2()).then(() => asyncfn3()).then(() => done()); // same as ES5: asyncfn1().then(function() { asyncfn2(); }).then(function() { asyncfn3(); }).done(function() { done(); });

Những điều quan trọng cần lưu ý khi sử dụng các hàm Mũi tên

Nếu bạn sử dụng từ khóa 'mới' với các hàm =>, nó sẽ báo lỗi. Không thể sử dụng các hàm mũi tên làm hàm tạo - các hàm thông thường hỗ trợ 'mới' thông qua nguyên mẫu thuộc tính và phương thức nội bộ [[Construct]]. Các hàm mũi tên không sử dụng, do đó (() => {}) mới tạo ra lỗi.

Những vấn đề khác cần xem xét:

// Line breaks are not allowed and will throw a syntax error let func1 = (x, y) => { return x + y; }; // SyntaxError // But line breaks inside of a parameter definition is ok let func6 = ( x, y ) => { return x + y; }; // Works! // If an expression is the body of an arrow function, you don’t need braces: asyncFunc.then(x => console.log(x)); // However, statements have to be put in braces: asyncFunc.catch(x => { throw x }); // Arrow functions are always anonymous which means you can’t just declare them as in ES5: function squirrelLife() { // play with squirrels, burrow for food, etc. } // Must be inside of a variable or object property to work properly: let squirrelLife = () => { // play with squirrels, burrow for food, etc. // another super squirrel action. }

Chúc mừng! Bạn đã hoàn thành nó thông qua Tìm hiểu ES6 The Dope Way Phần II và bây giờ bạn đã có cơ sở cho kiến ​​thức về hàm mũi tên, những lợi ích từ vựng mà nó mang lại cho ' cái này ' và cũng có cho mình một số kỹ năng JavaScript! :)

Hãy cập nhật sự thông thái của bạn bằng cách thích và theo dõi khi biết thêm Tìm hiểu ES6 The Dope Way sắp có trên Medium!

Phần I: const, let & var

Phần II: (Mũi tên) => các hàm và từ khóa 'this'

Phần III: Chữ mẫu, Nhà khai thác và Máy tạo Spread!

Phần IV: Các tham số mặc định, Gán cơ cấu và một phương pháp ES6 mới!

Phần V: Lớp học, chuyển mã ES6 và nhiều tài nguyên khác!

Bạn cũng có thể tìm thấy tôi trên github ❤ //github.com/Mashadim