ในไฟล์ JavaScript ที่ฉันเห็น:
function Somefunction(){
var that = this;
...
}
อะไรคือวัตถุประสงค์ของการประกาศthat
และมอบหมายthis
สิ่งนี้ให้กับมัน?
ในไฟล์ JavaScript ที่ฉันเห็น:
function Somefunction(){
var that = this;
...
}
อะไรคือวัตถุประสงค์ของการประกาศthat
และมอบหมายthis
สิ่งนี้ให้กับมัน?
คำตอบ:
ฉันจะเริ่มคำตอบนี้ด้วยภาพประกอบ:
var colours = ['red', 'green', 'blue'];
document.getElementById('element').addEventListener('click', function() {
// this is a reference to the element clicked on
var that = this;
colours.forEach(function() {
// this is undefined
// that is a reference to the element clicked on
});
});
คำตอบของฉันเดิมแสดงให้เห็นนี้ด้วย jQuery ซึ่งแตกต่างกันเล็กน้อยเท่านั้น:
$('#element').click(function(){
// this is a reference to the element clicked on
var that = this;
$('.elements').each(function(){
// this is a reference to the current element in the loop
// that is still a reference to the element clicked on
});
});
เนื่องจากthis
การเปลี่ยนแปลงบ่อยครั้งเมื่อคุณเปลี่ยนขอบเขตโดยการเรียกใช้ฟังก์ชันใหม่คุณจะไม่สามารถเข้าถึงค่าดั้งเดิมได้โดยใช้มัน aliasing มันจะช่วยให้คุณยังคงสามารถเข้าถึงค่าเดิมของthat
this
โดยส่วนตัวแล้วฉันไม่ชอบการใช้that
นามแฝง มันไม่ค่อยชัดเจนว่ามันหมายถึงอะไรโดยเฉพาะอย่างยิ่งถ้าฟังก์ชั่นมีความยาวมากกว่าสองบรรทัด ฉันมักจะใช้นามแฝงที่เป็นคำอธิบายมากกว่านี้ clickedEl
ในตัวอย่างของฉันข้างต้นผมอาจต้องการใช้
var self = this;
ฉันมักจะไปกับ คำว่าthat
ดูเหมือนจะบ่งบอกตัวแปรคืออะไร this
แต่
forEach
ฟังก์ชั่นใช้เวลาสองคืออาร์กิวเมนต์ตัวเลือกที่จะผูกพันของฟังก์ชั่น colours.forEach(function(){/* 'this' is bound correctly --> */}, this);
ดังนั้นโน้ตควรจะเพิ่มที่var that = this
ไม่ได้จริงforEach
ที่จำเป็นด้วย
จากCrockford
โดยการประชุมเราทำให้เอกชนที่ ตัวแปร ใช้เพื่อทำให้วัตถุพร้อมใช้งานกับวิธีการส่วนตัว นี่คือวิธีแก้ปัญหาสำหรับข้อผิดพลาดในข้อมูลจำเพาะภาษา ECMAScript ซึ่งเป็นสาเหตุนี้จะถูกตั้งค่าไม่ถูกต้องสำหรับการทำงานภายใน
function usesThis(name) {
this.myName = name;
function returnMe() {
return this; //scope is lost because of the inner function
}
return {
returnMe : returnMe
}
}
function usesThat(name) {
var that = this;
this.myName = name;
function returnMe() {
return that; //scope is baked in with 'that' to the "class"
}
return {
returnMe : returnMe
}
}
var usesthat = new usesThat('Dave');
var usesthis = new usesThis('John');
alert("UsesThat thinks it's called " + usesthat.returnMe().myName + '\r\n' +
"UsesThis thinks it's called " + usesthis.returnMe().myName);
การแจ้งเตือนนี้ ...
ใช้ที่คิดว่ามันเรียกว่าเดฟ
ใช้นี่คิดว่ามันเรียกว่าไม่ได้กำหนด
that
ตัวแปรที่ไม่ได้ใช้ในตัวอย่างของเขาเลย มันทำให้ดูเหมือนว่าเพียงแค่สร้างตัวแปรการถือครองthis
ทำสิ่งที่เหลือของรหัส
นี่คือแฮ็คที่จะทำให้ฟังก์ชั่นภายใน (ฟังก์ชั่นที่กำหนดไว้ในฟังก์ชั่นอื่น ๆ ) ทำงานได้มากขึ้นกว่าที่ควร ในจาวาสคริปต์เมื่อคุณกำหนดฟังก์ชั่นหนึ่งภายในฟังก์ชั่นอื่นthis
โดยอัตโนมัติได้รับการตั้งค่าให้ขอบเขตทั่วโลก สิ่งนี้อาจทำให้สับสนเนื่องจากคุณคาดหวังว่าthis
จะมีค่าเหมือนกันกับในฟังก์ชั่นด้านนอก
var car = {};
car.starter = {};
car.start = function(){
var that = this;
// you can access car.starter inside this method with 'this'
this.starter.active = false;
var activateStarter = function(){
// 'this' now points to the global scope
// 'this.starter' is undefined, so we use 'that' instead.
that.starter.active = true;
// you could also use car.starter, but using 'that' gives
// us more consistency and flexibility
};
activateStarter();
};
นี่เป็นปัญหาโดยเฉพาะเมื่อคุณสร้างฟังก์ชั่นเป็นวิธีการของวัตถุ (เช่นcar.start
ในตัวอย่าง) จากนั้นสร้างฟังก์ชั่นภายในวิธีการนั้น (เช่นactivateStarter
) ในวิธีการระดับบนสุดthis
ชี้ไปที่วัตถุมันเป็นวิธีการ (ในกรณีนี้car
) แต่ในฟังก์ชั่นด้านในthis
ตอนนี้ชี้ไปที่ขอบเขตทั่วโลก นี่คือความเจ็บปวด
การสร้างตัวแปรที่จะใช้โดยการประชุมในขอบเขตทั้งสองเป็นวิธีแก้ปัญหาที่พบได้ทั่วไปในจาวาสคริปต์ นี่คือเหตุผลที่ทำให้เกิดเสียงชื่อทั่วไปมากthat
ถูกนำมาใช้ เป็นการประชุมที่จดจำได้ง่ายสำหรับการเอาชนะข้อบกพร่องทางภาษา
เช่นเดียวกับคำแนะนำของ El Ronnoco ที่Douglas Crockfordคิดว่านี่เป็นความคิดที่ดี
การใช้งานthat
นั้นไม่จำเป็นจริงๆถ้าคุณใช้วิธีแก้ปัญหาด้วยการใช้call()
หรือapply()
:
var car = {};
car.starter = {};
car.start = function(){
this.starter.active = false;
var activateStarter = function(){
// 'this' now points to our main object
this.starter.active = true;
};
activateStarter.apply(this);
};
บางครั้งthis
สามารถอ้างถึงขอบเขตอื่นและอ้างถึงสิ่งอื่นตัวอย่างเช่นสมมติว่าคุณต้องการเรียกเมธอดตัวสร้างภายในเหตุการณ์ DOM ในกรณีนี้this
จะอ้างถึงองค์ประกอบ DOM ไม่ใช่วัตถุที่สร้างขึ้น
HTML
<button id="button">Alert Name</button>
JS
var Person = function(name) {
this.name = name;
var that = this;
this.sayHi = function() {
alert(that.name);
};
};
var ahmad = new Person('Ahmad');
var element = document.getElementById('button');
element.addEventListener('click', ahmad.sayHi); // => Ahmad
วิธีการแก้ปัญหาข้างต้นจะthis
ทำให้that
เราสามารถเข้าถึงและเข้าถึงคุณสมบัติชื่อภายในsayHi
วิธีการจากthat
นั้นจึงสามารถเรียกได้โดยไม่มีปัญหาในการโทร DOM
อีกวิธีคือการกำหนดthat
วัตถุที่ว่างเปล่าและเพิ่มคุณสมบัติและวิธีการนั้นแล้วส่งคืน แต่ด้วยวิธีนี้คุณจะสูญเสียprototype
ตัวสร้าง
var Person = function(name) {
var that = {};
that.name = name;
that.sayHi = function() {
alert(that.name);
};
return that;
};
นี่คือตัวอย่าง `
$(document).ready(function() {
var lastItem = null;
$(".our-work-group > p > a").click(function(e) {
e.preventDefault();
var item = $(this).html(); //Here value of "this" is ".our-work-group > p > a"
if (item == lastItem) {
lastItem = null;
$('.our-work-single-page').show();
} else {
lastItem = item;
$('.our-work-single-page').each(function() {
var imgAlt = $(this).find('img').attr('alt'); //Here value of "this" is '.our-work-single-page'.
if (imgAlt != item) {
$(this).hide();
} else {
$(this).show();
}
});
}
});
});`
ดังนั้นคุณจะเห็นว่าค่าของสิ่งนี้คือสองค่าที่แตกต่างกันขึ้นอยู่กับองค์ประกอบ DOM ที่คุณกำหนดเป้าหมาย แต่เมื่อคุณเพิ่ม "ที่" ในโค้ดด้านบนคุณจะเปลี่ยนค่าของ "this" ที่คุณกำหนดเป้าหมาย
`$(document).ready(function() {
var lastItem = null;
$(".our-work-group > p > a").click(function(e) {
e.preventDefault();
var item = $(this).html(); //Here value of "this" is ".our-work-group > p > a"
if (item == lastItem) {
lastItem = null;
var that = this;
$('.our-work-single-page').show();
} else {
lastItem = item;
$('.our-work-single-page').each(function() {
***$(that).css("background-color", "#ffe700");*** //Here value of "that" is ".our-work-group > p > a"....
var imgAlt = $(this).find('img').attr('alt');
if (imgAlt != item) {
$(this).hide();
} else {
$(this).show();
}
});
}
});
});`
..... $ (ว่า) .css ("background-color", "# ffe700"); // นี่คือค่าของ "that" คือ ".our-work-group> p> a" เพราะค่าของ var that = this; ดังนั้นแม้ว่าเราจะอยู่ที่ "this" = '.our-work-single-page' แต่เรายังสามารถใช้ "that" เพื่อจัดการองค์ประกอบ DOM ก่อนหน้า