ඇමතුම සහ අයදුම් කිරීම අතර ඇති වෙනස කුමක්ද?


3110

ශ්‍රිතයක් භාවිතා කිරීම callසහ applyකැඳවීම අතර ඇති වෙනස කුමක්ද?

var func = function() {
  alert('hello!');
};

func.apply(); එදිරිව func.call();

ඉහත සඳහන් ක්‍රම දෙක අතර කාර්ය සාධන වෙනස්කම් තිබේද? විට එය භාවිතා කිරීමට හොඳම callකට applyසහ අනෙක් අතට?


727
aආග්ස් පෙළක් සඳහා ඉල්ලුම් කිරීමට සහ ආග් cතීරු සඳහා කැඳවීමට සිතන්න .
ලැරී සටන

176
Ar ලැරීබැට්ල් මම බොහෝ දුරට එක හා සමානයි, නමුත් මම සිතන්නේ අරා සඳහා ඉල්ලුම් කරන අතර කොමාව සඳහා කැඳවීමේදී (එනම් කොමා වලින් වෙන් කරන ලද තර්ක).
සමී

3
මම එකඟයි ඒක මෝඩ වැඩක් කියලා. කරදරකාරී දෙය නම් සම්මුඛ සාකච්ඡා අතරතුර කෙසේ හෝ මෙම ප්‍රශ්නය ඇසීමයි. මන්දයත් සමහර බලගතු චම්ප් ඔවුන්ගේ වැදගත් js ප්‍රශ්න ලැයිස්තුවට ප්‍රශ්නය එක් කළ බැවිනි.
රින්ගෝ

6
ඔබ අයදුම් (එක් තර්කයක්), ඔබ [දුරකතන] වරක් රැකියාවක් ඇමතුමක් ජනතාව බොහෝ වතාවක් (තර්ක කිහිපයක්). විකල්ප: බොහෝ කෝල් ඔෆ් ඩියුටි ක්‍රීඩා තිබේ.
ග්‍රාස් ඩබල්

1
"මෙම" අගය නොසලකා තර්ක අගයන් ලැයිස්තුවක් සහිත විචල්‍ය ශ්‍රිතයක් යෙදීමට අදහස් කරන විට, ඊඑස් 6 පැතිරුම් ක්‍රියාකරු භාවිතා කරන්න, උදා: fn(...input)ආදානය අරාවකි. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
Gajus

Answers:


3653

වෙනස වන්නේ අරාව ලෙස applyශ්‍රිතය කැඳවීමට ඔබට ඉඩ සලසයි arguments; callපරාමිතීන් පැහැදිලිව ලැයිස්තුගත කිරීම අවශ්‍ය වේ. ප්රයෝජනවත් mnemonic වේ " සඳහා වූ rray හා සී සඳහා omma."

අයදුම් කිරීම සහ ඇමතීම පිළිබඳ MDN හි ලේඛන බලන්න .

ව්‍යාජ වාක්‍ය ඛණ්ඩය:

theFunction.apply(valueForThis, arrayOfArgs)

theFunction.call(valueForThis, arg1, arg2, ...)

ES6 වන විට, ශ්‍රිතය spreadසමඟ අරාව සඳහා ඇති callහැකියාව ද ඇත, ඔබට මෙහි අනුකූලතා දැකිය හැකිය .

නියැදි කේතය:

function theFunction(name, profession) {
    console.log("My name is " + name + " and I am a " + profession +".");
}
theFunction("John", "fireman");
theFunction.apply(undefined, ["Susan", "school teacher"]);
theFunction.call(undefined, "Claude", "mathematician");
theFunction.call(undefined, ...["Matthew", "physicist"]); // used with the spread operator


25
එකතු කළ යුතු එක් දෙයක් නම්, ආග්ස් සංඛ්‍යාත්මක අරාව ([]) විය යුතුය. සහායක අරා ({}) ක්‍රියා නොකරනු ඇත.
කෙවින් ෂ්‍රෝඩර්

326
@KevinSchroeder: ජාවාස්ක්රිප්ට් ව්යවහාරයේ දී []හැඳින්වෙන්නේ අරාව , {}හැඳින්වෙන්නේ වස්තුව .
මාර්ටිජන්

89
මම බොහෝ විට අමතක කර දැමුවේ කුමන අරාවක් ගත යුතුද යන්න සහ ඔබ තර්ක ලැයිස්තුගත කිරීමට අපේක්ෂා කරන දේ. සමග මෙම ක්රමය ආරම්භ පළමු ලිපිය නම් මම එය මතක තබා ගැනීමට යොදා ඒ තාක්ෂණය වන්නේ එය එසේ නම් එය එනම් රැසක් ගනී වූ pply අරා
අසීස් punjani

