学习JS第一周总结

160 阅读12分钟

JS的基本概念

js是一种弱类型的语言,变量保存的数据可以是随意的,数据类型由数据来执行决定。
例如:1 -- 代表Number 数字1;"1" -- 代表String 字符串
js的特点:可以使用任何编辑工具编写js代码,可以做一切css完成不了的效果,和服务器端进行沟通。
如何使用:使用方式有两种,
    ①直接在HTML上写一个script标签,写在body里面,一般放在body的最后,body结束标签的上面。
    ②创建一个xx.js文件,在其中写入一个js代码,最后在HTML里面引入。

输出方式

在控制台上输出日志:console.log();
在页面上输出日志:document.write();这一方式有一个缺点,如果绑定了点击事件,会将页面上的所有内容全部替换掉
在浏览器的警告框输出日志:alert; //会卡住整个页面。
注意:数字颜色:蓝色;字符串颜色:黑色

变量和常量

变量:创建后,值可以再次修改
语法:var 变量名 = 值;
何时使用:以后会反复用到数据,都要提前保存在一个变量中,以后使用变量名相当于使用的是一个变量的值
特殊:① 变量名不是随意的,不能以数字开头。
     ② 命名要见名知意,使用驼峰命名法或者下划线取法
     ③ 变量名不能是关键字,比如:var this 
     ④ 变量可以只创建,不赋值,默认值为undefined
     ⑤ 如果多个变量连续创建,可以多个赋值。比如:
       var name = "Lucy", age = 16, gender = "man";
常量:创建后,值不允许再次修改的
    语法:const 常量名 = 值;

数据类型有哪些?分为两大类

有原始类型和引用类型两大类
①原始类型:5个
 <1>.Number - 数字,取值有无数个,而且数字就是直接写,不用加任何东西(控制台输出一个蓝色数字)
 <2>.String - 字符串,取值有无数个,但必须加上""'';控制台输出为蓝色
 <3>.Boolean - 布尔,取值有两个,truefalse,一般用于判断条件
 <4>.NUll - 空,取值只有一个,就是null,唯一的作用就是用于释放我们的内存(变量)空间的,节约内存,但是每次需要我们手动释放。
 <5>.undefined - 未定义的,取值只有一个,就是undefined,变量默认值就是undefined
②引用/对象类型:有11个,可以暂时理解为有11个对象(属性和方法)

运算符

运算符有:算数运算符、比较/关系运算符、逻辑运算符、赋值运算符、自增和自减运算符、位运算符。
1.算数运算符:+ - * / %
    特殊:% 模运算 小的数%大的数 取的是小的数; 
    作用:任意数%2 - 判断奇偶数
        取出某个数字的后N位 1234%10 -> 4; 1234%100 -> 34;
    默认带有隐式转换:会悄悄的将运算符左右两边转为数字,再运算。
    true -> 1 ; false -> 0 ; null -> 0 ; undefined -> NaN 
    字符串 -> NaN;
2.比较/关系运算符 > < >= <= != == === !==
    何时使用:一般出现在分支结构,我们可以通过判断条件满不满足,走不同的路线
    结果:一定是布尔值
    默认也带有隐式转换,默认左右两边都会转为数字再比较大小。
    特殊:1.如果参与比较的两边都是一个字符串,则会按位pk每个字符的十六进制Unicode号(或十进制ASCII码)
    数字0-9 < 大写A-Z < 小写a-z < 汉字
    常识:汉字的第一个字:一 Unicode号:4e00 ASCII:19968
         汉字的最后一个字:龥 Unicode号:9fa5 ASCII40869
          2.NaN参与任何比较运算结果都为false,如何判断是不是NaN:!isNaN(x)
          3.undefined == null;//true
            解决:=== 全等,不带隐式转换的等值比较,要求数据相同,值也相同
