1,JS中的thisjavascript
见下面例子,注意函数中的函数 中的this指的是window对象了!!!php
document.addEventListener('click', function (e) { console.log(this);//this->document,添加在谁上的事件this就是指的谁
(function () { console.log(this);//this->window
})(); }); var o = { a : function () { console.log(this);//this->o,this指代对象o
var b = function () { console.log(this);//this->window
}() } }; o.a();//o['a']()
2,定时器函数 setTimeout() 函数说明 (JavaScript单线程相关)html
语法:
java
var timeoutID = scope.setTimeout(function[, delay, param1, param2,....]);
var timeoutID = scope.setTimeout(function[, delay]);
var timeoutID = scope.setTimeout(code[, delay]);
参数说明:
function:function
是你想要在delay
毫秒以后执行的 回调函数。
code:这是一个替代语法,你可使用字符串代替function
,在delay
毫秒以后执行字符串 (使用该语法是不推荐的, 缘由和使用eval()
同样,有安全风险)。
delay: 可选延迟的毫秒数 (一秒等于1000毫秒),函数的调用会在该延迟以后发生。若是省略该参数,delay取默认值0。实际的延迟时间可能会比 delay 值长,缘由请查看Reasons for delays longer than specified。param1, ..., paramN
可选附加参数,一旦定时器到期,它们会做为参数传递给function
或 执行字符串(setTimeout参数中的code)
例子:
这个函数有两种用法,第一个参数能够是一个函数名称,也能够是字符串形式的代码。见下面两个例子:
setTimeout("location.reload()", 5000)//5秒以后执行代码, 刷新页面
setTimeout(reload, 4000); //4秒以后执行reload函数
若是这么写:setTimeout(location.reload(), 5000);效果是这样的:页面一直不停刷新,不会等5秒以后才刷新。缘由是:没有用字符串形式的第一个参数实际上就是当即执行此代码,即刷新页面,刷新页面后,又从新执行setTimeout()这个函数,而这个函数又一次当即执行location.reload(),如此循环....jquery深度解析JavaScript中的settimeout()和setInterval()函数: git
https://blog.csdn.net/chiuwingyan/article/details/80322289程序员
http://www.javashuo.com/article/p-udfbgzos-h.htmlgithub
关于JavaScript单线程的一些事正则表达式
小结一下:setTimeout()比setInterval()稳定,通常不使用setInterval()而是使用链式调用setTimeout()模拟setInterval()。缘由是JavaScript引擎是单线程的,主要分为主线程和事件队列。同步操做是在主线程上执行的,异步操做通常是首先放在事件队列中,等JavaScript主线程空闲了才会去事件队列中取出代码放入主线程中去执行。定时器函数属于异步事件,参数里设置的时间并非延迟多少秒去执行回调函数,这个时间表明的是延迟多少秒把回调函数放入到异步事件队列中,等到主线程空闲再被执行。这意味着至少要等这么多时间后才会执行回调函数。算法
一个例子:下面的代码会输出什么结果?
for (var i = 0; i < 10; i++) { setTimeout(function() { console.log(i); }, 100 * i); } 结果是打印出10个10!解释以下:setTimeout在若干毫秒后执行一个函数而且是在for循环结束后。for循环结束后,i的值为10.因此当函数被调用的时候,它会打印出10! 若是想打印出1~9,有两个方法,1,将var变成let关键词(ES6才开始支持)或者 2,使用当即执行函数捕捉每次循环的i的值。代码以下: for (var i = 0; i < 10; i++) { (function(j){ setTimeout(function () { console.log(j); }, j * 10); })(i); }
setInterval()函数的问题:假如设置了一个每隔100ms执行一次的定时器,第一次执行到该定时器时,会在100ms以后将回调函数加入到事件队列中,再过100ms又会将这个回调函数加入到事件队列中,而若是主线程在此期间一直没有空闲,那么事件队列中的回调函数就一直不会被拿到主线程中取执行。可能出现的状况就是主线程空闲的时候会一次性将这些回调函数同时执行而没有任什么时候间间隔。JavaScript引擎对此的处理办法是:当使用setInterval()定时器时,只有当事件队列中没有该定时器的任何实例时,才会将定时器中的回调函数加入到事件队列中。 这确保了最小的时间间隔,可是引起的另外一个问题是可能 有些间隔 被跳过了。若是功能需求是每一个定时器函数都必须执行,那么就不能知足需求了。因此通常都使用递归调用settimeout()定时器模拟setInterval()的效果。不会出现上面的两个问题。
3, html标签里写事件 传 值
<select name="type" onchange="show_sub(this.options[this.options.selectedIndex].value)"> <option value="0">请选择主菜名</option> <option value="1">白菜</option> <option value="2">萝卜</option> </select> js代码比较简单 <script> function show_sub(v){ alert(v); } </script> 最重要的知识点是获在select onchange时获取option的value值: this.options[this.options.selectedIndex].value
4,JS中的"0" 是true仍是false
if ('0') alert("'0' is true");
if ('0' == false) alert("'0' is false");
结果是,两次都 alert 了!那么 '0' 究竟是 true 仍是 false 呢?
答案是:在js作比较的时候,有这样的三条规则:
- 若是比较的二者中有boolean,会把 boolean 先转换为对应的 number,即 0 和 1(false是0,1是true)
- 若是比较的双方中有一方为number一方为string,会把string转换为数字
- 把string直接转换为boolean的时候,空字符串‘’转换为 false,除此外的一切字符串转换为 true
5,浏览器兼容的enter事件
<input type="text" id="text"> <script> document.getElementById("text").onkeypress = function(e) { e = e || window.event; key = e.keyCode || e.which || e.charCode; alert("按键码: " + key + " 字符: " + String.fromCharCode(key));
if (key == 13) {enter事件} };
6,JavaScript当即执行某个函数 深度思考 https://www.tangshuang.net/2020.html
几种方式当即执行函数 在javascript中定义一个函数,而且当即去执行它。(这个状况虽然看上去很疯狂,可是实际上必定会用到,由于函数一旦执行完,内部的局部变量会被释放,内存也释放出来。)咱们可能第一种想到的方法是: // 第一种 function a() {} a(); 没错,这个太简单不过了。 固然,还有另一种相对高深的办法: window.onload = function() {} 这段代码表示在网页加载完以后当即执行function中的代码,但这里面隐含了另一层意思,也就是能够把函数赋值给变量,使变量成为一个其余语言意义上的类。 // 第二种 var a = function(){}a(); 不过这也给了咱们另一个思路: function fun() {} var a = fun(); a(); 给咱们留下一个思考: function(){}; // javascript语句中以function开始没有实际的效果 一旦某条语句以function开始,这条语句没办法赋值给某个变量去执行它(说到这里,函数名能够能够理解为一个被赋值为某个函数的变量而已)。 下面是真相的时候: function a() {} a(); 若是函数名是一个被赋值的变量(也就是a),那么为什么不将其实际的值替换掉变量名呢(也就是把a()替换为function()())?因而,上面这段代码变为: function(){}(); // 前面加粗部分表明a 可是在前面已经提到了,function开始的语句没有实际的效果,所以,上面这个语句不会有实际效果。不只如此,这句代码还会抛出错误提示:SyntaxError: Unexpected token。 此处括号的正确理解 形成上述这个异常的缘由是,javascript对语句的结束并非以;做为标识,在这种普通状况下,}被做为语句结束的标识,所以,上述语句被解释为: function(){};(); 所以在执行()时,会抛出表达式错误。而若是咱们执行: function(){};(1); 则不会出错。缘由在于:语法正确。 我理解的(),在javascript中有两种:一种是肯定优先级,另外一种是分组。固然,在声明函数和函数使用的时候也会用到(),但这是一种语法,而不是运算。肯定优先级就是括号内的表达式先于括号外的表达式运算,例如: 1+(2*5)和(1+2)*5或(1+2)*(2+3) 而分组通常是在正则表达式中使用的概念,例如: /<(.*)ok(this) is myhouse(.*)>/ 在进行匹配的时候,上面的小括号将匹配结果分为三组进行返回,在替换的时候,能够对每一个组分别进行替换。所以,分组的概念,应该和本文没有关系。所以,本文中的(),只有两种理解,一种是运算符,一种是语法。 在上面的代码中(1);中的();很明显是一个运算符,括号内必须有表达式,不然就是语法错误。 咱们在回到上面的代码,若是咱们给function加上()会怎样? (function(){}); 恭喜你,你的函数初始化,虽然从结果上并无什么卵用,并且和直接function(){}也没有什么不一样,只不过是把function(){}提升了运算的优先级而已。 但是,当咱们执行下面的代码的时候,状况就大不相同了: (function(){})(); 代码是从左往右执行的,就像a() || b();同样若是a()为真,就不执行b()了。一样的道理,上面的代码中,红色部分做为一个表达式,执行完毕,表明着一个函数已经初始化完毕,若是咱们回到:function(){}();,也就是前文抛出错误的那个语句你就会发现,神奇的事情发生了,红色部分俨然就是咱们要的a,因此整个语句合起来也就是:a();,就这样,函数被执行了。 在这条代码中,第二个()再也不是运算符,而是函数的括号。而第一个(),则是一个运算符,提升了内部function的运算优先级,内部被优先执行,获得结果后,与第二个()构成函数语法,执行了函数。 咱们再回头来看()运算符的做用,来看一下下面这个代码: ()(); 这是一个神奇的代码,世界上不会有任何程序员这样去用,固然,它也会报错。可是咱们如何正确去理解这种状况呢?世界上是否存在下面这种javascript代码: (a+b)(c+d); 历来没有见过。若是世界上存在一种运算,就是没有任何运算,那么上面是成立的,可是,若是这种假设不成立的话,上面的代码就是错误的。咱们历来没有见过(1+2)(3+4),虽然咱们小学的时候写过这样的算式,可是在代码中是不存在的。 所以,咱们换一个思惟,不要只把它当作运算,而是运算和函数的结合呢?在你的浏览器中运行下面这段代码试试: (1+2)(3+4);// TypeError: (1 + 2) is not a function 提示的不是语法错误,而是数据类型错误,第二个括号 前面的不是一个函数。也就是说,第二个括号前面的,若是是函数类型,就正确了!那么世界上有没有一种算法,使运算后返回值为函数呢?好比 fun1+fun2=fun3?好像我还历来没有遇到过,所以,想在第一个括号中构建一种运算使该代码成立,还须要高高手来实现。惟一的解决办法,就是在 第一个括号中委以函数,也就是(function(){})(3+4),而3+4不过仅仅是做为前面这个函数的参数予以运行。 匿名函数的当即执行 当你觉得挖到宝藏的时候,下面的解释或许让你再一次开了脑洞。咱们提到function开头的语句虽然初始化函数,可是函数并不被执行,其运行效果至关于什么也没发生。 为了提交它的优先级,咱们再用一次()吧: (function(){}()); 此次,咱们直接把函数表达式和后面的()放在一个()里面,这下子奇迹也发生了,空号内部是一个表达式,表达式的意思就是}不表明结束,因此咱们前文提到的}表示语句结束的论断不起做用了。()内部必须运算完成,才能结束此次表达式运算,因此上面代码中的红色部分又再次先运算了,运算完又和()组成了a(),因而,函数又执行了。 OK,咱们如今终于get到了终点:表达式必须运行完成,才会结束表达式。这简直就是天同样的玄机,紧紧记住表达式这个概念以后,咱们再来看下面的几个代码: !function(){}(); +function(){}(); -function(){}(); ~function(){}(); …… 没错,上面的!+-~,所有表明表达式,!表示非,~表示按位非。你能够想出所有的表达式符号(固然必须得考虑运行是否合法,好比/0就不合法,分母不能为0),从而实现上面的这个效果。 因而,咱们看到几乎全部的插件,都会用上面的其中一种方式来定义整个代码。 正是由于这个缘由,上面的全部代码,均可以让function(){}内部的代码当即执行。 遗留问题:第二个括号内的参数 在多数插件中,咱们能够看到以下的代码: !function(){}(jQuery); 基本上咱们都看懂了,可是第二个括号内有个jQuery表明什么意思呢? 你想一下下面这个用法: function a(var) {} a(1); 而后把第二行的a替换为function(var){},结果就变成了function(var){}(1); 没错,第二个括号内的值,是本来函数的特定参数。因此,上面那个jQuery的,咱们能够将它还原为: var fun = function(a) {} fun(jQuery); 就是这样了。可是,jQuery是什么呢?是一个对象啊!因此下面的代码就来了: !function($){ // 在function中,$实际上就是jQuery,因此用$尽情玩耍吧。 }(jQuery); 难道你觉得到此就结束了吗?不,看看下面的代码: !function(fun){}(function($){}); 什么鬼?你觉得我想表达什么?其实,这是不少插件中的一种写法,用以兼容不一样的加载模式(CommonJS、CMD、CMD),具体是这样的: !function(fun){ "use strict"; if(typeof define === 'function' && define.amd) { define(['jquery'], fun) } else { fun((typeof(jQuery) != 'undefined') ? jQuery : window.Zepto) } }(function($){ "use strict"; // 真正的插件代码都在这里 }); 这是一个双重传值的过程。第一重,第一个function(fun)中的fun是第二个function($),所以,在第一个function中的代码中fun($)和第二个function($)是等效的。第二重,第二个function($)中的$参数,是在第一个函数中进行传递过来的,第一个函数中,define(['jquery'],fun)和fun(jQeury)实际上在执行第二个函数,既然如此,真正的插件代码就应该在第二个函数中去写,第一个函数仅仅是经过多个判断,返回正确的调用模式而已。 实际上,了解了上述以后,本文的题目是为了当即执行某个函数,在实践中,还有不少作法能够在申请一个函数后当即执行它,好比: (function(){}).call(); 好了,这个问题就阐述到这里,可能也有一些不足的地方,欢迎你们指正。
7, JavaScript中的数组或对象 循环方法总结
1, 普通for循环 [数组,对象] //注意,将长度赋给一个变量,防止每次循环都要算一下长度。for (var i=0, len=arr.length; i < len; i++){}
2, for in 【数组,对象】//注意 for (var i in arr){} 中的i类型始终是string类型的,有时候须要int类型时要注意。
3, array.forEach(function(value, index){})【数组】// ES5推出的数组自带的循环,主要功能是遍历数组,实际性能比for 还弱。forEach这种方法也有一个小缺陷:你不能使用break语句中断循环,也不能使用return语句返回到外层函数
4,array.map(functino(value, index){})【数组】//也是ES5推出的,支持return 语句
5,for ... of 【数组】//ES6新增功能
6,jQuery的静态方法$.each(array/obj, function(index, value){})
7, underScoreJS中的方法:_.each(array/obj, function(index, value){})
8, 关于 jQuery的 tmpl 模板插件的说明
var html = $("#menu_tmpl").tmpl({data:retval.data}).outerHTML();
$("#phpNav").html(html);
使用tmpl()方法时,必定要用对象模式,不容易出问题! (自己这里的参数只能是对象格式,而不能是数组)
5
5
5
5
5
5
5
5