首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Matrix-iOS 卡顿监控

Matrix-iOS 卡顿监控

作者头像
微信终端开发团队
发布于 2019-05-16 07:51:25
发布于 2019-05-16 07:51:25
13.6K0
举报

前言


在早期开发 iOS 微信的过程中,我们时不时会收到类似的反馈:

  • “我的微信卡在主界面,怎么也滑动不了”
  • “我的微信从后台切换前台卡了一下,最近偶尔会遇到几次”,等等。

这类问题有个共同点:用户的微信在一段时间内无法点击;即使获得用户的操作路径,也无法重现。

我们把这类问题叫做卡顿问题。这类问题很影响用户的体验,是必须进行解决的。为了精确地定位用户的卡顿问题,iOS 微信在 2014 年 9 月份上线了卡顿监控系统。在这几年间,卡顿监控经历了几次优化,不断成熟,在这里我们将其分享出来。

什么是卡顿


卡顿就是在应用使用过程中出现界面不响应或者界面渲染粘滞的情况。而应用界面的渲染以及事件响应是在主线程完成的,出现卡顿的原因可以归结为主线程阻塞。

在开发过程中,遇到的造成主线程阻塞的原因可能是:

  • 主线程在进行大量I/O操作:为了方便代码编写,直接在主线程去写入大量数据;
  • 主线程在进行大量计算:代码编写不合理,主线程进行复杂计算;
  • 大量UI绘制:界面过于复杂,UI绘制需要大量时间;
  • 主线程在等锁:主线程需要获得锁A,但是当前某个子线程持有这个锁A,导致主线程不得不等待子线程完成任务。

针对这些问题,如果我们能够捕获得到卡顿当时应用的主线程堆栈,那么问题就迎刃而解了。有了堆栈,就可以知道主线程在什么函数哪一行代码卡住了,是在等什么锁,还是在进行I/O操作,或者是进行复杂计算。有了堆栈,就可以对问题进行针对性解决。

原理


在 iOS/macOS 平台应用中,主线程有一个 Runloop。Runloop 是一个 Event Loop 模型,让线程可以处于接收消息、处理事件、进入等待而不马上退出。在进入事件的前后,Runloop 会向注册的 Observer 通知相应的事件。

Runloop 的详细介绍可以网上查阅《深入理解RunLoop》。一个简易的 Runloop 流程如下所示:

Matrix 卡顿监控在 Runloop 的起始最开始和结束最末尾位置添加 Observer,从而获得主线程的开始和结束状态。卡顿监控起一个子线程定时检查主线程的状态,当主线程的状态运行超过一定阈值则认为主线程卡顿,从而标记为一个卡顿。

目前微信使用的卡顿监控,主程序 Runloop 超时的阈值是 2 秒,子线程的检查周期是 1 秒。每隔 1 秒,子线程检查主线程的运行状态;如果检查到主线程 Runloop 运行超过 2 秒则认为是卡顿,并获得当前的线程快照。

同时,我们也认为 CPU 过高也可能导致应用出现卡顿,所以在子线程检查主线程状态的同时,如果检测到 CPU 占用过高,会捕获当前的线程快照保存到文件中。目前微信应用中认为,单核 CPU 的占用超过了 80%,此时的 CPU 占用就过高了。

退火算法

为了降低检测带来的性能损耗,我们为检测线程增加了退火算法:

  • 每次子线程检查到主线程卡顿,会先获得主线程的堆栈并保存到内存中(不会直接去获得线程快照保存到文件中);
  • 将获得的主线程堆栈与上次卡顿获得的主线程堆栈进行比对:
    • 如果堆栈不同,则获得当前的线程快照并写入文件中;
    • 如果相同则会跳过,并按照斐波那契数列将检查时间递增直到没有遇到卡顿或者主线程卡顿堆栈不一样。

这样,可以避免同一个卡顿写入多个文件的情况;避免检测线程遇到主线程卡死的情况下,不断写线程快照文件。

耗时堆栈提取


子线程检测到主线程 Runloop 时,会获得当前的线程快照当做卡顿文件。但是这个当前的主线程堆栈不一定是最耗时的堆栈,不一定是导致主线程超时的主要原因。