16
භාවිතා කරමින් @SAM ඇමතුමක් ඔබ අගය වෙනස් කිරීමට අවශ්ය නම් ඒ වෙනුවට සාමාන්ය කාර්යය ඇමතුමක් පමණක් තේරුමක් මෙම උත්සවයට ඇමතුමක් සඳහා. උදාහරණයක් (ශ්‍රිත තර්ක-වස්තුව අරාවකට පරිවර්තනය කරන): Array.prototype.slice.call(arguments)හෝ [].slice.call(arguments). ඔබට අරාවෙහි තර්ක තිබේ නම් අයදුම් කිරීම අර්ථවත් කරයි, උදාහරණයක් ලෙස එකම පරාමිතීන් සහිත (පාහේ) වෙනත් ශ්‍රිතයක් කැඳවන ශ්‍රිතයක. නිර්දේශයfuncname(arg1) ඔබට අවශ්‍ය දේ කරන්නේ නම් සාමාන්‍ය ක්‍රියාකාරී ඇමතුමක් භාවිතා කරන්න , සහ ඇමතුම සුරකින්න සහ ඔබට විශේෂ අවස්ථා අවශ්‍ය වූ විට ඒවා ඉල්ලුම් කරන්න.
සමහර

4
@KunalSingh දෙකම callහා applyපරාමිතීන් දෙක ගනී. apply' and ඇමතුම් ශ්‍රිතයේ පළමු තර්කය හිමිකරු වස්තුව විය යුතු අතර දෙවන පරාමිතිය පිළිවෙලින් අරාව හෝ කොමාවෙන් වෙන් කළ පරාමිතීන් වේ. ඔබ සමත් වුවහොත් nullහෝ undefinedපළමු තර්කය ලෙස දැඩි නොවන ආකාරයෙන් ඒවා ගෝලීය වස්තුවෙන් ප්‍රතිස්ථාපනය වේwindow
ඒ. ජේ. කර්ෂි

229

කේ. ස්කොට් ඇලන්ට මේ කාරණය සම්බන්ධයෙන් හොඳ ලිවීමක් තිබේ.

මූලික වශයෙන්, ඔවුන් ක්‍රියාකාරී තර්ක හසුරුවන ආකාරය අනුව වෙනස් වේ.

අයදුම් කරන්න () ක්‍රමය ඇමතුමට සමාන වේ () අයදුම් කිරීම හැර () දෙවන පරාමිතිය ලෙස අරාවක් අවශ්‍ය වේ. අරාව ඉලක්ක ක්‍රමය සඳහා වන තර්ක නියෝජනය කරයි.

ඒ නිසා:

// assuming you have f
function f(message) { ... }
f.call(receiver, "test");
f.apply(receiver, ["test"]);

42
අයදුම් කිරීමේ () සහ ඇමතුම () හි දෙවන පරාමිතිය අත්‍යවශ්‍ය නොවේ, අවශ්‍ය නොවේ.
කෝපාවි කිවි

34
පළමු පරාමිතිය ද අවශ්‍ය නොවේ.
ඉක්රොම්

K ඉක්‍රොම්, පළමු පරාමිතිය අවශ්‍ය නොවන callනමුත් අවශ්‍යතාවයක් apply
iamcastelli

160

එක් එක් ශ්‍රිතය භාවිතා කළ යුත්තේ කවදාද යන්න පිළිබඳ කොටසට පිළිතුරු සැපයීම සඳහා, applyඔබ සම්මත කරන තර්ක ගණන ඔබ නොදන්නේ නම් හෝ ඒවා දැනටමත් අරාවෙහි හෝ අරාව වැනි වස්තුවක තිබේ නම් ( argumentsඔබේම තර්ක ඉදිරිපත් කිරීමට වස්තුව වැනි) භාවිතා කරන්න. callඅරාව තුළ තර්ක එතීමට අවශ්‍ය නොවන බැවින් වෙනත් ආකාරයකින් භාවිතා කරන්න .

f.call(thisObject, a, b, c); // Fixed number of arguments

f.apply(thisObject, arguments); // Forward this function's arguments

var args = [];
while (...) {
    args.push(some_value());
}
f.apply(thisObject, args); // Unknown number of arguments

මම කිසිදු තර්කයක් ඉදිරිපත් නොකරන විට (ඔබේ උදාහරණය මෙන්), මම ශ්‍රිතය කැඳවනcall බැවින් මම කැමැත්තෙමි . එයින් කියවෙන්නේ ඔබ (නොපවතින) තර්ක සඳහා ශ්‍රිතය යොදන බවයි.apply

සමහර විට ඔබ applyඅරාව අරාවෙහි භාවිතා කර ඔතා ඇත්නම් හැර වෙනත් කාර්ය සාධන වෙනස්කම් නොතිබිය යුතුය (උදා: f.apply(thisObject, [a, b, c])ඒ වෙනුවට f.call(thisObject, a, b, c)). මම එය අත්හදා බලා නැත, එබැවින් වෙනස්කම් තිබිය හැකිය, නමුත් එය බ්‍රව්සරයට විශේෂිත වේ. එය විය හැකි දෙයක් callඔබ දැනටමත් සැරසී තර්ක ඇති අතර නැති නම් වේගවත් වේ applyකරන්නේ නම්, වේගවත් වේ.


112

මෙන්න හොඳ සිහිවටනයක්. Pply එකක් A rarays භාවිතා කරන අතර A lways තර්ක එකක් හෝ දෙකක් ගනී. ඔබ භාවිතා කරන විට සී කිරීමට ඔබ සියලු සී තර්ක සංඛ්යාව ount.


