JS-core第一周学习总结 4.6-4.8

141 阅读11分钟

JS-core第一周学习总结 4.6-4.8

一.数字类型转换

(一)强制类型转换

1.转字符串:2种

  A. x.toString(); //undefined和null不能使用,不能调用方法
  B.String(x); // 万能的,但是没什么用,千万不要手动使用,完全相当于隐式转换,还不如+""
  都没什么用,页面上的一切数据都是字符串

2.转数字:3种

  A.parseInt(str/num); //专门用于将字符串转为整数的
     执行原理:从左往右依次读取每个字符,碰到非字符则停止,一来就不认识则为NaN
     ex:parseInt("3.5px"); //3
        parseInt("px35");  //NaN
        parseInt(ture);//NaN            
  B.parseFloat(str);//专门用于将字符串转为浮点数的
      执行原理:几乎和parseInt一致,但是认识第一个小数点
      ex:parseFloat("3.5px");//3.5
  C.Number(x);//万能的,但是没什么用,千万不要手动使用,完全相当于隐式转换,还不如-0 *1 /1

3.转布尔:Boolean(x); //万能的,但是没什么用,千万不要手动使用,完全相当于隐式转换,还不如!!x

   A.以下六个会转为false:
       0,"",undefined,null,NaN,false
       其余的全部都为true
    B.注意:一定要记住哪些人会会为false,有用!在循环或分支的条件判断中,不管你写的是什么,都会悄悄的隐式转为布尔值。
    if(Boolean(条件)){
    }
    while(Boolean(循环条件)){
    }

(二)隐式类型转换

   都出现在运算符之中,哪怕我不用console.log,心里也知道最后的结果是什么
   

二.运算符和表达式

(一)算术运算:+-/%

   1.隐式转换:默认,转为数字再运算
   2.特殊:
           A.+运算,只要碰上一个字符串,则变为拼接
           B.-*/%,纯数字组成的字符串页可以转为数字,但是非纯数字字符串则为NaN
              NaN参与任何算术运算结果都为NaN
 

(二)比较运算:> < >= <= == != === !==

    1.结果:布尔值
    2.隐式转换:默认,左右两边都会悄悄的转换数字,再比较
    3.特殊:
        A.如果左右两边参与比较的都是字符串,则是按位PK每个字符的十六进制的unicoade号(十进制ascii码);
         不需要记忆,但是要知道常识:
	      0-9<A-Z<a-z<汉字
	      汉字:记不了,太多了,20000+个以上,汉字一定比数字、英文大
	      百度搜索:中文字符集 Unicode 编码范围
	      汉字的第一个字:一(unicode:4e00,ASCII码:19968);
	      汉字的最后一个字:龥(unicode:9fa5,ASCII码:40869);
	     了解着玩的常识
         B.NaN参与任何比较运算结果都为false,甚至不认识自己,解决:
             !isNaN(x); //true->有效数字  false->NaN
         C.undefined==null;
           问题:==区分不开undefined和null,怎么才能区分开?
           全等:===,要求值和数据类型都要相同,换句话说,就是不再带有隐式转换的比较运算
                 !==,不带有隐式转换的不等比较

(三)逻辑运算符

隐式转换:悄悄的都变为布尔值,然后再综合比较
&&:全部条件都满足,结果为true
    只要一个条件不满足,则为false     
||:全部条件都不满足,结果为false
    只要一个条件满足,则为true
 !:颠倒布尔值
 
 特殊:用法
   短路逻辑:只要前一个条件已经可以得出最后结论,则后续条件不再执行:
      &&短路:如果前一个条件为true,则后一个操作才执行
              如果前一个条件为false,则后一个操作不执行
              简化简单的分支:if(条件){操作}
                语法:条件&&(操作);
                
                举例:曾经:if(total>=500){total*=0.8}
                      现在:total>=500&&(total*=0.8);
                特殊:简单的->操作只能有一句话
                建议:简单的操作可用&&短路代替,但是操作如果复杂了还是建议使用if结构
                
       ||短路:如果前一个条件为true,则后一个不看
               如果前一个条件为false,则后一个才看
               使用场景:两个值二选一 --后期做浏览器的兼容性问题的
               e=e||window.event; 见小案例,bom部分

