ฉันจะส่งผ่านบริบทนี้ไปยังฟังก์ชันได้อย่างไร


213

ฉันคิดว่านี่จะเป็นสิ่งที่ฉันสามารถทำได้อย่างง่ายดาย google แต่บางทีฉันไม่ได้ถามคำถามที่ถูกต้อง ...

ฉันจะตั้งค่าสิ่งใด "สิ่งนี้" ในฟังก์ชันจาวาสคริปต์ที่กำหนดได้อย่างไร

ตัวอย่างเช่นชอบฟังก์ชั่นส่วนใหญ่ของ jQuery เช่น:

$(selector).each(function() {
   //$(this) gives me access to whatever selector we're on
});

ฉันจะเขียน / เรียกใช้ฟังก์ชันสแตนด์อโลนของตัวเองที่มีการอ้างอิง "นี่" ที่เหมาะสมเมื่อถูกเรียกได้อย่างไร ฉันใช้ jQuery ดังนั้นหากมีวิธีเฉพาะในการทำ jQuery นั่นจะเหมาะอย่างยิ่ง


ซ้ำซ้อนที่เป็นไปได้: stackoverflow.com/questions/520019/…
user123444555621

ฉันรู้ว่านี่เป็นคำถามเก่า แต่สำหรับคนอื่น ๆ ที่เชื่อมโยงไปถึงที่นี่ดู jQuery$.proxy
RyBolt

คำตอบ:


303

Javascripts .call()และ.apply()เมธอดอนุญาตให้คุณตั้งค่าบริบทสำหรับฟังก์ชัน

var myfunc = function(){
    alert(this.name);
};

var obj_a = {
    name:  "FOO"
};

var obj_b = {
    name:  "BAR!!"
};

ตอนนี้คุณสามารถโทร:

myfunc.call(obj_a);

FOOซึ่งจะแจ้งเตือน วิธีอื่น ๆ , ผ่านจะแจ้งเตือนobj_b BAR!!ความแตกต่างระหว่าง.call()และ.apply()คือ.call()ใช้รายการคั่นด้วยเครื่องหมายจุลภาคหากคุณส่งอาร์กิวเมนต์ไปยังฟังก์ชันของคุณและ.apply()ต้องการอาร์เรย์

myfunc.call(obj_a, 1, 2, 3);
myfunc.apply(obj_a, [1, 2, 3]);

ดังนั้นคุณสามารถเขียนฟังก์ชันได้อย่างง่ายดายhookโดยใช้apply()เมธอด ตัวอย่างเช่นเราต้องการเพิ่มคุณสมบัติให้กับ.css()วิธีการjQuerys เราสามารถจัดเก็บการอ้างอิงฟังก์ชั่นดั้งเดิมเขียนทับฟังก์ชั่นด้วยรหัสที่กำหนดเองและเรียกใช้ฟังก์ชั่นที่เก็บไว้

var _css = $.fn.css;
$.fn.css = function(){
   alert('hooked!');
   _css.apply(this, arguments);
};

ตั้งแต่มายากลวัตถุเป็นอาร์เรย์เช่นวัตถุเราก็สามารถผ่านมันไปarguments apply()ด้วยวิธีนี้เรารับประกันว่าพารามิเตอร์ทั้งหมดจะถูกส่งผ่านไปยังฟังก์ชั่นดั้งเดิม


4
เพียงชิ้นอาหารอันโอชะที่สนุกสนาน: หากคุณต้องการเรียกใช้ฟังก์ชันซ้ำ ๆ โดยอ้างอิงจากobj_aตัวอย่างเช่นคุณสามารถสร้างสำเนาของมันด้วยvar boud_myfunc = myfunc.bind(obj_a)และเพียงแค่เรียกbound_myfunc()ตามที่ต้องการ
wbadart

44

การใช้function.call :

var f = function () { console.log(this); }
f.call(that, arg1, arg2, etc);

ในกรณีที่thatเป็นวัตถุที่คุณต้องการthisในการทำงานที่จะเป็น


1
functionเป็นคำหลักที่สงวนไว้; ลองอัปเดตการตอบกลับของคุณเพื่อรวมฟังก์ชั่นที่มีชื่อเนื่องจากfunction.call(...)ไม่ถูกต้อง
Daniel Allen

1
@DanielAllen: หากไม่มีคำจำกัดความของชื่อฟังก์ชั่นตัวอย่างใด ๆ ที่ฉันจะให้รหัสจะยังคงโยนข้อผิดพลาด JS แต่ฉันอัพเดทชื่อฟังก์ชั่นตัวอย่าง
palswim

16

jQuery ใช้.call(...)วิธีการกำหนดโหนดปัจจุบันให้thisภายในฟังก์ชันที่คุณส่งผ่านเป็นพารามิเตอร์

แก้ไข:

อย่ากลัวที่จะมองเข้าไปในโค้ดของ jQuery เมื่อคุณมีข้อสงสัยมันเป็นจาวาสคริปต์ที่ชัดเจนและมีเอกสารครบถ้วน

เช่น: คำตอบสำหรับคำถามนี้อยู่ที่เส้น 574
callback.call( object[ name ], name, object[ name ] ) === false


12

คุณสามารถใช้ฟังก์ชันbindเพื่อตั้งค่าบริบทthisภายในฟังก์ชัน

function myFunc() {
  console.log(this.str)
}
const myContext = {str: "my context"}
const boundFunc = myFunc.bind(myContext);
boundFunc(); // "my context"

12

อีกตัวอย่างพื้นฐาน:

ไม่ทำงาน:

var img = new Image;
img.onload = function() {
   this.myGlobalFunction(img);
};
img.src = reader.result;

ที่ทำงาน:

var img = new Image;
img.onload = function() {
   this.myGlobalFunction(img);
}.bind(this);
img.src = reader.result;

ดังนั้นโดยพื้นฐาน: เพียงเพิ่ม. ผูก (นี่) ในฟังก์ชันของคุณ


นี่ควรเป็นคำตอบที่ยอมรับได้ ไวยากรณ์ง่ายขึ้นมากในใจ ... ทำได้ดีมาก Joery
nenea
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.