2
ප්‍රයෝජනවත් සිහිවටන එතනම! පළමු හෝ දෙවන පරාමිතීන් applyඅවශ්‍ය නොවන බැවින් 'උපරිම තර්ක දෙකක්' යැයි පැවසීමට මම 'තර්ක එකක් හෝ දෙකක්' වෙනස් කරමි . මම එක් කතා ඇයි නමුත් විශ්වාස නෑ applyහෝ callපරාමිතිය තොරව. මෙහි ඇති හේතුව සොයා ගැනීමට යමෙකු උත්සාහ කරන බවක් පෙනේ. Stackoverflow.com/questions/15903782/…
dantheta

92

මෙය පැරණි මාතෘකාවක් වන අතර, මට පෙන්වා දීමට අවශ්‍ය වූයේ .කෝල් .ප්ලයිට වඩා තරමක් වේගවත් බවය. ඇයි කියලා මට හරියටම කියන්න බැහැ.

JsPerf, http://jsperf.com/test-call-vs-apply/3 බලන්න


[ UPDATE!]

ඩග්ලස් ක්‍රොක්ෆර්ඩ් මේ දෙක අතර වෙනස කෙටියෙන් සඳහන් කරයි, එය කාර්ය සාධන වෙනස පැහැදිලි කිරීමට උපකාරී වේ ... http://youtu.be/ya4UHuXNygM?t=15m52s

අයදුම් කිරීම තර්ක රාශියක් ගන්නා අතර ඇමතුම ශුන්‍ය හෝ ඊට වැඩි තනි පරාමිතීන් ගනී! අහ් හාහ්!

.apply(this, [...])

.call(this, param1, param2, param3, param4...)


මෙය පරාමිතීන් / අරාව සමඟ කරන දේ මත රඳා පවතී, එය අරාව සැකසීමට අවශ්‍ය නොවන්නේ නම්, ඊට අඩු කාලයක් ගත වේද?
එරික් හොඩොන්ස්කි

12
අරාව නොමැතිව වුවද ඇමතුම තවමත් වේගවත්ය. jsperf.com/applyvscallvsfn2
ජොෂ් මැක්

Osh ජොෂ්එම්සී එය ඉතා බ්‍රව්සර් විශේෂිත වනු ඇත. IE 11 හි, මම ඇමතුම මෙන් දෙගුණයක් වේගයෙන් ඉල්ලුම් කරමි.
වින්සන්ට් මැක්නාබ්

1
1. නව අරාවක් නිර්මාණය කිරීම යන්නෙන් අදහස් වන්නේ කසළ එකතු කරන්නාට යම් අවස්ථාවක දී එය පිරිසිදු කිරීමට අවශ්‍ය වනු ඇති බවයි. 2. විචල්‍යතාවයකට (පරාමිතියකට) කෙලින්ම ප්‍රවේශ වීමට වඩා විරූපණය භාවිතයෙන් අරාවෙහි ඇති අයිතම වෙත ප්‍රවේශ වීම අඩු කාර්යක්ෂම වේ. (මම විශ්වාස කරන්නේ kmatheny යන්නෙහි අර්ථය “විග්‍රහ කිරීම” යන්නයි. එය ඇත්ත වශයෙන්ම ඊට වඩා වෙනස් දෙයකි.) නමුත් මගේ තර්ක දෙකම jsperf පැහැදිලි නොකරයි. එය එන්ජින් ශ්‍රිත දෙක ක්‍රියාත්මක කිරීම හා සම්බන්ධ විය යුතුය, උදා: ඒවා කිසිවක් සම්මත නොකළේ නම් කෙසේ හෝ හිස් අරා නිර්මාණය කරයි.
joeytwiddle

පරීක්ෂණය සහ වීඩියෝව බෙදාහදා ගැනීමට ස්තූතියි
ගැරී

76

වසා දැමීමෙන් උපුටා ගැනීමක් අනුගමනය කරයි : මයිකල් බොලින් විසින් නිර්වචනය කළ මාර්ගෝපදේශය . එය ටිකක් දිග පෙනුමක් ඇති නමුත් එය විශාල තීක්ෂ්ණ බුද්ධියකින් සංතෘප්ත වේ. "උපග්‍රන්ථය B. නිතර වැරදියට වටහාගෙන ඇති ජාවාස්ක්‍රිප්ට් සංකල්ප" වෙතින්:


thisශ්‍රිතයක් කැඳවූ විට අදහස් කරන්නේ කුමක්ද

පෝරමයේ ශ්‍රිතයක් අමතන විට foo.bar.baz(), වස්තුව foo.barග්‍රාහකය ලෙස හැඳින්වේ. ශ්‍රිතය හැඳින්වූ විට, එහි අගය ලෙස භාවිතා කරන්නේ ග්‍රාහකයයි this:

var obj = {};
obj.value = 10;
/** @param {...number} additionalValues */
obj.addValues = function(additionalValues) {
  for (var i = 0; i < arguments.length; i++) {
    this.value += arguments[i];
  }
  return this.value;
};
// Evaluates to 30 because obj is used as the value for 'this' when
// obj.addValues() is called, so obj.value becomes 10 + 20.
obj.addValues(20);