(四)位运算:垃圾

      左移:m<<n,读作m左移了n位,相当于m*2的n次方
      右移:m>>n,读作m右移了n位,相当于m/2的n次方
      缺点:底数永远只能是2

(五)赋值运算:一句话执行了两个操作,先运算,再赋值

    += -= *= /= %= ++ --;
    何时使用:只要取出变量中的值,再做运算,之后还要保存回去时,就用它
    推荐:i+=1 或者i++;
    
    递增:i++;每次只能+1
    累加:i+=n;每次想加几,都可以
    
    笔试题:++分为++ii++
        1.单独使用时,没有参与别的表达式,放前放后都一样
        2.如果参与了别的表达式(和别的代码放在一起的):
             变量中的值其实都会+1
               ++1:返回的是递增后的新值
               i++:返回的是递增前的旧值

(六)三目运算:简化了if(){}else if(){}else if(){}else

    语法:
      1.条件?操作1:默认操作;
      2.条件1?操作1:条件2?操作2:默认操作;
    问题:
       1.只能简化简单的分支结构--三目操作也只能有一句话,其实以后你会发现很多if结果中操作恰巧只有一句话
       2.默认操作是不能省略的,哪怕条件都不满足,至少还要做一件事
    总结:
       if(){}                    ==    &&短路
       if(){}else                ==    三目
       if(){}else if(){}else     ==    三目

三.自定义function

 什么是函数:需要先定义好,可以反复调用的一个代码段
 何时使用:1.不希望打开页面立刻执行
          2.以后可以反复的使用
          3.希望绑定在页面元素上      

(一)如何使用

1.创建:2种

   A.【声明方式】创建函数:
       function 函数名(形参,...){
            函数体;
            return 返回值;
         }
    B.【直接量方式】创建函数
      var 函数名=function(形参,...){
             函数体:
             return 返回值;
          }

2.调用并且接住结果

  var 接住返回的结果=函数名(实参,...);
 
    //return的本意其实是退出函数,但如果return后面跟着一个数据
     顺便将数据返回到函数作用域的外部,但是return只负责返回,不负责保存
  //就算你省略return,默认也会return undefined;
 //具体要不要return,全看你需要不需要获得函数的结果
//往往前辈们提供的预定义函数底层都有一句return操作

(二)作用域:2种***

1.全局作用域:全局变量和全局函数

 特点:在页面的任何位置都可以使用

2.函数/局部作用域:局部变量和局部函数

特点:在当前函数调用时内部可用
导致变量的使用规则:优先使用自己,自己没有找全局,全局没有就报错
特殊:缺点:
  A.千万不要在函数中对未声明的变量直接赋值--导致全局污染,解决:尽量变量使用前都要记得先var一下
  B.局部可以用全局的,但是全局不能用到局部的--解决:看上面,搭配上return

3.声明提前:--笔试题

 在程序正式执行之前,将var声明的变量(轻)和function声明的函数(重),都会悄悄的集中定义在当前作用域的顶部,但是赋值留在原地
 
 声明方式创建的函数会完整的提前(第一种)
 直接量方式创建的函数不会完整的提前,只有变量部分会提前(第二种)
 
 何时使用:永远不会自己使用,垃圾,干扰我们的判断-只会在笔试中遇到
 
 只要你遵守以下规则:
     A.变量名和函数名尽量不要重复
     B.先创建后使用
     C.如果笔试时,遇到先使用后创建,多半都是在考你声明提前,先转换为我们认识的代码,再去判断

