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]';
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章