ශ්‍රිතයක් කැඳවූ විට පැහැදිලි ග්‍රාහකයක් නොමැති නම්, ගෝලීය වස්තුව ග්‍රාහකයා බවට පත්වේ. 47 වන පිටුවේ “goog.global” හි විස්තර කර ඇති පරිදි, වෙබ් බ්‍රව්සරයක ජාවාස්ක්‍රිප්ට් ක්‍රියාත්මක කරන විට කවුළුව යනු ගෝලීය වස්තුවයි. මෙය පුදුම සහගත හැසිරීම් වලට තුඩු දෙයි:

var f = obj.addValues;
// Evaluates to NaN because window is used as the value for 'this' when
// f() is called. Because and window.value is undefined, adding a number to
// it results in NaN.
f(20);
// This also has the unintentional side effect of adding a value to window:
alert(window.value); // Alerts NaN

වුවත් obj.addValuesසහ fඑම කාර්යය වෙත යොමු වන්න, ඔවුන් ලබන්නා වටිනාකම එක් එක් ඇමතුමක් දී වෙනස් නිසා හමු වූ අවස්ථාවේ දී වෙනස් හැසිරීමක්. මෙම හේතුව නිසා, යොමු කරන ශ්‍රිතයක් ඇමතීමේදී this, එය thisකැඳවූ විට එය නිවැරදි අගයක් ඇති බව සහතික කිරීම වැදගත්ය . පැහැදිලිව කිවහොත්, thisක්‍රියාකාරී ශරීරයේ සඳහන් කර නොමැති නම් , f(20)සහ හැසිරීමobj.addValues(20) සමාන වේ.

කාර්යයන් ජාවාස්ක්‍රිප්ට් හි පළමු පන්තියේ වස්තු වන බැවින් ඒවාට ඔවුන්ගේම ක්‍රම තිබිය හැකිය. සියළුම ශ්‍රිතයන්ට ක්‍රමවේදයන් ඇති call()අතර apply()එමඟින් ශ්‍රිතය කැඳවීමේදී ග්‍රාහකය (එනම්, යොමු කරන වස්තුව this) නැවත අර්ථ දැක්වීමට හැකි වේ. ක්‍රම අත්සන් පහත පරිදි වේ:

/**
* @param {*=} receiver to substitute for 'this'
* @param {...} parameters to use as arguments to the function
*/
Function.prototype.call;
/**
* @param {*=} receiver to substitute for 'this'
* @param {Array} parameters to use as arguments to the function
*/
Function.prototype.apply;

සටහන අතර එකම වෙනස call()හා apply()බවයි call()බැවින්ද, මෙම උත්සවය පරාමිතීන් තනි තර්ක ලෙස ලැබෙන apply()තනි මාලාවක් ලෙස ලැබෙන:

// When f is called with obj as its receiver, it behaves the same as calling
// obj.addValues(). Both of the following increase obj.value by 60:
f.call(obj, 10, 20, 30);
f.apply(obj, [10, 20, 30]);

පහත සඳහන් ඇමතුම්, සමාන බැවින් fහා obj.addValuesසමාන කාර්යයක් වෙත යොමු වන්න:

obj.addValues.call(obj, 10, 20, 30);
obj.addValues.apply(obj, [10, 20, 30]);

කෙසේ වෙතත්, ලබන්නාගේ තර්කය නිශ්චිතව දක්වා නොමැති විට එය ආදේශ කිරීම සඳහා තමන්ගේම ග්‍රාහකයේ වටිනාකම call()හෝ apply()භාවිතා නොකරන බැවින් , පහත සඳහන් දෑ ක්‍රියා නොකරනු ඇත:

// Both statements evaluate to NaN
obj.addValues.call(undefined, 10, 20, 30);
obj.addValues.apply(undefined, [10, 20, 30]);

වටිනාකම thisහැකි විය කවදාවත් nullහෝ undefinedඋත්සවයකට නමින් වන විට පමණි. ලබන්නා වෙත හෝ ලබා දෙන විට nullහෝ undefinedලබා දෙන විට , ගෝලීය වස්තුව ඒ වෙනුවට ලබන්නා සඳහා වටිනාකම ලෙස භාවිතා කරයි. එමනිසා, පෙර කේතයට ගෝලීය වස්තුවට නම් කළ දේපලක් එක් කිරීමේ අනවශ්‍ය අතුරු ආබාධ ඇත .call()apply()value

ශ්‍රිතයක් පවරා ඇති විචල්‍යය පිළිබඳ දැනුමක් නොමැති යැයි සිතීම ප්‍රයෝජනවත් විය හැකිය. මෙය අර්ථ දැක්වීමේදී නොව ශ්‍රිතය කැඳවූ විට මෙහි වටිනාකම බැඳී පවතිනු ඇතැයි යන අදහස ශක්තිමත් කිරීමට මෙය උපකාරී වේ.


නිස්සාරණයේ අවසානය.


කාරණය සැලකිල්ලට ගැනීම සඳහා, additionalValuesඑය obj.addValuesශරීරය තුළ සඳහන් නොවේ
වික්ටර් ස්ටොල්බින්

