Baseline Widely available
apply()
æ¹æ³æå¼å«ä¸å以 this ç代表å¼åä¸åé£åå½¢å¼çå¼çµï¼ææ¯ä¸å array-like objectï¼çºåæ¸çå½å¼ã
åè¨»ï¼ éåå½å¼çèªæ³å call()
å¹¾ä¹ä¸æ¨£ï¼æå¤§çä¸åæ¯ call()
æ¥åä¸é£ä¸²ç忏ï¼è apply()
æ¥åä¸çµé£åå½¢å¼ç忏ã
fun.apply(thisArg, [argsArray])
忏
thisArg
è® fun
å¼å«æå¯ä»¥è¦çº this çå¼ã注æï¼éå¯è½ä¸¦ä¸æ¯æå¾æå¨æ¹æ³è£¡çè¦çå¼ï¼å¦æéæ¯ä¸åå¨é non-strict mode ä¸éä½çç¨å¼ç¢¼ï¼null
å undefined
å°æè¢«å
¨åç©ä»¶å代ï¼èåå§é¡å¥å°è¢«å°è£ã
argsArray
ä¸å array-like ç©ä»¶ ï¼å®ç¾©äº fun
è¦å¼å«çä¸çµåæ¸ï¼å¦ææ²æéè¦æä¾ï¼å¯ä»¥å³å
¥ null
æ undefined
ãå¾ ECMAScript 5 éå§ï¼éäºåæ¸ä¸å
å¯ä»¥æ¯æ³åç array-like ç©ä»¶ï¼èä¸ä¸å®è¦æ¯ä¸çµé£åãæ¥ç䏿¹çç覽å¨ç¸å®¹æ§è³è¨ã
å³å
¥ this
å¼åä¸çµåæ¸å¾å¾å°ççµæã
å¨å¼å«ä¸åç¾åçå½å¼æï¼ä½ å¯ä»¥å³å
¥ä¸åç this
ç©ä»¶å¼ãthis åèå°ç¾å¨çç©ä»¶ï¼ä¹å°±æ¯æ£å¨å·è¡çç©ä»¶ãapply è®ä½ å¯ä»¥åªå¯«ä¸æ¬¡æ¹æ³å¾ï¼è®å
¶ä»ç©ä»¶ä¹ç¹¼æ¿å°éåæ¹æ³ï¼èä¸ç¨ä¸åé寫ã
apply
è call()
é常ç¸ä¼¼ï¼ä¸åçæ¯æ¯æ´çå³å
¥åæ¸é¡åã使ç¨é£åå½¢å¼ç忏ï¼è䏿¯å½åéçæ¥æ¶åæ¸ãä½¿ç¨ apply
æï¼ä½ å¯ä»¥é¸æä½¿ç¨é£å實åï¼fun.apply(this, ['eat', 'bananas']);
ææ¯ Array
ç©ä»¶ï¼fun.apply(this, new Array('eat', 'bananas'))
ã
餿¤ä¹å¤ï¼ä½ ä¹å¯ä»¥ä½¿ç¨ arguments
代表 argsArray
忏ãarguments æ¯å¨å½å¼è£¡çååè®æ¸ï¼å¯ç¨ä¾ååæææ²æç¹å¥è¢«æå¼å«ç©ä»¶æå®çå³å
¥åæ¸ãå æ¤ï¼ä½¿ç¨ apply æä½ ä¸éè¦ç¥éæå¼å«å½å¼çæå®åæ¸ãä½¿ç¨ arguments
æææåæ¸å³å
¥å¼å«çæ¹æ³è£¡ï¼è被å¼å«çæ¹æ³ææ¥æèçéäºåæ¸ã
å¾ ECMAScript 5th çæ¬å¾ï¼ä¹å¯ä»¥ä½¿ç¨é£åå½¢å¼çç©ä»¶ï¼å¨å¯¦è¸ä¸éä»£è¡¨ä»æææ length
以忴æ¸ç¯å (0...length-1)
ç屬æ§ãèä¾ä¾èªªï¼ä½ å¯ä»¥ä½¿ç¨ NodeList
ææ¯ä¸åå鿍£çèªå®ç¾©å±¬æ§ï¼{ 'length': 2, '0': 'eat', '1': 'bananas' }
ã
åè¨»ï¼ ä¸è¬ç覽å¨ï¼å æ¬ Chrome 14 å Internet Explorer 9ï¼ä»ä¸æ¯æ´é£åå½¢å¼çç©ä»¶ï¼æä»¥æå°æ¤ä¸åºä¸åé¯èª¤ã
ç¯ä¾ 使ç¨apply
è建æ§åéçµ
ä½ å¯ä»¥ä½¿ç¨ apply
éçµ constructors ä¸åç©ä»¶ï¼è Java ç¸ä¼¼ï¼å¦ä¸ç¯ä¾ä¸æåå¯ä»¥å»ºç«ä¸åå
¨åç Function
æ¹æ³å« construct
ï¼ä½¿ä½ å¯ä»¥ä½¿ç¨é¡é£åçç©ä»¶è建æ§å廿¿ä»£åæ¸å表ã
Function.prototype.construct = function (aArgs) {
var oNew = Object.create(this.prototype);
this.apply(oNew, aArgs);
return oNew;
};
åè¨»ï¼ å¦ä¸ç¯ä¾ç Object.create()
æ¹æ³æ¯å±¬æ¼æ¯è¼æ°ç寫æ³ãå¦é使ç¨éå
çæ¿ä»£æ¹æ³ï¼è«åè以ä¸çç¯ä¾ï¼
Function.prototype.construct = function (aArgs) {
var fConstructor = this,
fNewConstr = function () {
fConstructor.apply(this, aArgs);
};
fNewConstr.prototype = fConstructor.prototype;
return new fNewConstr();
};
使ç¨ç¯ä¾ï¼
function MyConstructor() {
for (var nProp = 0; nProp < arguments.length; nProp++) {
this["property" + nProp] = arguments[nProp];
}
}
var myArray = [4, "Hello world!", false];
var myInstance = MyConstructor.construct(myArray);
console.log(myInstance.property1); // logs 'Hello world!'
console.log(myInstance instanceof MyConstructor); // logs 'true'
console.log(myInstance.constructor); // logs 'MyConstructor'
åè¨»ï¼ This non-native Function.construct
method will not work with some native constructors (like Date
, for example). In these cases you have to use the Function.prototype.bind
method (for example, imagine having an array like the following, to be used with Date
constructor: [2012, 11, 4]
; in this case you have to write something like: new (Function.prototype.bind.apply(Date, [null].concat([2012, 11, 4])))()
â anyhow this is not the best way to do things and probably should not be used in any production environment).
apply
æ¼å
§å»ºç彿¸
apply å¯ä»¥å·§å¦ç卿äºä»»åä¸ä½¿ç¨å
§å»ºå½æ¸ï¼å¦åå¯è½æå¾ªç°éæ·æ´åé£åä¾å¯«å
¥ãå¦ä¸ç¯ä¾ï¼æåä½¿ç¨ Math.max/Math.min
便¾åºé£å䏿大/æå°çå¼ã
// 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);
// vs. simple loop based algorithm
((max = -Infinity), (min = +Infinity));
for (var i = 0; i < numbers.length; i++) {
if (numbers[i] > max) {
max = numbers[i];
}
if (numbers[i] < min) {
min = numbers[i];
}
}
But beware: in using apply
this way, you run the risk of exceeding the JavaScript engine's argument length limit. The consequences of applying a function with too many arguments (think more than tens of thousands of arguments) vary across engines (JavaScriptCore has hard-coded argument limit of 65536), because the limit (indeed even the nature of any excessively-large-stack behavior) is unspecified. Some engines will throw an exception. More perniciously, others will arbitrarily limit the number of arguments actually passed to the applied function. (To illustrate this latter case: if such an engine had a limit of four arguments [actual limits are of course significantly higher], it would be as if the arguments 5, 6, 2, 3
had been passed to apply
in the examples above, rather than the full array.) If your value array might grow into the tens of thousands, use a hybrid strategy: apply your function to chunks of the array at a time:
function minOfArray(arr) {
var min = Infinity;
var QUANTUM = 32768;
for (var i = 0, len = arr.length; i < len; i += QUANTUM) {
var submin = Math.min.apply(null, arr.slice(i, Math.min(i + QUANTUM, len)));
min = Math.min(submin, min);
}
return min;
}
var min = minOfArray([5, 6, 2, 3, 7]);
Using apply in "monkey-patching"
Apply can be the best way to monkey-patch a built-in function of Firefox, or JS libraries. Given someobject.foo
function, you can modify the function in a somewhat hacky way, like so:
var originalfoo = someobject.foo;
someobject.foo = function () {
// Do stuff before calling function
console.log(arguments);
// Call the function as it would have been called normally:
originalfoo.apply(this, arguments);
// Run stuff after, here.
};
This method is especially handy where you want to debug events, or interface with something that has no API like the various .on([event]...
events, such as those usable on the Devtools Inspector).
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4