ตั้งค่าตัวแปร“ นี่” ได้อย่างง่ายดายหรือไม่


139

ฉันมีความเข้าใจ Javascript ค่อนข้างดียกเว้นว่าฉันไม่สามารถหาวิธีที่ดีในการตั้งค่าตัวแปร "this" พิจารณา:

var myFunction = function(){
    alert(this.foo_variable);
}

var someObj = document.body; //using body as example object
someObj.foo_variable = "hi"; //set foo_variable so it alerts

var old_fn = someObj.fn;   //store old value
someObj.fn = myFunction;   //bind to someObj so "this" keyword works
someObj.fn();              
someObj.fn = old_fn;       //restore old value

มีวิธีการทำเช่นนี้โดยไม่ต้อง 4 บรรทัดสุดท้ายหรือไม่? มันค่อนข้างน่ารำคาญ ... ฉันได้ลองผูกฟังก์ชั่นที่ไม่ระบุตัวตนซึ่งฉันคิดว่ามันสวยงามและฉลาด แต่ก็ไม่มีประโยชน์:

var myFunction = function(){
    alert(this.foo_variable);
}

var someObj = document.body;        //using body as example object
someObj.foo_variable = "hi";        //set foo_variable so it alerts
someObj.(function(){ fn(); })();    //fail.

เห็นได้ชัดว่าการส่งผ่านตัวแปรไปยังฟังก์ชั่นของฉันเป็นตัวเลือก ... แต่นั่นไม่ใช่ประเด็นของคำถามนี้

ขอบคุณ

คำตอบ:


221

มีสองวิธีที่กำหนดไว้สำหรับการทำงานทั้งหมดใน JavaScript เป็นและcall() apply()ไวยากรณ์ของฟังก์ชันดูเหมือนว่า:

call( /* object */, /* arguments... */ );
apply(/* object */, /* arguments[] */);

อะไรฟังก์ชันเหล่านี้ทำคือการเรียกใช้ฟังก์ชันที่พวกเขาถูกเรียกในการกำหนดค่าของวัตถุพารามิเตอร์นี้

var myFunction = function(){
    alert(this.foo_variable);
}
myFunction.call( document.body );

3
นอกจากนี้หากคุณใช้ jQuery คุณสามารถใช้$.proxy(function, element)เพื่อที่ว่าเมื่อใดก็ตามที่เรียกใช้ฟังก์ชันนั้นฟังก์ชันนั้นจะอยู่ในบริบทขององค์ประกอบ api.jquery.com/jquery.proxy
Trevin Avery

อีกวิธีที่มีประโยชน์คือ.bind()
Soroush Falahati

55

ฉันคิดว่าคุณกำลังมองหาcall:

myFunction.call(obj, arg1, arg2, ...);

นี้เรียกร้องmyFunctionกับชุดthisobj

นอกจากนี้ยังมีวิธีที่แตกต่างกันเล็กน้อยapplyซึ่งใช้พารามิเตอร์ฟังก์ชั่นเป็นอาร์เรย์:

myFunction.apply(obj, [arg1, arg2, ...]);

1
ดูหัวข้อ 15.3.4.3, 15.3.4.4 และ 10.1.8 ในข้อมูลจำเพาะภาษา ECMAScript: ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
บาง

18

หากคุณต้องการ 'เก็บ' thisค่าของฟังก์ชั่นเพื่อให้คุณสามารถเรียกมันได้อย่างราบรื่นในภายหลัง (เช่นเมื่อคุณไม่สามารถเข้าถึงค่านั้นได้อีกต่อไป) คุณสามารถทำได้bind(ไม่สามารถใช้ได้ในทุกเบราว์เซอร์):

var bound = func.bind(someThisValue);

// ... later on, where someThisValue is not available anymore

bound(); // will call with someThisValue as 'this'

7
FYI bindใช้ได้เห็นได้ชัดใน IE9 + FF4 +, Safari และ Chrome 5.1.4+ 7+ (ต้นฉบับ) นอกจากนี้คุณยังสามารถเรียกการผูกโดยตรงกับฟังก์ชั่นที่ไม่ระบุชื่อ:var myFunction = function(){ /* this = something */ }.bind(something);
Adam