මම දන්නවා ඔබ ප්‍රශ්නයට පිළිතුරු දුන් නමුත් එකතු කිරීමට කැමතියි: f නිර්වචනය කිරීමේදී ඔබට බන්ධනය භාවිතා කළ හැකිය. var f = obj.addValues;බවට පත්වන var f = obj.addValues.bind(obj) අතර දැන් සෑම විටම ඇමතුමක් හෝ අයදුම් කිරීමකින් තොරව f (20) ක්‍රියා කරයි.
ජ්ලිබර්ටි

ඔබ එය ලියා නැති බව මම දනිමි, නමුත් ඔබ පොතේ පෙළ සහ උදාහරණ අදාළ ලෙස ඉස්මතු කර දැක්වූ අතර මම ඉතා කෘත ful වෙමි. ඒවා ඉතා ප්‍රයෝජනවත් විය.
ෆ්‍රල්කොන්

34

එක් වස්තුවකට තවත් වස්තුවක ක්‍රියාකාරිත්වය ණයට ගැනීම ඇතැම් විට ප්‍රයෝජනවත් වේ, එයින් අදහස් කරන්නේ ණයට ගන්නා වස්තුව ණය දීමේ ක්‍රියාව තමන්ගේම ලෙස ක්‍රියාත්මක කරන බවයි.

කුඩා කේත උදාහරණයක්:

var friend = {
    car: false,
    lendCar: function ( canLend ){
      this.car = canLend;
 }

}; 

var me = {
    car: false,
    gotCar: function(){
      return this.car === true;
  }
};

console.log(me.gotCar()); // false

friend.lendCar.call(me, true); 

console.log(me.gotCar()); // true

friend.lendCar.apply(me, [false]);

console.log(me.gotCar()); // false

වස්තූන්ට තාවකාලික ක්‍රියාකාරිත්වය ලබා දීම සඳහා මෙම ක්‍රම ඉතා ප්‍රයෝජනවත් වේ.


1
බලන්න ආකාරය දැන ගැනීමට කැමති අයට console.logපරීක්ෂා කරන්න: console.log යනු කුමක්ද සහ මම එය භාවිතා කරන්නේ කෙසේද?
මයිකල් අයිරෙස්

26

ඇමතුම, අයදුම් කිරීම සහ බැඳීම සමඟ තවත් උදාහරණයක්. ඇමතුම සහ අයදුම් කිරීම අතර වෙනස පැහැදිලිව පෙනේ, නමුත් බයින්ඩ් මේ ආකාරයට ක්‍රියා කරයි:

  1. බයින්ඩ් මඟින් ක්‍රියාත්මක කළ හැකි ශ්‍රිතයක උදාහරණයක් ලබා දෙයි
  2. පළමු පරාමිතිය ' මෙය '
  3. දෙවන පරාමිතිය කොමා මඟින් වෙන් කරන ලද තර්ක ලැයිස්තුවකි ( ඇමතුම වැනි )

}

function Person(name) {
    this.name = name; 
}
Person.prototype.getName = function(a,b) { 
     return this.name + " " + a + " " + b; 
}

var reader = new Person('John Smith');

reader.getName = function() {
   // Apply and Call executes the function and returns value

   // Also notice the different ways of extracting 'getName' prototype
   var baseName = Object.getPrototypeOf(this).getName.apply(this,["is a", "boy"]);
   console.log("Apply: " + baseName);

   var baseName = Object.getPrototypeOf(reader).getName.call(this, "is a", "boy"); 
   console.log("Call: " + baseName);

   // Bind returns function which can be invoked
   var baseName = Person.prototype.getName.bind(this, "is a", "boy"); 
   console.log("Bind: " + baseName());
}

reader.getName();
/* Output
Apply: John Smith is a boy
Call: John Smith is a boy
Bind: John Smith is a boy
*/

23

'ValueForThis' තර්කය භාවිතා කරන උදාහරණයක් පෙන්වීමට මම කැමතියි:

Array.prototype.push = function(element) {
   /*
   Native code*, that uses 'this'       
   this.put(element);
   */
}
var array = [];
array.push(1);
array.push.apply(array,[2,3]);
Array.prototype.push.apply(array,[4,5]);
array.push.call(array,6,7);
Array.prototype.push.call(array,8,9);
//[1, 2, 3, 4, 5, 6, 7, 8, 9] 

** විස්තර: http://es5.github.io/#x15.4.4.7 *


20

ඇමතුම් () කොමා මඟින් වෙන් කරන ලද තර්ක ගනී, උදා:

.call(scope, arg1, arg2, arg3)

සහ අයදුම් කරන්න () තර්ක මාලාවක් ගනී, උදා:

.apply(scope, [arg1, arg2, arg3])

මෙන්න තවත් භාවිත උදාහරණ කිහිපයක්: http://blog.i-evaluation.com/2012/08/15/javascript-call-and-apply/


`// ඇමතුම () === කොමාවෙන් වෙන් කරන ලද තර්ක (තර්ක-ලැයිස්තුව). අමතන්න (මෙය, ආර්ග්ස් 1, ආර්ග්ස් 2, ආර්ග්ස් 3, ...) // අයදුම් කරන්න () === තර්ක පෙළ (අරාව-අයිතම). අයදුම් කරන්න (මෙය, [arr0, arr1, arr2, ...]) `
xgqfrms

19

