MXOXW

Life always finds a way.

JavaScript 权威指南-函数

| Comments

8.1 函数定义

  • 函数表达式
  • 函数声明式

8.2 函数调用

  • 作为函数
  • 作为方法
  • 作为构造函数
  • 通过它们的call()和apply()方法间接调用

8.3 函数的实参和形参

8.3.1 可选形参
传入的实参比形参个数少,剩余的形参置为undefined。

8.3.2 实参对象
arguments指向实参对象的引用,是一个类数组对象
callee:当前正在执行的函数
caller(非标准的):调用当前正在执行的函数的函数

8.6 闭包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
var scope = "global scope"; // A global variable
function checkscope() {
var scope = "local scope"; // A local variable
function f() {
return scope;
} // Return the value in scope here
return f;
}
checkscope()() // What does this return?

/**
*
*/

function counter() {
var n = 0;
return {
count: function() {
return n++;
},
reset: function() {
n = 0;
}
};
}
var c = counter(),
d = counter(); // Create two counters
c.count() // => 0
d.count() // => 0: they count independently
c.reset() // reset() and count() methods share state
c.count() // => 0: because we reset c
d.count() // => 1: d was not reset

8.7 函数的属性、方法和构造函数

8.7.1 length属性
arguments.length表示传入实参的个数

8.7.2 prototype属性
指向一个对象的引用,这个对象称作“原型对象”

8.7.3 call()和apply()

1
2
f.call(o, 1, 2);
f.apply(o, [1,2]);

8.7.4 bind()

bind()是在ECMAScript 5中新增的方法,但在ECMAScript 3中可以轻易模拟bind()。从名字就可以看出,这个方法的主要作用就是将函数绑定至某个对象。当在函数f()上调用b1nd()方法并传入一个对象o作为参数,这个方法将返回一个新的函数。(以函数调用的方式)调用新的函数将会把原始的函数f()当做o的方法来调用。传入新函数的任何实参都将传入原始函数,比如:

1
2
3
4
5
6
7
8
9
10
11
12
var sum = function(x, y) {
return x + y
}; // Return the sum of 2 args
// Crethe this value bound to null
// and the 1st argument bound to 1. This newate a new function like sum, but with function expects just one arg.
var succ = sum.bind(null, 1);
succ(2) // => 3: x is bound to 1, and we pass 2 for the y argument
function f(y, z) {
return this.x + y + z
}; // Another function that adds
var g = f.bind({ x: 1 }, 2); // Bind this and y
g(3) // => 6: this.x is bound to 1, y is bound to 2 and z is 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* A Function.bind() method for ECMAScript 3
*/

if (!Function.prototype.bind) {
Function.prototype.bind = function(o /*, args */ ) {
// Save the this and arguments values into variables so we can
// use them in the nested function below.
var self = this,
boundArgs = arguments;
// The return value of the bind() method is a function
return function() {
// Build up an argument list, starting with any args passed
// to bind after the first one, and follow those with all args
// passed to this function.
var args = [],
i;
for (i = 1; i < boundArgs.length; i++) args.push(boundArgs[i]);
for (i = 0; i < arguments.length; i++) args.push(arguments[i]);
// Now invoke self as a method of o, with those arguments
return self.apply(o, args);
};
};
}

8.7.5 toString()
返回函数源码或者”[native code]”

8.7.6 Function()构造函数
var f = new Function("x", "y", "return x*y;");

关于Function()构造函数有几点需要特别注意:

  • Function()构造函数允许JavaScript在运行时动态地创建并编译函数。
  • 每次调用Function()构造函数都会解析函数体,并创建新的函数对象。如果是在一个循环或者多次调用的函数中执行这个构造函数,执行效率会受影响。相比之下,循环中的嵌套函数和函数定义表达式则不会每次执行时都重新编译。
  • 最后一点,也是关于Function()构造函数非常重要的一点,就是它所创建的函数并不是使用词法作用域,相反,函数体代码的编译总是会在顶层函数执行,正如下面代码所示:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    var scope = "global";

    function constructFunction() {
    var scope = "local";
    return new Function("return scope"); // Does not capture the local scope!
    }
    // This line returns "global" because the function returned by the
    // Function() constructor does not use the local scope.
    constructFunction()(); // => "global"

8.7.7 可调用的对象

1
2
3
4
5
6
/**
* 检测一个对象是否是真正的函数
*/

function isFunction(x) {
return Object.prototype.toString.call(x) === "[object Function]";
}

8.8 函数式编程
8.8.2 高阶函数
所谓高阶函数,就是操作函数的函数,它接受一个或多个函数作为参数,并返回一个新函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
// This higher-order function returns a new function that passes its
// arguments to f and returns the logical negation of f's return value;
function not(f) {
return function() { // Return a new function
var result = f.apply(this, arguments); // that calls f
return !result; // and negates its result.
};
}
var even = function(x) { // A function to determine if a number is even
return x % 2 === 0;
};
var odd = not(even); // A new function that does the opposite
[1, 1, 3, 5, 5].every(odd); // => true: every element of the array is odd

8.8.3 不完全函数
8.8.4 记忆

1
2
3
4
5
6
7
8
9
10
11
// Return a memoized version of f.
// It only works if arguments to f all have distinct string representations.
function memoize(f) {
var cache = {}; // Value cache stored in the closure.
return function() {
// Create a string version of the arguments to use as a cache key.
var key = arguments.length + Array.prototype.join.call(arguments, ",");
if (key in cache) return cache[key];
else return cache[key] = f.apply(this, arguments);
};
}

评论