1)浏览器会解析三个东西:
2)解析完成后,浏览器引擎会通过DOM Tree 和 CSS Rule Tree 来构造 Rendering Tree。注意:
3)最后通过调用操作系统Native GUI的API绘制。
渲染的流程基本上如下:
这里重要要说两个概念,一个是Reflow,另一个是Repaint。这两个不是一回事。
所以,下面这些动作有很大可能会是成本比较高的。
注:display:none会触发reflow,而visibility:hidden只会触发repaint,因为没有发现位置变化。
基本上来说,reflow有如下的几个原因:
function GetXmlHttpObject() { var xmlHttp = null; try { // Firefox, Opera 8.0+, Safari xmlHttp = new XMLHttpRequest(); } catch (e) { // Internet Explorer try { xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } } return xmlHttp; }
//关键点1 var xmlHttp = GetXmlHttpObject(); //关键点2:success,failue处理 xmlHttp.onreadystatechange = function () { if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { var data = xmlHttp.responseText; document.getElementById("myDiv").innerHTML = data; } }; xmlHttp.open("GET", "url", true); console.log(xmlHttp); xmlHttp.send(); var result = xmlHttp.responseText; console.log(result);
1)xmlHttpRequest对象创建谷歌、火狐、ie
2)回调函数处理
3)回调数据处理(原生ajax需要自己处理json)
我这里是从本地一个js文件中直接调用后台服务器的,所以需要处理浏览器跨域问题,如果你跟我一样也喜欢用chrome,则可在谷歌快捷方式中添加如下一行参数:
--args --disable-web-security
var Ajax = function () { function request(opt) { var xhr = GetXmlHttpObject(); xhr.onreadystatechange = function () { myOnreadystatechange(xhr, opt.success, opt.error); }; xhr.open(opt.method, opt.url, opt.async); xhr.send(); return xhr; } return { request: request }; }(); function myOnreadystatechange(xhr, success, error) { if (xhr.readyState === 4 && xhr.status === 200) { success(xhr); } else { error(xhr); } } console.log(Ajax); var opt = { url: "http://localhost:9999/gotian-ws/api/user/sayHello/fengshu", method: "GET", async: true, success: function (xhr) { var data = xmlHttp.responseText; console.log(data); }, error: function (xhr) { var data = xmlHttp.responseText; console.log(data); } }; Ajax.request(opt);
封装自定义ajax其实是为讲回调埋下一个伏笔,而回调其实就是一个”伏笔“,你能明白我这句话的意思吗?
什么是Javascript 回调函数?
函数和其他数据一样可以被赋值,删除,拷贝等,所以也可以把函数作为参数传入到另一个函数中。
这个函数就是所谓的回调函数。
函数A作为参数(函数引用)传递到另一个函数B中,并且这个函数B执行函数A。我们就说函数A叫做回调函数。如果没有名称(函数表达式),就叫做匿名回调函数。
function add(a, b, callback) { return callback(a, b); } var result = add(2, 4, function callbackAdd(a, b) { return a + b; });
通常大家都是上面那样写回调函数,但是这样对于不常或者没有接触过回调的开发人员会比较难懂,那么稍作改动一下,应该就懂了 吧?
function add(a, b, callback) { var result = callback(a, b); return result; } var result = add(2, 4, function callbackAdd(a, b) { return a + b; });
这里我们要想明白一件事情,add是一个方法,callbackAdd也是一个方法,callBackAdd除了是一个方法还是add方法的一个参数,那么既然是参数这里casllBackAdd方法总的参数a,b实际上需要add方法中来传的,再没传之前他只是个形参,当然传完后他还是一个形参。
有点绕,我在重写一下上面这个例子。
function add(a, b, callback) { var result = callback(a, b); return result; } var result = add(2, 4, function callbackAdd(形参a, 形参b) { return 形参a + 形参b; });
6、回调总结
1)如果想明白了回调函数就是一个参数,回调函数如何传参这两个问题你也就基本明白了什么是回调
2)用回调其实就是你为做某一件事情埋下伏笔,就是说你事先计划好想好了当系统执行完一些事情后你再开始执行你自己自定义的一些事情计划。
自定义ajax除了用到回调函数外还运用了自执行函数和javascript 闭包,自执行函数这里暂且不谈,我们来聊聊javascript闭包那些事,这是javascript中比较高大上的一个功能。
闭包就是能够读取其他函数内部变量的函数。由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。在下面的函数中print函数就是一个闭包
function randomAlert() { var x=Math.random(); function print() { console.log("产生的随机数",x); } return print; } var a=randomAlert(); var b=randomAlert(); a(); b();
闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,
另一个就是让这些变量的值始终保持在内存中。
function f1() { var n = 999; nAdd = function () { n += 1; }; // nAdd全局变量 function f2() { console.log(n); } return f2; } var result = f1(); result(); // 999 nAdd(); result(); // 1000
在这段代码中,result实际上就是闭包f2函数。它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。
为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,
而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。这段代码中另一个值得注意的地方,就是"nAdd=function(){n+=1}"这一行,首先在nAdd前面没有使用var关键字,因此nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。
在编程语言中,作用域控制着变量的可见性及生命周期。对程序员来说这是一个重要的帮助,因为它减少了命名冲突,并且提供了自动内存管理。
function fengshu() { // 函数体内存在三个局部变量 i j k var i = 0; if (i === 0) { var j = 10; for (var k = 0; k < 3; k++) { console.log(k); // 0 1 2 } console.log(k); // 3 } console.log(j); //10 }
大多数使用c语言语法的语言都拥有块级作用域,在一个代码块中(括在一对花括号中的语句集)定义的所有变量在代码块的外部是不可见的定义在代码块中的变量在代码块执行结束后被释放掉,这是件好事。
糟糕的是,尽管代码块的语法是否表现出它支持块级作用域,但实际上javascript并不支持,这个混淆之处可能成为错误之源。
javascript确实有函数作用域,那意味着定义在函数中的参数和变量在函数外部是不可见的,而且在一个函数中的任何位置定义的变量在该函数的任何地方都可见。
很多现代语言都推荐尽可能迟地声明变量。而且在javascript上的话却会成为糟糕的建议,因为它缺少块级作用域。所以最好的办法是在函数体的顶部声明函数中可能用到的所有变量。
所以,从javascript 作用域得出的结果是javascript有函数作用域,但并没有所谓的块级作用域。
通过阅读源码确认一下几件事情:
这里分享下一些javascript的学习经验。
学习javascript个人首选pdf,每天的上下班时间是最好的阅读时光。
在这里推荐一些比较好的去处。
前端学习的另一种途径是逛IT乱弹,看IT杂志。网上学习胜在资源比较丰富,但网站也分三六九等,三等网站又分三六九等开发人员,几乎每个网站都充斥着大学生和入门级开发人员,十分乱,你需要有一双火眼金睛来区分学习资源的好坏 。
阮一峰个人博客 网络大牛 http://www.ruanyifeng.com/blog/