4.按值传递:两个变量之间进行赋值

  如果传递的是【原始类型】的值:
      修改一个变量,另一个变量是不会受到影响的,其实是复制了一个副本给对方
   如果传递的是【引用类型】的对象:
       修改一个变量,另一个变量就会受到影响了,两者使用的是同一个地域值(浅拷贝)
         
    

函数的考点:

1、创建函数的三种方式

2、简单说说你作用域

3、声明提前鄙视题

4、按值传递

5、重载

6、闭包

四.预定义全局函数

前辈们提前定义好的方法,我们程序员可以直接调用,在哪里都可以使用

(一)编码和解码:- 玩悄悄话,你编码,发到群里,其他人来解码

问题:url中不允许出现多字节字符,如果出现会乱码
	utf-8编码格式下,一个汉字就是3字节
解决:发送前,前端将多字节字符编码为单字节字符(数字、字母)
      发送后,后端将单字节字符解码为多字节原文

如何:
	编码:var code=encodeURIComponent(str);
	解码:var 原文=decodeURIComponent(code);
	其实这个东西在某次浏览器更新后,就当场淘汰了,浏览器自带此功能了

(二)isFinite(num);

判断num是不是无穷大:true->有效数字 false->无穷大
哪些会为false:NaN/Infinity/分母为0

(三)牛逼的:parseInt/parseFloat/isNaN

五.分支结构:根据条件选择部分代码执行:if分支 switch分支

   语法:
   switch(变量/表达式){
        case1:
        操作1;
        break;
        case2;
        操作2;
        break;
        default:
        默认操作;
     }
     特殊:
        1.case的比较不带隐式转换的
        2.问题:默认只要一个case满足后,会将后面所有的操作全部做完
          解决:break;
          建议:每一个case的操作后都跟上一个break
                有的地方可以不加break:
                     A.最后的一个操作default可以省略break
                     B.如果中间多个条件,做的操作是一样的,也不需要
         3.default可以省略,如果条件都不满足的话,什么事都不会做到
         
   面试题:if vs switch
           1.switch...case:缺点:必须要知道结果才能使用,不能做范围判断
                            优点:执行效率相对较高
           2.if...else:缺点:执行效率相对较低
                       优点:能做范围判断
        建议:代码优化,尽量将if...else换成switch...case或者三目或者短路

六/循环结构

(一)while循环 --不确定循环次数的时候

  while(循环条件){
     循环体;变量变化;
   }            

(二)do..while循环

    do{
      循环体;变量变化;
   }
   while(循环条件)
   
   笔试/面试中:whiledo...while的区别:
       只看第一次:如果第一次大家都满足,两者没有区别
                   如果第一次都不满足,while什么都不执行,do...while至少会执行一次

(三)for循环 --确定循环次数的时候

    for(循环变量;循环条件;变量的变化){
         循环体;
      }

(四)循环流程控制语句

  退出循环:break;//退出整个循环
           continue;//退出本次循环,根据需求判断自己还需不需要执行后续的循环
           后面可能还会学到 for in/ forEach/ for of各种循环

七.数组的基础

(一)基础概念:

什么是数组:在一个内存(变量)中保存了多个数据的一个集合结构
何时:只要存储多个相关的数据,都要用数组集中保存
为什么:一个好的数据结构,可以极大地提升我们程序员的开发效率

(二)创建:2种

   A.直接量:var arr=[值1,...];
   B.构造函数:var arr=new Array(值1,...);   -还有一个坑:var arr2=new Array(5);//创建了一个长度为5的空数组

(三)访问:数组名[下标]; --当前元素

  添加/修改:数组名[下标]=新值;
  特殊:读取元素,下标越界--返回undefined
        添加元素,下标越界--下标不连续,导致变成一个稀疏数组

(四)数组的三大不限制

  A.不限制长度
  B.不限制类型
  C.不限制下标越界

(五)数组唯一的属性:arr.length;获取到数组的长度

   三个固定套路
     A.末尾添加:arr[arr.length]=新值;
     B.获取倒数第n个:arr[arr.length-n]
     C.删除倒数n个:arr.length-=n

