<pre id="bbfd9"><del id="bbfd9"><dfn id="bbfd9"></dfn></del></pre>

          <ruby id="bbfd9"></ruby><p id="bbfd9"><mark id="bbfd9"></mark></p>

          <p id="bbfd9"></p>

          <p id="bbfd9"><cite id="bbfd9"></cite></p>

            <th id="bbfd9"><form id="bbfd9"><dl id="bbfd9"></dl></form></th>

            <p id="bbfd9"><cite id="bbfd9"></cite></p><p id="bbfd9"></p>
            <p id="bbfd9"><cite id="bbfd9"><progress id="bbfd9"></progress></cite></p>

            PHP中閉包的一些常見問題

            時間:2025-10-23 09:23:01 php語言 我要投稿

            PHP中閉包的一些常見問題

              PHP具有非常強大的功能,所有的CGI的功能PHP都能實現,而且支持幾乎所有流行的數據庫以及操作系統。最重要的是PHP可以用C、C++進行程序的擴展!以下是小編為大家搜索整理的PHP中閉包的一些常見問題,希望能給大家帶來幫助!更多精彩內容請持續關注我們應屆畢業生考試網!

              首先說明下...閉包是js高級特性之一...但并非js獨有...perl, python, php(5.3以上版本) 都是支持閉包的..

              官方解釋: 所謂“閉包”,指的是一個擁有許多變量和綁定了這些變量的環境的表達式(通常是一個函數),因而這些變量也是該表達式的一部分

              john resig解釋: 閉包就是內部函數可以訪問外部函數中所定義的變量,即使該函數已經執行結束。

              如果你還是不能明白上面那句話...那么我就換句話來說:

              在js中...執行一個函數A...當函數A執行完后...理論上來講...改函數A內所有被定義的 臨時變量都將被 當成可回收的垃圾等待垃圾回收....然而在這個過程..有一種臨時變量是無法被垃圾回收的...當A函數中有一個內部函數a時.a函數內引用了A中定義的臨時變量...并且a函數在A函數執行完后..仍然可以被外部訪問到時...被a函數所引用的臨時變量就無法被當成垃圾等待垃圾回收.. 而a函數可以被外部訪問的同時..就生成了一個閉包...

              舉個例子吧..也是比較經典的例子

              /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>

              閉包并非定義函數時就生成的...而是在執行過程中 當a函數被當成一個返回值被返回時 才會生成一個閉包..

              閉包容易誤解的地方:

              1。 閉包總是在匿名函數中生成的

              閉包并非都是在匿名函數中生成的..比如上一段代碼中...被返回的函數有命名-a

              2。 閉包在定義時產生的...

              閉包并非是在定義時產生的...而是在內部函數可被外部訪問到時才會產生...

              3。 閉包很強大..用的越多就越牛A(==!)

              不否認閉包很強大.....但是并非用的越多就是越好的...使用閉包..會造成調試困難..所以要習慣做標識..另外...使用閉包會涉及到 增長函數作用域的 造成內部函數訪問全局變量變慢的問題...

              PHP中的閉包

              php-5.3 以上版本其中一個更新就是使php支持了簡單的閉包

              /**

              * 一個curry的加法函數

              * @param unknown_type $start 起始值

              * @return unknown 返回一個匿名函數

              */

              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>

              ?> 這段代碼的作用是 每調用一次add函數都會生成一個相應的$sum 每個函數執行后不沖突 可避免使用static變量 而且sum不會隨函數執行結束而消失 從而實現函數柯里化

              閉包的使用

              1. 函數柯里化

              閉包在js中經常會被用過函數柯里化

              比如上面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 ) );

              玩個有意思的函數 這個是別人曾經給我出的一道題目 當時我也沒想出來...(壓根把tostring這方法給忘了.)

              題目需求要求可以這樣調用(當時的需求只要求傳一個參數)

              /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>

              實現如下

              /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。模擬對象中的私有屬性和方法

              寫之前先解釋下 js非一門OO語言 它是一門基于對象的語言

              如 var i = 0; 則i是一個數值型對象 轉成對象寫法則是 var i = new Number(1); 前一種叫過直接量表示法 同JSON(js對象字面量,表示js中對象的直接量表示方法) 直接量表示的速度要比 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)模擬私有靜態方法(單例模式-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。事件回調函數中的使用

              /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;

              });

              } 以上是閉包絕大部分會出現的場景

              #############################################################################################################

              來看個問題吧:針對 #js的異步機制和大數據量的處理方案# 中的一段代碼段

              for( var i = 0; i < 10; i++ ){

              /pic/p>

              document.getElementById( 'test' + i ).onclick = function(){

              /pic/p>

              console.log( i );

              };

              }

              這段代碼執行后 點擊test0-test9并非象預期那樣.. 依次打印出0-9 而是每一個元素點擊后都打印了10

              造成的原因就是 綁定click事件時 回調函數并未執行 當回調函數執行時 i已經變成了10 所以打印的結果都會變成10

              解決方法:

              思路: 如果能找到一種方式可以將每一次的i都緩存起來 并且一直到click事件觸發的時候 它都一直不會消失 不就完了么

              我們都知道 一個函數作用域內執行完后..作用域中的所有臨時變量都會消失 但是有一種不讓臨時變量消失的方式就是使用閉包。。而上面講閉包的使用場景時 其中有一條就是事件回調函數 當一個事件回調函數位于一個作用域內的時候...作用域執行外后 由于回調函數并未馬上執行..而是等到相應事件觸發時才執行...當回調函數依賴該作用域內的臨時變量時...導致該作用域內部使用的臨時變量無法馬上被當垃圾回收(意味著該臨時變量不會消失)

              目前我們擁有一個事件回調函數 要做的就是需要讓這個事件回調函數位于一個函數作用域內

              代碼:

              for( var i = 0; i < 10; i++ ){

              /pic/p>

              function(){

              document.getElementById( 'test' + i ).onclick = function(){

              /pic/p>

              console.log( i );

              };

              };

              }

              這樣 事件綁定就位于一個匿名函數中了...但是這樣肯定不行...因為函數都沒有執行...函數內的代碼肯定不會起作用....也就是說..這段代碼能夠正常執行 不報錯..但是不會為每一個元素綁定一個事件..因為它的外部函數沒有執行

              繼續修改:

              for( var i = 0; i < 10; i++ ){

              /pic/p>

              (function(){

              document.getElementById( 'test' + i ).onclick = function(){

              /pic/p>

              console.log( i );

              };

              })();

              }

              恩 這次看起來差不多了....綁定事件的行為位于一個匿名函數中..并且匿名函數定義后立即執行....

              但是目前 綁定事件內的變量i并不是 匿名函數中所產生的臨時變量 i是一個全局變量 i不會因為匿名函數的執行而一直保持 你所希望的值

              所以我們需要在匿名函數內定義一個臨時變量 該臨時變量的值和當前相應的i值相等即可 將i直接賦值給該臨時變量就可以了..

              最終修改代碼:

              for( var i = 0; i < 10; i++ ){

              /pic/p>

              (function(){

              var j = i;

              document.getElementById( 'test' + j ).onclick = function(){

              /pic/p>

              console.log( j );

              };

              })();

              }其實不一定要直接賦值 當一個參數傳進去也行代碼如下(執行結果一樣..過程也沒什么區別..只是寫法不同)for( var i = 0; i < 10; i++ ){

              /pic/p>

              (function( j ){

              document.getElementById( 'test' + j ).onclick = function(){

              /pic/p>

              console.log( j );

              };

              })( i );

              }

              其實還有一種不使用閉包的方式...在事件的回調函數中直接引用 dom對象的一個屬性即可 因為dom對象是一直存在的 而指向當前的dom對象使用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中閉包的一些常見問題】相關文章:

            javascript中js閉包的深入理解09-29

            PHP中的Trait11-20

            細數PHP程序的一些缺陷08-19

            PHP中php://input和$-POST的區別11-07

            PHP中list的方法11-17

            PHP中的魔術方法03-05

            PHP中Json應用03-01

            PHP中的Reload操作12-19

            PHP中$-SERVER的詳解09-09

            • 相關推薦

                    <pre id="bbfd9"><del id="bbfd9"><dfn id="bbfd9"></dfn></del></pre>

                    <ruby id="bbfd9"></ruby><p id="bbfd9"><mark id="bbfd9"></mark></p>

                    <p id="bbfd9"></p>

                    <p id="bbfd9"><cite id="bbfd9"></cite></p>

                      <th id="bbfd9"><form id="bbfd9"><dl id="bbfd9"></dl></form></th>

                      <p id="bbfd9"><cite id="bbfd9"></cite></p><p id="bbfd9"></p>
                      <p id="bbfd9"><cite id="bbfd9"><progress id="bbfd9"></progress></cite></p>
                      飘沙影院