js爬坑备忘录

一 、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 表示根本不存在定义。根据此定义

  1. 变量被声明了,但没有赋值时,就等于undefined。
  2. 调用函数时,应该提供的参数没有提供,该参数等于undefined。
  3. 对象没有赋值的属性,该属性的值为undefined。
  4. 函数没有返回值时,默认返回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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值