一个函数excel第一次出现函数执行时间较长,请问下原因

性能之编程实践
*避免双重求值:javascript允许在程序中提取一个包含代码的字符串,然后动态执行它,eval() Function()构造函数 setTimeout() setInterval()。双重求值过程:当你在javascript代码中执行另一段javascript代码时,都会导致双重求值的性能消耗,此代码首先会以正常的方式求值,然后在执行过程中对包含字符串的代码发起另一个求值,双重求值是一项昂贵的操作,它比直接包含代码执行速度要慢很多。大多数时候,没有必要使用eval()和Function(),因此最好避免使用它们,至于另外两个函数:setTimeout()和setInterval(),建议传入函数而不是字符串来作为第一个参数。*使用Object/Array字面量*不要重复工作:别做无关紧要的工作,别重复做已经完成的工作,第一部分通常是很容易在代码重构的时候发现的,工作中存在各种代码的重复。举例:浏览器探测function addHandler(target,eventType,handler){&&if(target.addEventListener){& & target.addEventListener(eventType,handler,false);&&}else{& & target.attachEvent(&on&+eventType,handler);&&}}function removeHandler(target,eventType,handler){&&if(target.removeEventListener){& & target.removeEventListener(eventType,handler,false);&&}else{& & target.detachEvent(&on&+eventType,handler);&&}}隐藏的性能问题就是每次函数调用都做了重复判断指定方法是否存在。*延迟加载:延迟加载意味着在信息使用前不会做任何的操作。调用延迟加载函数时,第一次总会消耗较长的时间,因为它必须运行检测在接着再调用另一个函数完成任务,但随后调用相同的函数会更快,因为不需要再执行检测逻辑,当一个函数在页面中不会立刻调用,延迟加载时最好的选择。function addHandler(target,eventType,handler){&&if(target.addEventListener){& & addHandler=function(target,eventType,handler){& && &target.addEventListener(eventType,handler,false);& & }&&}else{& & addHandler=function(target,eventType,handler){& && &target.attachEvent(&on&+eventType,handler);& & }&&}&&addHandler(target,eventType,handler);}function removeHandler(target,eventType,handler){&&if(target.removeEventListener){& & removeHandler=function(target,eventType,handler){& && &target.removeEventListener(eventType,handler,false);& & };&&}else{& & removeHandler=function(target,eventType,handler){& && &target.detachEvent(&on&+eventType,handler);& & };&&}}*条件预加载:它是在脚本加载期间提前,而不会等待函数被调用的时候。var addHandler=document.body.addEventListener?function(target,eventType,handler){& &&&target.addEvenetListener(eventType,handler,false);}:function(target,eventType,handler){& &&&target.attachEvent(&on&+eventType,handler);}var removeHandle=document.body.removeEventListener?function(target,eventType,handler){& &&&target.removeEventListener(eventType,handler,false)}:function(target,eventType,handler){& &&&target.detachEvent(&on&+evenTyoe,handler);}先检测addEventListener()和removeEventListener()是否存在,然后根据结果指定选择最佳的函数,条件预加载确保所有函数调用消耗的时间相同,其代价是需要在脚本加载就检测,而不是加载后,预加载适用于一个函数马上就要被用到,并且在整个页面的生命周期中频繁出现的场合。*使用速度快的部分:javascript在某些部分运行快的使人难以置信。位操作:& | ^ ~原生方法:javascript引擎提供的原生方法要更快。Math.abs(num) Math.exp(num)E的指数 Math.log(num) Math.pow(num,power)Math.sqrt(num)num平方根 Math.cos(x) Math.sin(x) Math.tan(x)小结:1:避免使用eval()和Function()构造器来避免双重求值带来的性能消耗。同样的,给setTimeout()和setInterval()传递函数而不是字符串作为参数。2:尽量使用直接量创建对象和数组。3:避免做重复的工作,当需要检测浏览器时,可使用延迟加载或条件预加载。4:在进行数学计算时,考虑使用直接操作数字的二进制形式的位运算。5:javascript原生的方法总会你写的任何代码要快,尽量使用原生的方法。
&& //:谢谢 //:你是好样的,可很多人就贪快捷,整天学这框架、那框架的,学了N年,还是跟着升级版的框架屁股走。
谢谢 //:你是好样的,可很多人就贪快捷,整天学这框架、那框架的,学了N年,还是跟着升级版的框架屁股走。 //:开始学习的时候,都是学原生的方法。
你开始学的框架么? //:你是好样的,可很多人就贪快捷,整天学这框架、那框架的,学了N年,还是跟着升级版的框架屁股走。 //:开始学习的时候,都是学原生的方法。
原生的要了解,至于能不能用原生的做项目,是两回事…… //:你是好样的,可很多人就贪快捷,整天学这框架、那框架的,学了N年,还是跟着升级版的框架屁股走。 //:开始学习的时候,都是学原生的方法。
我就是,现在再回头学习原生 //:你是好样的,可很多人就贪快捷,整天学这框架、那框架的,学了N年,还是跟着升级版的框架屁股走。 //:开始学习的时候,都是学原生的方法。
你是好样的,可很多人就贪快捷,整天学这框架、那框架的,学了N年,还是跟着升级版的框架屁股走。 //:开始学习的时候,都是学原生的方法。 //:这个框架泛滥的时代,说用原生的方法,难难难。。。
开始学习的时候,都是学原生的方法。 //:这个框架泛滥的时代,说用原生的方法,难难难。。。
这个框架泛滥的时代,说用原生的方法,难难难。。。
118 总笔记数
11万 总阅读量
Copyright &
All Rights Reserved.
合作伙伴:JavaScript的单线程性质以及定时器的工作原理 - Rain man - PHP博客
我的图书馆
JavaScript的单线程性质以及定时器的工作原理 - Rain man - PHP博客
最近在写JavaScript时遇到一些问题,就是当JavaScript多事件连续触发,JavaScript的单线程引擎是如何控制的。找了一些资料,觉得很有用,在此分享一下。&
虽然不是原创,但是觉得此文章对JavaScript程序员非常有用。翻译的不是十分精确,但希望对大家有用。
原文:John Resig&&&
How JavaScript Timers Work
从基础的层面来讲,理解JavaScript的定时器是如何工作的是非常重要的。计时器的执行常常和我们的直观想象不同,那是因为JavaScript引擎是单线程的。我们先来认识一下下面三个函数是如何控制计时器的。
var id = setTimeout(fn, delay);&- 初始化一个计时器,然后在指定的时间间隔后执行。该函数返回一个唯一的标志ID(Number类型),我们可以使用它来取消计时器。
var id = setInterval(fn, delay);&- 和setTimeout有些类似,但它是连续调用一个函数(时间间隔是delay参数)直到它被取消。
clearInterval(id);,&clearTimeout(id);&- 使用计时器ID(setTimeout 和 setInterval的返回值)来取消计时器回调的发生
为了理解计时器的内在执行原理,有一个重要的概念需要加以探讨:计时器的延迟(delay)是无法得到保障的。由于所有JavaScript代码是在一个线程里执行的,所有异步事件(例如,鼠标点击和计时器)只有拥有执行机会时才会执行。用一个很好的图表加以说明:
在这个图表中有许多信息需要理解,如果完全理解了它们,你会对JavaScript引擎如何实现异步事件有一个很好的认识。这是一个一维的图标:垂直方向表示时间,蓝色的区块表示JavaScript代码执行块。例如第一个JavaScript代码执行块需要大约18ms,鼠标点击所触发的代码执行块需要11ms,等等。
由于JavaScript引擎同一时间只执行一条代码(这是由于JavaScript单线程的性质),所以每一个JavaScript代码执行块会“阻塞”其它异步事件的执行。这就意味着当一个异步事件发生(例如,鼠标点击,计时器被触发,或者Ajax异步请求)后,这些事件的回调函数将排在执行队列的最后等待执行(实际上,排队的方式根据浏览器的不同而不同,所以这里只是一个简化);
从第一个JavaScript执行块开始研究,在第一个执行块中两个计时器被初始化:一个10ms的setTimeout()和一个10ms的setInterval()。依据何时何地计时器被初始化(计时器初始化完毕后就会开始计时),计时器实际上会在第一个代码块执行完毕前被触发。但是,计时器上绑定的函数不会立即执行(不被立即执行的原因是JavaScript是单线程的)。实际上,被延迟的函数将依次排在执行队列的最后,等待下一次恰当的时间再执行。
此外,在第一个JavaScript执行块中我们看到了一个“鼠标点击”事件发生了。一个JavaScript回调函数绑定在这个异步事件上了(我们从来不知道用户什么时候执行这个(点击)事件,因此认为它是异步的),这个函数不会被立即执行,和上面的计时器一样,它将排在执行队列的最后,等待下一次恰当的时候执行。
当第一个JavaScript执行块执行完毕后,浏览器会立即问一个问题:哪个函数(语句)在等待被执行?在这时,一个“鼠标点击事件处理函数”和一个“计时器回调函数”都在等待执行。浏览器会选择一个(实际上选择了“鼠标点击事件的处理函数”,因为由图可知它是先进队的)立即执行。而“计时器回调函数”将等待下次适合的时间执行。
注意,当“鼠标点击事件处理函数”执行的时候,setInterval的回调函数第一次被触发了。和setTimeout的回调函数一样,它将排到执行队列的最后等待执行。但是,一定要注意这一点:当setInterval回调函数第二次被触发时(此时setTimeout函数仍在执行)setTimeout的第一次触发将被抛弃掉。当一个很长的代码块在执行时,可能把所有的setInterval回调函数都排在执行队列的后面,代码块执行完之后,结果便会是一大串的setInterval回调函数等待执行,并且这些函数之间没有间隔,直到全部完成。所以,浏览器倾向于的当没有更多interval的处理函数在排队时再将下一个处理函数排到队尾(这是由于间隔的问题)。
我们能够发现,当第三个setInterval回调函数被触发时,之前的setInterval回调函数仍在执行。这就说明了一个很重要的事实:setInterval不会考虑当前正在执行什么,而把所有的堵塞的函数排到队列尾部。这意味着两次setInterval回调函数之间的时间间隔会被牺牲掉(缩减)。
最后,当第二个setInterval回调函数执行完毕后,我们可以看到没有任何程序等待JavaScript引擎执行了。这就意味着浏览器现在在等待一个新的异步事件的发生。在50ms时一个新的setInterval回调函数再次被触发,这时,没有任何的执行块阻塞它的执行了。所以它会立刻被执行。
让我们用一个例子来阐明setTimeout和setInterval之间的区别:
& setTimeout(function(){& &&/* Some long block of code... */& & setTimeout(arguments.callee,&10);&&},&10);&&& setInterval(function(){& &&/* Some long block of code... */&&},&10);
这两句代码乍一看没什么差别,但是它们是不同的。setTimeout回调函数的执行和上一次执行之间的间隔至少有10ms(可能会更多,但不会少于10ms),而setInterval的回调函数将尝试每隔10ms执行一次,不论上次是否执行完毕。
在这里我们学到了很多知识,总结一下:
JavaScript引擎是单线程的,强制所有的异步事件排队等待执行
setTimeout&和&setInterval&在执行异步代码的时候有着根本的不同
如果一个计时器被阻塞而不能立即执行,它将延迟执行直到下一次可能执行的时间点才被执行(比期望的时间间隔要长些)
如果setInterval回调函数的执行时间将足够长(比指定的时间间隔长),它们将连续执行并且彼此之间没有时间间隔。
上述这些知识点都是非常重要的。了解了JavaScript引擎是如何工作的,尤其是大量的异步事件(连续)发生时,才能为构建高级应用程序打好基础。
TA的最新馆藏[转]&[转]&博客访问: 399075
博文数量: 126
博客积分: 2944
博客等级: 上校
技术积分: 1104
注册时间:
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: C/C++
void f(){&&static boolean flag = true;&&if(flag){&&&&...&&&&...&&&&flag = false;
&&}}与之前我用过的方法相比,通过使用static定义内部变量从而减少了一个全局变量。
阅读(455) | 评论(0) | 转发(0) |
相关热门文章
给主人留下些什么吧!~~
请登录后评论。转自 在unity的脚本,有大量的脚本执行按照预先确定的顺序执行的事件函数。此执行顺序说明如下:EditorReset: Reset调用来初始化脚本的属性,当它第一次附加到该对象,并且使用Reset命令时。第一次Scene Loadscene启动 (一次为每个场景中的对象) 时,会调用这些函数。Awake:此函数始终是开始任何职能之前调用,并且也是在一个预置实例化之后。(如果一个游戏对象处于非活动状态,Awake不会被调用当被激活时 或者一个附加到游戏对象的任何脚本中这个函数会被调用。OnEnable:(如果对象处于活动状态时被调用):在对象被启用后,将调用此函数。发生这种情况是在创建一个MonoBehaviour实例时,例如当加载一个level或游戏对象带有脚本组件被实例化。请注意对于对象添加到场景,所有脚本的清醒和 OnEnable函数将被调用之前启动、更新、 等统称为其中任何。当然,这不能强制执行时在游戏过程中实例化对象。在第一帧更新之前Start: Start第一帧更新仅当enabled了脚本实例之前,将调用 start。为对象添加到场景,开始将对所有脚本更新之前,调用函数等统称为其中任何。当然,这不能强制执行时在游戏过程中实例化对象。帧之间OnApplicationPause:这称为框架末尾暂停检测到,有效地之间正常的帧更新。OnApplicationPause调用,允许的比赛来证明表明暂停的状态的图形后,将发出一个额外的帧。Update Order当游戏逻辑和交互,动画,相机位置,等您要跟踪的时有几个不同的事件,您可以使用。常见的模式是执行大多数任务里面的更新功能,但也有其他可以使用的函数。FixedUpdate:FixedUpdate通常被称为比更新更频繁。它可以被多次调用每帧,如果帧率偏低,它可能不根本被称为帧之间如果帧率较高。FixedUpdate后立即发生的所有物理计算和更新。当应用在FixedUpdate内的运动计算,你不需要将你的Time.deltaTime的值相乘。这是因为在一个可靠的定时器,独立的帧速率上调用FixedUpdate。Update:Update每帧调用一次。它是主要的主力框架更新的功能。LateUpdate:LateUpdate是每帧,一次调用更新完毕后。LateUpdate开始时,将会完成在更新中执行的任何计算。常用的LateUpdate将以下的第三人称视角。如果你使你的性格,并且动转内更新,则可以在LateUpdate中执行所有摄像机的平移和旋转变换计算。这将确保该字符已经完全之前相机跟踪它的位置。呈现OnPreCull:在相机中挑选出现场之前调用。扑杀确定哪些对象是可见的相机。只是在扑杀发生之前,将调用消隐。OnBecameVisible/OnBecameInvisible:当对象变为可见/不可见的任何相机时调用。OnWillRenderObject:每个摄像头调用一次,如果对象是可见。OnPreRender:在相机开始渲染场景之前调用。OnRenderObject:所有普通的场景渲染完成后,调用你可以使用 GL类或 Graphics.DrawMeshNow,在这一点上绘制自定义几何。OnPostRender:在相机完成渲染场景之后调用。OnRenderImage (仅限专业版):在场景渲染完成允许屏幕图像的后处理后调用。OnGUI:每帧响应 GUI事件调用多次。布局和重绘事件处理第一,紧接着的布局和键盘/鼠标的事件,为每个输入事件。OnDrawGizmos用于可视化用于场景视图中绘制小玩意。协同程序更新函数返回后运行正常的协程的更新。协同是一个函数,可以暂停其执行 (收益率),直到完成给定的YieldInstruction。不同用途的协同程序:yield后所有的更新功能已呼吁下一帧,将继续协同。yieldWaitForSeconds在指定的时间延迟之后,继续后所有的更新功能一直呼吁的框架yieldWaitForFixedUpdate在所有的 FixedUpdate被称为对所有脚本后继续yield WWW在WWW下载已完成后继续。yieldStartCoroutine链协同,并将等待 MyFunc协同完成第一次。当对象被销毁OnDestroy:所有帧更新的对象的存在 (对象可能毁于响应 Object.Destroy或一幕结束时) 的最后一帧后,将调用此函数。退出时在你的场景中的所有活动对象上得到调用这些函数:OnApplicationQuit:在应用程序退出之前,在所有的游戏物体上调用此函数。在编辑器中时用户停止攻击性影响调用。在网络播放器时关闭了 web视图调用。OnDisable:调用此函数时的行为变得残疾人士或非活动状态。脚本生命周期流程图下面的关系图概述订购和重复事件函数在脚本的一生。Update
当MonoBehaviour启用时,其Update在每一帧被调用。
LateUpdate
当Behaviour启用时,其LateUpdate在每一帧被调用。
FixedUpdate
当MonoBehaviour启用时,其 FixedUpdate 在每一帧被调用。
当一个脚本实例被载入时Awake被调用。
Start仅在Update函数第一次被调用前调用。
重置为默认值。
OnMouseEnter
当鼠标进入到GUIElement(GUI元素)或Collider(碰撞体)中时调用OnMouseEnter。
OnMouseOver
当鼠标悬浮在GUIElement(GUI元素)或Collider(碰撞体)上时调用 OnMouseOver .
OnMouseExit
当鼠标移出GUIElement(GUI元素)或Collider(碰撞体)上时调用OnMouseExit。
OnMouseDown
当鼠标在GUIElement(GUI元素)或Collider(碰撞体)上点击时调用OnMouseDown。
当用户释放鼠标按钮时调用OnMouseUp。
OnMouseUpAsButton
OnMouseUpAsButton只有当鼠标在同一个GUIElement或Collider按下,在释放时调用。
OnMouseDrag
当用户鼠标拖拽GUIElement(GUI元素)或Collider(碰撞体)时调用 OnMouseDrag 。
OnTriggerEnter
当Collider(碰撞体)进入trigger(触发器)时调用OnTriggerEnter。
OnTriggerExit
当Collider(碰撞体)停止触发trigger(触发器)时调用OnTriggerExit。
OnTriggerStay
当碰撞体接触触发器时,OnTriggerStay将在每一帧被调用。
OnCollisionEnter
当此collider/rigidbody触发另一个rigidbody/collider时,OnCollisionEnter将被调用。
OnCollisionExit
当此collider/rigidbody停止触发另一个rigidbody/collider时,OnCollisionExit将被调用。
OnCollisionStay
当此collider/rigidbody触发另一个rigidbody/collider时,OnCollisionStay将会在每一帧被调用。
OnControllerColliderHit
在移动的时,当controller碰撞到collider时OnControllerColliderHit被调用。
OnJointBreak
当附在同一对象上的关节被断开时调用。
OnParticleCollision
当粒子碰到collider时被调用。
OnBecameVisible
当renderer(渲染器)在任何相机上可见时调用OnBecameVisible。
OnBecameInvisible
当renderer(渲染器)在任何相机上都不可见时调用OnBecameInvisible。
OnLevelWasLoaded
当一个新关卡被载入时此函数被调用。
当对象变为可用或激活状态时此函数被调用。
当对象变为不可用或非激活状态时此函数被调用。
当MonoBehaviour将被销毁时,这个函数被调用。
在相机消隐场景之前被调用。
OnPreRender
在相机渲染场景之前被调用。
OnPostRender
在相机完成场景渲染之后被调用。
OnRenderObject
在相机场景渲染完成后被调用。
OnWillRenderObject
如果对象可见每个相机都会调用它。
渲染和处理GUI事件时调用。
OnRenderImage
当完成所有渲染图片后被调用,用来渲染图片后期效果。
OnDrawGizmosSelected
如果你想在物体被选中时绘制gizmos,执行这个函数。
OnDrawGizmos
如果你想绘制可被点选的gizmos,执行这个函数。
OnApplicationPause
当玩家暂停时发送到所有的游戏物体。
OnApplicationFocus
当玩家获得或失去焦点时发送给所有游戏物体。
OnApplicationQuit
在应用退出之前发送给所有的游戏物体。
OnPlayerConnected
当一个新玩家成功连接时在服务器上被调用。
OnServerInitialized
当Network.InitializeServer被调用并完成时,在服务器上调用这个函数。
OnConnectedToServer
当你成功连接到服务器时,在客户端调用。
OnPlayerDisconnected
当一个玩家从服务器上断开时在服务器端调用。
OnDisconnectedFromServer
当失去连接或从服务器端断开时在客户端调用。
OnFailedToConnect
当一个连接因为某些原因失败时在客户端调用。
OnFailedToConnectToMasterServer
当报告事件来自主服务器时在客户端或服务器端调用。
OnMasterServerEvent
当报告事件来自主服务器时在客户端或服务器端调用。
OnNetworkInstantiate
当一个物体使用Network.Instantiate进行网络初始化时调用。
OnSerializeNetworkView
在一个网络视图脚本中,用于自定义变量同步  
如果您想留下此文,您可以将其发送至您的邮箱(将同时以邮件内容&PDF形式发送)
相关文章推荐
(Ctrl+Enter提交) &&
已有0人在此发表见解
&在& 17:22收藏到了
&&在信息爆炸的时代,您的知识需要整理,沉淀,积累!Lai18为您提供一个简单实用的文章整理收藏工具,在这里您可以收藏对您有用的技术文章,自由分门别类,在整理的过程中,用心梳理自己的知识!相信,用不了多久,您收藏整理的文章将是您一生的知识宝库!
· 蜀ICP备号-1}

我要回帖

更多关于 男的第一次给红包原因 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信