JavaScript Functionsexpress
js的函數能夠接受多個參數閉包
function sumOnSteroids() { var i, res = 0, number_of_params = arguments.length; for (i = 0; i < number_of_params; i++) { res += arguments[i]; } return res; } console.log(sumOnSteroids(1, 2, 43));//46 console.log(sumOnSteroids(1, 2, 3, 4));//10 console.log(sumOnSteroids(1, 2, 5, 6, 7));//21
There are a number of functions that are built into the JavaScript engine and are available for you to use. Let's take a lookat them. While doing so, you'll have aapp
chance to experiment with functions, their arguments and return values, and become comfortable working with functions. Following is a list of the built-in functions:less
parseInt()ide
parseFloat()函數
isNaN()oop
isFinite()ui
encodeURI()this
decodeURI()spa
encodeURIComponent()
decodeURIComponent()
eval()
var abc = "121221"; console.log(parseInt(abc));//121221 console.log(isNaN(abc));//false
內建的函數能夠直接使用
eval函數
eval('var ii = 2'); console.log(ii); //2
It's important to note, especially if you have come to JavaScript from another language, that variables in JavaScript are not defined in a block scope(JavaScript的變量不在塊級做用域裏定義), but in a function scope(在函數做用域). This means that if a variableis defined inside a function, it's not visible outside of the function. However, if it's defined inside an if or a for code block, it's visible outside the block. The term(術語) "global variables"(全局變量) describes variables you define outside of any function (in the global program code), as opposed to(相反地) "local variables", which are defined inside a function(在一個函數內定義). The code inside a function has access to all global variables as well as to its own local ones.
示例代碼:
var somevar = 12; function dowork() { var n = somevar; console.log(n);//12 if (n === 12) { var msg = "the value is 12"; } console.log(msg);//the value is 12 } dowork();
Functions in JavaScript are actually data. This is an important concept that we'll need later on. This means that you can create a function and assign it to a variable:
var f = function (a, b, c) { return a + b + c; }; var f2 = function () { return "you are a pig"; }; console.log(f(1, 2, 3));//6 console.log(f2());//you are a pig var f3 = f2; console.log(typeof f3);//function
So, JavaScript functions are data, but a special kind of data with two important features:
They contain code
They are executable (they can be invoked)
var f = function (a, b, c) { return a + b + c; };
This is also often called an anonymous function(匿名函數) (as it doesn't have a name), especially when such a function expression is used even without assigning it to a variable. In this case, there can be two elegant(優雅地) uses for such anonymous functions:
You can pass an anonymous function as a parameter to another function.(當作一個參數進行傳遞) The receiving function can do something useful with the function that you pass.
You can define an anonymous function and execute it right away.(能夠當即執行一個匿名函數)
When you pass a function, A, to another function, B, and then B executes A, it's often said that A is a callbackfunction. If A doesn't have a name, then you can say that it's an anonymous callback function.
function invokeAdd(a, b) { return a() + b(); } function one() { return 1; } function two() { return 2; } var result1 = invokeAdd( function () { return 1; }, function () { return 2; }); var result2 = invokeAdd(one, two); console.log(result1);//3 console.log(result2);//3
One good application of immediate (self-invoking) anonymous functions is when you want to have some work done without creating extra global variables. A drawback, of course, is that you cannot execute the same function twice. This makes immediate functions best suited for one-off or initialization tasks.
(function () { console.log("hello"); })(); (function (name) { console.log("hello," + name); })("lyx");
使用Immediate functions返回值
var result = (function (name) { console.log("hello," + name); return "complete"; })("lyx"); console.log(result);//complete
Bearing in mind that a function is just like any other value, there's nothing that stops you from defining a function inside another function:
function outer(param) { function inner(theinput) { return theinput * 2; } return 'The result is ' + inner(param); } console.log(outer(12));//The result is 24
在outer函數做用域外面訪問不到inner函數
The benefits of using private functions are as follows:
You keep the global namespace clean (less likely to cause naming collisions)
Privacy—you exposeonly the functions you decide to the "outside world", keeping to yourself functionality that is not meant to be consumed by the rest of the application
沒有return語句的函數返回undefined
function test() { console.log("so called"); } console.log(test());//undefined
As mentioned earlier, a function always returns a value, and if it doesn't do it explicitly with return, then it does soimplicitly by returning undefined. A function can return only one value, and this value can just as easily be another function:
function a() { console.log('A!'); return function () { console.log('B!'); }; } console.log(typeof a());//函數a返回的是一個函數function var newFUnc = a();//執行函數a,並把返回值賦給newFunc變量 newFUnc();//執行函數a返回的函數 a()();//當即執行返回的函數
function a() { console.log('A!'); return function () { console.log('B!'); }; } a = a();//打印A! a();//打印B!
If you call this function for the first time, it will:
Alert A!(consider this as being the one-off preparatory work)
Redefine the global variable a, assigning a new function to it
var global = 1; function outer() {//函數做用域 var outer_local = 2; function inner() {//一個內部函數inner()has access to all variables var inner_local = 3; return inner_local + outer_local + global; } return inner(); } console.log(outer());//6
從這個示例中能夠看到inner()函數能夠訪問到全部的變量,這就是做用域鏈的效果。
var a = "global variable"; var F = function () { var b = "local variable"; var N = function () { //The function N has access to its private space, to the F() function's space, and to the global space. var c = "inner local"; return b; }; return N; };
The function N has access to its private space, to the F() function's space, and to the global space. So, it can see b. Since F() is callable from the global space (it's a global function), you can call it and assign the returned value to another global variable. The result: a new global function that has access to the F() function's private space:
var inner = F(); var b = inner(); console.log(b);//local variable
另外一個閉包的例子:
var inner; // placeholder var F = function () { var b = "local variable"; var N = function () { return b; }; inner = N; }; F();
A new function, N(),is defined inside F() and assigned to the global inner. During definition time, N() was inside F(), so it had access to the F() function's scope. inner()
will keep its access to the F() function's scope, even though it's part of the global space:
var b = inner(); console.log(b);//local variable
Every function can be considered a closure. This is because every function maintains a secret link to the environment (the scope) in which it was created. But, most of the time this scope is destroyed unless something interesting happens (as shown above) that causes this scope to be maintained.
Based on what you've seen so far, you can say that a closure is created when a function keeps a link to its parent scope even after the parent has returned. And, every function is a closure because, at the very least, every function maintains access to the global scope, which is never destroyed.
再看一個閉包的例子,這個閉包的例子是有關函數的參數的:
Function parameters behave like local variables to this function(函數的參數就像函數做用域中的本地變量同樣), but they are implicitly(隱式的) created (you don't need to use var for them). You can create a function that returns another function, which in turn returns its parent's parameter:
function F(param) { var N = function () { return param; }; param++; return N; } var inner = F(123); var result = inner(); console.log(result);
Notice how param++was incremented after the function was defined and yet, when called, inner() returned the updated value. This demonstrates that
the function maintains a reference to the scope where it was defined, not to the variables and their values found in the scope during the function definition.
function F() { var arr = [], i; for (i = 0; i < 3; i++) { arr[i] = function () { return i; }; } return arr; } var arr = F(); console.log(arr[0]());//3 console.log(arr[1]());//3 console.log(arr[2]());//3
三次循環,每次循環保存當前循環的變量i,但從結果來看,沒有獲得咱們想要的效果:
程序應該這樣改:
function F() { var arr = [], i; for (i = 0; i < 3; i++) { arr[i] = (function (x) { return function () { return x; }; }(i)); } return arr; } var arr = F(); console.log(arr[0]());//0 console.log(arr[1]());//1 console.log(arr[2]());//2
Here, instead of just creating a function that returns i, you pass the ivariable's current value to another immediate function. In this function, ibecomes the local value x, and xhas a different value every time.
Alternatively(另外), you can use a "normal" (as opposed to an immediate) inner function to achieve the same result. The key is to use the middle function to "localize" the value of iat every iteration:
function F() { function binder(x) { return function () { return x; }; } var arr = [], i; for (i = 0; i < 3; i++) { arr[i] = binder(i); } return arr; } var arr = F(); console.log(arr[0]());//0 console.log(arr[1]());//1 console.log(arr[2]());//2
var getValue, setValue; (function () { var secret = 0; getValue = function () { return secret; }; setValue = function (v) { if (typeof v === "number") { secret = v; } }; }()); console.log(getValue());//0 setValue(123); console.log(getValue());//123
In this case, the function that contains everything is an immediate function. It defines setValue()and getValue()as global functions, while the secretvariable remains local and inaccessible directly.
The last closure example (also the last example in the chapter) shows the use of a closure to accomplish an iterator functionality.
function setup(x) { var i = 0; return function () { return x[i++]; }; } var next = setup(['a', 'b', 'c']); console.log(next());//a console.log(next());//b console.log(next());//c
For this example, let's just use a simple array and not a complex data structure. Here's an initialization function that takes an input array and also defines a secret pointer, i, that will always point to the next element in the array.
===========END===========