递归调用———————————————————————————
1.函数调用函数自身,开始执行递的动作。
2.最后一次给他一个判断终止的条件,开始回头执行归的动作
3.简单的递归实例
//求阶乘
function jieCheng(i){
if(i<=1)
//2.最后一次给他一个判断终止的条件,开始回头执行归的动作
return 1;
//1.函数调用函数自身,开始执行递的动作。
return i*jieCheng(i-1);
}
快速排序———————————————————————————
1.找一个基准点
2.建立两个数组,分别存储左边和右边的数组
3.利用递归方式进行下
function quickSort(arr){
if(arr<=1){
return arr; //空数组和单元素数组直接返回 。归
}
var num=Math.floor(arr.length/2);//先找到数组的中间位置
var numValue=arr.splice(num,1);//用splice方法取出这个值
var left = [];
var right =[];
//创建两个数组用于存放大于中间值和小于中间值的数。
for(var i = 0;i<arr.length;i++)
{
if(arr[i]>numValue)
{
right.push(arr[i]);//大于中间值的放右边
}
if(arr[i]<=numValue)
{
left.push(arr[i]);//小于中间值的放左边
}
}
//return left.concat(numValue,right);
return quickSort(left).concat(numValue,quickSort(right));
//将左和右数组继续快排然后同中间值拼接。 递
}
表达式—————————————————————————-
函数声明:function 函数名(){}
函数表达式:function 函数名(可写可不写)(){} 命名/匿名函数表达式
function aaa(){}; //函数声明
var a=function a(){}; // 命名函数表达式
var a=function(){}; //匿名函数表达式
(function aaa(){}); //表达式
~function aaa(){};
-function aaa(){};
+function aaa(){};
!function aaa(){};
函数声明和函数表达式的区别:
1.函数表达式在后面加()可以直接执行函数,而函数申明不行。
2.函数申明可以被预解析,而表达式要等预解析完毕后根据程序流程顺序去生效。
var a=function aaa(){
alert(1);
alert(typeOf aaa);//在内部是能找到的
}
a(); //任何浏览器都能兼容
aaa(); //标准浏览器在外面是找不到的,而IE8以下会将上面的函数表达式分为函数表达式和函数声明两个,所以会调用该函数。
( function aaa(){ alert(1) } );
aaa();
//标准浏览器会报错。
function aaa(){
return bbb();
}
var bbb = (function bbb(){
return function(){
debugger;
}
})();
aaa();
事件委托—————————————————————————-
事件委托:利用事件冒泡的原理,把事件加到父级身上,触发执行效果
event对象-事件源:不管在那个事件中,你操作的那个对象就是事件源
ie下:window.event.srcElement
标准下: event.target
var target = ev.target||ev.srcElement;
nodeName:找到当前元素的标签名
好处:1.提高性能
2.新添加的元素还会有之前父级的委托事件
枚举算法—————————————————————————–
枚举算法,用for来从众多的候选答案中,用if找出正确的解。
经典实例:
枚 举 算 法 题
* 枚
———————————————————————————
题 题 题 题 题 题
求出每个字所代表的数字。
循环判断,从循环的候选答案中找到符合要求的解
布局:
<body>
<p><span>枚</span>
<span>举</span>
<span>算</span>
<span>法</span>
<span>题</span>
</p>
*
<p><span>枚</span></p>
=
<p>
<span>题</span>
<span>题</span>
<span>题</span>
<span>题</span>
<span>题</span>
<span>题</span>
</p>
</body>
枚举算法脚本:
window.onload=function(){
var oP0=document.getElementsByTagName('p')[0];
var oP1=document.getElementsByTagName('p')[1];
var oP2=document.getElementsByTagName('p')[2];
for(var i=1;i<=9;i++)
{
for(var j=0;j<=9;j++)
{
for(var k=0;k<=9;k++)
{
for(var m=0;m<=9;m++)
{
for(var n=0;n<=9;n++)
{
var a=i*10000+j*1000+k*100+m*10+n;
var b=i;
var c=n*100000+n*10000+n*1000+n*100+n*10+n;
if(a*b===c)
{
oP0.getElementsByTagName('span')[0].innerHTML=i;
oP0.getElementsByTagName('span')[1].innerHTML=j;
oP0.getElementsByTagName('span')[2].innerHTML=k;
oP0.getElementsByTagName('span')[3].innerHTML=m;
oP0.getElementsByTagName('span')[4].innerHTML=n;
oP1.getElementsByTagName('span')[0].innerHTML=i;
for(var x=0;x<oP2.getElementsByTagName('span').length;x++)
{
oP2.getElementsByTagName('span')[x].innerHTML=n;
}
}
}
}
}
}
}
}
对象引用—————————————————————————–
对象和函数都是引用的关系
例如:
var a=[1,2,3];
var b=a;
b=[1,2,3,4];
alert(b); //1234 因为b是[1,2,3,4]的地址
alert(a); //123 因为第三行的引用将第二行的引用覆盖了,
b的指向从原本指向a([1,2,3])变为了指向[1,2,3,4],
而a并没有改变指向,所以还是指向[1,2,3]
再如:
var obj={ a:10 };
var obj2=obj;
obj2.a=20;
alert(obj.a); //弹出 20
//因为obj2指向obj指向的地址,
//修改的也是该地址内容,而不是拷贝一份
如果要做到拷贝一份,修改obj2不会影响obj的地址内容,要使用自定义方法
function copy(obj){
var newObj={};
for(var attr in obj)
{
newObj[attr]=obj[attr];
}
return newObj;
}
obj2=copy(obj); //这样对obj2的修改就不会影响到之前obj的内容
这种方法叫做浅拷贝。
浅拷贝的问题:
将上面例子的 a的值改为一个json。
var obj={
a:{
b:10
}
};
var obj2=copy(obj);
obj2.a.b=20;
alert(obj.a.b); //弹出的值为20,说明原址内容还是被修改了
原因是copy方法进行到newObj[attr]=obj[attr];的时候。
obj只是将其属性a的索引赋值给了newObj的a属性,也就是说
obj.a和newObj.a还是指向同一个地址,所以对新对象a属性的修改
还是会影响到之前对象的属性a。这和之前的 var obj2=obj; 是一个道理
这样就要用到深拷贝
function deepCopy(obj){
if(typeof obj !='object')
// 当传进来的值已经不是对象,开始归
{
return obj;
}
var newObj={};
for(var attr in obj)
{
newObj[attr]=deepCopy(obj[attr]);
//递归调用,确保赋值的是一个新的对象
}
return newObj;
}
操作iFrame—————————————————————————–
1.操作本页的iframe中的元素,要用到contentWindow属性,这个属性所有浏览器都支持。
而在非IE下时,由于安全限制,只有部署在服务器上才能使用这个属性。
除了在IE6-7下,我们可以用contentDocument来代替contentWindow.document
oIframe.contentWindow.document.getElementsByTagName('div')[0];
或
oIframe.contentDocument.getElementsByTagName('div')[0];
//得到iframe中的div元素
2.在iframe中操作本页元素,用window.parent。支持和限制性能同contentWindow
3.在嵌套iframe中操作最外层元素,用window.top
4.和window.onload一样,iframe也能用oIframe.onload,ie下要使用oIframe.attachEvent来绑定onload事件
5.网站的防iframe嵌套处理
if(window!=window.top)
{
window.top.location.href=window.location.href;
}
6.让iframe高度与其内容自适应
oIframe.height=oIframe.contentWindow.document.body.offsetHeight;
js闭包—————————————————————————–
1.什么是闭包
函数嵌套函数,内部函数可以引用外部的参数和变量,参数和变量不会被
垃圾回收机制所收回,外部函数最终返回内部函数的函数名。
从垃圾回收机制来看,一个闭包就是当一个函数返回时,一个没有释放资源的栈区。
例如:
function test(num){
var sum=5;
function alertSum(){
sum+=num;
alert(sum);
}
return alertSum;
}
var a=test(5);
a();//10
2.闭包的作用,应用在哪里
好处
1.希望一个变量长期驻扎在内存中
2.避免全局变量的污染
3.私有成员的存在,保护内部变量不被外部调用
用法
1.模块化代码,减少全局变量污染。
2.在循环中直接找到对应元素的索引。
3.闭包需要注意的地方
IE避免内存泄漏
例如:
function closureTest(){
var testDiv=document.getElementById('div1');
testDiv.onclick=function(){
testDiv.style.left=100+'px';
}
}
closureTest方法创建了一个内部匿名函数,由于testDiv的onclick
属性引用了该匿名函数,testDiv是一个外部对象,所以该匿名函数会在
内存中保存。而该函数所要用的testDiv对象也一直保存在内存中。
(本来的意愿是不希望testDiv长久保留的)
这样就形成了内存泄漏。
解决办法:利用window.onunload=function(){ testDiv.onclick=null; }
结束循环引用。
JS跨域———————————————————————————
www.a.com/a.js
www.a.com/c/b.js //同域名下不存在跨域问题
www.a.com
b.a.com //子域名下存在跨域问题
www.a.com
www.b.com //不同域名存在跨域问题
ajax : XMLHttpRequest(); //不能跨域
跨域解决方法
1.主域和子域跨域的时候,主域和子域同时设置document.domain='a.com';
这里的a.com指的是主域名
2.不同域名下,通过服务器代理。在服务器那边做一个XMLHttpRequest代理文件。
3.用script标签:jsonp的形式(script标签不存在跨域问题)
jsonp: json+padding(把json内填充到一个盒子中)
将一个script动态填充到head标签的最后,
而这个script中的src就是调用函数的文件地址
4.location.hash
5.window.name
6.flash
7.html5 postMessage
firebug————————————————————————-
console.log();//打印信息
console.warn();//警告信息
console.error();//错误信息
console.group();//分组打印信息
console.log();
console.log();
console.groupEnd();
console.dir(cat);//输出对象所有信息
console.dirxml(oDiv);//输出元素对象代码结构
console.assert(false);//断言,断言失败会有信息显示
console.trace(); //显示函数调用情况
console.time('计时器名');//测试代码运行时间
...
console.timeEnd('计时器名');
console.profile();//显示其中的函数调用情况、性能
...
console.profileEnd();
firebuglite 给其他浏览器使用firebug
JS性能DOM优化—————————————————————————-
JS:DOM+ECMA+BOM+EVENT
DOM:xml/html文档对象模型 例如document
ECMA:JS语法 例如if else switch
BOM:浏览器对象模型 例如window location open()
EVENT:事件 例如 ev.attachEvent
用console.time-console.timeEnd
可以测得代码运行时间,同样效果的代码运行时间越少效率越高,
性能越好
【DOM与javascript】
DOM与javascript在浏览器下为两个独立的文件夹
js操作dom需要消耗性能,减少性能消耗可以优化dom
要循环操作oDiv.innerHTML时,先把操作结果存在str变量中,
最后赋值给innerHTML
dom createElement方法(循环创建)和oDiv.innerHTML(先用str循环再赋值)的对比
chrome(-webkit-) : dom方法要比innerHTML性能好??
(实测为innerHTML性能更好)
火狐和IE : dom方法要比innerHTML性能要差
dom createElement方法( 循环创建 )和oLi.cloneNode( true );
( 循环内创建,循环外克隆 )性能对比
克隆的性能略好。
aLis.length也是dom操作,最好先把其存为一个变量再循环。
document.getElementById(''); 当多次进行这个操作时应该把document存为一个局部变量doc,
减少dom操作数
获取元素时,尽量只用纯获取元素节点的方法。如使用children方法代替childNode方法
获取元素时,可以用新的方法,例如document.querySelectorAll('#ul li');来减少dom操作
不过IE8及该版本以下不支持
【DOM与浏览器】
重排:改变页面内容
重绘:浏览器显示内容
重排和重绘都会对性能产生很大影响,所以要减少该过程。
方法:
1.最好在appendChild之前操作好元素。可以一次性到位。减少重排重绘。
2.合并dom操作,如使用style.cssText代替 style.width[height][background]等一系列的
dom操作。减少重绘
3.缓存布局信息:
将oDiv.offsetLeft等需要dom操作的布局信息转为变量left保存起来,
然后操作变量。
4.文档碎片。
每次oUl.appendChild(oLi)会重排重绘。
可以先var oFrag = document.createDocumentFragment();
然后每次先添加到oFrag最后再一次性添加到oUl里,一次性到位。
【DOM与事件】
用事件委托机制,不但减少dom操作,还能动态地给新增的内容绑定事件
【DOM与前端模版】
MVC基础
HTML5历史管理—————————————————————————-
1.用window.location.hash来记录。
然后点击前进后退时,用window.onhashchange来判断hash值改变
然后通过hash值来获取历史值
2.history:
history.pushState():三个参数:数据 标题(浏览器都没实现) 地址(可选)
window.onpopstate
popstate事件:读取数据 even.state
注意:当给了第三个参数时,当onpopstate发生的时候,网址是虚假的,
需要在服务器指定对应页面,不然刷新找不到页面