შემთხვევით რაღაც JavaScript კოდის გარჩევისას თვალი მოვკარი მსგავს: func.call() და func.apply() კოდს. თავიდან არ მივაქციე ყურადღება მაგრამ რამდენიმე დღის შემდეგ სხვა ადგილას მოვკარი თვალი იგივე ტიპის კოდს, თუმცა პირველად და მეორედ ნანახ კოდს ერთმანეთთან კავშირი არ ქონდა. დავინტერესდი და მოვიძიე ინფორმაცია ამ ორი მეთოდის call() და apply() – ს შესახებ და აღმოვაჩინე რომ…
თურმე ყველა ფუნქციას გააჩნია call() და apply() მეთოდი, (JavaScript – ში ხომ ყველაფერი ობიექტია, თვით ფუნქციაც ასე რომ ფუნქციას სავსებით შეიძლება გააჩნდეს მეთოდები). ეს მეთოდები ფუნქციის ისე გამოძახების საშულებას გვაძლევს თითქოს ეს ფუნქცია სხვა რომელიმე ობიექტის მეთოდი იყოს.
ტესტირების მიზნით დავწერე ასეთი სკრიპტი:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | function test() { this.variable = "test"; this.member(); } function testParams(paramOne, paramTwo) { this.memberParams(paramOne, paramTwo); } var objOne = { member: function() { alert(this.variable); }, memberParams: function(paramOne, paramTwo) { alert(paramOne + " - " + paramTwo); } } //call test() test.call(objOne); //call tetsParams() testParams.call(objOne, 'paramOne test', 'paramTwo test'); |
თუ კოდს დააკვირდებით დაინახავთ რომ test() ფუნქცია ოდნავ უცნაურად გამოიყურება, კერძოდ კი this.member() მეთოდის გამოძახება, რადგან test() ფუნქციაში მსგავსი წევრი არ არსებობს. member() მეთოდი სინამდვილეში objOne ობიექტის წევრია და მას არანაირი კავშირი არ აქვს test() ფუნქციასთან (გარდა იმისა რომ test() ფუნქცია გლობალურია და member() მეთოდს მასზე წვოდამ გააჩნია). თავის მხრივ თუ დავაკვრიდებით member() მეთოდს ისიც უცნაურად გამოიყურება რადგანდ objOne ობიექტს არანაირი “variable” წევრი არ გააჩნია, თუმცა ცვლადს იგივე სახელით test() ფუნქციაში ვხედავთ.
ამ კოდის test.call(objOne); შესრულების რეზულტატი კი აბსოლუტურად სწორია და test() ფუნქცია წარმატებით იძახებს member() მეთოდს ისე თითქოს ის მისი წევრი მეთოდი იყოს, ხოლო member() ფუნქციას წვდომა გააჩნია “variable” ცვლადზე თითქოს ეს ცვლადი objOne ობიექტის წევრი იყოს.
რა ხდება სინამდვილეში? როგორც ზემოთ ავღნიშნე call() მეთოდი ფუნქციის (ამ შემთხვევაში test() ფუნქცია) ისე გამოძახების საშულებას გვაძლევს თითქოს ეს ფუნქცია სხვა რომელიმე ობიექტის (ამ შემთხვევაში objOne ობიექტი) მეთოდი იყოს. იგივე ეხება apply() მეთოდსაც.
უფრო მეტი სიცხადისათვის პირველი მაგალითი შეგვიძლია გადავწეროთ ასე:
1 2 3 4 5 6 7 8 9 10 11 | var objTwo = { variable: "test simple", test: function() { this.member(); }, member: function() { alert(this.variable); } } objTwo.test(); |
თუ შევასრულებთ ამ კოდს დავინახავთ რომ რეზულტატი იდენტურია პირველად შესრულებული კოდისა.
რა განსხვავებაა call() და apply() მეთოდებს შორის? ერთადერი განსხვავება რაც ამ ორ მეთოდს შორის არის ეხება პარამეტრებს. call() მეთოდის გამოყენების შემთხვევაში, თუ გამოძახებულ ფუნქციას გვინდა გადავცეთ პარამეტრი ან პარამეტრები კოდი დაიწერება ასე tetsParams.call(objOne, ‘paramOne test’, ‘paramTwo test’); ანუ პარამეტრები გამოიყოფა ტრადიციულად მძიმით. ხოლო apply() მეთოდის გამოყენების შემთხვევაში კი კოდს უნდა ქონდეს ასეთი სახე: tetsParams.apply(objOne, ['paramOne test', 'paramTwo test']); ანუ პარამეტრები გამოძახებულ ფუნქციას უნდა გადაეცეს მასივის სახით.
ტეგები: JavaScript, JavaScript WTF
ძალიან საინტერესო სტატიაა, დიდი მადლობა
[...] გამოსავალი მდგომარეობს ფუნქციის call მეთოდის გამოყენებაში(იხ. პოსტი call და apply მეთოდების შესახებ). [...]
[...] თუ კოდის ეს ნაწილი მაინც გაუგებარია თქვენთვის გირჩევთ გადაიკითხოთ ფუნქციის call და apply მეთოდების შესახებ ჩემს მიერ რამდენიმე წლის წინ დაწერილი პოსტი. [...]