//记一段JavaScript 高性能的优化笔记;
function collectionGlobal() { var coll = document.getElementsByTagName_r('div'), len = coll.length, //缓存动态collection的length name = ''; for (var count = 0; count < len; count++) { name = document.getElementsByTagName_r('div')[count].nodeName; name = document.getElementsByTagName_r('div')[count].nodeType; name = document.getElementsByTagName_r('div')[count].tagName; } return name; }; // faster function collectionLocal() { var coll = document.getElementsByTagName_r('div'), len = coll.length, //缓存动态collection的length name = ''; for (var count = 0; count < len; count++) { name = coll[count].nodeName; //使用缓存的coll 集合, name = coll[count].nodeType; name = coll[count].tagName; } return name; }; // fastest function collectionNodesLocal() { var coll = document.getElementsByTagName_r('div'), len = coll.length, //缓存动态collection的length name = '', el = null; for (var count = 0; count < len; count++) { el = coll[count]; //访问变量的速度要比访问 集合快 name = el.nodeName; name = el.nodeType; name = el.tagName; } return name; };
彻底领悟,js面向对象:http://www.admin10000.com/document/13628.html
http://doc.pfan123.com/
//这了,我们在复习js中的自定义事件地呀;
与自定义事件的函数有 Event、CustomEvent 和 dispatchEvent。
//直接自定义事件,使用 Event 构造函数: var event = new Event('build'); // Listen for the event. elem.addEventListener('build', function (e) { ... }, false); // Dispatch the event. elem.dispatchEvent(event);
CustonEvent
CustomEvent 可以创建一个更高度自定义事件,还可以附带一些数据,具体用法如下:
var myEvent = new CustomEvent(eventname, options);
其中options可以是:
{
detail: {
...
},
bubbles: true,
cancelable: false
}
其中 detail 可以存放一些初始化的信息,可以在触发的时候调用。其他属性就是定义该事件是否具有冒泡等等功能。
dispatchEvent
这个用于触发自定义的事件。
http://www.admin10000.com/document/6089.html
jq 中阻止事件冒泡和默认行为的方法;
1.event.stopPropagation();
事件处理过程中,阻止了事件冒泡,但不会阻击默认行为(它就执行了超链接的跳转)
2.returnfalse;
事件处理过程中,阻止了事件冒泡,也阻止了默认行为(比如刚才它就没有执行超链接的跳转)
还有一种有冒泡有关的:
3.event.preventDefault();
如果把它放在头部A标签的click事件中,点击“点击我”。
会发现它依次弹出:我是最里层---->我是中间层---->我是最外层,但最后却没有跳转到百度
它的作用是:事件处理过程中,不阻击事件冒泡,但阻击默认行为(它只执行所有弹框,却没有执行超链接
绑定事件时的回调函数不能是匿名函数,必须是一个声明的函数,因为解除事件绑定时需要传递这个回调函数的引用,才可以断开绑定。
关于数组类型的数据判断,在我们的js中一直是一个比较难的话题,具体的可以参考我们的:http://www.cnblogs.com/xiaohuochai/p/5680833.html(js中完善的数组类型的判断滴滴呀)
js 中数据类型的判断;
在 js 里使用 typeof 来判断数据类型,只能区分基本类型,即 “number”,”string”,”undefined”,”boolean”,”object” 五种。对于数组、函数、对象来说,其关系错综复杂,使用 typeof 都会统一返回 “object” 字符串。
要想区别对象、数组、函数单纯使用 typeof 是不行的,javascript中,通过Object.prototype.toString方法,判断某个对象值属于哪种内置类型。常常使用Object.prototype.toString()来进行类型识别,返回代表该对象的[object 数据类型]字符串表示,
[注 意]Object.prototype.toString()可以识别标准类型及内置对象类型,但不能识别自定义类型
console.log(Object.prototype.toString.call("jerry"));//[object String] console.log(Object.prototype.toString.call(12));//[object Number] console.log(Object.prototype.toString.call(true));//[object Boolean] console.log(Object.prototype.toString.call(undefined));//[object Undefined] console.log(Object.prototype.toString.call(null));//[object Null] console.log(Object.prototype.toString.call({name: "jerry"}));//[object Object] console.log(Object.prototype.toString.call(function(){}));//[object Function] console.log(Object.prototype.toString.call([]));//[object Array] console.log(Object.prototype.toString.call(new Date));//[object Date] console.log(Object.prototype.toString.call(/\d/));//[object RegExp] function Person(){}; console.log(Object.prototype.toString.call(new Person));//[object Object]
我们可进行一个简单封装;
function type(obj){ return Object.prototype.toString.call(obj).slice(8,-1).toLowerCase(); }
还可以进行其他类型的基本识别滴呀;
(function(){ console.log(Object.prototype.toString.call(arguments));//[object Arguments] })() console.log(Object.prototype.toString.call(document));//[object HTMLDocument]
函数Function类型返回函数代码
当我们对一个自定义函数调用toString()方法时,可以得到该函数的源代码;如果对内置函数使用toString()方法时,会得到一个'[native code]'字符串。因此,可以使用toString()方法来区分自定义函数和内置函数
function test(){ alert(1);//test } test.toString();/*"function test(){ alert(1);//test }"*/ Function.toString();//"function Function() { [native code] }"
如果存在任意原始值,它就默认将对象转换为表示它的原始值;对象是复合值,而大多数对象无法真正表示为一个原始值,因此默认的valueOf()方法简单地返回对象本身,而不是返回一个原始值
toString()和valueOf()的主要不同点在于,toString()返回的是字符串,而valueOf()返回的是原对象
2、由于undefined和null不是对象,所以它们toString()和valueOf()两个方法都没有
3、数值Number类型的toString()方法可以接收转换基数,返回不同进制的字符串形式的数值;而valueOf()方法无法接受转换基数
4、时间Date类型的toString()方法返回的表示时间的字符串表示;而valueOf()方法返回的是现在到1970年1月1日00:00:00的数值类型的毫秒数
5、包装对象的valueOf()方法返回该包装对象对应的原始值
6、使用toString()方法可以区分内置函数和自定义函数
js 操作dom的一些基本练习;
js实现简单的额两级联动菜单的使用;
<select id="province"> <option value="0">--请选择--</option> <option value="1">北京</option> <option value="2">重庆</option> </select> 城市:<select id="city"> <option>--请选择--</option> </select> <script type="text/javascript"> //这是一个动态的级联操作; //这的东西可以实时的从数据库中去取,取出来之后,缓存在我们也地呀; //页面加载的时候,就用去加载数据了的呀; var province=document.getElementById("province"); var city=document.getElementById("city"); var arr=new Array(); arr[1]=new Array("海淀","昌平","西城"); arr[2] = new Array("沙坪坝","万州","南岸"); window.onload=function (){ province.onchange=function (){ //当改成省份的时候,需要清空之前的数据; city.options.length=1; //从数据中取出值地呀; var selected=arr[this.value]; var len=selected.length; //然后添加到我们的city中去地呀; for(let i=0;i<len;i++){ city.add(new Option(selected[i],selected[i])); } } }
js 操作dom练习,之,table表格的操作;(js操作table列,这种做法是很初级的,简直就是demo级别的,无法应用在实际的生产中滴呀)
当然,你也可以不用通过创建节点的方式来操作,可使用我们innerHTML 的方式来实现滴呀;
姓名:<input type="text" id="name" /> <br /> 联系方式:<input type="text" id="email" /> <br /> 年龄:<input type="text" id="age" /> <br /> <input type="button" value="添加用户" onclick="addLine()"/> <br /> <br /><br /><hr /><br /> <table id="userTable" align="center" border=1 cellspacing=0 cellpadding=5 width="50%"> <tr> <th>姓名</th> <th>联系方式</th> <th>年龄</th> <th>操作</th> </tr> <tr> <td id="en">大哥</td> <td>fda@fd.com</td> <td>15</td> <td> <input type="button" value="删除" onclick="delLine(this)" /> </td> </tr> </table> <script type="text/javascript"> //第一种实现方式;xml dom 方式; //这个是最基本的额写法,有种意义对应的方式滴呀;会看到很多的重复代码,当我后面吧面向对象的方式 //学习了之后,我会尝试用oo的方式进行封装滴呀; // 这里有太多额重复代码了,后期我进行一定程度的优化滴呀; function bind(fn,context){ return function (){ return fn.apply(context,arguments); } } // 好吧,基本的删除事件是完成了滴呀; table 的基本操作地呀; function addLine(){ var name=document.getElementById("name").value; var email=document.getElementById("email").value; var age=document.getElementById("age").value; var table=document.getElementById("userTable"); var tr=document.createElement("tr"); // 节点操作; var tdNode1 = document.createElement("td"); var textNode1 = document.createTextNode(name); tdNode1.appendChild(textNode1); var tdNode2 = document.createElement("td"); var textNode2 = document.createTextNode(email); tdNode2.appendChild(textNode2); var tdNode3 = document.createElement("td"); var textNode3 = document.createTextNode(age); tdNode3.appendChild(textNode3); //创建删除按钮; var tdNode4 = document.createElement("td"); var btn=document.createElement("input"); btn.type="button"; btn.value="删除"; //可用这种方式来添加事件滴呀‘ //btn.setAttribute("onclick", "javascript:alert('This is a text!');"); btn.setAttribute("onclick", "delLine(this)"); //btn.οnclick=bind(delLine,btn); tdNode4.appendChild(btn); tr.appendChild(tdNode1); tr.appendChild(tdNode2); tr.appendChild(tdNode3); tr.appendChild(tdNode4); table.appendChild(tr); } //删除的方法; function delLine(thisObj){ trNode=thisObj.parentNode.parentNode;//tr trNode.parentNode.removeChild(trNode); }
我们也可以这样写滴呀;
btn.οnclick=function (){
delLine(this);
}
操作方式二:
//同样,我们可以这样写,和改造滴呀; function addLine2(){ var name=document.getElementById("name").value; var email=document.getElementById("email").value; var age=document.getElementById("age").value; var table=document.getElementById("userTable"); //还有这种神奇的做法滴呀;效果还算比较理想滴呀;小 var tr=table.insertRow(table.rows.length); tr.innerHTML = "<td>"+name+"</td><td>"+email+"</td><td>"+age+"</td><td>"+ "<input type='button' value='删除' onclick='delLine(this)' /> </td>"; }
//不写了,下次接着继续:http://www.flyne.org/article/420
(function() { var a = b = 5; })(); console.log(b); //5 (function() { 'use strict'; var a = window.b = 5; })(); console.log(b);
知识点:立即执行函数,作用域,严格模式
// 在 String 对象上定义一个 repeatify 函数。这个函数接受一个整数参数,来明确字符串需要重复几次。这个函数要求字符串重复指定的次数。举个例子: // console.log('hello'.repeatify(3)); // 应该打印出 hellohellohello . String.prototype.repeatify=String.prototype.repeatify || function (times){ var result=''; for(var i=0;i<times;i++){ str+=this; } return result; }
知识点:原型 怎样避免重写可能已经定义了的方法
function test() { console.log(a); console.log(foo()); var a = 1; function foo() { return 2; } } test(); //这段代码的执行结果是 undefined 和 2 。 (function(a){ console.log(a); var a=10; function a(){}; }(100)) //function a(){}
知识点:关于hostting,变量和函数的提升;
console.log(typeof null); // object console.log(typeof {}); //object console.log(typeof []); //object console.log(typeof undefined); //undefined //最令人惊讶的输出结果可能是第三个。大多数开发人员认为 typeof [] 会返回 //Array 。如果你想测试一个变量是否为数组,您可以执行以下测试: var myArray = []; if (myArray instanceof Array) { // do something... }
知识点,数据类型;
function printing() { console.log(1); setTimeout(function() { console.log(2); }, 1000); setTimeout(function() { console.log(3); }, 0); console.log(4); } printing();
想知道为什么输出顺序是这样的,你需要弄了解 setTimeout()
做了什么,以及浏览器的事件循环原理。浏览器有一个事件循环用于检查事件队列,处理延迟的事件。UI事件(例如,点击,滚动等),Ajax回调,以及提供给 setTimeout()
和 setInterval()
的回调都会依次被事件循环处理。因此,当调用 setTimeout()
函数时,即使延迟的时间被设置为 0
,提供的回调也会被排队。回调会呆在队列中,直到指定的时间用完后,引擎开始执行动作(如果它在当前不执行其他的动作)。因此,即使 setTimeout()
回调被延迟 0
毫秒,它仍然会被排队,并且直到函数中其他非延迟的语句被执行完了之后,才会执行。
有了这些认识,理解输出结果为“1”就容易了,因为它是函数的第一句并且没有使用 setTimeout()
函数来延迟。接着输出“4”,因为它是没有被延迟的数字,也没有进行排队。然后,剩下了“2”,“3”,两者都被排队,但是前者需要等待一秒,后者等待0秒(这意味着引擎完成前两个输出之后马上进行)。这就解释了为什么“3”在“2”之前。
参考链接:http://www.tuicool.com/articles/2MVJBnZ
这是js 的一些代码片段,所以未命题滴呀;
这个,我们先打一个草稿,我们后面再进一步的进行补充;
第一种方式:
function Person(name,age,job){ //这样写,就限制了,call 和 apply的引用滴哎呀; this.name=name; this.age=age; this.job=job; this.show=function (){ console.log(this.name+"---"+this.job); } } function son(address){ this.address=address; } var p=new Person("jack",18,"javascript"); son.prototype=p; //这个还要在生成 对象 之前执行 ,,哎,这个都是很基础的啦,原型继承,, var s=new son("chengdu"); s.show();
第二种方式:
我曹,这个又涉及到我们得继承了滴呀;
function Person(name,age,job){ //这样写,就限制了,call 和 apply的引用滴哎呀; this.name=name; this.age=age; this.job=job; this.show=function (){ console.log(this.name+"---"+this.job); } } function son(name,age,job,address){ Person.call(this,name,age,job) this.address=address; } var s=new son("jack",18,"javascript","chengdu"); s.show();
第三种方式:(我们可以在传递参数上)
function Person(name,age,job){ //这样写,就限制了,call 和 apply的引用滴哎呀; this.name=name; this.age=age; this.job=job; this.show=function (){ console.log(this.name+"---"+this.job); } } function son(name,age,job,address){ Person.call(this,...arguments) //不过这个要用到es6的特性; this.address=address; } var s=new son("jack",18,"javascript","chengdu"); s.show();
这个是我们函数的惰性加载,的两种实现方式,好处就是不用每次调用的时候,都去if else 进行一次的判断滴呀;(反正,我个人觉得是挺秒的一个方法滴呀;效果非常好滴呀;)
对了,这里还得注意一个参数:addEventListener()方法中的第三个参数设置为true时,即为事件捕获阶段
//所谓惰性载入, 指函数执行的分支只会发生一次 //所谓的惰性载入,值函数执行的分支只会执行一次; function addEvent(type,element,fn){ if (element.addEventListener){ addEvent=function (type,element,fn){ element.addEventListener(type,fun,false) } }else if(element.attachEvent){ addEvent=function(type,element,fn){ element.attachEvent('on'+type,fn); } }else{ addEvent=function(type,element,fn(){ element['on'+type]=fn; } } //返回正确的需要执行的函数滴呀; // return addEvent(type,element,fn); //这样 函数只需要执行一次之后,就能判断, //浏览的兼容性,不用重复的判读了滴啊;效果是非常好滴呀; // 在这个惰性载入的addEvent()中,if语句的每个分支都会为addEvent变量赋值,有效覆盖了原函数。最后一步便是调用了新赋函数。下一次调用addEvent()时,便会直接调用新赋值的函数,这样就不用再执行if语句了 } //第二种是声明函数时就指定适当的函数。 这样在第一次调用函数时就不会损失性能了,只在代码加载时会损失一点性能 //// 以下就是按照这一思路重写的addEvent()。以下代码创建了一个匿名的自执行函数,通过不同的分支以确定应该使用哪个函数实现 var addEvent=(function (){ if(document.addEventListener){ return function (type,element,fn){ element.addEventListener(type,fn,false); }else if(document.addEventListener){ return function (type,element,fn){ element.attachEvent('on'+type,fn); } }else{ return function (type,element,fn){ element.['on'+type]=fn; } } } })();//在第一次执行的时候,就能确定下俩,我们浏览器的兼容性的东西,是怎样滴呀;效果是很好的;
这些,都是我们函数使用过程的的一些高级技巧滴哎呀;
这个只是一些草稿demo滴呀;
//这个有点老僧长谈了,还不是作用域,编报的问题; //解决方法有很多呢; var a=12; var ff={a:11,fn:function (){ alert(this.a)}}; window.onload=ff.fn; window.onload=function (){ ff.fn(); //这样才是我们想要额基本函数效果滴呀; } var handler={ msg:"this is fuck life", handlerFun:function (){ alert(this.msg); }, show:function (){ var _this=this; return function (){ alert(_this.msg); } }, fuck:function(){ return ()=>{ alert(this.msg) } } } var obj=document.getElementById("test"); // obj.οnclick=handler.handlerFun; //错误的释放滴呀; 问题所在之处, // //解决方法,你懂滴呀; // obj.οnclick=function (){ // handler.handlerFun(); // } // //或则这样; // obj.οnclick=handler.show(); obj.οnclick=handler.fuck();
顺便来不洗一下我们的箭头函数:
/箭头函数的出现,效果是非常好滴呀; // 而箭头函数的出现就可以很好的解决该问题。箭头函数根据当前的词法作用域而不是根据this机制顺序来决定this,所以,箭头函数会继承外层函数调用的this绑定,而无论this绑定到什么 var test = () => { console.log(this.a); } //形式上等价于 var test = function(){ console.log(this.a); } //实质上等价于 function fn(){ var that = this; var test = function(){ console.log(that.a); } } function f(){ console.log(this===window); } function fx(){ 'use strict' console.log(this===window); } var test = () => { console.log(this===window); } var test1 = () => { 'use strict' console.log(this===window); } var test2=function (){ 'use strict' console.log(this===window); } f(); //true fx(); //false test(); //true test1();//true test2();//false 滴呀; var timer0=function(){ setTimeout(function (){ console.log(this.msg) },3000) } var timer1=function(){ var _this=this; setTimeout(function (){ console.log(_this.msg) },4000) } var timer2=function(){ var _this=this; setTimeout(()=>{ console.log(this.msg) },5000) } var timer={ msg:"fuck life", timer0:timer0, timer1:timer1, timer2:timer2, }; timer.timer0(); //undefined timer.timer1(); //fuck life timer.timer2(); //fuck life
//这个函数似乎简单,但其功能是非常强大的。在bind()中创建了一个闭包,闭包使用apply()调用传入的函数,并给apply()传递context对象和参数。当调用返回的函数时,它会在给定环境中执行被传入的函数并给出所有参数 function bind(fn,context){ return function (){ return fn.apply(context,arguments); } }
接着上面的话题,再来看我们想要的效果,这个,还是挺好滴呀;
function bind(fn,context){ return function(){ return fn.apply(context,arguments); //这里为啥一定要return呢,不return也能事项相同的效果滴哎呀; } } var handler={ message:"Event handled.", handlerFun:function(){ alert(this.message); } }; var obj=document.getElementById("test"); // obj.οnclick=bind(handler.handlerFun,handler); // obj.οnclick=function (){ // return handler.handlerFun.call(handler); //返回一个可执行(立即执行的函数) // }
//或则,这样,我曹; obj.onclick=function(){ handler.handlerFun(); }
这里还有一些关于js事件代理的实例方法滴呀;
由于事件会在事件冒泡向上传播到父节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件。这种方法叫做事件的代理(delegation),也叫事件委托
事件代理应用事件目标的target和srcElement属性完成。利用事件代理,可以提高性能及降低代码复杂度
有一个需求,一个<ul>中有5个<li>,移入时变浅蓝,移出时变品红
下面分别用常规方法和事件代理方法来实现
<style> #box{background-color: pink;} .in{height: 30px;} </style> <ul id="box"> <li class="in">1</li> <li class="in">2</li> <li class="in">3</li> <li class="in">4</li> <li class="in">5</li> </ul> <script> //常规方法 var tags = box.getElementsByTagName('li'); for(var i = 0; i < tags.length; i++){ tags[i].onmouseover = function(e){ this.style.backgroundColor = 'lightblue'; } tags[i].onmouseout = function(e){ this.style.backgroundColor = 'pink'; } } </script> <script> //事件代理方法 box.onmouseover = function(e){ e = e || event; var target = e.target || e.srcElement; target.style.backgroundColor = 'lightblue'; } box.onmouseout = function(e){ e = e || event; var target = e.target || e.srcElement; target.style.backgroundColor = 'pink'; } </script>
阻止事件冒泡 和 默认的事件的兼容性写法,效果很好滴哎呀
//阻止事件冒泡的兼容性写法 function stopBubble(e) { // 如果提供了事件对象,则这是一个非IE浏览器 if ( e && e.stopPropagation ) { // 因此它支持W3C的stopPropagation()方法 e.stopPropagation(); } else { // 否则,我们需要使用IE的方式来取消事件冒泡 window.event.cancelBubble = true; } } //阻止默认事件的 兼容性写法; function stopDefault( e ) { // 阻止默认浏览器动作(W3C) if ( e && e.preventDefault ) { e.preventDefault(); } else { // IE中阻止函数器默认动作的方式 window.event.returnValue = false; } return false; } function clicked(event) { stopDefault(event); alert("我阻止了点击A标签的默认事件"); }
var handler = function(e){ e = e || event; if(e.stopPropagation){ e.stopPropagation(); }else{ e.cancelBubble = true; } }
defaultPrevented 属性表示默认行为是否被阻止; 返回true表示阻止,返回false表示表示没有阻止;
注意,ie8 不支改属性;我曹;
阻止,默认行为的方式一(两种方式):
<a id="a0" href="http://www.cnblogs.com" target="_blank">链接</a> <a id="a1" href="http://www.cnblogs.com" οnclick="return false;" target="_blank">链接</a> <script type="text/javascript"> var a=document.getElementById("a0"); a.onclick=function (){ return false; ///这届通过returnfalse 也可以阻止我们额默认行为; } </script>
还有就是我们的returnValue 属性,是可读写的,默认是我们的true,将起设置为false,可以取消默认的行为,但是他们的 firefox 和 ie9 不支持;
preventDefault() 方法取消浏览器对当前事件的默认行为,无返回值,但是他妈的ie8 又不支持,所有就有了我们的兼容性写法滴呀;效果还是挺不错滴呀;
var handler=function (e){ var e=e|| event; if(e.preventDefault){ e.preventDefault(); }else{ e.returnValue=false; } }
cancelable
cancelable属性返回一个布尔值,表示事件是否可以取消。该属性为只读属性。返回true时,表示可以取消。否则,表示不可取消。
总结:
1、在DOM0级事件处理程序中取消默认行为,使用returnValue、preventDefault()和return false都有效
2、在DOM2级事件处理程序中取消默认行为,使用return false无效
3、在IE事件处理程序中取消默认行为,使用preventDefault()无效
关于input中的value的一点点
。如果是一个表单元素,则它的作用域链是 this -> this.form -> document 。先从<input type="button">对象中寻找username属性,发现没有。然后找到它的父级form,form的username可以找到<input type="text">元素(表单元素可以直接通过name值访问),然后找到其value值123后弹出