3.逻辑运算符:&& 与  || 或  !非
4.赋值运算符:= += -= *= /= %=
5.自增自减运算符:++ --
    自增/自减:固定每次加/减1
    (i++/i--)和(++i/--i)的区别?
    单独使用没有任何区别,但参加了表达式,变量始终都会加/减1,只是返回的结果不同,(i++/i--)返回的是加/减了之前的旧值,(++i/--i)返回的是加/减了之后的新值。
6.位运算
    左移:m<<n,读作m左移了n位,翻译:m*2的n次方
    右移:m>>n,读作m右移了n位,翻译:m/2的n次方
    缺点:底数只能是2,不可以修改

分支结构

3大类:if分支 if...else switch...case分支  
    if(条件){                        
        操作;
    }
    
    if(条件){
        操作;
    }else if(条件1){
        操作1;
    }...else if(条件n){
        操作n;
    }else{
        默认操作;
    }

    swicth(变量/表达式){
        case1:操作1;
        break;
        ...
        case 值n:操作n;
        break;
        default:默认操作;
    }
    
    ifswitch的区别?谁好谁坏?
        1.switch...case:优点:执行效率高,速度比较快;且他比较的时候,
          case做的是等值比较而不是范围查找,且不带隐式转换
        2.if...else:优点:可以做范围比较
                     缺点:执行效率低,速度比较慢
         代码优化,尽量少用if...else,尽量替换成switch...case
        3.三目运算:纯粹是为了简化简单的分支,操作只能一句话!
          语法:条件?操作1:默认操作; === if...else
                条件?操作1:条件2?操作2:默认操作; === if..else if..else
          扩展:短路逻辑:条件&&(操作) === if
          注意:1.默认操作是不能省略的,省略了会报错
               2.如果操作比较复杂,不能使用三目运算

强制数据类型转换(显式)

1.转字符串
    ① var str = x.toString(); x不能undefinednullvar str = String(x); 万能的,任何人都可转字符串,完全等效于隐式转换
      其实String()就是隐式转换的底层原理,还不如"+";
2.转数字:3种
    ① ParseInt(str/num) - parse解析 Int整形
      执行原理,从左向右依次读取每个字符,碰到非数字字符就停止,且不认识小数点
      如果一来就不认识就会转换为NaNParseFloat(str) - Float浮点型(小数)认识第一个小数点
    ③ Number(x); 万能的,任何人都可以转换数字,完全等效于隐式转换,不如x-0
      *1 /1;
3.转布尔
    Boolean(x); 万能的,任何人都可以转布尔,完全等效隐式转换,还不如!!X;
    只有六个会为false0, undefined, NaN, null, false, " ",其余为true

循环结构

1.循环结构:反复执行 相同 或 相似的操作
  循环三要素:
           1.循环条件:开始 - 结束,循环的次数
           2.循环体:每次循环要做什么操作
           3.循环变量:记录着我们当前在哪一次,且它会不断的变化,变化往往
           是向着不满足循环条件前进的。
2.三种循环结构
    1.while循环:
           语法:var 循环变量 = 值;
                while(循环条件){
                        循环体;
                        循环变量变化;
                } 
                
                死循环操作,在不确定循环次数的时候用
                语法:while(true){
                        死循环操作;
                     }
                break - 退出整个循环 - 多半都是搭配死循环
                continue - 退出当前迭代,从下一次迭代继续执行
    2.for循环:
        语法:for(var 循环变量 = 值;循环条件;循环变量变化起来){
                      循环体;
                }
        死循环:for( ; ; ){ 循环体;}     
    
    ***whilefor的区别?
        whilefor从原理上没有区别
        while更麻烦,一般不确定循环次数的时候使用死循环
        for更简单,一般确定循环次数的时候使用 - 大部分情况都是使用他。

函数的基础

1.概念:function函数,也称为方法,先预定义好,以后可以反复使用的代码段
2.如何使用函数:有2步
    ① 定义/创建/声明;
        function 函数名(){ 函数体/代码段; }
    ② 调用函数:2种
        直接在js内部书写:函数名();
        在HTML页面上绑定点击事件:<elem onclick="函数名()">文字</elem>
        用户点几次就调用几次