例如,主线程在绘制一个微信logo,过程如下:

子线程在检测到超出阈值时获得的线程快照,主线程的当前任务是“画小气泡”。但其实“画大气泡”才是耗时操作,导致主线程超时的主要原因。Matrix 卡顿监控通过主线程耗时堆栈提取来解决这个问题。

卡顿监控定时获取主线程堆栈,并将堆栈保存到内存的一个循环队列中。如下图,每间隔时间 t 获得一个堆栈,然后将堆栈保存到一个最大个数为 3 的循环队列中。有一个游标不断的指向最近的堆栈。

微信的策略是每隔 50 毫秒获取一次主线程堆栈,保存最近 20 个主线程堆栈。这个会增加 3% 的 CPU 占用,内存占用可以忽略不计。

当主线程检测到卡顿时,通过对保存到循坏队列中的堆栈进行回溯,获取最近最耗时堆栈。

如下图,检测到卡顿时,内存的循环队列中记录了最近的20个主线程堆栈,需要从中找出最近最耗时的堆栈。Matrix 卡顿监控用如下特征找出最近最耗时堆栈:

  • 以栈顶函数为特征,认为栈顶函数相同的即整个堆栈是相同的;
  • 取堆栈的间隔是相同的,堆栈的重复次数近似作为堆栈的调用耗时,重复越多,耗时越多;
  • 重复次数相同的堆栈可能很有多个,取最近的一个最耗时堆栈。

获得的最近最耗时堆栈会附带到卡顿文件中。

卡死卡顿


Matrix 中内置了应用被杀原因的检测机制。这个机制从 Facebook 的博文 中获得灵感,在其基础上增加了系统强杀的判定。Matrix 检测应用被杀原因的具体机制如下图所示:

Matrix 检测到应用卡死被强杀,会把应用上次存活时的最后一份卡顿日志标记为卡死卡顿。

性能数据


Matrix 卡顿监控不打开耗时堆栈提取,性能损耗可以忽略不计。

打开耗时堆栈提取后,性能损耗和定时获取主线程堆栈的间隔有关。实测,每隔 50 毫秒不断获取主线程堆栈,会增加 3% 的 CPU 占用。

结尾


以上是 iOS 微信卡顿监控的原理性介绍,它同样可以应用在 macOS 平台上。iOS 微信团队通过卡顿监控上报的堆栈,找到微信的代码不合理之处或者是一些性能瓶颈,通过卡顿监控的辅助,尽可能地提升 iOS 微信的流畅性,给用户带来更加极致美好的体验。

卡顿监控依然在不断进行优化,不断地扩展能力,近期我们计划会为它增添捕获应用的耗电堆栈等,使其功能更加完备。我们决定通过 Matrix 将其开源,并希望能获得大家的意见和建议。

开源地址

[Matrix]https://github.com/Tencent/matrix/tree/master/matrix/matrix-apple

请给 Matrix 一个 Star !

欢迎提出你的 issue 和 PR。

var first_sceen__time = (+new Date());if ("" == 1 && document.getElementById('js_content')) { document.getElementById('js_content').addEventListener("selectstart",function(e){ e.preventDefault(); }); } (function(){ if (navigator.userAgent.indexOf("WindowsWechat") != -1){ var link = document.createElement('link'); var head = document.getElementsByTagName('head')[0]; link.rel = 'stylesheet'; link.type = 'text/css'; link.href = "//res.wx.qq.com/mmbizwap/zh_CN/htmledition/style/page/appmsg_new/winwx45ba31.css"; head.appendChild(link); } })();

陈志炯

赞赏

长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

阅读原文

阅读

分享 在看

已同步到看一看

取消 发送

我知道了

朋友会在“发现-看一看”看到你“在看”的内容

确定

已同步到看一看写下你的想法

最多200字,当前共字 发送

已发送

朋友将在看一看看到

确定

写下你的想法...

取消

发布到看一看

确定

最多200字,当前共字

发送中

微信扫一扫 关注该公众号

微信扫一扫 使用小程序

即将打开""小程序