(六)遍历数组:对数组中每个元素执行相同或相似的操作

for(var i=0;i<arr.length;i++){
    arr[i]; //当前元素
 }

(七)如何释放一个引用类型

请你看清楚你的这个引用类型的数据有几个变量引用着,每个变量都要释放后,才能真正的释放干净
建议:我们的代码都要封装到一个函数中,函数中的变量会自动释放

(八)索引数组:下标都是数字组成的数组

关联(hash)数组:下标是可以自定义的
为什么:索引数组的下标没有具体的意义,不便于查找
如何使用:
   1.创建:2步
      A.先创建一个空数组:var arr=[];
      B.为数组添加自定义下标并且添加元素值:arr["自定义"]=新值;
   2.访问:arr["自定义"]
   3.强调:hash数组length永久生效,永远为0
      遍历hash数组:不能使用for循环,必须使用for in循环--专门用于遍历hash数组准备的方式,但是个人不爱称呼他叫做一个循环
      for(var i in arr){
         arr[i];
       }
       for in虽然不能定义从哪里开始,到哪里结束,专门用于遍历hash数组的
       个人推荐:索引数组依然使用for循环,hash数组再用for in
    4.hash数组的原理:
         hash算法:将字符串,计算出一个尽量不重复的数字(地址值)
                字符串内容相同,则计算出的数字也一定是相同的
          添加元素:将自定义下标交给hash算法,得到一个数字(地址值),把我的元素保存到了这个地址值之中
          读取元素:将指定的自定义下标交给hash算法,得到一个和添加时完全相同的数字(地址值),根据地址值找到之前保存的东西
    5.js里面一切的东西都是对象:除了undefined和null,【一切对象的底层都是hash数组】

八.Array的API

其实就是函数,只不过这些函数是前辈们提前定义好的,我们程序员可以直接使用的,这些方法只有数组可用

(一) var str=arr.join

  *arr.toString():
   var str=arr.join("自定义连接符");
   
   固定套路:
     1.笔试题:将数组中的内容拼接在一起形成一句话/单词;
               无缝拼接:var str=arr.join("");
     2.将数组的元素拼接成DOM页面元素
         //数据
           var arr==["-请选择-","北京","南京","西京","东京","重庆"];
         //转为字符串,并且拼接好了标签
           var str="<option>"+arr.join("</option><option>")+"</option>";
         //渲染到DOM树上
           sel.innerHTML=str;

(二)数组拼接:添加新元素的新方式

根据你传入的实参全部拼接到arr的末尾
var newArr=arr.concat(新值1,...);
特殊:
  1.不修改原数组,只会返回一个新数组
  2.concat支持传入数组参数,悄悄的将你传入的数组打散为单个元素后在拼接

(三)截取子数组:

 根据你传入的开始下标截取到结束下标
 var subArr=arr.slice(starti,endi+1);
 特殊:
    1.不修改原数组,只会返回一个新数组
    2.含头不含尾
    3.endi可以省略不写,会从starti位置一直截取到末尾
    4.其实两个实参都可以省略不写:从头截到尾
      深拷贝:和以前的按值传递的浅拷贝不一样,是复制了一个副本给对方,两者互不影响了
      

这条线以上的API都不会修改原数组

这条线以下的API都会修改原数组

(四)删除、插入、替换

 1.删除:var dels=arr.splice(starti,n);//n代表删除的个数
       特殊:其实splice也有返回值,返回的是你删除的元素组成的一个新数组
 2.插入:arr.splice(starti,0,值1,...);
        特殊:A.插入新的元素会将原有元素和后续元素都推到后面去
              B.其实插入也有返回值,只不过没有删除任何元素则为一个空数组
              C.千万不要直接插入一个数组,会变成一个部分二维数组
 3.替换:arr.splice(starti,n,值1,...);
         特殊:删除的元素个数不必和插入的元素个数一致

(五)翻转数组:arr.reverse(); --以后不会使用