1

การค้นหาของฉันเกี่ยวกับการผูกthisพาฉันมาที่นี่ดังนั้นฉันโพสต์สิ่งที่ฉันค้นพบ: ใน 'ECMAScript 2015' เรายังสามารถตั้งค่าคำศัพท์นี้โดยใช้ฟังก์ชั่นลูกศรเป็น

โปรดดู: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions

แทน:

function Person() {
  setInterval(function growUp() {
    // The callback refers to the `self` variable of which
    // the value is the expected object.
    this.age++;
  }.bind(this), 1000);
}

ตอนนี้เราสามารถทำได้:

function Person(){
  this.age = 0;

  setInterval(() => {
    this.age++; // |this| properly refers to the person object
  }, 1000);
}

var p = new Person();

0

การตั้งค่าthisคำหลักใน javascript

Javascript มี 3 วิธีในการตั้งค่าthisคำหลักอย่างสะดวก ตั้งอยู่บนFunction.prototypeวัตถุดังนั้นทุกฟังก์ชั่นสามารถใช้งานได้ (เนื่องจากทุกฟังก์ชั่นสืบทอดจากต้นแบบนี้ผ่านการสืบทอดต้นแบบ) ฟังก์ชั่นเหล่านี้มีดังต่อไปนี้:

  1. Function.prototype.call(): ฟังก์ชั่นนี้ใช้วัตถุที่คุณต้องการใช้เป็นthisอาร์กิวเมนต์แรก จากนั้นส่วนที่เหลือของข้อโต้แย้งเป็นข้อโต้แย้งตามลำดับของฟังก์ชั่นที่เรียกว่า
  2. Function.prototype.apply(): ฟังก์ชั่นนี้ใช้วัตถุที่คุณต้องการใช้เป็นthisอาร์กิวเมนต์แรก จากนั้นอาร์กิวเมนต์ที่สองคืออาร์เรย์ที่มีค่าของอาร์กิวเมนต์ของฟังก์ชันที่เรียกว่า (องค์ประกอบแรกของอาร์เรย์คืออาร์กิวเมนต์แรกของฟังก์ชันอาร์กิวเมนต์ที่สองของอาร์เรย์คืออาร์กิวเมนต์ที่สองของฟังก์ชันเป็นต้น)
  3. Function.prototype.bind(): thisฟังก์ชั่นนี้จะส่งกลับฟังก์ชันใหม่ที่มีค่าที่แตกต่างกันของ ใช้วัตถุที่คุณต้องการตั้งthisค่าเป็นอาร์กิวเมนต์แรกแล้วส่งกลับวัตถุฟังก์ชั่นใหม่

ความแตกต่างระหว่างการโทร / สมัครและผูก:

  • callและapplyมีความคล้ายคลึงกันในความจริงที่ว่าพวกเขาเรียกใช้ฟังก์ชันได้ทันที (ด้วยค่าที่กำหนดไว้ล่วงหน้าของthis)
  • bindแตกต่างจากcallและapplyในความจริงที่ว่าฟังก์ชั่นนี้จะส่งกลับฟังก์ชั่นใหม่ที่มีผลผูกพันที่แตกต่างกันของthisค่า

ตัวอย่าง:

const thisObj = {
  prop1: 1,
  prop2: 2,
};

function myFunc(arg1, arg2) {
  console.log(this.prop1, this.prop2);
  console.log(arg1, arg2);
}

// first arg this obj, other arguments are the  
// respective arguments of the function
myFunc.call(thisObj, 'Call_arg1', 'Call_arg2');

// first arg this obj, other argument is an array which  
// are the respective arguments of the function
myFunc.apply(thisObj, ['Apply_arg1', 'Apply_arg2']);


// the bind method returns a new function with a different
// this context which is stored in the newMyFunc variable
const newMyFunc = myFunc.bind(thisObj);

// now we can call the function like a normal function 
newMyFunc('first', 'second');

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