js中遇到的问题

1.逻辑与"&&",逻辑或"||"

先看代码
1)逻辑与

 var a = 10;
 var b = 0;
 var c = b && a++;
 var d = a++ && b;
 console.log(a);  
 console.log(b);  
 console.log(c);  
 console.log(d);  

在逻辑与"&&"中,遵从从左到右的运算规则,先看第一个操作数的值是否能够决定运算的结果,如果是0的话,就会结束运算,在c的运算中,结果c=0;a的值并没有运算,还是10;如果b的值是5,那么就会看第二个操作数,运算结果就由第二个操作数所决定,所以运算结果是c的值是10,而a 的值变成了11。
2)逻辑或

    var a = 0;
    var b = 2;
    var c = a || b++;
    console.log(a);  // 0
    console.log(b);  // 3
    console.log(c);  // 2

在逻辑或中,第一个操作数并不能决定整个式子的运算结果,当a的值为0的时候就会看第二个操作数,只要有一个操作数是true,那么整个式子的运算结果就是真的。所以式子中的c的值是2,b的值自增1,为3.
注意
像0、-0、null、undefined、"",他们在经过隐式类型转化后都会转为false。

//来看一个例子
let x = 1 || 2 && 3 || 4 && 0 || 5;

逻辑与的优先级大于逻辑或的优先级,所以在运算的时候先算逻辑与,剩下来的都是或运算,先看第一个操作数,因为第一个数都已经决定了值,就不用往下运算了。所以x的值是1.

2.同步与异步

在我们平常写的代码中,95%的代码都是同步的,代码从上到下顺序执行,但也有异步的,目前经常遇见的有三种,像事件的绑定、计时器、ajax,这些都是异步的。代码在读取的时候会跳过异步的代码。

//先来看这个例子
<button id="btn1">按钮1</button>
<button id="btn2">按钮2</button>
<button id="btn3">按钮3</button>
<script>
        let btns=document.getElementsByTagName("button");
        var a=document.getElementById("btn1");
         for(var i=0;i<btns.length;i++){
            btns[i].onclick=function(){
                alert("这是第"+i+"个按钮");
            }
        }
</script>        
// 问题:异步提交是不按顺序执行的,所以代码执行完i的值是3,
// 不会因为按按钮而产生变化,只会弹出第三个按钮,

这里列举了三种解决办法

//第一种,使用闭包
 for(var i=0;i<btns.length;i++){
            btns[i].onclick=(function(i){
                   return function f(){
                   alert("这是第"+i+"个按钮");
                  }
            })(i);
        }

第一种使用闭包,既然他会跳过不执行,那么我们就想办法在每次循环让里面的先执行,并且把每次循环的i值保存起来,还有绑定的事件发生;函数可以使用括号包裹,使用IIFE,又因为里面的代码段会引用外面函数的变量,外面函数就保存循环的i值,里面的函数可以引用外面函数的局部变量。并返回地址给onclick,这样就可以使每次点击中的i值为所想的值。

//第二种方法,使用属性
for(var i=0;i<btns.length;i++){
            btns[i].index=i;
            btns[i].onclick=function(){
                alert("这是第"+this.index+"个按钮");
            }
        }

第二种方法使用变量,给每个按钮设置一个属性,每次循环获取的i值保存在属性里面,每次使用的时候就调用这个属性,就可以那到i值,但是直接使用属性会报错,因为函数中并没有这个属性,这里可以使用this关键字,这里的this指向事件源btns,就可以调用属性了。

//第三种方法,使用let加大括号
for(let i=0;i<btns.length;i++){
            btns[i].onclick=function(){
                alert("这是第"+i+"个按钮");
            }
        }

第三种方法使用let加括号,形成块级作用域。每次循环都会形成一个EC,所以i值就成了局部变量,并且不会和其他的EC中的i值发生混淆。

3.数组查重和数组重复统计

//定义个数组
var a=[1,2,1,2,3,5,5,8,8,4,4];
//再定义一个数组,用来存储查重后的数据
var b=[];
//1)定义一个对象,用来判断是否有重复的数据
//2)还用来输出数据的重复次数
var c={};
//使用for循环进行遍历a数组
for(var i=0;i<a.length;i++){
    //定义c对象的属性
    var t=a[i];
    //判断c中是否有a[i]这个属性,如果有跳过,没有
    //就把他添加到新的数组中
    if(c[t]){ //或者用(c.hasOwnProperty(t))
        //同相同的数据,自身加一
        c[t]+=1;
    }else{
        //添加值
        b.push(a[i]);
        //给对象遍历过的属性赋值,下次对象中就会有这个
        //属性,因为要统计重复数量,这里赋值1.
        c[t]=1;  
    }  
}
//因为对象中的属性是数字,不能用打点来调用
//只能用[]

4.typeof的不足之处

不足:
当用typeof判断变量的数据类型的时候,如果变量是基本数据类型
那么用typeof判断是ok的,如果是函数function那么也是可以的,但
他判断其他类型的时候就会都报成object的类型,像  math、Array、
RegExp()正则表达式;
改进:
我们可以使用Object.prototype.toString.call()方法来判断数据类型
这里是引用了Object.prototype中的toString方法,通过call()来让他的
this指向call()括号里面的对象,并且让toString方法运行。
<script>
    // 利用Object.prototype.toString.call可以非常精确地检测一个数据的数据类型
    // toString()    Object.prototype上面的方法
    console.log(Object.prototype.toString.call(1));
    // 此时会把1瞬间包装成对象
    console.log(Object.prototype.toString.call("hello")); 
    // 此时"hello"也瞬间包装成对象了
    console.log(Object.prototype.toString.call(true))
    var a;
    console.log(Object.prototype.toString.call(a))
    // call  1)改变toString中的this的指向   指向了{}
    //       2)让toString执行
    console.log(Object.prototype.toString.call({}))
    console.log(Object.prototype.toString.call([]))
    function f(){}
    console.log(Object.prototype.toString.call(f))
    let d = new Date()
    console.log(Object.prototype.toString.call(d))
    let r = new RegExp();
    console.log(Object.prototype.toString.call(r))
</script>

5.new是个运算符,new的作用

//创建一个空对象
  //this指向这个空对象
  //返回这个空对象
  注意:
  function F(){
  }
  var a=new F();
  var b=new F;
  //在实例化对象的时候,后面的括号可以不写,他的区别是
  //能否传参的问题;

6.关于This的结论

这里只是把结论罗列了出来,自己可以尝试推导

1)如果this出现在普通的函数中,this表示window,如果你通过window打点调用一个函数,这个函数中的this也是window。

2)事件绑定,事件处理程序,事件发生时,浏览器帮我们调用这个函数,此函数中的this表示事件源

3)在一个对象中,如果有方法(函数),如果通过这个对象调用方法,方法中的this表示这个对象

4)在IIFE中,this表示window

5)前四点都是在非严格模式下,在严格模式下,调用一个普通函数,this表示und,IIFE中的this也表示und

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值