深入解析jQuery中的延时对象的概念

首先我们需要明白延时对象有什么用?

第一个作用,解决时序以及动态添加执行函数的问题。

function a(){alert(1)};
function b(){alert(2)};
function c(){alert(3)};
a();
setTimeout(function(){b();},0);
c();

很明显函数执行顺序是a->c->b,而不是按照函数添加的顺序执行。如果我要保证函数按顺序执行,那么c 必须写紧跟在b后面执行

setTimeout(function(){b(); c();},0);

如果添加的函数按顺序执行,比如添加在b后面的函数都在b执行后执行(如果b已经执行过了,那么久马上执行)。如果按照这种方式,我们必须在执行之前就知晓说有要执行的函数,然后都加到setTimeout里面去,这个限制非常可恶。我希望的是即使b执行过了,我后面还能动态的添加函数并得到执行。比如

var defer = $.Deferred(); //构建异步对象
function a(){alert(1)};
function b(){alert(2)};
//添加函数
defer.done(
a);
//添加函数
defer.done(b);
setTimeout(function(){
  defer.resolve();//alert(1),alert(2)
},0);
//添加函数
defer.done(function c(){alert(3)});//马上执行出结果alert(3)

第二,解决参数传递的问题,所有的执行函数需要的参数相同,我希望我只传递一个参数就将所有的结果执行出来,特别是后续添加的函数执行我也希望使用原来的参数。

function a(value){alert("a = "   value)};
function b(value){alert("b = "   value)};
var list = [],
val = 0;;
list[list.length] = a;
list[list.length] = b;
function runList(listArray,value){
for(var i = 0; i < listArray.length; i  ){
listArray[i](value);
}
listArray.length  = 0;
}
val = 5;
runList(list,val );//执行a = 5;b = 5;
list[list.length] = function c(value){alert("c = "   value)};
runList(list,val);//执行结果c = 5

在保证runList函数有自己的作用域,不使用外部变量的情况下,那么我们每次执行runList都需要重新传递list和val这个变量。这种重复劳动没有任何意义。看看deferred的处理方式

var defer = $.Deferred(); //构建异步对象
function a(value){alert("a = "   value)};
function b(value){alert("b = "   value)};
defer.done(a,b);//添加函数
defer.resolve(5);//执行结果a = 5; b = 5;
defer.done(function c(value){alert("c = "   value)});//添加函数,执行结果c = 5

首先你要承认的是代码简化和可读性都高很多,其次,传递的执行参数值5只需要一次便足够,哪怕是后面添加的函数c也会用先前传递过来的参数执行。

Deferred函数将Callbacks函数抽离出去以后Deferred函数变得很精简。如下

jQuery.extend({
Deferred : function(){…}
when : function(){…}
)}