සිට (Function.prototype.apply මත MDN ලේඛන) :

Apply () ක්‍රමය මඟින් ලබා දී ඇති thisඅගයක් සහිත ශ්‍රිතයක් සහ අරාව (හෝ අරාව වැනි වස්තුවක්) ලෙස දක්වා ඇති තර්ක කැඳවයි .

සින්ටැක්ස්

fun.apply(thisArg, [argsArray])

සිට (Function.prototype.call මත MDN ලේඛන) :

ඇමතුම් () ක්‍රමය මඟින් ලබා දී ඇති thisඅගය සහ ශ්‍රිතයන් තනි තනිව සපයනු ලැබේ.

සින්ටැක්ස්

fun.call(thisArg[, arg1[, arg2[, ...]]])

JavaScript හි Function.apply සහ Function.call වෙතින් :

අයදුම් කරන්න () ක්‍රමය ඇමතුමට සමාන වේ () අයදුම් කිරීම හැර () දෙවන පරාමිතිය ලෙස අරාවක් අවශ්‍ය වේ. අරාව ඉලක්ක ක්‍රමය සඳහා වන තර්ක නිරූපණය කරයි.


කේත උදාහරණය:

var doSomething = function() {
    var arr = [];
    for(i in arguments) {
        if(typeof this[arguments[i]] !== 'undefined') {
            arr.push(this[arguments[i]]);
        }
    }
    return arr;
}

var output = function(position, obj) {
    document.body.innerHTML += '<h3>output ' + position + '</h3>' + JSON.stringify(obj) + '\n<br>\n<br><hr>';
}

output(1, doSomething(
    'one',
    'two',
    'two',
    'one'
));

output(2, doSomething.apply({one : 'Steven', two : 'Jane'}, [
    'one',
    'two',
    'two',
    'one'
]));

output(3, doSomething.call({one : 'Steven', two : 'Jane'},
    'one',
    'two',
    'two',
    'one'
));

මෙම ෆෙඩෙල් ද බලන්න .



10

මෙන්න කුඩා ඊෂ් පෝස්ට් එකක්, මම මේ ගැන ලිව්වා:

http://sizeableidea.com/call-versus-apply-javascript/

var obj1 = { which : "obj1" },
obj2 = { which : "obj2" };

function execute(arg1, arg2){
    console.log(this.which, arg1, arg2);
}

//using call
execute.call(obj1, "dan", "stanhope");
//output: obj1 dan stanhope

//using apply
execute.apply(obj2, ["dan", "stanhope"]);
//output: obj2 dan stanhope

//using old school
execute("dan", "stanhope");
//output: undefined "dan" "stanhope"

මෙන්න තවත් එකක්: blog.i-evaluation.com/2012/08/15/javascript-call-and-apply නමුත් මූලික වශයෙන් එය නිවැරදියි: .කෝල් (විෂය පථය, arg1, arg2, arg3)
මාර්ක් කාර්වොව්ස්කි


6

අපට පහත පරිදි ඇමතුම් සහ අයදුම් කිරීමේ ක්‍රම වෙන්කර හඳුනාගත හැකිය

අමතන්න: තර්කය සහිත ශ්‍රිතයක් තනි තනිව සපයයි. සම්මත කළ යුතු තර්ක ඔබ දන්නේ නම් හෝ සම්මත කිරීමට තර්කයක් නොමැති නම් ඔබට ඇමතුම භාවිතා කළ හැකිය.

අයදුම් කරන්න: අරාව ලෙස සපයා ඇති තර්කය සහිත ශ්‍රිතයක් අමතන්න. ශ්‍රිතයට කොපමණ තර්ක ප්‍රමාණයක් ඉදිරිපත් වේදැයි ඔබ නොදන්නේ නම් ඔබට යෙදුම භාවිතා කළ හැකිය.

App over over call භාවිතා කිරීමේ වාසියක් ඇත, අපට තර්ක ගණන වෙනස් කිරීමට අවශ්‍ය නැත, අපට සම්මත කළ අරාව වෙනස් කළ හැක්කේ අපට පමණි.

කාර්ය සාධනයේ විශාල වෙනසක් නැත. නමුත් ඉල්ලුම් ක්‍රමයට සාපේක්ෂව ඇමතුම තරමක් වේගවත් යැයි අපට පැවසිය හැකිය.


5

ක්‍රම අතර මේවා අතර වෙනස නම්, ඔබට පරාමිතීන් සමත් විය යුතු ආකාරයයි.

“A සඳහා අරාව සහ C සඳහා කොමාව” යනු ඉතා පහසු මතකයකි.


11
වෙනත් පිළිතුරුවල දැනටමත් නිසි ලෙස සපයා නොමැති මෙම පිළිතුර සපයන්නේ කුමක්ද?
කිල්

5

thisශ්‍රිතයක් ක්‍රියාත්මක වන විට අගය බල කිරීම සඳහා අමතන්න සහ යොදන්න . එකම වෙනස නම්, callගනී n+11 කොහෙද තර්ක thisහා 'n' arguments. applyතර්ක දෙකක් පමණක් ගනී, එකක් thisඅනෙක තර්ක අරාවයි.

