JavaScript权威指南之函数

闭包

词法作用域:函数的执行依赖于作用域,这个作用域是在函数定义时决定的,而不是在函数调用时决定的。
定义:当调用函数时的作用域和定义函数时的作用域不是同个作用域,就叫闭包。

var scoped = 'global scoped';
function getScoped () {
	var scoped = 'local scoped';
	function func () {
		return scoped;
	}
	return func();
}
getScoped();     //'local scoped'
var scoped = 'global scoped';
function getScoped () {
	var scoped = 'local scoped';
	function func () {
		return scoped;
	}
	return func;
}
getScoped()();     //'local scoped'

这就验证了词法作用域的原则:作用域链是在定义函数时决定的,所以作用域链还是指向局部变量。
何为作用域链?
作用域链可以理解为一个对象列表。每次调用函数的时候,会创建一个保存局部变量的新对象,并把这个对象添加至作用域链中。
当函数返回时,从作用域链中把这个绑定变量的对象删除。如果不存在嵌套的函数,也没有其他引用指向这个绑定对象,它就会被当成垃圾回收。如果存在嵌套的函数,每个嵌套的函数都有对应的作用域链,并且这个作用域链指向一个绑定变量的对象。但如果这些变量在外部函数被保存下来,那么它们也会和它们绑定的变量对象被回收。
如果这个函数定义了嵌套函数,并将它作为返回值返回或者存储在某个属性中,这是就有一个外部引用指向这个嵌套的函数,它就不会被当成垃圾回收,并且它指向的绑定变量对象也不会被回收。
闭包经典问题:

function constFunc (v) { return function () {return v;} };
var funcs = [];
for (var i = 0;i < 10;i++) {
	funcs[i] = constFunc(i);
}
funcs[5]();    //5
var funcs = [];
for (var i = 0;i < 10;i++) {
	funcs[i] = function () {return i;};
}
funcs[5]();    //10

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

length属性

arguments代表函数的实参列表
arguments.callee代表函数本身,在使用匿名函数递归的时候,可以使用该属性调用本身
arguments代表函数的实参个数
arguments.callee.length代表函数形参个数

prototype属性

每个函数都包含一个prototype属性,这个属性是对这个对象的引用,成为原型对象。当用构造函数创建对象的时候,新创建的对象的原型会指向函数的原型对象。

call()和apply()方法

call和apply方法的第一个实参是要调用函数的母对象,它是调用上下文,在函数体内通过this来获得它的引用。
通过对象o调用函数f()

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

类似于

o.m = f;
o.m();
delete o.m;
bind()方法

当函数f()上调用bind()方法并传入一个对象o作为参数,这个方法将返回一个新的函数。

toString()方法

大多数函数的toString方法返回的是函数完整的源码
内置函数的toString方法返回的是"[native code]"的字符串

函数的构造函数为Function函数

允许JavaScript动态地创建并编译函数

var f = new Function('x', 'y', 'return x + y;');
var f = function(x, y) {return x + y;}
检测函数对象
function isFunction (x) {
	return Object.prototype.toString,call(x) === '[object Function]';
}

你可能感兴趣的:(JavaScript)