其中Deferred的整体结构如下

  Deferred: function( func ) {
var tuples = [
// action, add listener, listener list, final state
[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
[ "notify", "progress", jQuery.Callbacks("memory") ]
],
state = "pending",
promise = {
state: function() {…},
always: function() {…},
then: function( /* fnDone, fnFail, fnProgress */ ) {…},
promise: function( obj ) {…}
},
deferred = {}; 
//兼容老版本
promise.pipe = promise.then; 
// 添加promise的三个方法[done | fail | progress]方法
    // 添加deferred的六个方法[resolve |resolveWith | reject | rejectWith | notify | notifyWith]
jQuery.each( tuples, function( i, tuple ) { ... });     // Make the deferred a promise promise.promise( deferred ); ...     return deferred; }

主要做了几个工作。

  1. 定义promise的几个对外接口state/always/then/promise
  2. 通过tuples初始化deferred的几个接口resolve/resolveWith/reject/rejectWith/notify /notifyWith,并且为promise定义了另外的三个接口done/fail/progress。其中会被添加到这些个接口都与tuples创建的三个Callbacks有关。后续再详解。
  3. 使用promise.promise拓展deferred返回。我们看一下这个返回有哪些个方法  

deferred.done(fns)

将回调添加到成功回调列表(doneCallbacks),当Deferred(延迟)对象解决(调用resolve)时会执行成功回调列表中的所有函数。参数fns可以是函数,也可以是函数数组

 deferred.fail(fns)

 将回调添加到失败回调列表(failCallbacks),当Deferred(延迟)对象拒绝(调用reject)时会执行失败回调列表中的所有函数。参数fns可以是函数,也可以是函数数组

deferred.always(fns)

将回调添加到成功回调列表(doneCallbacks和失败回调列表(failCallbacks)。确保当Deferred(延迟)对象解决(调用resolve)或拒绝(调用reject)时,都会执行到该回调。参数fns可以是函数,也可以是函数数组

 

deferred.progress(fns)

 将回调添加到进度回调列表(progressCallbacks),当Deferred(延迟)对象生成进度通知(调用notify)时,执行进度回调列表中的所有函数。参数fns可以是函数,也可以是函数数组

 

deferred.resolve(args)

 解决Deferred(延迟)对象,并根据给定的args参数执行成功回调列表(doneCallbacks)的所有函数。

 

deferred.resolveWith(context, args)

 解决Deferred(延迟)对象,并根据给定的 context和args参数执行成功回调列表(doneCallbacks)的所有函数。这是jQuery.Callbacks的内部方法fireWith的引用,deferred.resolve()方法内部调用该方法来实现。不建议外部使用。

 

deferred.reject(args)

 拒绝Deferred(延迟)对象,并根据给定的args参数调用失败回调列表(failCallbacks)中的所有函数。

 

deferred.rejectWith(context, args)

 拒绝Deferred(延迟)对象,并根据给定的 context和args参数执行失败回调列表(failCallbacks)的所有函数。这是jQuery.Callbacks的内部方法fireWith的引用,deferred.reject()方法内部调用该方法来实现。不建议外部使用。

 

deferred.notify(args)

 根据给定的 args参数 调用Deferred(延迟)对象上进度回调列表(progressCallbacks)的所有函数。

 

deferred.notifyWith(contex,args)

 根据给定的上下文(context)和args递延调用Deferred(延迟)对象上进度回调列表(progressCallbacks )上的所有函数。这是jQuery.Callbacks的内部方法fireWith的引用,deferred.notify()方法内部调用该方法来实现。不建议外部使用。

 

deferred.state()

 确定一个Deferred(延迟)对象的当前状态。"pending"、"resolved"、"rejected"

 

deferred.pipe()/deferred.then()

 当Deferred(延迟)对象解决(resolve)、拒绝(reject)或生成进度(notify),调用相应回调列表的所有函数。

 

jQuery.Deferred()

  一个构造函数,返回一个延时对象。

 

jQuery.when(subordinate /* , ..., subordinateN */)

 提供一种方法来执行一个或多个对象的回调函数, Deferred(延迟)对象通常表示异步事件。

 

.promise()

 返回一个 Promise 对象用来观察当某种类型的所有行动绑定到集合,排队与否还是已经完成

  

a. $.Deferred()详解


关键源码如下

Deferred: function( func ){
var tuples = [
    // 执行名, 添加监听器(回调), 监听列表(回调列表), 最终状态
[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
[ "notify", "progress", jQuery.Callbacks("memory") ]
],
state = "pending",
promise = {
...
promise: function( obj ) {
      return obj != null ? jQuery.extend( obj, promise ) : promise;
}
},
deferred = {};
  
  //
添加列表指定的方法   jQuery.each( tuples, function( i, tuple ) {     var list = tuple[ 2 ], stateString = tuple[ 3 ];     // promise[ done | fail | progress ] = list.add     promise[ tuple[1] ] = list.add;     // 只有tuples[0]和tuples[1]进入该分支     if ( stateString ) {       //给Callbacks对象添加回调列表       list.add(function() {         // state = [ resolved | rejected ]         state = stateString;         // [ reject_list | resolve_list ].disable; progress_list.lock       }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); }     // deferred[ resolve | reject | notify ]     deferred[ tuple[0] ] = function() { deferred[ tuple[0] "With" ]( this === deferred ? promise : this, arguments );       return this; }; deferred[ tuple[0] "With" ] = list.fireWith; });   // 给deferred添加promise的函数接口   promise.promise( deferred );   ...
  return
deferred; }

我们把tuples[index][2]中的jQuery.Callbacks返回的对象所代表的回调列表分别取名叫做doneCallbacks(成功回调列表),failCallbacks(失败回调列表),progressCallbacks(进度回调列表)。则到函数执行到promise.promise( deferred );之前。promise变量变成了

promise = {
state: function() {…},
always: function() {…},
then: function( /* fnDone, fnFail, fnProgress */ ) {…},
promise: function( obj ) {…},
done: doneCallbacks.add,
fail: failCallbacks.add,
progress: progressCallbacks.add
}

deferred变量变成了

deferred = {
resolve: function() {
deferred["resolveWith" ]( this === deferred ? promise : this, arguments );
return this;
},
resolveWith: doneCallbacks.fireWith,
reject: function() {
deferred["rejectWith" ]( this === deferred ? promise : this, arguments );
return this;
},
rejectWith: failCallbacks.fireWith,
notify: function() {
deferred["notifyWith" ]( this === deferred ? promise : this, arguments );
return this;
},
notifyWith: progressCallbacks.fireWith
}    

初始化结束后doneCallbacks中回调队列如下

[
function(){state = “resolved”:},
failCallbacks.disable,
progressCallbacks.lock
]

初始化结束后failCallbacks中回调队列如下

[
function(){state = “rejected”;},
doneCallbacks.disable,
progressCallbacks.lock
]

初始化结束后progressCallbacks的回调列表中没有任何回调

需要注意的是doneCallbacks、failCallbacks的设置是”once memory”,progressCallbacks设置是”memory”

这样,应当好理解Deferred的原理了。我们使用done/fail是”once memory”设置下的add。意味着如果如果先执行了resolve/ reject方法,后调用done/fail则会直接执行回调。

eg:

var defer = $.Deferred(); //构建异步对象
//执行doneCallbacks的回调,保存场景,这个时候doneCallbacks有三个回调函数,依序执行。其中第二个回//调禁用failCallbacks(禁用reject/rejectWith),第三个回调锁progressCallbacks(锁notify/notifyWith) defer.resolve( 5 ); defer.done(function( value ) { console.log('打印出值',value) });//doneCallbacks.add,立刻执行回调

如果是先调用done/fail,后执行resolve/reject。根据”once memory”将会先添加回调,然后fire。

eg:

var defer = $.Deferred(); //构建异步对象 
//1秒钟后执行doneCallbacks回调,保存场景。这个时候的doneCallbacks有四个回调函数,依序执行
setTimeout(function(){
defer.resolve( 5 );   
},1000); 
//根据”once memory”,第一次fire之前会把回调添加到doneCallbacks中。等待调用
defer.done(function( value ) {console.log('打印出值',value)});

当延迟对象被 resolved 时,任何通过 deferred.then或deferred.done 添加的 doneCallbacks,都会被调用。回调函数的执行顺序和它们被添加的顺序是一样的。传递给 deferred.resolve() 的 args 参数,会传给每个回调函数。当延迟对象进入 resolved 状态后,再添加的任何 doneCallbacks,当它们被添加时,就会被立刻执行,并带上传入给 .resolve()的参数

 b. Deferred.promise.then详解

API是这么定义的:

deferred.then( doneFilter [, failFilter ] [, progressFilter ] )

从jQuery 1.8开始, 方法返回一个新的promise(承诺),通过一个函数,可以过滤deferred(延迟)的状态和值。替换现在过时的deferred.pipe()方法。   doneFilter 和 failFilter函数过滤原deferred(延迟)的解决/拒绝的状态和值。 progressFilter 函数过滤器的任何调用到原有的deferred(延迟)的notify 和 notifyWith的方法。

这些过滤器函数可以返回一个新的值传递给的 promise(承诺)的.done() 或 .fail() 回调,或他们可以返回另一个观察的对象(递延,承诺等)传递给它的解决/拒绝的状态和值promise(承诺)的回调。

 

如果过滤函数是空,或没有指定,promise(承诺)将得到与原来值相同解决(resolved)或拒绝(rejected)。

源码解析:

then: function( /* fnDone, fnFail, fnProgress */ ) {
  var fns = arguments;
return jQuery.Deferred(function( newDefer ) {
//遍历tuples,将fnDone, fnFail, fnProgress分别绑定到tuples[0-2][2]的回调列表上
jQuery.each( tuples, function( i, tuple ) {
var action = tuple[ 0 ],//resolve/reject/notify
fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
      //执行deferred[ done | fail | progress ] 函数,将回调fnDone, fnFail, fnProgress分别添加到回调列表
      //需要明确的是这些回调函数是添加到deferred中的,不是newDefer中的。
deferred[ tuple[1] ](function() {
        //执行fnDone, fnFail, fnProgress函数
        var returned = fn && fn.apply( this, arguments );
        //如果返回的是Deferred对象或是Deferred.promise对象
        if ( returned && jQuery.isFunction( returned.promise ) ) {
          //当Deferred(延迟)对象解决/拒绝/生成进度通知时
//调用添加处理程续resolve/reject/notify
returned.promise()
.done( newDefer.resolve )
.fail( newDefer.reject )
.progress( newDefer.notify );
} else {
          //执行resolveWith/rejectWith/notifyWith函数执行所有剩余回调
          newDefer[ action   "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
}
});
});
fns = null;
}).promise();
}。

我们抓住几点:

返回的是新的promise对象

内部有一个过滤器函数

我们将最外层初始化的延时对象叫做主延时对象mainDeferred,经过mainDeferred.then()方法处理的代码中返回的jQuery.Deferred(...).promise(),不是原来的mainDeferred了,我们把它命名为thenDeferred。thenDeferred初始化的时候有这个一段

            // 调用给定的func参数
if ( func ) {
func.call( deferred, deferred );
}

刚好thenDeferred的初始化带有函数参数我们命名为thenParamfunc。thenParamfunc的参数是newDefer,结合上面执行func的代码我们可知,这个newDefer就是thenDeferred嘛,饶了半天。thenParamfunc中做一个操作:

往mainDeferred的三个回调列表中添加回调,每个回调内部会执行mainDeferred.then添加的对应的回调函数。

      //deferred是主延时对象mainDeferred
      deferred[ tuple[1] ](function() {
        
//执行fnDone, fnFail, fnProgress函数
        
var returned = fn && fn.apply( this, arguments );
        
...
      });

还需要注意的是当这些回调被调用时,mainDeferred.then添加的回调执行后,会执行下面的代码

newDefer[ action   "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );

这表明mainDeferred.then生成的延时对象thenDeferred的状态依赖于主延时对象mainDeferred。当mainDeferred解决(resolve),那么thenDeferred也会被解决(resolve),并且mainDeferred.then设置的doneFilter的返回值将作为参数传递给thenDeferred的回调列表。

eg:

var deferred = $.Deferred();
var m = deferred
.done(function(val){console.log('done function '   val)})
.then(function(val){console.log('done then '   val); return 10;},
  function(val){console.log('fail then '   val);},
  function(val){console.log('progress then'   val);})
  
//主延时对象解决
//打印done function 5;
done then 5;
deferred.resolve(5);

//执行then deferred done 10
m.done(function(val){console.log("then deferred done " value)})

现在完整的分析一个例子的数据

eg:

var deferred = $.Deferred();
deferred
.done(function(val){console.log('done function '   val)})
.then(function(val){console.log('done then'   val);},
  function(val){console.log('fail then'   val);},
  function(val){console.log('progress then'   val);})
deferred.resolve(5);

说明:

deferred.done(...).then(...)执行后,done的回调列表doneCallbacks是下面的样子

doneCallbacks = [
  function () {     // state = [ resolved | rejected ] state = stateString;     // [ reject_list | resolve_list ].disable; progress_list.lock },   function () { list = stack = memory = undefined;     return this; },   function () { stack = undefined;     if ( !memory ) { self.disable(); }     return this; },   function (val){ console.log('done function ' val) },   function () {     var returned = fn && fn.apply( this, arguments );     if ( returned && jQuery.isFunction( returned.promise ) ) { returned.promise() .done( newDefer.resolve ) .fail( newDefer.reject ) .progress( newDefer.notify ); } else { newDefer[ action "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); } }
]

其中doneCallbacks前面三个是Callbacks自带的,第四个是.done添加的,

第五个这个是.then的第一个参数添加的,对应的fn是function(val){console.log('done then' val);}

fail的回调列表failCallbacks的样式是

  failCallbacks = [
    function () { // state = [ resolved | rejected ] state = stateString; // [ reject_list | resolve_list ].disable; progress_list.lock }, function () { list = stack = memory = undefined; return this; }, function () { stack = undefined; if ( !memory ) { self.disable(); } return this; }, function () { var returned = fn && fn.apply( this, arguments ); if ( returned && jQuery.isFunction( returned.promise ) ) { returned.promise() .done( newDefer.resolve ) .fail( newDefer.reject ) .progress( newDefer.notify ); } else { newDefer[ action "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); } }
]

前面三个元素是Callbacks自带的,

第四个是.then的第二个参数添加的,对应的fn是function(val){console.log('fail then' val);}

progress对应回调列表progressCallbacks的样子是

progressCallbacks = [
    function () { var returned = fn && fn.apply( this, arguments ); if ( returned && jQuery.isFunction( returned.promise ) ) { returned.promise() .done( newDefer.resolve ) .fail( newDefer.reject ) .progress( newDefer.notify ); } else { newDefer[ action "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); } }
]

只有一个元素是.then的第三个参数添加的,fn对应为function(val){console.log('progress then' val);})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/367592.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c mysql5.7_CentOS7下MySQL5.7的三种安装方式详解

操作系统环境&#xff1a;CentOS 7.4最小化安装[rootnode3 src]# cat /etc/redhat-releaseCentOS Linux release 7.4.1708 (Core)[rootnode3 ~]# uname -r3.10.0-693.5.2.el7.x86_64[rootnode3 ~]#安装版本为&#xff1a;MySQL 5.7.20一、编译安装MySQL5.71、下载源码包[rootno…

Struts2 学习之小白开始

Struts2 基础知识学习总结 Struts2 概述&#xff1a;Struts2 是一个用来开发 MVC 应用程序的框架&#xff0c;他提供了 Web 应用程序开发过程中的一些常见问题的解决方案&#xff0c;比如对于用户输入信息合法性的验证&#xff0c;统一的布局&#xff0c;国际化等&#xff0c;既…

机器学习的数学基础 - 信息论

机器学习的数学基础 - 信息论 信息论 信息论本来是通信中的概念&#xff0c;但是其核心思想“熵”在机器学习中也得到了广泛的应用。比如决策树模型ID3&#xff0c;C4.5中是利用信息增益来划分特征而生成一颗决策树的&#xff0c;而信息增益就是基于这里所说的熵。所以它的重要…

了解ElasticSearch分析器

令人遗憾的是&#xff0c;许多早期的互联网啤酒配方不一定采用易于消化的格式。 也就是说&#xff0c;这些食谱是通常在电子邮件或论坛帖子中最初组成的非结构化的方向和成分混合列表。 因此&#xff0c;尽管很难轻松地将这些配方放入传统的数据存储中&#xff08;表面上看是为…

c++简单程序设计-2

1.验证性实验部分①函数声明和函数定义各自的作用及二者的区别&#xff1a;函数声明就是调用函数之前提示一下有这个函数函数定义就是写一个函数②什么是形参&#xff1f;什么是实参&#xff1f;函数参数和返回值在函数中起到什么作用&#xff1f;函数定义时写的参数叫做形参&a…

java 同步的方法_关于Java中的同步方法

我有一个关于Java中方法同步的问题.考虑一个具有3个同步方法的类.class MyClass{public synchronized void methodA(){ ... }public synchronized void methodB(){ ... }public synchronized void methodC(){ ... }}考虑myObject,myClass的一个实例.以下内容哪些是对的&#xf…

jQuery获取隐藏域和radio单项框的值

获得只有Name的隐藏Input的值$("input[typehidden][name隐藏Input的名称]").val() 或 $("input[name隐藏Input的名称]:hidden").val()radio设值$("input[typeradio][value值]").attr("checked",true);eg.$("input[typeradio][v…

Linux虚机安装配置Tomcat

d第一步&#xff1a;下载Tomcat包&#xff0c;网址http://tomcat.apache.org/ 选择tar.gz包下载&#xff0c;并传到虚机中 第二步&#xff1a;解压下载好的Tomcat包 命令&#xff1a;tar -zxvf apache-tomcat-8.0.53.tar.gz 第三步&#xff1a;配置环境变量 进入到Tomcat下bin包…

Java Comparable接口的陷阱

Java Comparable接口提供了一种对实现该接口的类进行自然排序的方法。 自然顺序对标量和其他非常简单的对象有意义&#xff0c;但是当我们使用面向业务的领域对象时&#xff0c;自然顺序就变得更加复杂。 从业务经理的角度来看&#xff0c;交易对象的自然顺序可以是交易的价值&…

mysql 创建视图

CREATE VIEW v_image_org_user_album AS--创建视图并命名v_image_org_user_album SELECT --先开from中表的命名 a.id AS imgid,--将a表中的id命名为新的表&#xff08;视图&#xff09;中的imgid字段&#xff0c;剩下的都一样&#xff0c;就是将之前的字段重新命名到…

jQuery.ajaxPrefilter()函数的使用

jQuery.ajaxPrefilter( [dataTypes ], handler(options, originalOptions, jqXHR) )返回: undefined 描述: 在每个请求之前被发送和 $.ajax()处理它们前处理&#xff0c;设置自定义Ajax选项或修改现有选项。 添加的版本: 1.5jQuery.ajaxPrefilter( [dataTypes ], handler(optio…

linux php自动执行_linux下实现定时执行php脚本

在linux中输入命令复制代码 代码如下:crontab -e然后使用vim的命令编辑打开的文件&#xff0c;输入复制代码 代码如下:0 * * * * /usr/bin/php -f /home/userxxx/update.php保存&#xff0c;退出&#xff0c;好了&#xff0c;现在系统会在每个0点自动执行update.php脚本&#x…

Nginx安装及配置详解

nginx概述 nginx是一款自由的、开源的、高性能的HTTP服务器和反向代理服务器&#xff1b;同时也是一个IMAP、POP3、SMTP代理服务器&#xff1b;nginx可以作为一个HTTP服务器进行网站的发布处理&#xff0c;另外nginx可以作为反向代理进行负载均衡的实现。 这里主要通过三个方面…

Gradle:我们需要另一个构建工具吗?

在Java开发的早期&#xff0c;我们要么没有太多的构建工具需求&#xff0c;要么就使用了其他环境中的工具。 我仍然记得构建shell脚本并创建用于开发Java的文件。 生成文件特别有趣&#xff0c;因为这是一个在设计时就没有考虑Java的工具。 迁移到不同的操作系统环境也很困难。…

servlet简单概括总结

最近在看java web的相关内容&#xff0c;不管是整体还是细节&#xff0c;要学习的知识有很多&#xff0c;所以有一个好的学习体系非常重要。在阅读学习一些博客和教程中关于servlet的内容后&#xff0c;现将知识体系和自己的总结体会进行梳理&#xff0c;希望在更深入理解的同时…

jquery学习之-查找父元素方法parent() parents() closest()的区别

parent()、parents()与closest()方法两两之间有类似又有不同&#xff0c;本篇简短的区分一下这三个方法。通过本篇内容&#xff0c;大家将会在以后使用.parent()、parents()和closest()时不会显得无从下手。 我们直接看例子来来说明一下这三个方法的使用区别&#xff1a; <u…

二叉树的递归遍历与复制

1 #include <iostream>2 3 //定义树的数据结构4 struct BiTNode5 {6 int data;7 struct BiTNode *lchild, *rchild;8 };9 10 typedef struct BiTNode BiTNode;11 typedef struct BiTNode* BiTree;12 13 14 //前序遍历15 void preOrder(BiTNode *root)16 {17…

php超强后门在任意位置创建文件,php大马:.user.ini文件构成的超强PHP后门

这个估计很多同学看了不屑&#xff0c;认为是烂大街的东西了&#xff1a;那么我来个新的吧&#xff1a;。它比用的更广&#xff0c;不管是nginx/apache/IIS&#xff0c;只要是以fastcgi运行的php都可以用这个方法。我的nginx服务器全部是fpm/fastcgi&#xff0c;我的IIS php5.3…

CSS3-字体渐变色

示例&#xff1a;Maugers Blog <!DOCTYPE HTML> <html> <head><meta charset"utf-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><title>Maugers Blog</title><style type"text/css…

Restlet框架– Hello World示例

Restlet是用于Java平台的轻量级&#xff0c;全面的开源REST框架。 Restlet适用于服务器和客户端Web应用程序。 它支持主要的Internet传输&#xff0c;数据格式和服务描述标准&#xff0c;例如HTTP和HTTPS&#xff0c;SMTP&#xff0c;XML&#xff0c;JSON&#xff0c;Atom和WAD…