මා දකින වාසිය applyපුරා callඅප ඉතා පහසුවෙන් බොහෝ උත්සාහයක් තොරව අනෙකුත් ක්රියාකාරීත්වය කාර්යය ඇමතුමක් නියෝජිතයන්ට භාර දිය හැකි බව ය;

function sayHello() {
  console.log(this, arguments);
}

function hello() {
  sayHello.apply(this, arguments);
}

var obj = {name: 'my name'}
hello.call(obj, 'some', 'arguments');

අපි කොහොමද නියෝජිතයකුට නිරීක්ෂණය helloකිරීමට sayHelloභාවිතා apply, නමුත් සමග callමෙම සාක්ෂාත් කර ගැනීම ඉතා දුෂ්කර වී ඇත.


4

වුවත් callසහ applyඑකම දේ විටකය, මම ඔබ භාවිතා නොහැකි කටවත් එක් එක් ස්ථානය සිතන්නේ callපමණක් භාවිතා කළ හැකි apply. එවිට ඔබට උරුමයට සහය දැක්වීමට අවශ්‍ය වන අතර ඉදිකිරීම්කරු අමතන්න.

මෙන්න ශ්‍රිතයක් මඟින් ඔබට පන්ති නිර්මාණය කිරීමට ඉඩ සලසයි.

function makeClass( properties ) {
    var ctor = properties['constructor'] || function(){}
    var Super = properties['extends'];
    var Class = function () {
                 // Here 'call' cannot work, only 'apply' can!!!
                 if(Super)
                    Super.apply(this,arguments);  
                 ctor.apply(this,arguments);
                }
     if(Super){
        Class.prototype = Object.create( Super.prototype );
        Class.prototype.constructor = Class;
     }
     Object.keys(properties).forEach( function(prop) {
           if(prop!=='constructor' && prop!=='extends')
            Class.prototype[prop] = properties[prop];
     });
   return Class; 
}

//Usage
var Car = makeClass({
             constructor: function(name){
                         this.name=name;
                        },
             yourName: function() {
                     return this.name;
                   }
          });
//We have a Car class now
 var carInstance=new Car('Fiat');
carInstance.youName();// ReturnsFiat

var SuperCar = makeClass({
               constructor: function(ignore,power){
                     this.power=power;
                  },
               extends:Car,
               yourPower: function() {
                    return this.power;
                  }
              });
//We have a SuperCar class now, which is subclass of Car
var superCar=new SuperCar('BMW xy',2.6);
superCar.yourName();//Returns BMW xy
superCar.yourPower();// Returns 2.6

තෝරාගත් පිළිතුරෙහි විස්තර කර ඇති පරිදි ඇමතුම පැතිරීමේ ක්‍රියාකරු සමඟ ක්‍රියා කරනු ඇතැයි මම විශ්වාස කරමි. මට යමක් මග හැරුනේ නැත්නම්.
jhliberty

4

සාරාංශය:

දෙකම call()සහ apply()පිහිටා ඇති ක්‍රම වේ Function.prototype. එබැවින් ඒවා සෑම ක්‍රියාකාරී වස්තුවකම මූලාකෘති දාමය හරහා ලබා ගත හැකිය. දෙකම call()සහ apply()නිශ්චිත අගයක් සහිත ශ්‍රිතයක් ක්‍රියාත්මක කළ හැකියthis .

අතර ප්රධාන වෙනස call()සහ apply()ඔබ එය බවට තර්ක සමත් කර තිබීමයි. දෙකෙහිම call()සහ apply()ඔබ පළමු තර්කය ලෙස සම්මත කළ යුත්තේ ඔබට අවශ්‍ය වස්තුව ලෙසය this. අනෙක් තර්ක පහත පරිදි වෙනස් වේ:

  • සමඟ call()ඔබ සාමාන්‍යයෙන් තර්ක ඉදිරිපත් කළ යුතුය (දෙවන තර්කයේ සිට)
  • apply()ඔබ සමඟ තර්ක රාශියක් ඉදිරිපත් කළ යුතුය.

උදාහරණයක්:

let obj = {
  val1: 5,
  val2: 10
}

const summation = function (val3, val4) {
  return  this.val1 + this.val2 + val3 + val4;
}

console.log(summation.apply(obj, [2 ,3]));
// first we assign we value of this in the first arg
// with apply we have to pass in an array


console.log(summation.call(obj, 2, 3));
// with call we can pass in each arg individually

මට මෙම කාර්යයන් භාවිතා කිරීමට අවශ්‍ය ඇයි?

thisසමහර විට ජාවාස්ක්‍රිප්ට් වල වටිනාකම ව්‍යාකූල විය හැකිය. ශ්‍රිතයක් ක්‍රියාත්මක වන විටthis තීරණය කරනු ලබන අගය ශ්‍රිතයක් අර්ථ දක්වන විට නොවේ. අපගේ ක්‍රියාකාරිත්වය නිවැරදි thisබන්ධනයක් මත රඳා පවතී නම් අපට භාවිතා කළ හැකි call()අතර apply()මෙම හැසිරීම බලාත්මක කළ හැකිය. උදාහරණයක් වශයෙන්:

var name = 'unwantedGlobalName';

const obj =  {
  name: 'Willem',
  sayName () { console.log(this.name);}
}