3.何时使用函数:不希望打开页面立刻执行、希望由用户来触发
4.形参函数的创建:带参数的函数其实就是一个变量,只不过不需要写var,且不需要复制
    语法:function 函数名(形参,...){ 函数体;}
    使用带参数的函数必须传入实参,函数名(实参,...);
    注意传入的实际参数的顺序必须和形参的顺序一一对应,数量不要多也不要少
    总之:不带参数的函数用于一些固定操作;带有参数的根据传入的实参不同,执行不同操作
5.总结:循环可以反复执行,函数也可以反复执行,他们的区别在于时机不同
        1.循环:几乎是页面打开一瞬间就完成了
        2.函数:需要调用后执行

自定义函数Function

1.创建:2种(目前) - 其实3种
    ① 声明方式 - 创建函数
    function 函数名(形参){ 函数体; return 返回值;}
    ② 直接量方式 - 创建函数
    var 函数名 = function(形参){ 函数体; return 返回值;}
2.调用函数:var 变量名 = 函数名(实参);
    return后跟一个数据是将数据返回到函数作用域的外部,return只负责返回不负责
    保存,所以在调用函数时需要用一个变量去接住它。
    注:就算省略return,默认也会有一个return,会悄悄返回一个undefined,所以
    函数有返回值才去用变量接住它
3.作用域:21.全局作用域:全局变量和全局函数,在页面的任何一个位置都可以访问和使用
    2.函数作用域:局部变量和局部函数,只能在函数调用时,内部可用。
    注意:它带来了变量的使用规则,优先使用局部的,局部没有找全局的
    缺点:1.局部可以使用全局的,但全局不能使用局部的;解决:加return
         2.千万不要在函数中对未声明的变量赋值(例:a=1;)会造成全局污染,
         全局本身没有这个东西,但函数作用域却给他添加上了。会降低网站性能
4.声明提前 
    原理:在程序执行之前,会将var声明的变量(轻)和function声明的函数(重),集中提前
    到当前作用域的顶部,但赋值会留在原地
    **强调:声明方式创建的函数会完整提前,直接量创建的方式不会完整提前,只有变量名部分会提前**
    **变量名和函数名尽量不要重复,遵循先创建后使用**
5.函数内部的变量,都会在函数值执行完后,自动释放,意味着我们不需要自己写xx=null
6.重载
    相同的函数名,根据传入的实参不同,自动选择对应的函数去执行,但js不支持,如果函数名重复了,后面的会把前面的覆盖
    解决:在函数的内部自带一个arguments对象(类数组对象)
    作用:哪怕没有写过任何形参,它也可以接收所有实参。
    固定套路:
        通过下标去获取传入的某一个实参:argument[i]  –  i下标从0开始
        通过length去获取到到底传入了几个实参:arguments.length;
        所以我们可以通过在函数内部开启分支判断arguments的不同,而执行不同的操作

数组Array的基础

数组:创建一个变量可以保存【多个数据】
数组都是线性排列的,除了第一个元素,每一个元素都有唯一的前驱元素
除了最后一个元素,每一个元素都有唯一的后继元素
**每个元素都有一个自己的位置,称之为下标,下标都是从0开始的,到最大长度减1**
1.创建数组:2种
    1. *直接量方式:var arr=[];//空数组
        var arr=[“数据1”,…..];
    2.构造函数方式:var arr = new Array();//空数组
        var arr = new Array(“数据1”,…..);
2.获取数组中的数据:数组名[i];
3.后续添加/替换元素
        数组名[i]=新数据;
        如果下标处没有,则为添加,如果下标处有则为替换
4.数组具有三大不限制
    ① 不限制元素类型
    ② 不限制元素个数
    ③ 不限制下标越界
        如果获取下标越界,返回的是一个undefined
        如果添加元素下标越界,会得到一个稀疏数组
5.问:自己数下标,多了过后,难免数错,导致下标越界怎么解决?
      解决:数组中的唯一属性:length
      语法:数组名.length 
      作用:获取到数组的长度,长度是从1开始数的
      三个固定套路:获取数组倒数的第n个元素:arr[arr.length-n];
                   向数组添加元素:arr[arr.length]=新值;
                   缩容:删除数组倒数n个元素:arr.length -= n;
