ฟังก์ชั่นลูกศรถูกสร้างขึ้นเพื่อลดความซับซ้อนของฟังก์ชั่นscope
และการแก้ไขthis
คำหลักโดยทำให้มันง่ายขึ้น พวกเขาใช้=>
ไวยากรณ์ซึ่งดูเหมือนลูกศร
หมายเหตุ: มันไม่ได้แทนที่ฟังก์ชั่นที่มีอยู่ หากคุณแทนที่ทุกฟังก์ชั่นไวยากรณ์ด้วยฟังก์ชั่นลูกศรมันจะไม่ทำงานในทุกกรณี
ลองดูที่ไวยากรณ์ ES5 ที่มีอยู่ถ้าthis
คำสำคัญอยู่ในวิธีการของวัตถุ (ฟังก์ชั่นที่เป็นของวัตถุ) มันจะหมายถึงอะไร?
var Actor = {
name: 'RajiniKanth',
getName: function() {
console.log(this.name);
}
};
Actor.getName();
ข้อมูลข้างต้นจะอ้างถึงและพิมพ์ชื่อobject
"RajiniKanth"
ลองสำรวจตัวอย่างด้านล่างและดูว่าจุดนี้จะอยู่ตรงไหน
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
showMovies: function() {
this.movies.forEach(function(movie) {
alert(this.name + " has acted in " + movie);
});
}
};
Actor.showMovies();
ทีนี้ถ้าthis
คำสำคัญอยู่ข้างในmethod’s function
ล่ะ
นี่นี้จะอ้างถึงwindow object
กว่าเป็นลดลงออกจากinner function
scope
เพราะthis
มักจะอ้างอิงถึงเจ้าของฟังก์ชั่นที่มันมีอยู่ในกรณีนี้ - เนื่องจากขณะนี้อยู่นอกขอบเขต - วัตถุหน้าต่าง / โกลบอล
เมื่อมันอยู่ในobject
เมธอด 's - function
เจ้าของคือวัตถุ ดังนั้นคำหลักนี้ถูกผูกไว้กับวัตถุ แต่เมื่อมันอยู่ภายในฟังก์ชั่นไม่ว่าจะเป็นแบบสแตนด์อะโลนหรือในวิธีอื่นมันจะอ้างถึงwindow/global
วัตถุเสมอ
var fn = function(){
alert(this);
}
fn(); // [object Window]
มีวิธีในการแก้ปัญหานี้ในES5
ตัวเราเองให้เราดูก่อนที่จะดำดิ่งลงในฟังก์ชันลูกศร ES6 เกี่ยวกับวิธีแก้ปัญหา
โดยทั่วไปแล้วคุณจะสร้างตัวแปรนอกฟังก์ชั่นด้านในของวิธีการ ตอนนี้‘forEach’
วิธีการเข้าถึงthis
และทำให้object’s
คุณสมบัติและค่าของพวกเขา
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
showMovies: function() {
var _this = this;
this.movies.forEach(function(movie) {
alert(_this.name + " has acted in " + movie);
});
}
};
Actor.showMovies();
โดยใช้bind
แนบคำหลักที่หมายถึงวิธีการที่จะthis
method’s inner function
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
showMovies: function() {
this.movies.forEach(function(movie) {
alert(this.name + " has acted in " + movie);
}.bind(this));
}
};
Actor.showMovies();
ขณะนี้มีES6
ฟังก์ชั่นลูกศรเราสามารถจัดการกับlexical scoping
ปัญหาได้ง่ายขึ้น
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
showMovies: function() {
this.movies.forEach((movie) => {
alert(this.name + " has acted in " + movie);
});
}
};
Actor.showMovies();
Arrow functions
มีมากขึ้นเช่นงบฟังก์ชั่นยกเว้นว่าพวกเขานี้ไปbind
parent scope
ถ้าarrow function is in top scope
, this
อาร์กิวเมนต์จะอ้างถึงwindow/global scope
ในขณะที่ฟังก์ชั่นภายในลูกศรฟังก์ชั่นปกติจะมีเรื่องนี้มันเป็นเช่นเดียวกับฟังก์ชั่นด้านนอก
ด้วยarrow
ฟังก์ชั่นที่this
ถูกผูกไว้กับสิ่งที่แนบมาscope
ในเวลาการสร้างและไม่สามารถเปลี่ยนแปลงได้ ผู้ประกอบการใหม่ผูกโทรและนำไปใช้ไม่มีผลกับสิ่งนี้
var asyncFunction = (param, callback) => {
window.setTimeout(() => {
callback(param);
}, 1);
};
// With a traditional function if we don't control
// the context then can we lose control of `this`.
var o = {
doSomething: function () {
// Here we pass `o` into the async function,
// expecting it back as `param`
asyncFunction(o, function (param) {
// We made a mistake of thinking `this` is
// the instance of `o`.
console.log('param === this?', param === this);
});
}
};
o.doSomething(); // param === this? false
ในตัวอย่างด้านบนเราสูญเสียการควบคุมสิ่งนี้ เราสามารถแก้ตัวอย่างข้างต้นโดยใช้การอ้างอิงตัวแปรหรือใช้this
bind
ด้วย ES6 ก็กลายเป็นเรื่องง่ายในการจัดการกับการผูกพันของthis
lexical scoping
var asyncFunction = (param, callback) => {
window.setTimeout(() => {
callback(param);
}, 1);
};
var o = {
doSomething: function () {
// Here we pass `o` into the async function,
// expecting it back as `param`.
//
// Because this arrow function is created within
// the scope of `doSomething` it is bound to this
// lexical scope.
asyncFunction(o, (param) => {
console.log('param === this?', param === this);
});
}
};
o.doSomething(); // param === this? true
เมื่อไม่ใช้ฟังก์ชั่น Arrow
ภายในวัตถุที่แท้จริง
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
getName: () => {
alert(this.name);
}
};
Actor.getName();
Actor.getName
ถูกกำหนดให้มีฟังก์ชั่นลูกศร แต่ในการภาวนามันแจ้งเตือนไม่ได้กำหนดเพราะthis.name
เป็นแล้วแต่บริบทจะยังคงที่undefined
window
มันเกิดขึ้นเพราะฟังก์ชั่นลูกศรเชื่อมโยงบริบทกับwindow object
ขอบเขต ... คือขอบเขตภายนอก การดำเนินการthis.name
เทียบเท่ากับwindow.name
ซึ่งไม่ได้กำหนด
ต้นแบบวัตถุ
prototype object
กฎเดียวกันกับเมื่อกำหนดวิธีการใน แทนที่จะใช้ฟังก์ชันลูกศรเพื่อกำหนดเมธอด sayCatName ซึ่งทำให้เกิดข้อผิดพลาดcontext window
:
function Actor(name) {
this.name = name;
}
Actor.prototype.getName = () => {
console.log(this === window); // => true
return this.name;
};
var act = new Actor('RajiniKanth');
act.getName(); // => undefined
เรียกการก่อสร้าง
this
ในการขอร้องการก่อสร้างเป็นวัตถุที่สร้างขึ้นใหม่ เมื่อมีการดำเนิน Fn () ใหม่บริบทของเป็นวัตถุใหม่:constructor Fn
this instanceof Fn === true
this
เป็นการตั้งค่าจากบริบทที่ปิดล้อมเช่นขอบเขตด้านนอกซึ่งทำให้ไม่ได้กำหนดให้กับวัตถุที่สร้างขึ้นใหม่
var Message = (text) => {
this.text = text;
};
// Throws "TypeError: Message is not a constructor"
var helloMessage = new Message('Hello World!');
โทรกลับด้วยบริบทแบบไดนามิก
ฟังก์ชั่นลูกศรผูกcontext
แบบคงที่ในการประกาศและเป็นไปไม่ได้ที่จะทำให้มันเป็นแบบไดนามิก การแนบตัวรับเหตุการณ์ของเหตุการณ์ไปยังองค์ประกอบ DOM เป็นงานทั่วไปในการเขียนโปรแกรมฝั่งไคลเอ็นต์ เหตุการณ์จะเรียกใช้ฟังก์ชันตัวจัดการด้วยสิ่งนี้เป็นองค์ประกอบเป้าหมาย
var button = document.getElementById('myButton');
button.addEventListener('click', () => {
console.log(this === window); // => true
this.innerHTML = 'Clicked button';
});
this
เป็นหน้าต่างในฟังก์ชั่นลูกศรที่กำหนดไว้ในบริบทโลก เมื่อมีเหตุการณ์การคลิกเกิดขึ้นเบราว์เซอร์จะพยายามเรียกใช้ฟังก์ชันตัวจัดการด้วยบริบทของปุ่ม แต่ฟังก์ชันลูกศรจะไม่เปลี่ยนบริบทที่กำหนดไว้ล่วงหน้า this.innerHTML
เทียบเท่าwindow.innerHTML
และไม่มีเหตุผล
คุณต้องใช้นิพจน์ฟังก์ชั่นซึ่งจะช่วยให้การเปลี่ยนแปลงนี้ขึ้นอยู่กับองค์ประกอบเป้าหมาย:
var button = document.getElementById('myButton');
button.addEventListener('click', function() {
console.log(this === button); // => true
this.innerHTML = 'Clicked button';
});
เมื่อผู้ใช้คลิกปุ่มสิ่งนี้ในฟังก์ชั่นการจัดการคือปุ่ม ดังนั้นการthis.innerHTML = 'Clicked button'
ปรับเปลี่ยนข้อความปุ่มอย่างถูกต้องเพื่อสะท้อนสถานะการคลิก
ข้อมูลอ้างอิง:
https://dmitripavlutin.com/when-not-to-use-arrow-functions-in-javascript/
Fixed this bound to scope at initialisation
เป็นข้อ จำกัด หรือไม่?