一 、jq的事件代理
<ul id='demo'>
<li>费德勒</li>
<li>纳达尔</li>
<li>桑普拉斯</li>
</ul>
给里边的li增加点击事件我首先想到的,就是:
$('#demo li').on('click',function(){})
静态的肯定没问题,但是ul里边的li是后台异步请求过来,动态生成的,就会出现问题,因为有可能这句代码执行的时候,li还没创建。就失效咯。一计不成,又生一技。
$('#demo').on('click','li',function(){})
因为ul#demo肯定是一直存在的。所以这样能有效。
以上是通过jq实现的事件代理。原生js也有,addEventListener和attachEvent,它不支持‘li’这样的选择器。但是,可以在e.target里边实现
var UL=document.getElementsByTagName('ul')[0];
UL.addEventListener('click',function(e){
if(e.target.nodeName=='LI'){
console.log(this);
}
})
二、css3 的calc函数的妙用
去了五十四所,拿到的是人家写好的框架,发现里边都是height:calc(100% - 50px);哎呦,好好奇,竟然真的能用。又学了一招,这样用它来实现容器撑起整个屏幕就不用麻烦js了,很厉害。
三、数组的复制(json)
以前项目中用到过拷贝json,当时是ng的项目,所以一句angular.copy搞定。
五十四所这个项目,jq的,写java的大哥当时想拷贝一个数组,肯定不能直接“=”赋值咯,大哥是遍历数组中元素实现的。(当时我不会,被大哥鄙视了,我想不能把,肯定有优雅的方法)
后来,发现,用空数组concat链接,就能实现。
var a=['this','is','a demo']
var b=[].concat(a);
a[0]='that';
console.log(b)//this is a demo;
网上还有种slice(0)的方法,也是很nice。
“浅拷贝”见链接,通过concat和slice(0)的方法实现的叫“深拷贝”
除了数组,json用jq怎么拷贝呢 ? 用jq的extend(根据第一个参数true,false来判断是否是浅拷贝和深拷贝)
var a={id:001,text:'first'};
var b=$.extend({},a);
a.id=002;
console.log(b.id)//001
现在有ES6了,可以抛开jq,用原生的Object.assign()(浅拷贝)
var a={id:001,text:'first'};
var b=Object.assign({},a);
a.id=002;
console.log(b.id)//001
四、变量提升
var getName=function(){alert(3);}
function getName(){alert(4)}
getName();//3
执行顺序:1定义了个变量getName,2定义了个函数getname,3变量赋值,弹出3
五、js基本变量类型和typeof
js的基本数据类型有:Undefined,Null,Boolean,Number,String,Object.(一家之言)
typeof()的结果有六种可能:”undefined”,”boolean”,”number”,”string”,”object”,”function”,并没有array和null,全是字符串。
那么怎么判断一个变量是个数组呢?
用typeof是不行的,最快速的,是用instanceof和constructor
var arr = [1,2,3,1];
arr instanceof Array; // true
arr.construntor==Array//true
但是这样的跨页面,或者跨js文件的还是会出一些问题,搜了下得出终极奥义
var arr = [];
Object.prototype.toString.call(arr)==="[object Array]" //true
var a=function(){alert(1)}
Object.prototype.toString.call(a)==="[object Function]"//true
经观察可得,这Object.prototype.toString会得到一个【obejct XX】的一个值。给出大神解析。
还有一个偷懒的模式,如果项目是IE9以上,也就是支持ECMA5标准的浏览器可以用Array.isArray()方法
var ar = [1,4];
Array.isArray(ar)//true
六、数组去重
这是我去面试中遇到的一个笔试题,当时我刚看es6,就用了新对象Set实现的(虽然被刷了)
function cutDup(arr){
if(arr.constructor==Array){
var s=new Set();
arr.map(index=>s.add(index));
return Array.from(s);
}
}
目前的浏览器IE9+已经支持了,但是被群里朋友喷了,给出的方法是
function unique(arr){
arr.sort();//先进行排序,从小到大
var re = [arr[0]];//定义一个新数组赋值,并进行循环,如果它和前一个值不同就push进数组新数组
for (var i = 1; i < arr.length; i++) {
if (arr[i] !== re[re.length - 1]) {
re.push(arr[i]);
}
}
return re;//返回新数组
}
效率要快一些,不明就里,先记录下来
七、转换为字符串
要把一个值转换为字符串有两种方式,第一种是使用几乎每个值都有的toString()方法,这个方法唯一要做的就是返回相应值得字符串表现。
var age=11;
var ageAsString=age.toString(); //字符串"11"
var found=true;
var foundAsString=found.toString(); //字符串"true"
数值,布尔值,对象和字符串(没错,字符串也有一个toString方法,返回的是字符串的一个副本)都有toString()方法。但是null和undefined没有。toString()参数是数值的基数。默认以十进制返回。
var num=10;
alert(num.toString()); //“10”
alert(num.toString(2)); //“1010”
alert(num.toString(8)); //“12”
alert(num.toString(10)); //“10”
alert(num.toString(16)); //“a”
在不知道要转换的是不是null和undefined的情况下,还可以使用String(),这个函数能够将任何类型转换为字符串。规则如下
- 如果值有toString()方法,则调用toString()方法(不带参数)并返回相应结果
- 如果是null,则返回“null”
- 如果是undefined,则返回“undefined”
八、js小数计算bug
js计算小数算是个人尽皆知的bug了
var result=133.33-93.33;
console.loe(result) //40.00000000000014
console.log(32915.63*100)//3291562.9999999995
所以,你计算小数,可以先转换为整数。我们是四舍五入的,所以,通过取整函数toFixed()来解决。
九、array的fill和unshift方法
在React的Tutorial中碰到了数组的fill方法,感觉好好用,可以少用一个for循环。原来这是es6的方法
从start到end赋value值。
arr.fill(value, start, end)
//example
[1, 2, 3].fill(4); // [4, 4, 4]
[1, 2, 3].fill(4, 1); // [1, 4, 4]
[1, 2, 3].fill(4, 1, 2); // [1, 4, 3]
[1, 2, 3].fill(4, 1, 1); // [1, 2, 3]
[1, 2, 3].fill(4, -3, -2); // [4, 2, 3]
[1, 2, 3].fill(4, NaN, NaN); // [1, 2, 3]
Array(3).fill(4); // [4, 4, 4]
[].fill.call({ length: 3 }, 4); // {0: 4, 1: 4, 2: 4, length: 3}
第一个参数是fill的值,第二个是开始的值,默认为0,第三个是结束的值,默认是数组的长度。
而unshift方法则是跟push反方向,push是从后往前添加数据,unshift是从前往后添加数据。
十、undefined vs. null
首先undefined和null在if语句中,都会被自动转为false;undefined==null 是真值。undefined===true是假值
1. typeof()返回值不同
typeof(null) //'object'
typeof(undefined) //'undefined'
2.转为数组时,null为0,undefined为NaN
null+0 //0
undefined+0 //NaN
3.null 表示一个值被定义了,定义为“空值”;undefined 表示根本不存在定义。根据此定义
- 变量被声明了,但没有赋值时,就等于undefined。
- 调用函数时,应该提供的参数没有提供,该参数等于undefined。
- 对象没有赋值的属性,该属性的值为undefined。
- 函数没有返回值时,默认返回undefined。
var i;
i // undefined
function f(x){console.log(x)}
f() // undefined
var o = new Object();
o.p // undefined
var x = f();
x // undefined
(盗自阮一峰博客,已加深印象)
null == document.getElementById('notExistElement')
从页面上取一个不存在的元素为null
4.当把object里边的某个属性值给清除的时候有两种方法。
- object[key]=null;
- delete object[key]
第一种方法,使用for in遍历的时候依然会遍历到对应key的属性值,只不过为null、第二种方法,就不会遍历到key的属性值了。此时他的object[key]为undefined。
十一、ng的http.post vs. jq的$.post
项目中一直用的angular自带的http.post来请求,微信端轻量版没引入ng,用原生的js或者jq都不能正确返回结果。查了下ng的api,$http的content-type与众不同。
angular是appliction/json,jquery是application/x-www-form-urlencoded,原生js是text/plain,根据需要得自己设置。
十二、闭包使用不当会带来内存泄漏
记录一个好文http://www.cnblogs.com/developer-ios/p/6014335.html
十三、JS二分查找
其实在js里谈二分查找挺鸡肋的,因为其首先要求必须按关键字大小有序排列,而且,js的数组中还有indexof这种强劲的方法。但是这种思想还是值得学习。
可以这样理解,因为是有序数列,所以要寻找的值可以先跟中点(较大值+较小值/2的大小)比较,如果,要寻找的值大于中点,可以将中点赋值给较小值,如果要寻找的值小于中点,可以将中点赋值给较大值,在做判断,直到,中间值等于要寻找的值,则此中点就是要寻找值的位置。
http://www.cnblogs.com/zuojiayi/p/6229902.html
十四、数组的sort方法排序
sort是将数组中的每一项经过转为字符后排序的,就会出现5在11之前的情况。后发现它可以传入参数,参数为一个函数,通过其函数的判断来进行排序。
var arr=new Array(11,8,7,6);
arr.sort(function(a,b){
return b-a;
});
//此时arr为[6,7,8,11]
十五、currentTarget vs. target
<div class="recharge recharge1 ">
<ul>
<li>
<span class="title">1、如何注册?</span>
<p class="subtitle uhide">A、网页端:登录平方贷官网,点击网页右上角【注册】。</p>
</li>
<li>
<span class="title">2、注册的时候收不到短信怎么办?</span>
<p class="subtitle uhide">A、请确认手机是否安装短信拦截或过滤软件;</p>
</li>
</ul>
</div>
<script>
var wrap=document.getElementsByClassName('recharge')[0];
var lis=wrap.getElementsByTagName('li');
for(var i=0;i<lis.length;i++){
(function(i){
lis[i].addEventListener('click',function(e){
console.log(e.currentTarget,':',e.target,':',this)
var tagP=this.getElementsByTagName('p')[0];
tagP.className=tagP.className.replace('uhide','')
})
})(i)
}
</script>
运行代码,如果捕获层上有多个节点,那么在单击时,得到的 currentTarget 是设定的捕获层节点,而 target 则是实际被单击的节点,实际被单击的节点通常是位于currentTarget 之内的子节点或是其本身,这就是它们的差别。
也就是这里的currentTarget一直都是li,而target可能是span,p和li。这里的currentTarget和this一定是同一个。
十六、运算符优先级
今天被同事问了个问题:“ !submitArr[i].receipt.actualAmountTotal<0 你是不是想写成这样是 !(submitArr[i].receipt.actualAmountTotal<0 )“,我想这不一样么,后来发现我错了。
javascript的运算符优先级看了才发现,取非(!)的优先级是高于大于(>)的,所以会先执行!submitArr[i].receipt.actualAmountTotal 就会得到false(这个值不为0),而false<0 ,一直是false。