6.遍历数组
    往往很多情况,我们不会拿出数组的某个数组来操作,而是拿出数组中的所有数组来进行 
    相同 或 相似的操作 - 搭配循环
    公式:for(var i = 0;i<=arr.length;i++){
                    arr[i];
          }
注:JS里面只有两大类数据类型:1.原始 2.引用

DOM

  1.全称:Document Object Model 文档对象模型;专门用来操作HTML文档的,提供了一些方法
  2.DOM树概念:DOM将我们的HTML看作一个倒挂的树结构,但树根不是HTML标签,而是document对象
      一个页面只有一个document对象
      作用:可以通过树根对象找到我们想要的任何一个DOM元素/节点/对象(属性和方法)
      DOM会将页面上的每个元素、属性、文本、注释等都会被视为一个DOM元素/节点/对象
  3.查找元素:两大方面
      <1>.直接通过HTML的特点去查找元素:
         ① 通过ID去查找元素:
              var elem = document.getElementById("id值");
          特殊:
              返回值:找到了返回当前找到的DOM元素,没找到返回一个null
              如果出现多个相同的id,那么只会找到第一个(id的唯一性)
              **其实id根本不需要查找。可以直接使用,id的唯一性**
      <2>.通过标签名去查找元素
              var elem = document.getElementsByTagName("标签名");
          特殊:
              返回值:找到了返回的是一个类数组DOM集合,没找到返回一个空数组
              JS只能操作DOM元素,不能直接操作DOM集合!解决:要么拿到某一个下标,要么遍历拿到所有人。
              不一定非要从document开始查找,如果从document去找,会找到所有的元素,可以换成已经找到的某个元素。
      <3>.通过class名去查找元素
          var elem = document.getElementsByClassName("Class名");
  4.通过元素之间的关系去查找元素:前提:至少要【先找到一个元素】才可以使用
          父级:elem.ParentNode; //单个元素
          子级:elem.Children; //集合
          子级之间的第一个:elem.firstElementChild; //单个元素 子级元素的查找
          子级之间的最后一个:elem.lastElementChild;
          兄弟元素之间的前一个:elem.PreviousElementSibling;//单个元素,兄弟元素之间的查找
          兄弟元素之间的后一个:elem.nextElementSibling;
  5.操作元素:前提是先找到元素
     1.内容的获取与设置:
      <1>. 内容:.innerHTML 获取或设置开始标签到结束标签之间的内容【支持识别标签】
           获取:elem.innerHTML;
           设置:elem.innerHTML = " ";
      <2>. innerText - 获取或设置开始标签到结束标签之间的纯文本【不支持识别标签】
           获取:elem.innerText;
           设置:elem.innerText = " ";
          以上两个专门双标签准备的,而有一个单标签也可以写内容:<input/>
      <3>. value - 专门用于获取或设置input的内容
           获取:input.value;
           设置:input.value = " ";
     2.属性的获取与设置
       <1>.获取属性:elem.getAttribute("属性名");
           设置属性:elem.setAttribute("属性名","属性值");
           简化版:获取属性:elem.属性名;
                  设置属性:elem.属性名 = "属性值";
           简化版有两个小缺陷:
                 class必须写为className,ES2015(es6)class变成了一个关键字
                 只能操作标准属性,不能操作自定义属性
     3.样式:
         一般JS是操作的内联样式
           获取样式:elem.Style.css属性名;
           设置样式:elem.Style.css属性名 = "属性值";
           特殊点:css属性名,有横线的地方,去掉横线,换为小驼峰命名
                   例:border-radius 换为 borderRadius
                   小缺陷:获取时,只能获取内联样式
     4.绑定事件:
         elem.onclick = function(){
                     操作;
                     ***关键字this***
                     如果单个元素绑定事件,this->这个元素
                     如果多个元素绑定事件,this->当前元素
         }
结束