ФÑнкÑии - клÑÑÐµÐ²Ð°Ñ ÐºÐ¾Ð½ÑепÑÐ¸Ñ Ð² JavaScript. ÐажнейÑей оÑобенноÑÑÑÑ ÑзÑка ÑвлÑеÑÑÑ Ð¿Ð¾Ð´Ð´ÐµÑжка ÑÑнкÑии пеÑвого клаÑÑа (functions as first-class citizen). ÐÑÐ±Ð°Ñ ÑÑнкÑÐ¸Ñ ÑÑо обÑекÑ, и ÑледоваÑелÑно ÐµÑ Ð¼Ð¾Ð¶Ð½Ð¾ манипÑлиÑоваÑÑ ÐºÐ°Ðº обÑекÑом, в ÑаÑÑноÑÑи:
ÐÑо опÑеделÑÐµÑ Ð²ÑÑокÑÑ Ð²ÑÑазиÑелÑнÑÑ Ð¼Ð¾ÑноÑÑÑ JavaScript и позволÑÐµÑ Ð¾ÑноÑиÑÑ ÐµÐ³Ð¾ к ÑиÑÐ»Ñ ÑзÑков, ÑеализÑÑÑÐ¸Ñ ÑÑнкÑионалÑнÑÑ Ð¿Ð°ÑÐ°Ð´Ð¸Ð³Ð¼Ñ Ð¿ÑогÑаммиÑованиÑ.
ФÑнкÑÐ¸Ñ Ð² JavaScript ÑпеÑиалÑнÑй Ñип обÑекÑов, позволÑÑÑий ÑоÑмализоваÑÑ ÑÑедÑÑвами ÑзÑка опÑеделÑннÑÑ Ð»Ð¾Ð³Ð¸ÐºÑ Ð¿Ð¾Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¸ обÑабоÑки даннÑÑ .
ÐÐ»Ñ Ð¿Ð¾Ð½Ð¸Ð¼Ð°Ð½Ð¸Ñ ÑабоÑÑ ÑÑнкÑий Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ (и доÑÑаÑоÑно?) имеÑÑ Ð¿ÑедÑÑавление о ÑледÑÑÑÐ¸Ñ Ð¼Ð¾Ð¼ÐµÐ½ÑÐ°Ñ :
arguments
)Scope
) и замÑÐºÐ°Ð½Ð¸Ñ (Closures
)this
)return
)throw
)garbage collector
)ÐбÑÑвление ÑÑнкÑии (function definition, или function declaration, или function statement) ÑоÑÑÐ¾Ð¸Ñ Ð¸Ð· клÑÑевого Ñлова function
и ÑледÑÑÑиÑ
ÑаÑÑей:
()
и ÑазделÑннÑÑ
запÑÑÑми.{ }
.ÐапÑимеÑ, ÑледÑÑÑий код обÑÑвлÑÐµÑ Ð¿ÑоÑÑÑÑ ÑÑнкÑÐ¸Ñ Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ square:
function square(number) {
return number * number;
}
ФÑнкÑÐ¸Ñ square
пÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ Ð¾Ð´Ð¸Ð½ паÑамеÑÑ, названнÑй number.
СоÑÑÐ¾Ð¸Ñ Ð¸Ð· одной инÑÑÑÑкÑии, коÑоÑÐ°Ñ Ð¾Ð·Ð½Ð°ÑÐ°ÐµÑ Ð²ÐµÑнÑÑÑ Ð¿Ð°ÑамеÑÑ ÑÑой ÑÑнкÑии (ÑÑо number
) ÑмноженнÑй на Ñамого ÑебÑ. ÐнÑÑÑÑкÑÐ¸Ñ return ÑказÑÐ²Ð°ÐµÑ Ð½Ð° знаÑение, коÑоÑÑе бÑÐ´ÐµÑ Ð²Ð¾Ð·Ð²ÑаÑено ÑÑнкÑией.
ÐÑимиÑивнÑе паÑамеÑÑÑ (напÑимеÑ, ÑиÑло) пеÑедаÑÑÑÑ ÑÑнкÑии знаÑением; знаÑение пеÑедаÑÑÑÑ Ð² ÑÑнкÑиÑ, но еÑли ÑÑнкÑÐ¸Ñ Ð¼ÐµÐ½ÑÐµÑ Ð·Ð½Ð°Ñение паÑамеÑÑа, ÑÑо изменение не оÑÑазиÑÑÑ Ð³Ð»Ð¾Ð±Ð°Ð»Ñно или поÑле вÑзова ÑÑнкÑии.
ÐÑли Ð²Ñ Ð¿ÐµÑедадиÑе обÑÐµÐºÑ ÐºÐ°Ðº паÑамеÑÑ (не пÑимиÑив, напÑимеÑ, маÑÑив
или опÑеделÑемÑе полÑзоваÑелем обÑекÑÑ), и ÑÑнкÑÐ¸Ñ Ð¸Ð·Ð¼ÐµÐ½Ð¸Ñ ÑвойÑÑво пеÑеданного в Ð½ÐµÑ Ð¾Ð±ÑекÑа, ÑÑо изменение бÑÐ´ÐµÑ Ð²Ð¸Ð´Ð½Ð¾ и вне ÑÑнкÑии, как показано в ÑледÑÑÑем пÑимеÑе:
function myFunc(theObject) {
theObject.make = "Toyota";
}
var mycar = { make: "Honda", model: "Accord", year: 1998 };
var x, y;
x = mycar.make; // x полÑÑÐ°ÐµÑ Ð·Ð½Ð°Ñение "Honda"
myFunc(mycar);
y = mycar.make; // y полÑÑÐ°ÐµÑ Ð·Ð½Ð°Ñение "Toyota"
// (ÑвойÑÑво бÑло изменено ÑÑнкÑией)
ФÑнкÑии вида "function definition expression"
ФÑнкÑÐ¸Ñ Ð²Ð¸Ð´Ð° "function declaration statement" по ÑинÑакÑиÑÑ ÑвлÑеÑÑÑ Ð¸Ð½ÑÑÑÑкÑией (statement), еÑÑ ÑÑнкÑÐ¸Ñ Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð²Ð¸Ð´Ð° "function definition expression". Ð¢Ð°ÐºÐ°Ñ ÑÑнкÑÐ¸Ñ Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð°Ð½Ð¾Ð½Ð¸Ð¼Ð½Ð¾Ð¹ (она не Ð¸Ð¼ÐµÐµÑ Ð¸Ð¼ÐµÐ½Ð¸). ÐапÑимеÑ, ÑÑнкÑÐ¸Ñ square
Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð²Ñзвана Ñак:
var square = function (number) {
return number * number;
};
var x = square(4); // x полÑÑÐ°ÐµÑ Ð·Ð½Ð°Ñение 16
Ðднако, Ð¸Ð¼Ñ Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¸ пÑиÑвоено Ð´Ð»Ñ Ð²Ñзова Ñамой ÑÐµÐ±Ñ Ð²Ð½ÑÑÑи Ñамой ÑÑнкÑии и Ð´Ð»Ñ Ð¾ÑладÑика (debugger) Ð´Ð»Ñ Ð¸Ð´ÐµÐ½ÑиÑиÑиÑованнÑе ÑÑнкÑии в ÑÑек-ÑÑÐµÐºÐ°Ñ (stack traces; "trace" â "Ñлед" / "оÑпеÑаÑок").
var factorial = function fac(n) {
return n < 2 ? 1 : n * fac(n - 1);
};
console.log(factorial(3));
ФÑнкÑии вида "function definition expression" ÑдобнÑ, когда ÑÑнкÑÐ¸Ñ Ð¿ÐµÑедаÑÑÑÑ Ð°ÑгÑменÑом дÑÑгой ÑÑнкÑии. СледÑÑÑий пÑÐ¸Ð¼ÐµÑ Ð¿Ð¾ÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÑÑнкÑÐ¸Ñ map
, коÑоÑÐ°Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° полÑÑиÑÑ ÑÑнкÑÐ¸Ñ Ð¿ÐµÑвÑм аÑгÑменÑом и маÑÑив вÑоÑÑм.
function map(f, a) {
var result = [], // СоздаÑм новÑй маÑÑив
i;
for (i = 0; i != a.length; i++) result[i] = f(a[i]);
return result;
}
Ð ÑледÑÑÑем коде наÑа ÑÑнкÑÐ¸Ñ Ð¿ÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ ÑÑнкÑиÑ, коÑоÑÐ°Ñ ÑвлÑеÑÑÑ function definition expression, и вÑполнÑÐµÑ ÐµÐ³Ð¾ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ ÑлеменÑа пÑинÑÑого маÑÑива вÑоÑÑм аÑгÑменÑом.
function map(f, a) {
var result = []; // СоздаÑм новÑй маÑÑив
var i; // ÐбÑÑвлÑем пеÑеменнÑÑ
for (i = 0; i != a.length; i++) result[i] = f(a[i]);
return result;
}
var f = function (x) {
return x * x * x;
};
var numbers = [0, 1, 2, 5, 10];
var cube = map(f, numbers);
console.log(cube);
ФÑнкÑÐ¸Ñ Ð²Ð¾Ð·Ð²ÑаÑаеÑ: [0, 1, 8, 125, 1000].
Ð JavaScript ÑÑнкÑÐ¸Ñ Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¾Ð±ÑÑвлена Ñ ÑÑловием. ÐапÑимеÑ, ÑледÑÑÑÐ°Ñ ÑÑнкÑÐ¸Ñ Ð±ÑÐ´ÐµÑ Ð¿ÑиÑвоена пеÑеменной myFunc
ÑолÑко, еÑли num
Ñавно 0:
var myFunc;
if (num === 0) {
myFunc = function (theObject) {
theObject.make = "Toyota";
};
}
Рдополнение к обÑÑвлениÑм ÑÑнкÑий, опиÑаннÑÑ
здеÑÑ, Ð²Ñ Ñакже можеÑе иÑполÑзоваÑÑ ÐºÐ¾Ð½ÑÑÑÑкÑÐ¾Ñ Function Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÑÑнкÑий из ÑÑÑоки во вÑÐµÐ¼Ñ Ð²ÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ (runtime), подобно eval()
.
ÐеÑод â ÑÑо ÑÑнкÑиÑ, коÑоÑÐ°Ñ ÑвлÑеÑÑÑ ÑвойÑÑвом обÑекÑа. УзнаÑÑ Ð±Ð¾Ð»ÑÑе пÑо обÑекÑÑ Ð¸ меÑÐ¾Ð´Ñ Ð¼Ð¾Ð¶Ð½Ð¾ по ÑÑÑлке: РабоÑа Ñ Ð¾Ð±ÑекÑами.
ÐÑÐ·Ð¾Ð²Ñ ÑÑнкÑийÐбÑÑвление ÑÑнкÑии не вÑполнÑÐµÑ ÐµÑ. ÐбÑÑвление ÑÑнкÑии пÑоÑÑо назÑÐ²Ð°ÐµÑ ÑÑнкÑÐ¸Ñ Ð¸ ÑказÑваеÑ, ÑÑо делаÑÑ Ð¿Ñи вÑзове ÑÑнкÑии.
ÐÑзов ÑÑнкÑии ÑакÑиÑеÑки вÑполнÑÐµÑ ÑказаннÑе дейÑÑÐ²Ð¸Ñ Ñ ÑказаннÑми паÑамеÑÑами. ÐапÑимеÑ, еÑли Ð²Ñ Ð¾Ð¿ÑеделиÑе ÑÑнкÑÐ¸Ñ square
, Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе вÑзваÑÑ ÐµÑ ÑледÑÑÑим обÑазом:
ÐÑа инÑÑÑÑкÑÐ¸Ñ Ð²ÑзÑÐ²Ð°ÐµÑ ÑÑнкÑÐ¸Ñ Ñ Ð°ÑгÑменÑом 5. ФÑнкÑÐ¸Ñ Ð²ÑзÑÐ²Ð°ÐµÑ Ñвои инÑÑÑÑкÑии и возвÑаÑÐ°ÐµÑ Ð·Ð½Ð°Ñение 25.
ФÑнкÑии могÑÑ Ð±ÑÑÑ Ð² облаÑÑи видимоÑÑи, когда они Ñже опÑеделенÑ, но ÑÑнкÑии вида "function declaration statement" могÑÑ Ð±ÑÑÑ Ð¿Ð¾Ð´Ð½ÑÑÑ (поднÑÑие â hoisting), Ñакже как в ÑÑом пÑимеÑе:
console.log(square(5));
/* ... */
function square(n) {
return n * n;
}
ÐблаÑÑÑ Ð²Ð¸Ð´Ð¸Ð¼Ð¾ÑÑи ÑÑнкÑии â ÑÑнкÑиÑ, в коÑоÑом она опÑеделена, или ÑÐµÐ»Ð°Ñ Ð¿ÑогÑамма, еÑли она обÑÑвлена по ÑÑÐ¾Ð²Ð½Ñ Ð²ÑÑе.
ÐÑимеÑание: ÐÑо ÑабоÑÐ°ÐµÑ ÑолÑко Ñогда, когда обÑÑвлении ÑÑнкÑии иÑполÑзÑÐµÑ Ð²ÑÑеÑпомÑнÑÑÑй ÑинÑакÑÐ¸Ñ (Ñ.е. function funcName(){}
). Ðод ниже не бÑÐ´ÐµÑ ÑабоÑаÑÑ. ÐмееÑÑÑ Ð² Ð²Ð¸Ð´Ñ Ñо, ÑÑо поднÑÑие ÑÑнкÑии ÑабоÑÐ°ÐµÑ ÑолÑко Ñ function declaration и не ÑабоÑÐ°ÐµÑ Ñ function expression.
console.log(square); // square поднÑÑ Ñо знаÑением undefined.
console.log(square(5)); // TypeError: square is not a function
var square = function (n) {
return n * n;
};
ÐÑгÑменÑÑ ÑÑнкÑии не огÑаниÑиваÑÑÑÑ ÑÑÑоками и ÑиÑлами. ÐÑ Ð¼Ð¾Ð¶ÐµÑе пеÑедаваÑÑ ÑелÑе обÑекÑÑ Ð² ÑÑнкÑиÑ. ФÑнкÑÐ¸Ñ show_props()
(обÑÑÐ²Ð»ÐµÐ½Ð½Ð°Ñ Ð² РабоÑа Ñ Ð¾Ð±ÑекÑами) ÑвлÑеÑÑÑ Ð¿ÑимеÑом ÑÑнкÑии, пÑинимаÑÑей обÑекÑÑ Ð°ÑгÑменÑом.
ФÑнкÑÐ¸Ñ Ð¼Ð¾Ð¶ÐµÑ Ð²ÑзваÑÑ ÑÐ°Ð¼Ñ ÑебÑ. ÐапÑимеÑ, Ð²Ð¾Ñ ÑÑнкÑÐ¸Ñ ÑекÑÑÑивного вÑÑиÑÐ»ÐµÐ½Ð¸Ñ ÑакÑоÑиала:
function factorial(n) {
if (n === 0 || n === 1) return 1;
else return n * factorial(n - 1);
}
ÐаÑем Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе вÑÑиÑлиÑÑ ÑакÑоÑÐ¸Ð°Ð»Ñ Ð¾Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ до пÑÑи ÑледÑÑÑим обÑазом:
var a, b, c, d, e;
a = factorial(1); // a полÑÑÐ°ÐµÑ Ð·Ð½Ð°Ñение 1
b = factorial(2); // b полÑÑÐ°ÐµÑ Ð·Ð½Ð°Ñение 2
c = factorial(3); // c полÑÑÐ°ÐµÑ Ð·Ð½Ð°Ñение 6
d = factorial(4); // d полÑÑÐ°ÐµÑ Ð·Ð½Ð°Ñение 24
e = factorial(5); // e полÑÑÐ°ÐµÑ Ð·Ð½Ð°Ñение 120
ÐÑÑÑ Ð´ÑÑгие ÑпоÑÐ¾Ð±Ñ Ð²ÑзваÑÑ ÑÑнкÑиÑ. СÑÑеÑÑвÑÑÑ ÑаÑÑÑе ÑлÑÑаи, когда ÑÑнкÑии необÑ
одимо вÑзÑваÑÑ Ð´Ð¸Ð½Ð°Ð¼Ð¸ÑеÑки, или поменÑÑÑ Ð½Ð¾Ð¼ÐµÑа аÑгÑменÑов ÑÑнкÑии, или необÑ
одимо вÑзваÑÑ ÑÑнкÑÐ¸Ñ Ñ Ð¿ÑивÑзкой к опÑеделÑÐ½Ð½Ð¾Ð¼Ñ ÐºÐ¾Ð½ÑекÑÑÑ. ÐказÑваеÑÑÑ, ÑÑо ÑÑнкÑии Ñами по Ñебе ÑвлÑÑÑÑÑ Ð¾Ð±ÑекÑами, и ÑÑи обÑекÑÑ Ð² ÑÐ²Ð¾Ñ Ð¾ÑеÑÐµÐ´Ñ Ð¸Ð¼ÐµÑÑ Ð¼ÐµÑÐ¾Ð´Ñ (поÑмоÑÑиÑе обÑÐµÐºÑ Function
). Ðдин из ниÑ
ÑÑо меÑод apply()
, иÑполÑзование коÑоÑого Ð¼Ð¾Ð¶ÐµÑ Ð´Ð¾ÑÑигнÑÑÑ ÑÑой Ñели.
(function scope)
ÐеÑеменнÑе обÑÑвленнÑе в ÑÑнкÑии не могÑÑ Ð±ÑÑÑ Ð´Ð¾ÑÑÑпнÑми где-нибÑÐ´Ñ Ð²Ð½Ðµ ÑÑой ÑÑнкÑии, поÑÑÐ¾Ð¼Ñ Ð¿ÐµÑеменнÑе (коÑоÑÑе нÑÐ¶Ð½Ñ Ð¸Ð¼ÐµÐ½Ð½Ð¾ Ð´Ð»Ñ ÑÑнкÑии) обÑÑвлÑÑÑ ÑолÑко в scope ÑÑнкÑии. ÐÑи ÑÑом ÑÑнкÑÐ¸Ñ Ð¸Ð¼ÐµÐµÑ Ð´Ð¾ÑÑÑп ко вÑем пеÑеменнÑм и ÑÑнкÑиÑм, обÑÑвленнÑм внÑÑÑи ÐµÑ scope. ÐÑÑгими Ñловами ÑÑнкÑÐ¸Ñ Ð¾Ð±ÑÑÐ²Ð»ÐµÐ½Ð½Ð°Ñ Ð² глобалÑном scope Ð¸Ð¼ÐµÐµÑ Ð´Ð¾ÑÑÑп ко вÑем пеÑеменнÑм в глобалÑном scope. ФÑнкÑÐ¸Ñ Ð¾Ð±ÑÑÐ²Ð»ÐµÐ½Ð½Ð°Ñ Ð²Ð½ÑÑÑи дÑÑгой ÑÑнкÑии еÑÑ Ð¸Ð¼ÐµÐµÑ Ð´Ð¾ÑÑÑп и ко вÑем пеÑеменнÑм ÐµÑ ÑодиÑелÑÑкой ÑÑнкÑии и дÑÑгим пеÑеменнÑм, к коÑоÑÑм ÑÑа ÑодиÑелÑÑÐºÐ°Ñ ÑÑнкÑÐ¸Ñ Ð¸Ð¼ÐµÐµÑ Ð´Ð¾ÑÑÑп.
// СледÑÑÑие пеÑеменнÑе обÑÑÐ²Ð»ÐµÐ½Ð½Ñ Ð² глобалÑном scope
var num1 = 20,
num2 = 3,
name = "Chamahk";
// ÐÑа ÑÑнкÑÐ¸Ñ Ð¾Ð±ÑÑвленна в глобалÑном scope
function multiply() {
return num1 * num2;
}
multiply(); // веÑнÑÑ 60
// ÐÑÐ¸Ð¼ÐµÑ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½Ð¾Ð¹ ÑÑнкÑии
function getScore() {
var num1 = 2,
num2 = 3;
function add() {
return name + " scored " + (num1 + num2);
}
return add();
}
getScore(); // веÑнÑÑ "Chamahk scored 5"
Scope и ÑÑек ÑÑнкÑии
(function stack)
РекÑÑÑиÑФÑнкÑÐ¸Ñ Ð¼Ð¾Ð¶ÐµÑ Ð²ÑзÑваÑÑ ÑÐ°Ð¼Ñ ÑебÑ. ТÑи ÑпоÑоба Ñакого вÑзова:
arguments.callee
ÐÐ»Ñ Ð¿ÑимеÑа ÑаÑÑмоÑÑим ÑледÑÑÑие ÑÑнкÑиÑ:
var foo = function bar() {
// здеÑÑ Ð±ÑдÑÑ Ð²ÑÑажениÑ
};
ÐнÑÑÑи ÑÑнкÑии (function body) вÑе ÑледÑÑÑие вÑÐ·Ð¾Ð²Ñ ÑквиваленÑнÑ:
bar()
arguments.callee()
foo()
ФÑнкÑиÑ, коÑоÑÐ°Ñ Ð²ÑзÑÐ²Ð°ÐµÑ ÑÐ°Ð¼Ñ ÑебÑ, назÑваеÑÑÑ ÑекÑÑÑивной ÑÑнкÑией (recursive function). ÐолÑÑаеÑÑÑ, ÑÑо ÑекÑÑÑÐ¸Ñ Ð°Ð½Ð°Ð»Ð¾Ð³Ð¸Ñна ÑÐ¸ÐºÐ»Ñ (loop). Ðба вÑзÑваÑÑ Ð½ÐµÐºÐ¾ÑоÑÑй код неÑколÑко Ñаз, и оба ÑÑебÑÑÑ ÑÑÐ»Ð¾Ð²Ð¸Ñ (ÑÑÐ¾Ð±Ñ Ð¸Ð·Ð±ÐµÐ¶Ð°ÑÑ Ð±ÐµÑконеÑного Ñикла, веÑнее беÑконеÑной ÑекÑÑÑии). ÐапÑимеÑ, ÑледÑÑÑий Ñикл:
var x = 0;
while (x < 10) {
// "x < 10" â ÑÑо ÑÑловие Ð´Ð»Ñ Ñикла
// ÑÑо-Ñо делаем
x++;
}
можно бÑло измениÑÑ Ð½Ð° ÑекÑÑÑивнÑÑ ÑÑнкÑÐ¸Ñ Ð¸ вÑзовом ÑÑой ÑÑнкÑии:
function loop(x) {
if (x >= 10) {
// "x >= 10" â ÑÑо ÑÑловие Ð´Ð»Ñ ÐºÐ¾Ð½Ñа вÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ (Ñоже Ñамое, ÑÑо "!(x < 10)")
return;
}
// делаÑÑ ÑÑо-Ñо
loop(x + 1); // ÑекÑÑÑионнÑй вÑзов
}
loop(0);
Ðднако некоÑоÑÑе алгоÑиÑÐ¼Ñ Ð½Ðµ могÑÑ Ð±ÑÑÑ Ð¿ÑоÑÑÑми повÑоÑÑÑÑимиÑÑ Ñиклами. ÐапÑимеÑ, полÑÑение вÑÐµÑ ÑлеменÑов ÑÑÑÑкÑÑÑÑ Ð´ÐµÑева (напÑимеÑ, DOM) пÑоÑе вÑего ÑеализÑеÑÑÑ Ð¸ÑполÑзованием ÑекÑÑÑии:
function walkTree(node) {
if (node == null) return;
// ÑÑо-Ñо делаем Ñ ÑлеменÑами
for (var i = 0; i < node.childNodes.length; i++) {
walkTree(node.childNodes[i]);
}
}
Ð ÑÑавнении Ñ ÑÑнкÑией loop
, каждÑй ÑекÑÑÑивнÑй вÑзов Ñам вÑзÑÐ²Ð°ÐµÑ Ð¼Ð½Ð¾Ð³Ð¾ ÑекÑÑÑивнÑÑ
вÑзовов.
Также возможно пÑевÑаÑение некоÑоÑÑÑ ÑекÑÑÑивнÑÑ Ð°Ð»Ð³Ð¾ÑиÑмов в неÑекÑÑÑивнÑе, но ÑаÑÑо Ð¸Ñ Ð»Ð¾Ð³Ð¸ÐºÐ° оÑÐµÐ½Ñ Ñложна, и Ð´Ð»Ñ ÑÑого поÑÑебÑеÑÑÑ Ð¸ÑполÑзование ÑÑека (stack). Ðо ÑакÑÑ ÑекÑÑÑÐ¸Ñ Ð¸ÑполÑзÑÐµÑ stack: function stack.
Ðоведение ÑÑека можно ÑвидеÑÑ Ð² ÑледÑÑÑем пÑимеÑе:
function foo(i) {
if (i < 0) return;
console.log("begin: " + i);
foo(i - 1);
console.log("end: " + i);
}
foo(3);
// Output:
// begin: 3
// begin: 2
// begin: 1
// begin: 0
// end: 0
// end: 1
// end: 2
// end: 3
ÐложеннÑе ÑÑнкÑии (nested functions) и замÑÐºÐ°Ð½Ð¸Ñ (closures)
ÐÑ Ð¼Ð¾Ð¶ÐµÑе вложиÑÑ Ð¾Ð´Ð½Ñ ÑÑнкÑÐ¸Ñ Ð² дÑÑгÑÑ. ÐÐ»Ð¾Ð¶ÐµÐ½Ð½Ð°Ñ ÑÑнкÑÐ¸Ñ (nested function; inner) пÑиваÑÐ½Ð°Ñ (private) и она помеÑена в дÑÑгÑÑ ÑÑнкÑÐ¸Ñ (outer). Так обÑазÑеÑÑÑ Ð·Ð°Ð¼Ñкание (closure). Closure â ÑÑо вÑÑажение (обÑÑно ÑÑнкÑиÑ), коÑоÑое Ð¼Ð¾Ð¶ÐµÑ Ð¸Ð¼ÐµÑÑ ÑвободнÑе пеÑеменнÑе вмеÑÑе Ñо ÑÑедой, коÑоÑÐ°Ñ ÑвÑзÑÐ²Ð°ÐµÑ ÑÑи пеÑеменнÑе (ÑÑо "закÑÑваеÑ" ("close") вÑÑажение).
ÐоÑколÑÐºÑ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½Ð°Ñ ÑÑнкÑÐ¸Ñ ÑÑо closure, ÑÑо ознаÑаеÑ, ÑÑо Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½Ð°Ñ ÑÑнкÑÐ¸Ñ Ð¼Ð¾Ð¶ÐµÑ "ÑнаÑледоваÑÑ" (inherit) аÑгÑменÑÑ Ð¸ пеÑеменнÑе ÑÑнкÑии, в коÑоÑÑÑ Ñа вложена. ÐÑÑгими Ñловами, Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½Ð°Ñ ÑÑнкÑÐ¸Ñ ÑодеÑÐ¶Ð¸Ñ scope внеÑней ("outer") ÑÑнкÑии.
ÐодведÑм иÑог:
СледÑÑÑий пÑÐ¸Ð¼ÐµÑ Ð¿Ð¾ÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½ÑÑ ÑÑнкÑиÑ:
function addSquares(a, b) {
function square(x) {
return x * x;
}
return square(a) + square(b);
}
a = addSquares(2, 3); // возвÑаÑÐ°ÐµÑ 13
b = addSquares(3, 4); // возвÑаÑÐ°ÐµÑ 25
c = addSquares(4, 5); // возвÑаÑÐ°ÐµÑ 41
ÐоÑколÑÐºÑ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½Ð°Ñ ÑÑнкÑÐ¸Ñ ÑоÑмиÑÑÐµÑ closure, Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе вÑзваÑÑ Ð²Ð½ÐµÑнÑÑ ÑÑнкÑÐ¸Ñ Ð¸ ÑказаÑÑ Ð°ÑгÑменÑÑ Ð´Ð»Ñ Ð¾Ð±Ð¾Ð¸Ñ ÑÑнкÑий (Ð´Ð»Ñ outer и innner).
function outside(x) {
function inside(y) {
return x + y;
}
return inside;
}
fn_inside = outside(3); // ÐÑмайÑе об ÑÑом как: дайÑе мне ÑÑнкÑиÑ,
// коÑоÑÐ°Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÑÐµÑ 3 к лÑÐ±Ð¾Ð¼Ñ Ð²Ð²ÐµÐ´ÐµÐ½Ð½Ð¾Ð¼Ñ Ð·Ð½Ð°ÑениÑ
result = fn_inside(5); // возвÑаÑÐ°ÐµÑ 8
result1 = outside(3)(5); // возвÑаÑÐ°ÐµÑ 8
СоÑ
Ñанение пеÑеменнÑÑ
ÐбÑаÑиÑе внимание, знаÑение x
ÑоÑ
ÑанилоÑÑ, когда возвÑаÑалоÑÑ inside
. Closure должно ÑоÑ
ÑанÑÑÑ Ð°ÑгÑменÑÑ Ð¸ пеÑеменнÑе во вÑем scope. ÐоÑколÑÐºÑ ÐºÐ°Ð¶Ð´Ñй вÑзов пÑедоÑÑавлÑÐµÑ Ð¿Ð¾ÑенÑиалÑно ÑазнÑе аÑгÑменÑÑ, ÑоздаÑÑÑÑ Ð½Ð¾Ð²Ñй closure Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ вÑзова во вне. ÐамÑÑÑ Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¾ÑиÑена ÑолÑко Ñогда, когда inside
Ñже возвÑаÑилÑÑ Ð¸ болÑÑе не доÑÑÑпен.
ÐÑо не оÑлиÑаеÑÑÑ Ð¾Ñ Ñ ÑÐ°Ð½ÐµÐ½Ð¸Ñ ÑÑÑлок в дÑÑÐ³Ð¸Ñ Ð¾Ð±ÑекÑÐ°Ñ , но ÑаÑÑо менее оÑевидно, поÑÐ¾Ð¼Ñ ÑÑо не ÑÑÑанавливаÑÑÑÑ ÑÑÑлки напÑÑмÑÑ Ð¸ нелÑÐ·Ñ Ð¿Ð¾ÑмоÑÑеÑÑ Ñам.
ÐеÑколÑко ÑÑовней вложенноÑÑи ÑÑнкÑий (Multiply-nested functions)ФÑнкÑии можно вкладÑваÑÑ Ð½ÐµÑколÑко Ñаз, Ñ.е. ÑÑнкÑÐ¸Ñ (A) Ñ ÑÐ°Ð½Ð¸Ñ Ð² Ñебе ÑÑнкÑÐ¸Ñ (B), коÑоÑÐ°Ñ Ñ ÑÐ°Ð½Ð¸Ñ Ð² Ñебе ÑÑнкÑÐ¸Ñ (C). Ðбе ÑÑнкÑии B и C ÑоÑмиÑÑÑÑ closures, Ñак B Ð¸Ð¼ÐµÐµÑ Ð´Ð¾ÑÑÑп к пеÑеменнÑм и аÑгÑменÑам A, и C Ð¸Ð¼ÐµÐµÑ Ñакой же доÑÑÑп к B. Рдобавок, поÑколÑÐºÑ C Ð¸Ð¼ÐµÐµÑ Ñакой доÑÑÑп к B, коÑоÑÑй Ð¸Ð¼ÐµÐµÑ Ñакой же доÑÑÑп к A, C еÑÑ Ð¸Ð¼ÐµÐµÑ Ñакой же доÑÑÑп к A. Таким обÑазом closures Ð¼Ð¾Ð¶ÐµÑ Ñ ÑаниÑÑ Ð² Ñебе неÑколÑко scope; они ÑекÑÑÑивно Ñ ÑанÑÑ scope ÑÑнкÑий, ÑодеÑжаÑÐ¸Ñ ÐµÐ³Ð¾. ÐÑо назÑваеÑÑÑ chaining (chain â ÑепÑ; ÐоÑÐµÐ¼Ñ Ð½Ð°Ð·Ð²Ð°Ð½Ð¾ "chaining" бÑÐ´ÐµÑ Ð¾Ð±ÑÑÑнено позже)
РаÑÑмоÑÑим ÑледÑÑÑий пÑимеÑ:
function A(x) {
function B(y) {
function C(z) {
console.log(x + y + z);
}
C(3);
}
B(2);
}
A(1); // в конÑоле вÑводиÑÑÑ 6 (1 + 2 + 3)
Ð ÑÑом пÑимеÑе C Ð¸Ð¼ÐµÐµÑ Ð´Ð¾ÑÑÑп к y
ÑÑнкÑии B
и к x
ÑÑнкÑии A
. Так полÑÑаеÑÑÑ, поÑÐ¾Ð¼Ñ ÑÑо:
B
ÑоÑмиÑÑÐµÑ closure, вклÑÑаÑÑее A
, Ñ.е. B
Ð¸Ð¼ÐµÐµÑ Ð´Ð¾ÑÑÑп к аÑгÑменÑам и пеÑеменнÑм ÑÑнкÑии A
.C
ÑоÑмиÑÑÐµÑ closure, вклÑÑаÑÑее B
.B
вклÑÑÐ°ÐµÑ A
, Ñо closure С
Ñоже вклÑÑÐ°ÐµÑ A, C
Ð¸Ð¼ÐµÐµÑ Ð´Ð¾ÑÑÑп к аÑгÑменÑам и пеÑеменнÑм обоиÑ
ÑÑнкÑий B
и A
. ÐÑÑгими Ñловами, С
ÑвÑзÑÐ²Ð°ÐµÑ ÑепÑÑ (chain) scopes ÑÑнкÑий B
и A
в Ñаком поÑÑдке.РобÑаÑном поÑÑдке, однако, ÑÑо не веÑно. A
не Ð¸Ð¼ÐµÐµÑ Ð´Ð¾ÑÑÑп к пеÑеменнÑм и аÑгÑменÑам C
, поÑÐ¾Ð¼Ñ ÑÑо A
не Ð¸Ð¼ÐµÐµÑ Ñакой доÑÑÑп к B
. Таким обÑазом, C
оÑÑаÑÑÑÑ Ð¿ÑиваÑнÑм ÑолÑко Ð´Ð»Ñ B
.
Ðогда два аÑгÑменÑа или пеÑеменнÑÑ Ð² scope Ñ closure имеÑÑ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñе имена, пÑоиÑÑ Ð¾Ð´Ð¸Ñ ÐºÐ¾Ð½ÑÐ»Ð¸ÐºÑ Ð¸Ð¼ÐµÐ½Ð¸ (name conflict). Ðолее вложеннÑй (more inner) scope Ð¸Ð¼ÐµÐµÑ Ð¿ÑиоÑиÑеÑ, Ñак ÑамÑй вложеннÑй scope Ð¸Ð¼ÐµÐµÑ Ð½Ð°Ð¸Ð²ÑÑÑий пÑиоÑиÑеÑ, и наобоÑоÑ. ÐÑо ÑепоÑка облаÑÑей видимоÑÑи (scope chain). СамÑм пеÑвÑм звеном ÑвлÑеÑÑÑ ÑамÑй глÑбокий scope, и наобоÑоÑ. РаÑÑмоÑÑим ÑледÑÑÑие:
function outside() {
var x = 5;
function inside(x) {
return x * 2;
}
return inside;
}
outside()(10); // возвÑаÑÐ°ÐµÑ 20 вмеÑÑо 10
ÐонÑÐ»Ð¸ÐºÑ Ð¸Ð¼ÐµÐ½Ð¸ пÑоизоÑÑл в инÑÑÑÑкÑии return x * 2
Ð¼ÐµÐ¶Ð´Ñ Ð¿Ð°ÑамеÑÑом x
ÑÑнкÑии inside
и пеÑеменной x
ÑÑнкÑии outside
. Scope chain здеÑÑ Ð±ÑÐ´ÐµÑ Ñаким: {inside
==> outside
==> глобалÑнÑй обÑÐµÐºÑ (global object)}. СледоваÑелÑно x
ÑÑнкÑии inside
Ð¸Ð¼ÐµÐµÑ Ð±Ð¾Ð»ÑÑий пÑиоÑиÑÐµÑ Ð¿Ð¾ ÑÑÐ°Ð²Ð½ÐµÐ½Ð¸Ñ Ñ outside
, и нам веÑнÑлоÑÑ 20 (= 10 * 2), а не 10 (= 5 * 2).
(Closures)
Closures ÑÑо один из главнÑÑ Ð¾ÑобенноÑÑей JavaScript. JavaScript ÑазÑеÑÐ°ÐµÑ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½Ð¾ÑÑÑ ÑÑнкÑий и пÑедоÑÑавлÑÐµÑ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½Ð¾Ð¹ ÑÑнкÑии полнÑй доÑÑÑп ко вÑем пеÑеменнÑм и ÑÑнкÑиÑм, обÑÑвленнÑм внÑÑÑи внеÑней ÑÑнкÑии (и дÑÑгим пеÑеменнÑм и ÑÑнкÑии, к коÑоÑÑм Ð¸Ð¼ÐµÐµÑ Ð´Ð¾ÑÑÑп ÑÑа внеÑнÑÑ ÑÑнкÑиÑ).
Ðднако, внеÑнÑÑ ÑÑнкÑÐ¸Ñ Ð½Ðµ Ð¸Ð¼ÐµÐµÑ Ð´Ð¾ÑÑÑпа к пеÑеменнÑм и ÑÑнкÑиÑм, обÑÑвленнÑм во внÑÑÑенней ÑÑнкÑии. ÐÑо обеÑпеÑÐ¸Ð²Ð°ÐµÑ Ñвоего Ñода инкапÑÑлÑÑÐ¸Ñ Ð´Ð»Ñ Ð¿ÐµÑеменнÑÑ Ð²Ð½ÑÑÑи вложенной ÑÑнкÑии.
Также, поÑколÑÐºÑ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½Ð°Ñ ÑÑнкÑÐ¸Ñ Ð¸Ð¼ÐµÐµÑ Ð´Ð¾ÑÑÑп к scope внеÑней ÑÑнкÑии, пеÑеменнÑе и ÑÑнкÑии, обÑÑвленнÑе во внеÑней ÑÑнкÑии, бÑÐ´ÐµÑ Ð¿ÑодолжаÑÑ ÑÑÑеÑÑвоваÑÑ Ð¸ поÑле ÐµÑ Ð²ÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½Ð¾Ð¹ ÑÑнкÑии, еÑли на Ð½Ð¸Ñ Ð¸ на Ð½ÐµÑ ÑÐ¾Ñ ÑанилÑÑ Ð´Ð¾ÑÑÑп (имееÑÑÑ Ð²Ð²Ð¸Ð´Ñ, ÑÑо пеÑеменнÑе, обÑÑвленнÑе во внеÑней ÑÑнкÑии, ÑÐ¾Ñ ÑанÑÑÑÑÑ, ÑолÑко еÑли внÑÑÑеннÑÑ ÑÑнкÑÐ¸Ñ Ð¾Ð±ÑаÑаеÑÑÑ Ðº ним).
Closure ÑоздаÑÑÑÑ, когда Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½Ð°Ñ ÑÑнкÑÐ¸Ñ ÐºÐ°Ðº-Ñо ÑÑала доÑÑÑпной в неком scope вне внеÑней ÑÑнкÑии.
var pet = function (name) {
// ÐнеÑнÑÑ ÑÑнкÑÐ¸Ñ Ð¾Ð±ÑÑвила пеÑеменнÑÑ "name"
var getName = function () {
return name; // ÐÐ»Ð¾Ð¶ÐµÐ½Ð½Ð°Ñ ÑÑнкÑÐ¸Ñ Ð¸Ð¼ÐµÐµÑ Ð´Ð¾ÑÑÑп к "name" внеÑней ÑÑнкÑии
};
return getName; // ÐозвÑаÑаем вложеннÑÑ ÑÑнкÑиÑ, Ñем ÑамÑм ÑоÑ
ÑанÑÑ Ð´Ð¾ÑÑÑп
// к ней Ð´Ð»Ñ Ð´ÑÑгого scope
};
myPet = pet("Vivie");
myPet(); // ÐозвÑаÑаеÑÑÑ "Vivie",
// Ñ.к. даже поÑле вÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð²Ð½ÐµÑней ÑÑнкÑии
// name ÑоÑ
ÑанилÑÑ Ð´Ð»Ñ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½Ð¾Ð¹ ÑÑнкÑии
Ðолее ÑложнÑй пÑÐ¸Ð¼ÐµÑ Ð¿ÑедÑÑавлен ниже. ÐбÑÐµÐºÑ Ñ Ð¼ÐµÑодами Ð´Ð»Ñ Ð¼Ð°Ð½Ð¸Ð¿ÑлÑÑии вложенной ÑÑнкÑии внеÑней ÑÑнкÑией можно веÑнÑÑÑ (return).
var createPet = function (name) {
var sex;
return {
setName: function (newName) {
name = newName;
},
getName: function () {
return name;
},
getSex: function () {
return sex;
},
setSex: function (newSex) {
if (
typeof newSex === "string" &&
(newSex.toLowerCase() === "male" || newSex.toLowerCase() === "female")
) {
sex = newSex;
}
},
};
};
var pet = createPet("Vivie");
pet.getName(); // Vivie
pet.setName("Oliver");
pet.setSex("male");
pet.getSex(); // male
pet.getName(); // Oliver
Ркоде вÑÑе пеÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ name
внеÑней ÑÑнкÑии доÑÑÑпна Ð´Ð»Ñ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½Ð¾Ð¹ ÑÑнкÑии, и Ð½ÐµÑ Ð´ÑÑгого ÑпоÑоба доÑÑÑпа к вложеннÑм пеÑеменнÑм кÑоме как ÑеÑез вложеннÑÑ ÑÑнкÑиÑ. ÐложеннÑе пеÑеменнÑе вложенной ÑÑнкÑии ÑвлÑÑÑÑÑ Ð±ÐµÐ·Ð¾Ð¿Ð°ÑнÑми Ñ
ÑанилиÑами Ð´Ð»Ñ Ð²Ð½ÐµÑниÑ
аÑгÑменÑов и пеÑеменнÑÑ
. Ðни ÑодеÑÐ¶Ð°Ñ "поÑÑоÑннÑе" и "инкапÑÑлиÑованнÑе" даннÑе Ð´Ð»Ñ ÑабоÑÑ Ñ Ð½Ð¸Ð¼Ð¸ вложеннÑми ÑÑнкÑиÑми. ФÑнкÑии даже не Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¿ÑиÑваиваÑÑÑÑ Ð¿ÐµÑеменной или имеÑÑ Ð¸Ð¼Ñ.
var getCode = (function () {
var apiCode = "0]Eal(eh&2"; // ÐÑ Ð½Ðµ Ñ
оÑим, ÑÑÐ¾Ð±Ñ Ð´Ð°Ð½Ð½Ñй код мог бÑÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½ кем-Ñо извне...
return function () {
return apiCode;
};
})();
getCode(); // ÐозвÑаÑÐ°ÐµÑ apiCode
Ðднако еÑÑÑ ÑÑд подводнÑÑ ÐºÐ°Ð¼Ð½ÐµÐ¹, коÑоÑÑе ÑледÑÐµÑ ÑÑиÑÑваÑÑ Ð¿Ñи иÑполÑзовании замÑканий. ÐÑли закÑÑÑÐ°Ñ ÑÑнкÑÐ¸Ñ Ð¾Ð¿ÑеделÑÐµÑ Ð¿ÐµÑеменнÑÑ Ñ Ñем же именем, ÑÑо и Ð¸Ð¼Ñ Ð¿ÐµÑеменной во внеÑней облаÑÑи, Ð½ÐµÑ ÑпоÑоба Ñнова ÑÑÑлаÑÑÑÑ Ð½Ð° пеÑеменнÑÑ Ð²Ð¾ внеÑней облаÑÑи.
var createPet = function (name) {
// ÐнеÑнÑÑ ÑÑнкÑÐ¸Ñ Ð¾Ð¿ÑеделÑÐµÑ Ð¿ÐµÑеменнÑÑ Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ "name".
return {
setName: function (name) {
// ÐнÑÑÑеннÑÑ ÑÑнкÑÐ¸Ñ Ñакже опÑеделÑÐµÑ Ð¿ÐµÑеменнÑÑ Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ "name".
name = name; // Ðак Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ полÑÑиÑÑ Ð´Ð¾ÑÑÑп к "name", опÑеделÑнной во внеÑней ÑÑнкÑии?
},
};
};
ÐÑполÑзование обÑекÑа arguments
ÐбÑÐµÐºÑ arguments ÑÑнкÑии ÑвлÑеÑÑÑ Ð¿Ñевдо-маÑÑивом. ÐнÑÑÑи ÑÑнкÑии Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе ÑÑÑлаÑÑÑÑ Ðº аÑгÑменÑам ÑледÑÑÑим обÑазом:
где i
â ÑÑо поÑÑдковÑй Ð½Ð¾Ð¼ÐµÑ Ð°ÑгÑменÑа, оÑÑÑиÑÑваÑÑийÑÑ Ñ 0. РпеÑÐ²Ð¾Ð¼Ñ Ð°ÑгÑменÑÑ, пеÑÐµÐ´Ð°Ð½Ð½Ð¾Ð¼Ñ ÑÑнкÑии, обÑаÑаÑÑÑÑ Ñак arguments[0]
. РполÑÑиÑÑ ÐºÐ¾Ð»Ð¸ÑеÑÑво вÑеÑ
аÑгÑменÑов â arguments.length
.
С помоÑÑÑ Ð¾Ð±ÑекÑа arguments
ÐÑ Ð¼Ð¾Ð¶ÐµÑе вÑзваÑÑ ÑÑнкÑиÑ, пеÑÐµÐ´Ð°Ð²Ð°Ñ Ð² Ð½ÐµÑ Ð±Ð¾Ð»ÑÑе аÑгÑменÑов, Ñем ÑоÑмалÑно обÑÑвили пÑинÑÑÑ. ÐÑо оÑÐµÐ½Ñ Ð¿Ð¾Ð»ÐµÐ·Ð½Ð¾, еÑли Ð²Ñ Ð½Ðµ знаеÑе ÑоÑно, ÑколÑко аÑгÑменÑов должна пÑинÑÑÑ Ð²Ð°Ñа ÑÑнкÑиÑ. ÐÑ Ð¼Ð¾Ð¶ÐµÑе иÑполÑзоваÑÑ arguments.length
Ð´Ð»Ñ Ð¾Ð¿ÑÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ ÐºÐ¾Ð»Ð¸ÑеÑÑва аÑгÑменÑов, пеÑеданнÑÑ
ÑÑнкÑии, а заÑем полÑÑиÑÑ Ð´Ð¾ÑÑÑп к ÐºÐ°Ð¶Ð´Ð¾Ð¼Ñ Ð°ÑгÑменÑÑ, иÑполÑзÑÑ Ð¾Ð±ÑÐµÐºÑ arguments
.
ÐÐ»Ñ Ð¿ÑимеÑа ÑаÑÑмоÑÑим ÑÑнкÑиÑ, коÑоÑÐ°Ñ ÐºÐ¾Ð½ÐºÐ°ÑениÑÑÐµÑ Ð½ÐµÑколÑко ÑÑÑок. ÐдинÑÑвеннÑм ÑоÑмалÑнÑм аÑгÑменÑом Ð´Ð»Ñ ÑÑнкÑии бÑÐ´ÐµÑ ÑÑÑока, коÑоÑÐ°Ñ ÑказÑÐ²Ð°ÐµÑ ÑимволÑ, коÑоÑÑе ÑазделÑÑÑ ÑлеменÑÑ Ð´Ð»Ñ ÐºÐ¾Ð½ÐºÐ°ÑенаÑии. ФÑнкÑÐ¸Ñ Ð¾Ð¿ÑеделÑеÑÑÑ ÑледÑÑÑим обÑазом:
function myConcat(separator) {
var result = "";
var i;
// iterate through arguments
for (i = 1; i < arguments.length; i++) {
result += arguments[i] + separator;
}
return result;
}
ÐÑ Ð¼Ð¾Ð¶ÐµÑе пеÑедаваÑÑ Ð»Ñбое колиÑеÑÑво аÑгÑменÑов в ÑÑÑ ÑÑнкÑиÑ, и он конкаÑениÑÑÐµÑ ÐºÐ°Ð¶Ð´Ñй аÑгÑÐ¼ÐµÐ½Ñ Ð² Ð¾Ð´Ð½Ñ ÑÑÑокÑ.
// возвÑаÑÐ°ÐµÑ "red, orange, blue, "
myConcat(", ", "red", "orange", "blue");
// возвÑаÑÐ°ÐµÑ "elephant; giraffe; lion; cheetah; "
myConcat("; ", "elephant", "giraffe", "lion", "cheetah");
// возвÑаÑÐ°ÐµÑ "sage. basil. oregano. pepper. parsley. "
myConcat(". ", "sage", "basil", "oregano", "pepper", "parsley");
ÐÑимеÑание: arguments
ÑвлÑеÑÑÑ Ð¿Ñевдо-маÑÑивом, но не маÑÑивом. ÐÑо пÑевдо-маÑÑив, в коÑоÑом еÑÑÑ Ð¿ÑонÑмеÑованнÑе индекÑÑ Ð¸ ÑвойÑÑво length
. Ðднако он не Ð¾Ð±Ð»Ð°Ð´Ð°ÐµÑ Ð²Ñеми меÑодами маÑÑивов.
РаÑÑмоÑÑиÑе обÑÐµÐºÑ Function
в JavaScript-ÑпÑавоÑнике Ð´Ð»Ñ Ð±Ð¾Ð»ÑÑей инÑоÑмаÑии.
ÐаÑÐ¸Ð½Ð°Ñ Ñ ECMAScript 2015 поÑвилиÑÑ Ð´Ð²Ð° новÑÑ Ð²Ð¸Ð´Ð° паÑамеÑÑов: паÑамеÑÑÑ Ð¿Ð¾ ÑмолÑÐ°Ð½Ð¸Ñ (default parameters) и оÑÑаÑоÑнÑе паÑамеÑÑÑ (rest parameters).
ÐаÑамеÑÑÑ Ð¿Ð¾ ÑмолÑÐ°Ð½Ð¸Ñ (Default parameters)Ð JavaScript паÑамеÑÑÑ ÑÑнкÑии по ÑмолÑÐ°Ð½Ð¸Ñ Ð¸Ð¼ÐµÑÑ Ð·Ð½Ð°Ñение undefined
. Ðднако в некоÑоÑÑÑ
ÑиÑÑаÑÐ¸Ñ Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¿Ð¾Ð»ÐµÐ·Ð½Ñм поменÑÑÑ Ð·Ð½Ð°Ñение по ÑмолÑаниÑ. Ð ÑакиÑ
ÑлÑÑаÑÑ
default parameters могÑÑ Ð±ÑÑÑ Ð²ÐµÑÑма кÑÑаÑи.
РпÑоÑлом Ð´Ð»Ñ ÑÑого бÑло необÑ
одимо в Ñеле ÑÑнкÑии пÑовеÑÑÑÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ Ð¿Ð°ÑамеÑÑов на undefined
и в положиÑелÑном ÑлÑÑае менÑÑÑ ÑÑо знаÑение на деÑолÑное (default). Ð ÑледÑÑÑем пÑимеÑе в ÑлÑÑае, еÑли пÑи вÑзове не пÑедоÑÑавили знаÑение Ð´Ð»Ñ b
, Ñо ÑÑим знаÑением ÑÑÐ°Ð½ÐµÑ undefined
, Ñогда ÑезÑлÑÑаÑом вÑÑиÑÐ»ÐµÐ½Ð¸Ñ a * b
в ÑÑнкÑии multiply
бÑÐ´ÐµÑ NaN
. Ðднако во вÑоÑой ÑÑÑоке Ð¼Ñ Ð¿Ð¾Ð¹Ð¼Ð°ÐµÐ¼ ÑÑо знаÑение:
function multiply(a, b) {
b = typeof b !== "undefined" ? b : 1;
return a * b;
}
multiply(5); // 5
С паÑамеÑÑами по ÑмолÑÐ°Ð½Ð¸Ñ Ð¿ÑовеÑка налиÑÐ¸Ñ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ Ð¿Ð°ÑамеÑÑа в Ñеле ÑÑнкÑии не нÑжна. ТепеÑÑ Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе пÑоÑÑо ÑказаÑÑ Ð·Ð½Ð°Ñение по ÑмолÑÐ°Ð½Ð¸Ñ Ð´Ð»Ñ Ð¿Ð°ÑамеÑÑа b
в обÑÑвлении ÑÑнкÑии:
function multiply(a, b = 1) {
return a * b;
}
multiply(5); // 5
ÐÐ»Ñ Ð±Ð¾Ð»ÐµÐµ деÑалÑного ÑаÑÑмоÑÑÐµÐ½Ð¸Ñ Ð¾Ð·Ð½Ð°ÐºÐ¾Ð¼ÑÑеÑÑ Ñ Ð¿Ð°ÑамеÑÑами по ÑмолÑаниÑ.
ÐÑÑаÑоÑнÑе паÑамеÑÑÑ (Rest parameters)ÐÑÑаÑоÑнÑе паÑамеÑÑÑ Ð¿ÑедоÑÑавлÑÑÑ Ð½Ð°Ð¼ маÑÑив неопÑеделÑннÑÑ Ð°ÑгÑменÑов. РпÑимеÑе Ð¼Ñ Ð¸ÑполÑзÑем оÑÑаÑоÑнÑе паÑамеÑÑÑ, ÑÑÐ¾Ð±Ñ ÑобÑаÑÑ Ð°ÑгÑменÑÑ Ñ Ð¸Ð½Ð´ÐµÐºÑами Ñо 2-го до поÑледнего. ÐаÑем Ð¼Ñ Ñмножим каждÑй из Ð½Ð¸Ñ Ð½Ð° знаÑение пеÑвого аÑгÑменÑа. Ð ÑÑом пÑимеÑе иÑполÑзÑеÑÑÑ ÑÑÑелоÑÐ½Ð°Ñ ÑÑнкÑÐ¸Ñ (Arrow functions), о коÑоÑой бÑÐ´ÐµÑ ÑаÑÑказано в ÑледÑÑÑей ÑекÑии.
function multiply(multiplier, ...theArgs) {
return theArgs.map((x) => multiplier * x);
}
var arr = multiply(2, 1, 2, 3);
console.log(arr); // [2, 4, 6]
СÑÑелоÑнÑе ÑÑнкÑии
(Arrow functions)
СÑÑелоÑнÑе ÑÑнкÑии â ÑÑнкÑии вида "arrow function expression" (невеÑно fat arrow function) â имеÑÑ ÑкоÑоÑеннÑй ÑинÑакÑÐ¸Ñ Ð¿Ð¾ ÑÑÐ°Ð²Ð½ÐµÐ½Ð¸Ñ Ñ function expression и лекÑиÑеÑки ÑвÑзÑÐ²Ð°ÐµÑ Ð·Ð½Ð°Ñение this
. СÑÑелоÑнÑе ÑÑнкÑии вÑегда анонимнÑ. ÐоÑмоÑÑиÑе Ñакже поÑÑ Ð±Ð»Ð¾Ð³Ð° hacks.mozilla.org "ES6 In Depth: Arrow functions".
Ðа введение ÑÑÑелоÑнÑÑ
ÑÑнкÑий повлиÑли два ÑакÑоÑа: более коÑоÑкие ÑÑнкÑии и лекÑика this
.
РнекоÑоÑÑÑ ÑÑнкÑионалÑнÑÑ Ð¿Ð°ÑÑеÑÐ½Ð°Ñ Ð¿ÑивеÑÑÑвÑеÑÑÑ Ð¸ÑполÑзование более коÑоÑÐºÐ¸Ñ ÑÑнкÑий. СÑавниÑе:
var a = ["Hydrogen", "Helium", "Lithium", "Beryllium"];
var a2 = a.map(function (s) {
return s.length;
});
console.log(a2); // вÑÐ²Ð¾Ð´Ð¸Ñ [8, 6, 7, 9]
var a3 = a.map((s) => s.length);
console.log(a3); // вÑÐ²Ð¾Ð´Ð¸Ñ [8, 6, 7, 9]
ÐекÑика this
Ðо ÑÑÑелоÑнÑÑ
ÑÑнкÑий ÐºÐ°Ð¶Ð´Ð°Ñ Ð½Ð¾Ð²Ð°Ñ ÑÑнкÑÐ¸Ñ Ð¾Ð¿ÑеделÑла ÑÐ²Ð¾Ñ Ð·Ð½Ð°Ñение this
(новÑй обÑÐµÐºÑ Ð² ÑлÑÑае конÑÑÑÑкÑоÑа, undefined в strict mode, конÑекÑÑнÑй обÑекÑ, еÑли ÑÑнкÑÐ¸Ñ Ð²Ñзвана как меÑод обÑекÑа, и Ñ.д.). ÐÑо оказалоÑÑ ÑаздÑажаÑÑим Ñ ÑоÑки зÑÐµÐ½Ð¸Ñ Ð¾Ð±ÑекÑно-оÑиенÑиÑованного ÑÑÐ¸Ð»Ñ Ð¿ÑогÑаммиÑованиÑ.
function Person() {
// ÐонÑÑÑÑкÑÐ¾Ñ Person() опÑеделÑÐµÑ `this` как Ñамого ÑебÑ.
this.age = 0;
setInterval(function growUp() {
// Ðез strict mode ÑÑнкÑÐ¸Ñ growUp() опÑеделÑÐµÑ `this`
// как global object, коÑоÑÑй оÑлиÑаеÑÑÑ Ð¾Ñ `this`
// опÑеделÑнного конÑÑÑÑкÑоÑом Person().
this.age++;
}, 1000);
}
var p = new Person();
Ð ECMAScript 3/5 ÑÑа пÑоблема бÑла иÑпÑавлена пÑÑÑм пÑиÑÐ²Ð¾ÐµÐ½Ð¸Ñ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ this
пеÑеменной, коÑоÑÑÑ Ð¼Ð¾Ð¶Ð½Ð¾ бÑло Ð±Ñ Ð·Ð°Ð¼ÐºÐ½ÑÑÑ.
function Person() {
var self = this; // ÐекоÑоÑÑе вÑбиÑаÑÑ `that` вмеÑÑо `self`.
// ÐÑбеÑиÑе ÑÑо-Ñо одно и бÑдÑÑе поÑледоваÑелÑнÑ.
self.age = 0;
setInterval(function growUp() {
// ÐолбÑк ÑÑÑлаеÑÑÑ Ð½Ð° пеÑеменнÑÑ `self`,
// знаÑением коÑоÑой ÑвлÑеÑÑÑ Ð¾Ð¶Ð¸Ð´Ð°ÐµÐ¼Ñй обÑекÑ.
self.age++;
}, 1000);
}
ÐлÑÑеÑнаÑивой Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ ÑвÑÐ·Ð°Ð½Ð½Ð°Ñ ÑÑнкÑÐ¸Ñ (bound function), Ñ ÐºÐ¾ÑоÑой можно пÑавилÑно вÑÑÑнÑÑ Ð¾Ð¿ÑеделиÑÑ Ð·Ð½Ð°Ñение this
Ð´Ð»Ñ ÑÑнкÑии growUp()
.
Ð arrow function знаÑением this
ÑвлÑеÑÑÑ Ð¾ÐºÑÑжаÑÑий его конÑекÑÑ, Ñак ÑледÑÑÑий код ÑабоÑÐ°ÐµÑ Ð¾Ð¶Ð¸Ð´Ð°ÐµÐ¼Ð¾:
function Person() {
this.age = 0;
setInterval(() => {
this.age++; // |this| должнÑм обÑазом ÑÑÑлаеÑÑÑ Ð½Ð° обÑÐµÐºÑ Person
}, 1000);
}
var p = new Person();
Ðалее
ÐодÑобное ÑеÑ
ниÑеÑкое опиÑание ÑÑнкÑий в ÑÑаÑÑе ÑпÑавоÑника ФÑнкÑии
СмоÑÑиÑе Ñакже Function
в СпÑавоÑнике JavaScript Ð´Ð»Ñ Ð¿Ð¾Ð»ÑÑÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸ÑелÑной инÑоÑмаÑии по ÑÑнкÑии как обÑекÑÑ.
ÐнеÑние ÑеÑÑÑÑÑ:
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