取消 打开

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-04-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 WeMobileDev 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
javascript当中history的用法
6.history 例 1.6(firstIEFF.html) <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> </HEAD> <BODY> <A HREF="second.html">进入second.html</A> </BODY> </HTML> second.html <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <head>     <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <TITLE> New Document </TITLE> <SCRIPT LANGUAGE="JavaScript"> <!-- /*Window.history (Property) This property returns a history object for this window. Property/method value type:    History object JavaScript syntax:    -    history -    myWindow.history .*/ window.οnlοad=function(){     var num = Math.round(Math.random()*100);     document.getElementById("num").innerHTML=num; } //--> </SCRIPT> </HEAD>
马克java社区
2021/01/12
3650
javascript当中history的用法
javascript当中cloneNode的用法
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
马克java社区
2021/01/21
4550
javascript当中cloneNode的用法
javascript当中getElementsByTagName的用法
例 6.3:getElementsByTagName()IEFF.html <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <SCRIPT LANGUAGE="JavaScript"> <!-- window.onload=function(){ var arr = document.getElementsByTagName("option"); alert("arr[i].value is "+arr[2].value); } //--> </SCRIPT> </HEAD> <BODY> <SELECT NAME="" id="province" style="width:140px;background-color:red"> <option>红</option> <option>兰</option> <option>紫</option> </SELECT> </BODY> </HTML>
马克java社区
2019/11/27
5260
javascript当中getElementsByTagName的用法
javascript当中window open用法
5.window.open 例 5.1(onload&onunloadIEFF.html) <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <SCRIPT LANGUAGE="JavaScript"> <!-- function onloadq() { /*aNewWindow = myWindow.open(aURL, aName, aFeatureList), aFeatureList A list of attributes for the new window aName The name of a new or existing target window aURL A URL to load into the window */ window.open("adv.html", "", "WIDTH=600,HEIGHT=600,left=0,top=0"); } window.onload = onloadq; //--> </SCRIPT> </HEAD> <BODY> The onload event </BODY> </HTML>
马克java社区
2019/10/17
5190
javascript当中window open用法
javascript当中getElementsByName的用法
3.getElementsByName 例 3.1 getElementsByName()IEFF.html <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> </HEAD> <BODY> <script type="text/javascript"> <!-- function choiceAll(t) { var arr = document.getElementsByName("ch"); for (var i=0;i<arr.length ;i++ ) { arr[i].checked = t } } //--> </script> <INPUT TYPE="checkbox" onclick="choiceAll(this.checked)" >全选<P> <INPUT TYPE="checkbox" NAME="ch"><BR> <INPUT TYPE="checkbox" NAME="ch"><BR> <INPUT TYPE="checkbox" NAME="ch"><BR> <INPUT TYPE="checkbox" NAME="ch"><BR> <INPUT TYPE="checkbox" NAME="ch"><BR> </BODY> </HTML>
马克java社区
2019/11/27
5570
javascript当中getElementsByName的用法
javascript当中confirm的用法
1.confirm confirm是window的方法,返回值是真或假。 例 1.1(confirmIEFF.html) <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <Script> function check() {     if (confirm("想看北海照片吗?"))     {         alert("想看北海想的美!")     }     else     {         if(confirm("想看景山照片吗?"))         {             alert("想看景山想的美!")         }     } } </Script> </HEAD> <BODY> <INPUT TYPE="button" value="照片点击进入" οnclick="check()"> </BODY> </HTML>
马克java社区
2020/12/28
2K0
javascript当中confirm的用法
javascript当中isNaN用法
2)isNaN 例 4.2.1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> </head> <BODY> <SCRIPT LANGUAGE="JavaScript"> <!-- /*favo说isNaN是Global的方法, 而不是window的方法*/ var b1 = window.isNaN("25"); var b2 = isNaN("abc"); document.write("b1="+b1+",b2="+b2) //--> </SCRIPT> </BODY> </HTML>
马克java社区
2019/11/25
6370
javascript当中isNaN用法
javascript当中navigator的用法
3.navigator 例 1.3(navigatorIEFF.html) <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <TITLE> New Document </TITLE> <META NAME="Generator" CONTENT="EditPlus"> <META NAME="Author" CONTENT=""> <META NAME="Keywords" CONTENT=""> <META NAME="Description" CONTENT=""> </HEAD> <BODY> <SCRIPT LANGUAGE="JavaScript"> <!-- for(var p in navigator) { /*Window.navigator (Property) A reference to a navigator object that describes the browser.*/      document.write("属性"+p+"的属性值为:"+navigator[p]+"<br>"); } //--> </SCRIPT> </BODY> </HTML>
马克java社区
2021/01/07
5260
javascript当中navigator的用法
javascript当中prompt的用法
5.prompt 例 1.5(promptIEFF.html) <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <style type="text/css"> #divTest{ background-color:#9F3; /*没有底下的margin为负,fireFox中老有个白边*/ margin-top:-8px; margin-left:-8px; width:500px; height:500px; } </style> </head> <body> <div id="divTest">     body div </div> </body> <script language="javascript" type="text/javascript">  /* 返回值:Property/method value type:    String primitive   JavaScript syntax:    -    myResult = myWindow.prompt(aString, aDefaultValue)   -    myResult = prompt(aString, aDefaultValue)   Argument list:    aDefaultValue    An initial content for the text box   aString    Some text to explain what to enter
马克java社区
2021/01/12
8630
javascript当中prompt的用法
javascript当中Map Area Shape 的用法
例 4.3(MapAreaShapeMouseOverIEFF.html) <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>无标题文档</title> <script language="javascript"> function show(obj) { var pos=obj.coords; pos=pos.split(","); alert("pos is "+pos+" pos[1] is "+pos[1]+" pos[2] is "+pos[2]); var menu=document.getElementById("info"); menu.style.left=parseInt(pos[2])+"px"; menu.style.top=parseInt(pos[1])+"px"; menu.style.display="inline"; } function hide() { var menu=document.getElementById("info"); menu.style.display="none"; } </script> </head>
马克java社区
2019/11/27
5210
javascript当中Map Area Shape 的用法
javascript当中open&close的用法
4.open&close 例 1.4.1(open&closeIEFF.html) <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <SCRIPT LANGUAGE="JavaScript"> <!-- function choice() {     /* -  - aNewWindow = open() - aNewWindow = open(aURL) - aNewWindow = open(aURL, aName) - aNewWindow = open(aURL, aName, aFeatureList) */     window.open("cla.html"); } //--> </SCRIPT> </HEAD> <BODY> <FORM METHOD=POST ACTION="" name="form1"> <INPUT TYPE="text" name="cla"> <INPUT TYPE="button" value="点我" οnclick="choice()" > </FORM> </BODY> </HTML> cla.html <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <SCRIPT LANGUAGE="JavaScript"> <!-- function returnV(t) { /*  Window.opener (Property) A reference to the window that contained the link that opened this one. */     window.opener.document.form1.cla.value=t.value; /* Window.close() (Method) This will close the window. JavaScript syntax: - close()  - myWindow.close()  The method window.close() will attempt to close the window in which the script is executing.  */       close(); } //--> </SCRIPT> </HEAD>
马克java社区
2021/01/11
3940
javascript当中open&close的用法
javascript当中options的用法
6.options 选择列表 例 6.1(SelectOptionAddIEFF.html) <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <TITLE> </TITLE> <SCRIPT LANGUAGE="JavaScript"> <!-- /* a typical value is that document.getElementById("province").options[1]="河北", document.getElementById("city").options[1]= arr[0][1]= "石家庄" */ var arr = new Array( new Array("河北", "邯郸","石家庄"), new Array("山东", "济南", "枣庄", "威海"), new Array("河南", "开封", "郑州", "洛阳", "南洋") ); function setProvinces() { /* arr.length is the row number of arr, arr[i][0] the first column. in other words, 河北,山东,河南 */ for (var i = 0; i < arr.length; i++) { /*加到option最后,new Option(str1,str2)str1 是页面中看到的描述,而str2是这一项的值*/ document.getElementById("province").options[i + 1] = new Option(arr[i][0], arr[i][0]); } } function setCity(i) { alert(i+" "+document.getElementById("province").selectedIndex+document.getElementById("province").value+document.getElementById("province").options[document.getElementById("province").selectedIndex].text+document.getElementById("province").options[document.getElementById("province").selectedIndex].value); document.getElementById("city").options.length = 1;//reset city for (var j = 1; j < arr[i - 1].length; j++) { opt = new Option(arr[i - 1][j], arr[i - 1][j]); /*下面两种写法的结果是一样的*/ // document.getElementById("city").options[j] = new Option(arr[i - 1][j], arr[i - 1][j]); document.getElementById("city").add(opt,document.getElementById("city").options.length);//第二个参数指定元素放置所在的索引号 } // objSelect.add(objOption, objSelect.selectedIndex); } //--> </SCRIPT> </HEAD> <BODY onload="setProvinces()"> <!--Select.selectedIndex (Property) qi
马克java社区
2019/11/27
8600
javascript当中options的用法
javascript当中createElement的用法
例 1.2(CreateP&InputIEFF.html) <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <style type="text/css"> .test { background:#0000FF; } </style> <SCRIPT LANGUAGE="JavaScript"> <!-- window.onload=function(){ var para = document.createElement("p"); /*the following statement para.innerHTML="qixy"; also can work.*/ // para.innerHTML="qixy"; var message = document.createTextNode("hello world"); para.appendChild(message); para.className="test"; /* we must use the following statement, use document.appendChild(para); is wrong.马克-to-win:因为document里同时有head元素和body元素*/ document.body.appendChild(para); /*the following statement totally can work.*/ var in1 = document.createElement("input"); in1.value="abc"; in1.id = "in1id" document.body.appendChild(in1); alert(""+document.getElementById("in1id").value); } //--> </SCRIPT> </HEAD> <BODY> </BODY> </HTML>
马克java社区
2020/01/07
5900
javascript当中createElement的用法
javascript当中如何操纵Node,(创建,附加,克隆,取代,去除,插入Node)
1.操纵Node,(创建,附加,克隆,取代,去除,插入Node) 例 1.1(cloneNode()IEFF.html) <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <SCRIPT LANGUAGE="JavaScript"> <!-- window.onload=function(){ var para = document.createElement("p"); var message = document.createTextNode("hello world"); para.appendChild(message); document.body.appendChild(para); /* Element object (Object/HTML) A common name for an object that represents an HTML tag or container. Inherits from: Node object BODY object (Object/HTML) An object that represents the body of a document. Inherits from: Element object Node.cloneNode() (Method) The node object is cloned but the new instance has no parent node defined. Property/method value type: Node object JavaScript syntax: - myNode.cloneNode(aSwitch) Argument list: aSwitch Indicates whether a deep or shallow clone is required if it is false, then it is shallow, then its child is not copyed. */ var newpara = para.cloneNode(true); document.body.appendChild(newpara); var debugzhanwei="zhanwei"; } //--> </SCRIPT> </HEAD> <BODY> </BODY> </HTML>
马克java社区
2020/01/06
6780
javascript当中如何操纵Node,(创建,附加,克隆,取代,去除,插入Node)
javascript当中eval用法
1)eval 例 4.1.1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> </head> <BODY> <SCRIPT LANGUAGE="JavaScript"> <!-- /*马克-to-win:var scriptCode = "c = a * b"; var a = 5; var b = 10; var c = 2; eval(scriptCode); 以上的话就相当于: eval("c = a * b");===c = a * b eval是global的方法, */ var result = window.eval("1+2/4") ;//根据上面所说,result=1+2/4; document.write(result) var s="today=new Date();document.write(today.toLocaleString())" eval(s) //--> </SCRIPT> </BODY> </HTML> 例 4.1.2 <HTML> <HEAD> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <TITLE>在eclipse中直接open with火狐即可</TITLE> </HEAD> <BODY> <SCRIPT LANGUAGE="JavaScript"> <!-- //例1 var s = "2+31-18"; /*When the eval() function is called, it expects a string to be passed to it as its single argument value. The contents of that string should be syntactically correct executable script source text.*/ document.write(eval(s)); var s1 = "2+31a-18"; /* note that we must comment out the following statement, otherwise, it reports error.*/ //document.write(eval(s1)); //例2 eval("d =new Date();document.write(d.toLocaleString())") //eval()函数的参数为字符串,功能是将该字符串执行出来。体会“执行”的意思! //--> </SCRIPT> </BODY> </HTML>
马克java社区
2019/11/25
1.4K0
javascript当中eval用法
javascript当中global对象用法
4.global对象 1)eval 例 4.1.1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> </head> <BODY> <SCRIPT LANGUAGE="JavaScript"> <!-- /*马克-to-win:var scriptCode = "c = a * b"; var a = 5; var b = 10; var c = 2; eval(scriptCode); 以上的话就相当于: eval("c = a * b");===c = a * b eval是global的方法, */ var result = window.eval("1+2/4") ;//根据上面所说,result=1+2/4; document.write(result) var s="today=new Date();document.write(today.toLocaleString())" eval(s) //--> </SCRIPT> </BODY> </HTML>
马克java社区
2019/11/25
6570
javascript当中global对象用法
javascript当中link 的alternate stylesheet 用法
例 6.4:linkChangeCssFileIEFF.html 切换css文件:document.getElementsByTagName("link"); <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <TITLE> New Document </TITLE> <!-- 马克-to-win: here the idea is that for the whole page, sometimes, we use this css, sometimes, we use that css, with this method, we can switch. with this method, we can switch skin. "alternate stylesheet"是备用样式。 --> <link rel="alternate stylesheet" href="a.css" type="text/css" title="red" /> <link rel="stylesheet" href="b.css" type="text/css" title="green" /> <link rel="alternate stylesheet" href="c.css" type="text/css" title="blue" /> <script language="javascript"> function setActiveStyleSheet(t) { var links = document.getElementsByTagName("link"); links[0].disabled=false; links[1].disabled=true; links[2].disabled=true; alert(links[0].disabled+""+links[1].disabled+links[1].getAttribute("title")+links[2].getAttribute("href")); } </script> </HEAD> <body> 更多请见:https://blog.csdn.net/qq_43650923/article/details/102650892
马克java社区
2020/01/06
6940
javascript当中link 的alternate stylesheet 用法
javascript当中document.forms的用法
2.document.forms 例 2.1(FormActionSubmitIEFF.html) <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <head>     <meta http-equiv="content-type" content="text/html; charset=utf-8"/>     <TITLE></TITLE>     <SCRIPT LANGUAGE="JavaScript">  
马克java社区
2021/01/21
7490
javascript当中document.forms的用法
javascript当中location的用法
2.location 例 1.2(locationIEFF.html) <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <SCRIPT LANGUAGE="JavaScript"> <!-- window.οnlοad=function(){ /*round:si she wu ru, - myLocation.reload(aFlag) Argument list: aFlag A Boolean flag forcing a reload from the server when set to true */     var num = Math.round(Math.random()*100);     document.getElementById("num").innerHTML=num; } function fun() {  /*based on experiment, you can use any one of the following three statements. Location.href (Property) The URL for the page currently on display in the window owning this location. Property/method value type:    String primitive JavaScript syntax:    -    myLocation.href 马克-to-win:If you set this property, the window will load the new URL in, and replace the old content with the new. */   location.href="navigatorIEFF.html";//也可以用location.replace("navigator.html")   //location="navigator.html"; } //--> </SCRIPT> </HEAD> <BODY> <p>刷新演示:<div id="num"></div></p> <INPUT TYPE="button" value="刷新一下从新获取一个随机数" οnclick="location.reload()"> <p>转址演示:</p> <INPUT TYPE="button" value="将地址转到navigator.html" οnclick="fun()"> </BODY> </HTML>
马克java社区
2021/01/06
3750
javascript当中location的用法
javascript当中frame和frameset的用法
1.frame和frameset(企业用的少了,所以视频略过,见后面iframe部分)
马克java社区
2021/01/19
9670
javascript当中frame和frameset的用法
相关推荐
javascript当中history的用法
更多 >
交个朋友
加入架构与运维工作实战群
高并发系统设计 运维自动化实践
加入架构与运维趋势交流群
技术趋势前瞻 架构演进方向
加入架构与运维学习入门群
系统架构设计入门 运维体系构建指南
换一批
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档