let copiedMethod = obj.sayName;
// we store the function in the copiedmethod variable



copiedMethod();
// this is now window, unwantedGlobalName gets logged

copiedMethod.call(obj);
// we enforce this to be obj, Willem gets logged


4

ප්‍රධාන වෙනස නම්, ඇමතුම භාවිතා කිරීමෙන් අපට විෂය පථය වෙනස් කර සාමාන්‍ය පරිදි තර්ක ඉදිරිපත් කළ හැකි නමුත් අයදුම් කිරීම අරාව ලෙස තර්ක භාවිතා කර එය ඇමතීමට ඉඩ දෙයි (ඒවා අරාව ලෙස සම්මත කරන්න). නමුත් ඔවුන් ඔබේ කේතයේ කළ යුතු දේ අනුව, ඒවා බෙහෙවින් සමාන ය.

මෙම ශ්‍රිතයේ වාක්‍ය ඛණ්ඩය යෙදුම් () ට සමාන වන අතර, මූලික වෙනස වන්නේ ඇමතුම () තර්ක ලැයිස්තුවක් පිළිගන්නා අතර අයදුම් කරන්න () තනි තර්ක මාලාවක් පිළිගනී.

ඔබ දකින පරිදි, විශාල වෙනසක් නොමැත, නමුත් තවමත්, අපි ඇමතුම් () හෝ අයදුම් කිරීමට () භාවිතා කිරීමට කැමති අවස්ථා තිබේ. උදාහරණයක් ලෙස, අයදුම් කිරීමේ ක්‍රමය භාවිතා කරමින් MDN වෙතින් අරාවෙහි කුඩාම හා විශාලතම අංකය සොයා ගන්නා පහත කේතය දෙස බලන්න:

// min/max number in an array
var numbers = [5, 6, 2, 3, 7];

// using Math.min/Math.max apply
var max = Math.max.apply(null, numbers); 
// This about equal to Math.max(numbers[0], ...)
// or Math.max(5, 6, ...)

var min = Math.min.apply(null, numbers)

එබැවින් ප්‍රධාන වෙනස වන්නේ අප තර්ක සම්මත කරන ආකාරයයි:

අමතන්න:

function.call(thisArg, arg1, arg2, ...);

අයදුම් කරන්න:

function.apply(thisArg, [argsArray]);

2

මේ සඳහා කුඩා විස්තරයක් එක් කිරීමට මට ඉඩ දෙන්න.

මෙම ඇමතුම් දෙක බොහෝ දුරට සමාන ය:

func.call(context, ...args); // pass an array as list with spread operator

func.apply(context, args);   // is same as using apply

සුළු වෙනසක් ඇත:

  • මෙම spreadක්රියාකරු ... පසුකර ඉඩ iterable args ඇමතුමක් ගැනීමට ලැයිස්තුවක් ලෙස.
  • මෙම applyපමණක් පිළිගන්නා අරා වැනි args.

ඉතින්, මෙම ඇමතුම් එකිනෙකට අනුපූරක වේ. අපි බලාපොරොත්තු කොහෙද iterable , callඅපි බලාපොරොත්තු එහිදී ක්රියා, වැනි අරාව , applyක්රියා.

සහ දෙකම ඇති වස්තු සඳහා iterable සහ අරා වැනි , සැබෑ මාලාවක් මෙන් අපි තාක්ෂණික ඔවුන් ඕනෑම භාවිතා කළ හැකි නමුත්, අදාළ බොහෝ විට වනු ඇත වේගවත් බොහෝ JavaScript එන්ජින් අභ්යන්තර එය වඩා වඩා හොඳ උපරිම ඵල නිසා.


0

ෆ්ලැට්ලයින් විසින් හොඳින් පැහැදිලි කරන ලද . මට සරල උදාහරණයක් එක් කිරීමට අවශ්‍යයි. එය ආරම්භකයින් සඳහා තේරුම් ගැනීම පහසු කරයි.

func.call(context, args1 , args2 ); // pass arguments as "," saprated value

func.apply(context, [args1 , args2 ]);   //  pass arguments as "Array"

පහත කේතයේ අර්ථ දක්වා ඇති පරිදි යොමු කිරීම වෙනස් කිරීම සඳහා අපි "ඇමතුම්" සහ "අයදුම් කරන්න" ක්‍රමය ද භාවිතා කරමු

    let Emp1 = {
        name: 'X',
        getEmpDetail: function (age, department) {
            console.log('Name :', this.name, '  Age :', age, '  Department :', department)
        }
    }
    Emp1.getEmpDetail(23, 'Delivery')

    // 1st approch of chenging "this"
    let Emp2 = {
        name: 'Y',
        getEmpDetail: Emp1.getEmpDetail
    }
    Emp2.getEmpDetail(55, 'Finance')

    // 2nd approch of changing "this" using "Call" and "Apply"
    let Emp3 = {
        name: 'Z',
    }

    Emp1.getEmpDetail.call(Emp3, 30, 'Admin')        
// here we have change the ref from **Emp1 to Emp3**  object
// now this will print "Name =  X" because it is pointing to Emp3 object
    Emp1.getEmpDetail.apply(Emp3, [30, 'Admin']) //

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.