PHP中閉包的一些常見(jiàn)問(wèn)題
PHP具有非常強(qiáng)大的功能,所有的CGI的功能PHP都能實(shí)現(xiàn),而且支持幾乎所有流行的數(shù)據(jù)庫(kù)以及操作系統(tǒng)。最重要的是PHP可以用C、C++進(jìn)行程序的擴(kuò)展!以下是小編為大家搜索整理的PHP中閉包的一些常見(jiàn)問(wèn)題,希望能給大家?guī)?lái)幫助!更多精彩內(nèi)容請(qǐng)持續(xù)關(guān)注我們應(yīng)屆畢業(yè)生考試網(wǎng)!
首先說(shuō)明下...閉包是js高級(jí)特性之一...但并非js獨(dú)有...perl, python, php(5.3以上版本) 都是支持閉包的..
官方解釋: 所謂“閉包”,指的是一個(gè)擁有許多變量和綁定了這些變量的環(huán)境的表達(dá)式(通常是一個(gè)函數(shù)),因而這些變量也是該表達(dá)式的一部分
john resig解釋: 閉包就是內(nèi)部函數(shù)可以訪問(wèn)外部函數(shù)中所定義的變量,即使該函數(shù)已經(jīng)執(zhí)行結(jié)束。
如果你還是不能明白上面那句話...那么我就換句話來(lái)說(shuō):
在js中...執(zhí)行一個(gè)函數(shù)A...當(dāng)函數(shù)A執(zhí)行完后...理論上來(lái)講...改函數(shù)A內(nèi)所有被定義的 臨時(shí)變量都將被 當(dāng)成可回收的垃圾等待垃圾回收....然而在這個(gè)過(guò)程..有一種臨時(shí)變量是無(wú)法被垃圾回收的...當(dāng)A函數(shù)中有一個(gè)內(nèi)部函數(shù)a時(shí).a函數(shù)內(nèi)引用了A中定義的臨時(shí)變量...并且a函數(shù)在A函數(shù)執(zhí)行完后..仍然可以被外部訪問(wèn)到時(shí)...被a函數(shù)所引用的臨時(shí)變量就無(wú)法被當(dāng)成垃圾等待垃圾回收.. 而a函數(shù)可以被外部訪問(wèn)的同時(shí)..就生成了一個(gè)閉包...
舉個(gè)例子吧..也是比較經(jīng)典的例子
/pic/p>
function A(){
/pic/p>
var x = 1;
/pic/p>
/pic/p>
return function a(){
console.log( x );
};
}
/pic/p>
/pic/p>
/pic/p>
/pic/p>
var a = A();
/pic/p>
a(); /pic/p>
閉包并非定義函數(shù)時(shí)就生成的...而是在執(zhí)行過(guò)程中 當(dāng)a函數(shù)被當(dāng)成一個(gè)返回值被返回時(shí) 才會(huì)生成一個(gè)閉包..
閉包容易誤解的地方:
1。 閉包總是在匿名函數(shù)中生成的
閉包并非都是在匿名函數(shù)中生成的..比如上一段代碼中...被返回的函數(shù)有命名-a
2。 閉包在定義時(shí)產(chǎn)生的...
閉包并非是在定義時(shí)產(chǎn)生的...而是在內(nèi)部函數(shù)可被外部訪問(wèn)到時(shí)才會(huì)產(chǎn)生...
3。 閉包很強(qiáng)大..用的越多就越牛A(==!)
不否認(rèn)閉包很強(qiáng)大.....但是并非用的越多就是越好的...使用閉包..會(huì)造成調(diào)試?yán)щy..所以要習(xí)慣做標(biāo)識(shí)..另外...使用閉包會(huì)涉及到 增長(zhǎng)函數(shù)作用域的 造成內(nèi)部函數(shù)訪問(wèn)全局變量變慢的問(wèn)題...
PHP中的閉包
php-5.3 以上版本其中一個(gè)更新就是使php支持了簡(jiǎn)單的閉包
/**
* 一個(gè)curry的加法函數(shù)
* @param unknown_type $start 起始值
* @return unknown 返回一個(gè)匿名函數(shù)
*/
function add( $start = 0 ){
$sum = $start;
/pic/p>
return function () use ( &$sum ){
/pic/p>
$args = func_get_args();
for( $i = 0; $i < count($args); $i++ ){
$sum += (int)$args[$i];
}
return $sum;
};
}
/pic/p>
$add = add( 1 );
/pic/p>
$add( 1, 2, 3 );
/pic/p>
echo $add( 3 ); /pic/p>
?> 這段代碼的作用是 每調(diào)用一次add函數(shù)都會(huì)生成一個(gè)相應(yīng)的$sum 每個(gè)函數(shù)執(zhí)行后不沖突 可避免使用static變量 而且sum不會(huì)隨函數(shù)執(zhí)行結(jié)束而消失 從而實(shí)現(xiàn)函數(shù)柯里化
閉包的使用
1. 函數(shù)柯里化
閉包在js中經(jīng)常會(huì)被用過(guò)函數(shù)柯里化
比如上面php的那段代碼中 改成js則是:
/pic/p>
function add( start ){
var sum = start || 0;
/pic/p>
return function(){
for( var i = 0, j = arguments.length; i < j; i++ ){
sum += Number( arguments[i] );
}
return sum;
}
}
var a = add( 1 );
a( 1, 2, 3 );
console.log( a( 3 ) );
玩?zhèn)有意思的函數(shù) 這個(gè)是別人曾經(jīng)給我出的一道題目 當(dāng)時(shí)我也沒(méi)想出來(lái)...(壓根把tostring這方法給忘了.)
題目需求要求可以這樣調(diào)用(當(dāng)時(shí)的需求只要求傳一個(gè)參數(shù))
/pic/p>
var a = add( 1 );
/pic/p>
a( 1, 2, 3 )( 1, 2, 3 )( 1, 2, 3 );
/pic/p>
console.log( a ); /pic/p>
/pic/p>
console.log( a( 1, 2, 3 )( 1, 2, 3 ) ); /pic/p>
實(shí)現(xiàn)如下
/pic/p>
function add( start ){
var sum = start || 0;
/pic/p>
/pic/p>
return function(){
/pic/p>
for( var i = 0, j = arguments.length; i < j; i++ ){
sum += Number( arguments[i] );
}
/pic/p>
var func = arguments.callee;
/pic/p>
func.toString = function(){
return sum;
};
/pic/p>
return func;
}
}
2。模擬對(duì)象中的私有屬性和方法
寫之前先解釋下 js非一門OO語(yǔ)言 它是一門基于對(duì)象的語(yǔ)言
如 var i = 0; 則i是一個(gè)數(shù)值型對(duì)象 轉(zhuǎn)成對(duì)象寫法則是 var i = new Number(1); 前一種叫過(guò)直接量表示法 同JSON(js對(duì)象字面量,表示js中對(duì)象的直接量表示方法) 直接量表示的速度要比 new 快
(1)模擬私有屬性和私有方法
/pic/p>
function Smarty(){
/pic/p>
/pic/p>
this.leftLimiter = '{';
/pic/p>
this.rightLimiter = '}';
/pic/p>
/pic/p>
var cacheData = {};
/pic/p>
/pic/p>
/pic/p>
/pic/p>
this.assign = function( name, value ){
/pic/p>
cacheData[name] = value;
}
/pic/p>
/pic/p>
function fetch( tpl ){
/pic/p>
return tpl;
}
/pic/p>
this.display = function( tpl ){
/pic/p>
console.log( fetch( tpl ) );
}
}
/pic/p>
var template = new Smarty();
/pic/p>
template.leftLimiter = '<{';
/pic/p>
template.rightLimiter = '}>';
/pic/p>
template.assign( 'name', 'jsyczhanghao' );
/pic/p>
template.assign( 'age', 23 );
/pic/p>
template.display( document.getElementById( 'test' ).innerHTML );
(2)模擬私有靜態(tài)方法(單例模式-Zend framework 模擬前端控制器 phper你懂的..)
/pic/p>
/pic/p>
/pic/pic/p>
/pic/p>
var Zend_Controller = function(){
/pic/p>
this.setControllerDirectory = function(){};
/pic/p>
this.dispatch = function(){
console.log( 1 );
};
};
/pic/p>
/pic/p>
var intance;
/pic/p>
var Zend_Controller_Front = function(){};
/pic/p>
/pic/p>
Zend_Controller_Front.getInstance = function(){
/pic/p>
/pic/p>
return instance || ( instance = new Zend_Controller() );
};
/pic/p>
/pic/p>
/pic/p>
/pic/p>
/pic/p>
/pic/p>
/pic/p>
window.Zend_Controller_Front = Zend_Controller_Front;
})( this );
var zend_instance = Zend_Controller_Front.getInstance();
zend_instance.setControllerDirectory( '/root' );
zend_instance.dispatch();
3。事件回調(diào)函數(shù)中的使用
/pic/p>
/pic/p>
/pic/p>
function updateElement( elem, url ){
/pic/p>
/pic/p>
/pic/p>
/pic/p>
/pic/p>
/pic/p>
/pic/p>
$.get( url, function( data ){
/pic/p>
elem.innerHTML = data;
});
} 以上是閉包絕大部分會(huì)出現(xiàn)的場(chǎng)景
#############################################################################################################
來(lái)看個(gè)問(wèn)題吧:針對(duì) #js的異步機(jī)制和大數(shù)據(jù)量的處理方案# 中的一段代碼段
for( var i = 0; i < 10; i++ ){
/pic/p>
document.getElementById( 'test' + i ).onclick = function(){
/pic/p>
console.log( i );
};
}
這段代碼執(zhí)行后 點(diǎn)擊test0-test9并非象預(yù)期那樣.. 依次打印出0-9 而是每一個(gè)元素點(diǎn)擊后都打印了10
造成的原因就是 綁定click事件時(shí) 回調(diào)函數(shù)并未執(zhí)行 當(dāng)回調(diào)函數(shù)執(zhí)行時(shí) i已經(jīng)變成了10 所以打印的結(jié)果都會(huì)變成10
解決方法:
思路: 如果能找到一種方式可以將每一次的i都緩存起來(lái) 并且一直到click事件觸發(fā)的時(shí)候 它都一直不會(huì)消失 不就完了么
我們都知道 一個(gè)函數(shù)作用域內(nèi)執(zhí)行完后..作用域中的所有臨時(shí)變量都會(huì)消失 但是有一種不讓臨時(shí)變量消失的方式就是使用閉包。。而上面講閉包的使用場(chǎng)景時(shí) 其中有一條就是事件回調(diào)函數(shù) 當(dāng)一個(gè)事件回調(diào)函數(shù)位于一個(gè)作用域內(nèi)的時(shí)候...作用域執(zhí)行外后 由于回調(diào)函數(shù)并未馬上執(zhí)行..而是等到相應(yīng)事件觸發(fā)時(shí)才執(zhí)行...當(dāng)回調(diào)函數(shù)依賴該作用域內(nèi)的臨時(shí)變量時(shí)...導(dǎo)致該作用域內(nèi)部使用的臨時(shí)變量無(wú)法馬上被當(dāng)垃圾回收(意味著該臨時(shí)變量不會(huì)消失)
目前我們擁有一個(gè)事件回調(diào)函數(shù) 要做的就是需要讓這個(gè)事件回調(diào)函數(shù)位于一個(gè)函數(shù)作用域內(nèi)
代碼:
for( var i = 0; i < 10; i++ ){
/pic/p>
function(){
document.getElementById( 'test' + i ).onclick = function(){
/pic/p>
console.log( i );
};
};
}
這樣 事件綁定就位于一個(gè)匿名函數(shù)中了...但是這樣肯定不行...因?yàn)楹瘮?shù)都沒(méi)有執(zhí)行...函數(shù)內(nèi)的代碼肯定不會(huì)起作用....也就是說(shuō)..這段代碼能夠正常執(zhí)行 不報(bào)錯(cuò)..但是不會(huì)為每一個(gè)元素綁定一個(gè)事件..因?yàn)樗耐獠亢瘮?shù)沒(méi)有執(zhí)行
繼續(xù)修改:
for( var i = 0; i < 10; i++ ){
/pic/p>
(function(){
document.getElementById( 'test' + i ).onclick = function(){
/pic/p>
console.log( i );
};
})();
}
恩 這次看起來(lái)差不多了....綁定事件的行為位于一個(gè)匿名函數(shù)中..并且匿名函數(shù)定義后立即執(zhí)行....
但是目前 綁定事件內(nèi)的變量i并不是 匿名函數(shù)中所產(chǎn)生的臨時(shí)變量 i是一個(gè)全局變量 i不會(huì)因?yàn)槟涿瘮?shù)的執(zhí)行而一直保持 你所希望的值
所以我們需要在匿名函數(shù)內(nèi)定義一個(gè)臨時(shí)變量 該臨時(shí)變量的值和當(dāng)前相應(yīng)的i值相等即可 將i直接賦值給該臨時(shí)變量就可以了..
最終修改代碼:
for( var i = 0; i < 10; i++ ){
/pic/p>
(function(){
var j = i;
document.getElementById( 'test' + j ).onclick = function(){
/pic/p>
console.log( j );
};
})();
}其實(shí)不一定要直接賦值 當(dāng)一個(gè)參數(shù)傳進(jìn)去也行代碼如下(執(zhí)行結(jié)果一樣..過(guò)程也沒(méi)什么區(qū)別..只是寫法不同)for( var i = 0; i < 10; i++ ){
/pic/p>
(function( j ){
document.getElementById( 'test' + j ).onclick = function(){
/pic/p>
console.log( j );
};
})( i );
}
其實(shí)還有一種不使用閉包的方式...在事件的回調(diào)函數(shù)中直接引用 dom對(duì)象的一個(gè)屬性即可 因?yàn)閐om對(duì)象是一直存在的 而指向當(dāng)前的dom對(duì)象使用this即可for( var i = 0; i < 10; i++ ){
/pic/p>
var elem = document.getElementById( 'test' + i );
elem.index = i;
elem.onclick = function(){
/pic/p>
console.log( this.index );
};
}
【PHP中閉包的一些常見(jiàn)問(wèn)題】相關(guān)文章:
javascript中js閉包的深入理解09-29
PHP中的Trait11-20
PHP中php://input和$-POST的區(qū)別11-07
PHP中l(wèi)ist的方法11-17
PHP中的魔術(shù)方法03-05
PHP中Json應(yīng)用03-01
PHP中的Reload操作12-19
PHP中$-SERVER的詳解09-09
- 相關(guān)推薦