DOM优化
/*
* 什么是DOM
* 用于操作XML和人HTML
*
* 浏览器会把dom与js独立实现
* - 就像两个独立的小岛
*JS操作DOM
* - 从一个岛到另一个岛
* dom的性能
* - 岛与岛之间的桥,每次通过要收取过桥费
* - 尽量减少过桥的次数
*
* innerHTML与dom方法对比。
* */
var div1 = document.getElementById('div1');
var str = '';
console.time('hi');
for(var i =0;i<5000;i++){
// div1.innerHTML +='a';//使用的时间是236ms
str+='a';//使用的时间是0.9ms
}
div1.innerHTML = str;
console.timeEnd('hi');
var ul1 =document.getElementById('ul1');
var str = '';
console.time('hello');
for(var i=0;i<5000;i++){
/* var newLi = document.createElement('li');
ul1.appendChild(newLi);*///使用了16ms
str+='<li></li>'//使用了6ms
}
ul1.innerHTML = str;
console.timeEnd('hello');
/*
*
* 减少DOM操作
* 节点克隆
* -cloneNode
* 访问元素集合
* - 尽量用局部变量
* 元素节点
* - 尽量用只获取元素的节点方法
* 选择器API
* - 利用querySelector
* */
var ul1 = document.getElementById('ul1');
var str = '';
console.time('hello');
for(var i=0;i<5000;i++){
var oLi =document.createElement('li');
oLi.innerHTML = 'li';
ul1.appendChild(oLi);//使用时间34ms
}
console.timeEnd('hello');
-------------------------------------------
var ul1 = document.getElementById('ul1');
var str = '';
console.time('hello');
var oLi =document.createElement('li');
oLi.innerHTML = 'li';
for(var i=0;i<5000;i++){
var newLi = oLi.cloneNode(true);
ul1.appendChild(newLi);//使用时间是9ms
}
console.timeEnd('hello');
----------------------------------------------------------
//li是已经创建完毕了的
//- 尽量用局部变量
console.time('hello');
var len = aLi.length;//如果这样使用时间是700ms
for(var i=0;i<aLi.length;i++){//使用时间656ms
aLi[i].innerHTML = 'li';
}
console.timeEnd('hello');
//这样对性能也是有提升的,在做复杂网站的时候要注意
var oDiv = document.getElementById();
var doc = document;
var oDiv = doc.getElementById();
//尽量用只获取元素的节点方法
childNodes -> 元素节点,文本节点。
可以用替换成children
// 利用querySelector
新的选择器对性能也有提升。
//DOM与浏览器
/*
*
* 重排:改变页面的内容[如HTML,JS]
* 重绘:浏览器显示内容[浏览器进行显示]
*
* - 尽量在 appendChild前执行操作
*
* - 合并dom操作
* 使用cssText
*
* - 缓存布局信息
*
*- 文档碎片
* */
var oUl = document.getElementById('ul1');
console.time('hello');
for(var i=0;i<5000;i++){//使用时间 26ms。实测速度差不多。但是还是不要再appendCjhild后面操作
var oLi = document.createElement('li');
oUl.appendChild(oLi);
oLi.innerHTML = 'li';
}
console.timeEnd('hello');
//有关于cssText是覆盖掉之前的样式,并且是行内样式。
oLi.style.width = '100px';
oLi.style.height = '100px';
oLi.style.backgroundColor = 'red';
oLi.style.cssText = 'border: 1px solid #000;:'
// - 缓存布局信息。第二种性能要比第一种性能要好
var div1 = document.getElementById('div1');
setInterval(function(){
div1.style.left = div1.offsetLeft+1+'px';
div1.style.top = div1.offsetTop + 1+'px';
},30);
var L = div1.offsetLeft;
var T = div1.offsetTop;
setInterval(function(){
L++;
T++;
div1.style.left = L+'px';
div1.style.top = T +'px';
},30);
- 文档碎片。实际测试性能相差不大。
var oUl = document.getElementById('ul1');
var oFrag = document.createDocumentFragment();
console.time('hello');
for(var i=0;i<5000;i++){
var oLi =document.createElement('li');
// oUl.appendChild(oLi);
oFrag.appendChild(oLi);
}
oUl.appendChild(oFrag);
console.timeEnd('hello');
此外DOM优化还有
- DOM与事件
- 事件委托
- DOM与前端模板
- 能更好的对逻辑和试图风力,MVC架构的基础
快速排序
//使用快排
function quickSort(arr){
if(arr.length<=1){
return arr;
}
var centerNum = Math.floor(arr.length/2);
var numValue = arr.splice(centerNum,1);
var left =[];
var right = [];
for(var i =0;i<arr.length;i++){
if(arr[i]>numValue){
right.push(arr[i]);
}else{
left.push(arr[i]);
}
}
return quickSort(left).concat(numValue,quickSort(right));
}
03_函数声明与表达式
/*
函数声明与函数表达式
都存在匿名与命名
*/
var aa = function(){};//函数表达式
function bb(){};//函数声明
(function aa(){
alert(1);
});//函数表达式
~function aaa(){alert(1)};//函数表达式[在前面加位运算符的话就是函数表达式]
//函数表达式与函数声明的区别
/*
* 区别:
* 1.函数表达式可以直接后面添加括号执行,而函数声明是不可以的。
2.函数声明是可以被提前解析出来的[函数的预解析]
* */
// function aaa(){alert(1)}();//这样写就会报错
var a = function aa(){alert(1)}();//这样就是可以的
var b = function aaa(){
alert(222);
alert(typeof aaa);//不推荐这样用
}
b();
操作iframe
<iframe src="04_iframe.html" id="iframe1"></iframe>
<script>
var input = document.getElementById('input1');
var iframe1 = document.getElementById('iframe1');
input.onclick = function(){
/*在chrome下,为了安全起见做了限制。必须要求是在服务器环境下才能访问*/
// alert(iframe1.contentWindow);
iframe1.contentWindow.document.getElementById('div1').style.backgroundColor = 'pink';// IE6 7 是不支持的
}
/*
* //通过子页面修改父级,在chrome下,同样的有此问题,必须要在服务器环境下
* */
var btn =document.getElementById('btn');
btn.onclick = function(){
window.parent.document.getElementById('Fdiv').style.backgroundColor = 'red';
window.top.document.getElementById('divtop').style.backgroundColor = '#666';//这个修改的是最顶层
}
/*iframe加载完之后绑定的事件
*
* 在ie下:实测都支持onload事件
*
* */
iframeElem.onload = function(){
alert(1);
}
/*IE推荐事件绑定事件*/
iframeElem.attachEvent('onload',function(){
alert(124);
})
/*防钓鱼处理*/
/*
*
* */
setTimeout(function(){
if(window!=window.top){//如果现最顶层不是这个页面
window.top.location.href = window.location.href;//那么就修改为这个页面
}
},1000);
如何动态更改iframe高度?
枚举算法
编程常用算法之一
/*枚举,以为每一个都进行列举*/
/*
* A B C D E
* *
* F
* -----------------------
* G G G G G G
* */
var saveArr =[]
var meetLength = 0;
for(var i = 1;i<=9;i++){//用于表示A
for(var j=0;j<=9;j++){ //用于表示B
for(var k=0;k<=9;k++){//用于表示C
for(var m=0;m<=9;m++){//用于表示D
for(var n=0;n<=9;n++){//用于表示E
var nowValue = i*10000+j*1000+k*100+m*10+n;
var twoValue = i;
var result = n*111111;
if(nowValue*twoValue ==result){
meetLength++;
saveArr.push(nowValue+'*'+twoValue+'='+result);
}
}
}
}
}
}
console.log(saveArr);
console.log(meetLength);
<script>
var ul1 = document.getElementById('ul1');
var linkA =document.getElementsByTagName('a');
var objectLi = ul1.getElementsByTagName('li');
for( var i =0;i<linkA.length;i++){
linkA[i].onclick = function(){
if(testEvery(this.innerHTML)){//如果没有存在
var createLi = document.createElement('li');
createLi.innerHTML = this.innerHTML;
// ul1.appendChild(createLi);
ul1.insertBefore(createLi,ul1.children[0]);//添加在前面
}else{//如果已经存在
for(var i=0;i<objectLi.length;i++){
if(this.innerHTML == objectLi[i].innerHTML){
ul1.insertBefore(objectLi[i],ul1.firstElementChild);
}
}
}
}
}
function testEvery(text){//如果没有找到的就会返回true
var resule = true;
for(var i=0;i<objectLi.length;i++){
if(objectLi[i].innerHTML == text){
resule = false;
}
}
return resule;
}
</script>
事件委托
<script>
/*
* 还有一种叫法是事件代理
* */
var ul1 =document.getElementById('ul1');
var objectLi = ul1.children;
/*利用冒泡的原理,给ul添加*/
/*
* 事件委托就是利用冒泡的原理,把事件加到父级上,出发执行效果
* -好处就是可以提高性能
* - 新添加的元素,还会有之前的事件.[比如说微博发布事件]
*
* */
/* for(var i=0;i<objectLi.length;i++){
objectLi[i].onclick = function(){
alert(123);
}
}*/
/*
* event对象中的事件源:不管在哪个事件中,只要你操作的那个元素就是事件源
*
* ie: window.event.srcElement
* 标准: event.target
* */
/*
* nodeName:找到当前元素的标签名
* */
ul1.onmouseover = function(ev){
var ev =ev||event;
var target = ev.target||ev.srcElement;
console.log(target.nodeName.toLowerCase());
if(target.nodeName.toLowerCase() !='li'){
return;
}
// alert(target.innerHTML);
target.style.backgroundColor = 'red';
}
ul1.onmouseout = function(ev){
var ev =ev||event;
var target = ev.target||ev.srcElement;
target.style.backgroundColor = '';
}
</script>
闭包
/*
* - 什么是闭包
* - 函数嵌套函数
* - 内部函数可以引用外部函数的参数或者是变量
* */
/*
* 因为a和b都会被引用,所以不会被垃圾回收机制收回
*
* JS中的垃圾回收机制:一般函数被调用完之后,就会被垃圾回收机制收回
*
* 如果内部函数引用外部函数的参数或者是变量就不会被垃圾回收机制回收
* */
function aaa(a){
var b = 5;
function bbb(){
console.log(a);
console.log(b);
}
return bbb;
}
-----------------------------------------------------------------
// 关于闭包的测试。最后仍然是可以返回的
function aaa(){
var a =5;
function bbb(){
alert(a);
}
return bbb;
}
var c = aaa();
c();
<script>
/*
* JS有什么好处,应用在哪里
* - 希望一个变量长期存储在内存当中
* - 避免全局变量的污染
* -私有成员和私有方法的存在
* */
/* var a = 2;
function aaa(){
a++;
alert(a);
}
aaa();
aaa();*/
/* function bbb(){
var a = 1;
a++;
alert(a);
}
bbb();//失效
bbb();//失效
*/
/*
* 如何做到a既是一个局部变量,而又可以累加
* */
function ccc(){
var a= 1;
return function (){
a++;
alert(a);
}
}
var b = ccc();
console.log(b)
/*
//这是b
* ƒ (){
a++;
alert(a);
}
* */
b();//2
b();//3
alert(a);//到达这里的时候回报错,所以不是一个局部变量
</script>
(function(){alert(1)})();
/*闭包的改写*/
//目的就是让先执行一次。
//这种代码叫做模块化代码,减少全局变量的污染
var a= (function aaa(){
var a =1;
return function (){
a++;
console.log(a);;
}
})();
a();//2
a();//3
a();//4
//模块化代码。私有成员和私有变量,在外面是调用不到的
var aaa = (function(){
var num =0;
function fn1(){
num++;
console.log(num);
}
function fn2(){
num--;
console.log(num);
}
return {
fn1:fn1,
fn2:fn2
}
})();
aaa.fn1();
aaa.fn1();
aaa.fn2();
/*
*
* 用法:
* 1.模块化代码
* 2. 在循环中直接找到对应元素的索引
* */
var li = document.getElementsByTagName('li');
for(var i=0;i<li.length;i++){
//每次点击的都是3
li[i].onclick = function(){
alert(i);
}
}
------------------------------改正效果
// (function(i){console.log(i)})(6);
for(var i=0;i<li.length;i++){
(function(i){
li[i].onclick = function(){
alert(i);
}
})(i)
}
--------------------------------另外一种写法
//另外一种写法
for(var i =0;i<li.length;i++){
li[i].onclick = (function(i){
return function (){
alert(i);
}
})(i);
}
/*
* 在IE下有可能会引发内存泄露
*
* 当页面跳转的时候,变量就不会释放,一直存在于内存之中,只有关闭浏览器时候,才会释放内存
*
*
*引发原因是相互引用
* */
var div = document.getElementById('div1');
div.onclick = function(){
console.log(div.id);
}
//解决办法就是在页面关闭的时候,把事件给取消掉
window.onunload = function(){
div.onclick = null;
}
//另外一种防止内存泄露的办法
var div = document.getElementById('div1');
var id =div.id
div.onclick = function(){
console.log(div.id);
};
div.onclick = null;
对象引用
变量之间是一种赋值关系,对象之间是一种引用关系[如果重新赋值,那么引用链就断掉了]
// 如何拷贝一个对象.他们之间没有任何的关系
var obj = {//叫做浅克隆
a:10
}
function copy(obj){
var newObj = {};
for(var attr in obj){
newObj[attr] = obj[attr];
}
return newObj;
}
var obj2 = copy(obj);
obj2.a = 666;
console.log(obj.a);
<script>
// 浅拷贝的一些问题,因为浅拷贝只是拷贝了一层,其实还是一种引用的关系
var obj = {
a:{b:20}
}
function copy(obj){
var newObj = {};
for(var attr in obj){
newObj[attr] = obj[attr];
}
return newObj;
}
var obj2 = copy(obj);
obj2.a.b = 666;
console.log(obj.a.b);//这里被修改了。
</script>
///递归:函数调用函数自身,所以不会结束,最后一次给出一个终止条件。
function recu(num){
if(num==1){
console.trace();//追溯
return num;
}
return num*recu(num-1);
}
console.log(recu(10));
<script>
//深层拷贝
var obj_one = {
a:{b:6}
}
function deepCopy(obj){//深层的拷贝
if(typeof obj!='object'){
return obj;
}
var newObj = {};
for(var attr in obj){
newObj[attr] =deepCopy(obj[attr]);
}
return newObj;
}
var obj_two = deepCopy(obj_one);
obj_two.a.b = 6666;
console.log(obj_one.a.b);
</script>
JS中的跨域
学完ajax之后再来学习
firebug工具使用
<script>
//firebug是基于火狐浏览器
console.log('hello');
console.warn('这里是警告');//警告
console.error('这里是错误');//错误
console.group('第一组');//分组
console.log(1);
console.log(1);
console.log(1);
console.groupEnd();
console.group('第二组');//分组
console.log(1);
console.log(1);
console.log(1);
console.groupEnd();
var cat = {};
cat.name = '666';
cat.color = 'red';
cat.show = function(){
return 'show';
};
console.log(cat);
// alert(cat); 如果这样写弹出的是object
console.dir(cat);//输出所有信息
</script>
//显示全部内容
<div id="div1"></div>
<script>
var div1 = document.getElementById('div1');
console.dirxml(div1);
//段言
var a =0;
console.assert(a);
</script>
//选择出调用情况
function a(){
return b();
}
function b(){
return c();
}
function c(){
console.trace();
alert(1);
}
a();
//计算程序运行时间
console.time('运行时间');
var a = 0;
setTimeout(function(){
a++;
},100);
console.timeEnd('运行时间');
<script>
console.profile();
var a = 0;
var timer=setInterval(function(){
a++;
if(a===20){
clearInterval(timer);
}
},100);
console.profileEnd();
</script>
HTML5-history
var input1 =document.getElementById('input1');
var div1 =document.getElementById('div1');
input1.onclick = function(){
var number = randomNum(35,7);
div1.innerHTML = number;
window.location.hash = number;
}
function randomNum(allNum,numLength){//每次点击都有七个不同的出口产生
var arr = [];
var newArr =[];
for(var i=1;i<=allNum;i++){
arr.push(i);
}
for(var i=0;i<numLength;i++){
newArr.push(arr.splice(Math.floor(Math.random()*arr.length),1));
}
return newArr;
}
//onhashchange:事件,当hash值有变化的时候,就会触发。
//当hash发生改变的时候,就会记入历史管理
var input1 =document.getElementById('input1');
var div1 =document.getElementById('div1');
input1.onclick = function(){
var number = randomNum(35,7);
div1.innerHTML = number;
window.location.hash = number;
}
function randomNum(allNum,numLength){//每次点击都有七个不同的出口产生
var arr = [];
var newArr =[];
for(var i=1;i<=allNum;i++){
arr.push(i);
}
for(var i=0;i<numLength;i++){
newArr.push(arr.splice(Math.floor(Math.random()*arr.length),1));
}
return newArr;
}
//onhashchange:事件,当hash值有变化的时候,就会触发。
//当hash发生改变的时候,就会记入历史管理
window.onhashchange = function(){//前进后退的时候,修改值
var number = window.location.hash.substring(1);
div1.innerHTML = number;
// console.log(window.location.hash);
}
<script>
var input1 =document.getElementById('input1');
var div1 =document.getElementById('div1');
var obj = {};
input1.onclick = function(){
var number = randomNum(35,7);
div1.innerHTML = number;
var oRD = Math.random();
obj[oRD] = number;
window.location.hash = oRD;//把现在的哈希值修改为随机数
}
function randomNum(allNum,numLength){//每次点击都有七个不同的随机数产生
var arr = [];
var newArr =[];
for(var i=1;i<=allNum;i++){
arr.push(i);
}
for(var i=0;i<numLength;i++){
newArr.push(arr.splice(Math.floor(Math.random()*arr.length),1));
}
return newArr;
}
//onhashchange:事件,当hash值有变化的时候,就会触发。
//当hash发生改变的时候,就会记入历史管理
//这里是做了一个映射
window.onhashchange = function(){//前进后退的时候,修改值
var number =obj[window.location.hash.substring(1)]||'';
div1.innerHTML = number;
// console.log(window.location.hash);
}
</script>
网友评论