先感慨一下太久没有写学习笔记了,太懒惰了。
先说说这一年来在JavaSript学到的知识
一、原型、继承
JavaScript里的对象都有一个构造器,构造器都一个原型prototype。
先看JS是如何构造对象的:
1、如果构造器有一个原型对象A,则由该构造器创建的实例( Instance)都必然复制自A
2、空对象是所有对象的基础
3、写出复制、读时遍历
前面两点没有什么要说的,至于第三点:
JavaScript是一种脚本语言,解释执行,那么就要求高响应、低资源。所以在创建一个实例时,没法像C#、Java那样“大手笔”,先看一幅图
1、创建出来的对象都指向Object.prototype,这是没有任何属性
2、当我们要写某个属性的时候,才会复制一个属性到对象上,这样就粒度控制在了“属性”内
3、当我们要读取某个属性时,会延着原型链向上查找。例如上图,obj1.value先看自身有value属性没有,没有再看Object.prototype有value属性没有,当遇到没有的属性时就返回undefined;而obj2.value,本身的value属性则覆盖了Object.prototype的value属性
二、闭包、作用域链
闭包一个很让人头疼的概念,定义:“词法表示包括不必计算的变量的函数”(《JavaScript高级程序设计》)。光一个概念就看得云里雾里的,还好补充了一下“函数能使用函数外的定义变量”。看一下代码吧
function closure()
{
var i=1;
return function(){
alert(i);
i++;
}
}
var func=closure();
func();//这里是i=1;
func();//这里是i=2;
如上面所示,函数closure里的匿名函数(为了方便交流,我们叫它a吧),a使用变量i,但是i并没在a里定义,按照《JavaScript高级程序设计》的补充说明,闭包应该就是这个吧,确实也是这个。但是闭包仅仅如此就不会让我那么头疼了,再往下看func()第一次执行i=1无可厚非,第二次执行变成了2,你怎么就成了2了呢?好吧,就算我无奈的接受了这个事实,这就是闭包!!!但是总一个疙瘩在那里,于是追溯原因,归根在于变量i在函数closure执行后,就没有释放,也就是这个变量一存在于内存中,当第二次调用func函数时,自然就成了2!
再看为什么匿名函数a就能访问变量i呢?
在声明函数时会产生一个执行环境(执行上下文对象),执行环境包含一个作用域链,作用域链有一个或多个变量对象组成,作用域链中保存的是对变量对象的引用。变量对象定义了在当前作用域中声明的变量和函数。
再拿上面那个代码来说:
包含两个变量对象:一个是函数closure里的局部对象,包含了变量i,匿名函数等信息;另一个是全局对象(Global),包含了函数closure、变量func的定义。而前面那个局部对象又在全局对象中,这样就形成了一个链,全局对象<-局部对象,这就是所谓的作用域链。当调用func时(即匿名函数a,暂且这样认为),会从匿名函数的局部对象中去找是否有定义过变量i,没有就延着作用域链向上查找,直到全局对象。所以匿名函数a可以访问变量i,并且保持其不被回收。
想想,我们在自定义的函数里,使用document,location这些对象时,我们函数里并没有定义,而这些对象都被登记在全局对象(Global)里,正是作用域链这种机制,让我们可以访问他们。
闭包与作用域不是上面那么文字能说得清,鄙人不才,只能总结出那么出来。以后再仔细讨论这个话题。
三、极晚绑定
这里指的极晚绑定是指在对象实例化再定义他的方法。例:
var o=new Object();
Object.prototype.sayHi=function(){
alert("Hello World!");
}
o.sayHi();
其实这个没有什么特殊的,至少在javascript里。但是要说明一下的是,上面用的方法是修改原型,特别是在原型继承的时候,容易造原型污染。拿上面那段代码来说,如果把sayHi改为toString(),那么继承自object的类如果没有重写toString(),那么调用toString的时候就会出现“Hello World”。
四、DOM
其实谈到DOM说得更多的DOM API。HTML作为一种“不规范”的XML,在浏览器里也提供了API(DOM API) 。既然是操作XML,就少不了createElement()、createNode()、removeElement()、getElementsByTagName()等方法,这些都在DOM核心对象document里。浏览器把每个页面当作一个document。
浏览器先是HTML解析,构造成DOM树,然后是链接样式,再呈现(render),最后才是在浏览器里绘制。
王、JavaScript
为什么javascript的下载会阻塞,就是因为其中可能会有代码修改了DOM树,需要重新构建DOM树。
合理的加载JS,成为优化WEB必修一课。将JS代码段、JS文件放在页面最后,对于执行长的函数,作用SetTimeOut方法。
《高性能网站建设进阶指南》第四章讲了六种无阻塞加载JS文件的方法。
1、XHR Eval
2、XHR 注入
3、Iframe
4、DOM
5、Script Defer
6.document.write
六、其它
1、new 操作符
其实和其它面向对象语言差不多,再构造对象,再调用构造器。
2、cookie操作
这个主要是弄明白cookie的格式,document.cookie是一个字符串,每个分号将一个cookie隔开。对一个cookie,采用name=value这样的键值对,如果有多个子键则在value里使用&(也可以是其它符号)将其隔开。
然后对于每一个cookie有domain、path、expires、secure几个属性。
将expires设为在今天以前,cookie作废,自动删除,也就删除cookie的原理。我试着自己写了一个Cookie操作的函数库,点击查看
3、AJAX
以前一直都是用JQuery,感觉还不错,现在讲原生态的AJAX
1)、客户端请求
1、创建XHR
2、URL、参数处理
3、打开socket
4、指定回调函数
5、发送数据
2)、服务端处理
3)、接收数据并格式
1、状态码
2、responseXML还是responseText
3、parse 数据
代码就不贴上来了。说说几个常见的状态码吧:
200成功
304未修改,从缓存获取
400请求头错误
404未找到,即URL有错误
500服务端错误
记住这些常见的状态码有利我们AJAX调试,找准错误所在
4、Math,Date,Array
这些类及函数就不再记录在日志里