[TOC]

一、变量的类型

1.原始类型

JavaScript共有5种原始类型,如下

boolean    布尔,值为true或false
number    数字,值为任何整型或浮点数值
string    字符串,值为单引号或双引号括出的单个字符
null        空类型,该原始类型仅有一个值:null
undefined    未定义,该原始类型仅有一个值:undefined(undefined会被赋值给一个还没有初始化的变量)

前3种类型(boolean,number和string)表现的行为类似,而后两种(null和undefined)则有一点区别
一般用typeof操作符判断变量类型
注意:typeof判断引用类型的数据,除了Function返回function其他都返回object

  var num = 10;
  var str = "hello world";
  var b = true;  /* boolean   true  false */
        /* typeof 操作符去判断 */
  console.log(typeof num)
  console.log(typeof str)
  console.log(typeof b)

 /* typeof 操作符可能的返回值
 undefined------如果这个值未定义
 boolean  ------如果这个值是布尔值
 string   ------如果这个值是字符串
 number   ------如果这个值是数值
 object   ------如果这个值是对象或null
 function ------如果这个值是函数
 */

2.引用类型

JavaScript中引用类型有Array、Date、Function、Object、Error、RegExp
引用类型的值是保存在内存中的对象中,与其他语言不同,JavaScript不允许直接访问内存中的位置,也就是说不能直接操作对线的内存空间,在操作对象时,实际上是在操作对象的引用而不是实际的对象。

数组

   /* 1.声明一个数组 */
        var arr = ["html","css","js"];
        /* 2.Array.isArray()  判断一个对象是不是一个数组 */
        console.log(Array.isArray(arr))
        console.log(arr instanceof Array);
        /* 3.读取数组的值 */
        console.log(arr[0])
        console.log(arr[2])
        /* 4. length属性可以获取数组的长度 */
        console.log(arr.length)
        /* 5.获取数组的最后一位的值 */
        console.log(arr[arr.length-1])

数组的添加和删除

//1.push():栈方法,在数组最后面插入项,返回数组的长度
数组改后的长度 = 数组.push(元素);
//2.pop():取出数组中最后一个元素,返回被删除的元素
被删除的元素 = 数组.pop();    //注意括号里不含参数

//3.unshift():队列方法,在数组最前面插入项,返回数组长度
//4.shift():取出数组中的第一个元素,返回被删除的元素

函数

函数是封装一个特定功能的代码块,函数不调用不会执行

 var go = function(x){
            console.log(x)
        }
        go(20);

对象

 /* json对象  key,value的形式出现的 */
        var  cheng = {
           "name":"chengchao",
            age:20,
            sex:"男"
        }
        /* 2.读取对象属性的值 */
        console.log(cheng.name)
        /* Tip:如果属性名是变量的情况下,使用中括号去读取 */
        console.log(cheng["name"])
        /* 3.给对象新添加一个属性 */
        cheng.love= "看电影"
        console.log(cheng)
        /* 4.读取对象所有的属性  Object.keys(obj)*/
        console.log(Object.keys(cheng))
        /* 5.读取对象所有的value值 Object.values(obj) */
        console.log(Object.values(cheng))
        /* 6.for in遍历对象 */
        for(var k in cheng){
            console.log(k);    //这里打印的是key
            console.log(cheng[k]);    //这里打印的是value(用到了2中的tip)
        }

3.全局变量和局部变量

全局变量:可以在脚本中的任何位置被引用。一旦你在某个脚本里声明了一个全局变量,就可以从这个脚本中的任何位置(包括函数内部)引用它。全局变量的作用域使整个脚本。

局部变量:只存在于声明它的那个函数的内部,在那个函数的外部是无法引用它的。局部变量的作用域仅限于某个特定的函数。

函数中引用了全局变量

    var a=10;
        function go(){
             a=20;    //这里直接写a=20是引用了全局变量a
            return a;
        }
        b = go();
        console.log("a="+a);
        console.log("b="+b);

输出结果
image.png

把这个函数写成这样才正确

   var a=10;
        function go(){
            var a=20;        //加上var之后,函数里的a就是局部变量,和外面的a没关系
            return a;
        }
        b = go();
        console.log("a="+a);
        console.log("b="+b);

输出结果
image.png

二、JS基本语法

1.声明提前

es6语法以前JavaScript在执行代码的时候会将所有使用var声明的变量,放在作用域的顶部集中创建,赋值留在原地

  console.log("a="+a);
   var a = 20;

//输出结果为a=undefined

在es6中用let声明变量,没有声明提前。

2.数据类型转换

字符串和布尔转成数字

Number()强制转换

var a="12.132";
var bool = true;
var num1 = Number(a);            //num1为12.132
var num2 = Number(bool);    //num2为1

缺点:Number()只能识别纯数字的字符串,遇到字符串中含由非数字的会返回NaN

parseInt和parseFloat

 var str = "12.323px";
 console.log(Number(str));    //输出为NaN
 console.log(parseInt(str));    //输出为12
 console.log(parseFloat(str));    //输出为12.323

开头的字符必须以数字开头,遇到非数字的字符就停止解析

另外,parseInt还可以将其他进制的数转化为十进制

            /* JavaScript里面:
        八进制的数都是以0开头,类似:0750,060
        十六进制的数都是0x开头,类似:0xAF,0x5631 
        在ECMA3中,“070”会被当成八进制字面量,会被转化为十进制的56
        “0xAF”会被当成十六进制字面量,会被转换为175*/
        var a = 012;
                var b = 0xAF
        console.log(a);//输出会是10
                console.log(b);//输出会是175

                /*parseInt()函数提供了第二个参数:转换时使用的基数(即多少进制)*/
                var num1 = parseInt("012",8); //10  
                /*注意这里的012一定要用引号包住,否则会先被转换为10,然后成了parseInt(10,8)*/

                var num2 = parseInt("0xAF",16); //175

数字转成字符串和布尔

转字符串用String()或者toString(),注意toString是用num.toString()调用的
转布尔用Boolean()方法
注意只有5种情况才会返回false:1.”” 2.NaN 3.undefined 4.null 5.0

自动转换

算数计算中,先将两边的变量转换为Number再计算Number()
特殊情况:加运算中,碰到字符串,+会起到拼接符的作用

加法运算

         var a = 1;
         var b = true;
         var d = "2"
         var c = "hello world";
         var str = a+b;
         var sum = a+c;
         console.log(str);
         console.log(sum)
         console.log(a+d);

image.png

减法运算

        var a = true;
        var b = "3";
        var c = 4;
        console.log(a-b);              
        /* Number(a)-Number(b) */
        console.log(c-b);
        console.log(c-a);

image.png

3.运算符和表达式

比较运算符

>,<,>=,<=,==,!=

遇到比较运算符的时候会将对两边变量用number()方法,转换成Number类型再比较

        /* 
        >,<,>=,<=  比较运算返回的结果是boolean
        先将两边的值转换为Number再比较
         */
         var a = 10;
         var b = "20"
         var c = "true"
         console.log(a>b);  //false
        //  Number(a)>Number(b)
        console.log(a>c);
        // Number(a)>Number(c)  10>NaN  NaN是不能参与计算的,它和任何值做计算,结果都是NaN

在转换的过程中会有特殊情况,例如字符串转数字会出现NaN
特殊情况NaN:NaN不等于,不大于,不小于任何值(包括自己)。 用isNaN(n):用来判断n是否为NaN

三目运算符

表达式?值1:值2
如果表达式为真 返回值1
如果表达式为假 返回值2
注意:值1和值2类型要一致

              var a = 30;
        var b = 20;
        var c = (a>b)?"a大于b":"a小于b";
        console.log(c)

相等和全等

一、相等(==)和不相等(!=)
相等和不相等这两个操作符都会先转换操作数(通常称为强制转型),然后再比较它们的相等性
在转换不同的数据类型时,相等和不相等遵循下列基本规则:
1.如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前会先将字符串转换为数值

        var s = "123";    
        var num = 123;
        console.log(s==num); //true

2.如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法,用得到的基本类型值按照前面的规则进行比较;

        var num1 = new Number(13);    //num1为对象类型
        var num2 = 13;        //num2为number基本类型
        console.log(num1==num2);    //先去num1.valueOf()得到number类型的13,然后再比较

3.null和undefined是相等的,并且在比较相等性之前,不能将null和undefined转换成其他数据类型

undefined == 0;    //false
null == 0; //false
undefined == false; //false
null == false;    //false

4.如果有一个操作数是NaN,则相等操作符返回false
注意:NaN不等于任何数,包括他自己

5.如果两个操作数都是对象
如果两个都是对象(object)类型,则比较它们是不是同一个对象。如果两个操作数都指向同一个对象,则是相等操作符返回true,否则返回false。

        var num1 = new Number(1);
        var num2 = new Number(1);
        console.log(num1==num2);    //false
        //尽管这两个对象的valueOf()相等,但是不同的两个对象,并不是指向同一个对象

二、全等和不全等
除了在比较之前不转换操作数之外,全等和不全等与相等和不相等操作符没有什么区别。全等操作符只在两个操作数未经转换就相等的情况下返回true。

        var num1 = new Number(1);    //类型为对象
        var num2 = 1;                            //类型为数字
        var result1 = (num1==num2);   //true,因为转换后相等
        var result2 = (num1===num2);   //false,因为不同的数据类型不相等

三、DOM

1.什么是DOM

DOM:文档对象模型。DOM 为文档提供了结构化表示,并定义了如何通过脚本来访问文档结构。目的其实就是为了能让js操作html元素而制定的一个规范。
整个DOM体系可以用一棵DOM树来表示。
DOM树是由一个个节点组成
JavaScript基础 - 图5
上图可知,在HTML中,一切都是节点;

  • 元素节点:Html标签(nodeType==1)
  • 属性节点:标签的属性(nodeType==2)
  • 文本节点:标签中的文字(nodeType==3)

2.DOM节点和访问关系的获取

dom节点的获取

<p name="test" class="one" id="only-id">hello world</p>
    <script>
        var onlyid = document.getElementById("only-id");//通过id获取单个标签

        //以下四种方式获取到的都是集合
        var one = document.getElementsByClassName("one");
        var p = document.getElementsByTagName('p');
        var test = document.getElementsByName("test");

        //querySelectorAll方法就就和选择器一样,是class就用.xxx,是id就用#xxx
        var query = document.querySelectorAll("#only-id")
    <script>

dom访问关系的获取

dom的节点并不是孤立的,因此可以通过dom节点之间的相对关系对它们进行访问。js中的父子访问关系如下:
JavaScript基础 - 图6
1.获取父节点
调用者就是一个子节点,一个节点只有一个父节点,调用方式为

var parent = 节点.parentNode;

2.获取兄弟节点

var sibling1 = 节点.nextSibling;//获取下一个节点(包括标签,空文档,文本节点)
var sibling2 = 节点.nextElementSibling;//获取下一个元素节点
//next表示后面的,前面的用previous,用法同理

3.获取单个子节点

var firstchild1 = 父节点.firstChild;//获取下一个节点
var firstchild2 = 父节点.firstElementChild;//获取下一个元素节点
//first表示第一个,最后一个用last,用法同理


4.获取所有的子节点

var 子节点数组1 = 父节点.childNodes;//获取所有子节点,用的少
var 子节点数组2 = 父节点.children;//用的最多,得到了几乎所有游览器的支持

3.DOM节点的操作

上面讲了节点的访问关系都是属性。本段讲节点的操作都是函数

创建节点

格式:var 要创建节点名 = document.createElement(“标签名”);

//例如我们想要创建li标签
<script type="text/javascript">
    var a1 = document.createElement("li");   //创建一个li标签
    var a2 = document.createElement("adbc");   //创建一个不存在的标签

    console.log(a1);
    console.log(a2);

    console.log(typeof a1);
    console.log(typeof a2);
</script>

控制台输出结果:
image.png

插入节点

插入节点有两种方式,它们的含义是不同的
方式1:

父节点.appendChild(新的子节点);    //父节点的最后插入一个新的子节点

方式2:

父节点.insertBefore(新的子节点,作为参考的子节点);
//在参考节点前插入一个新的节点。如果参考节点为null,那么他将在父节点最后插入一个子节点

修改节点

父节点.repalceChild(新的子节点,老的被替换的节点)

删除节点

格式如下:

父节点.removeChild(子节点);

解释:用父节点删除子节点。必须要指定是删除哪个子节点。
如果想要自己删除自己,可以这么做:

   node1.parentNode.removeChild(node1);

复制节点

格式如下:

    要复制的节点.cloneNode();       //括号里不带参数和带参数false,效果是一样的。

    要复制的节点.cloneNode(true);

括号里带不带参数,效果是不同的。解释如下:

  • 不带参数/带参数false:只复制节点本身,不复制子节点。
  • 带参数true:既复制节点本身,也复制其所有的子节点。

设置节点属性

1.获取节点的属性值

元素节点.getAttribute("属性名称");

举例:

<img src="images/1.jpg" class="image-box" title="美女图片" alt="地铁一瞥" id="a1">

    <script>
            console.log(myNode.getAttribute("src"));
            console.log(myNode.getAttribute("class"));   //注意是class,不是className
            console.log(myNode.getAttribute("title"));
    </script>

2.设置节点的属性值

元素节点.setAttribute(属性名,属性值);
//举例(设置节点的属性值)
   myNode.setAttribute("src","images/3.jpg");
    myNode.setAttribute("class","image3-box");
    myNode.setAttribute("id","你好");

//注意,两个值都需要用引号包着

3.删除节点的属性

元素节点.removeAttribute(属性名);

4.DOM事件(event)

JavaScript与HTML之间的交互通过事件实现的

onclick
onfocus
onblur
onmouseover  //鼠标移到某元素之上
onmouseout  //鼠标从某元素移开
onload页面加载时触发
onchange域的内容改变时发生
onsubmit//表单中的确认按钮被点击时发生
//有事件一定有对应一个处理结果,用函数表示
onresize//浏览器的尺寸发生改变
onscroll //窗口滚动
onchange事件支持的标签input,select,textarea

键盘事件与keycode属性

onkeydown:用户按下一个键盘按键时发生
onkeypress:在键盘按键按下并释放一个键时发生
onkeyup:在键盘按键松开时发生
keyCode:返回onkeypress,onkeydown或onkeyup事件触发的键的值的字符代码,或键的代码

事例

      /* 键盘松开的时发生的事件 */
        input.onkeyup = function(event){
            /* keycode返回一个键盘码 */
            if(event.keyCode == 13){
                /* 只要是对象的属性,都可以通过点的方式去获取值 */
                console.log(this.value)
            }

窗口滚动onscroll

事例

    <div class="nav" id="nav">导航</div>
    <script>
        /* onscroll 滚动事件 */
        var nav = document.getElementById("nav")
        window.onscroll =  function(){
            /* 获取滚动条距离顶部的高度 */
            var scrollTop = document.documentElement.scrollTop;
            /* 当滚动条距离顶部的高度达到300时候完全显示 */
            var opacity = scrollTop/300;
            if(opacity>1){
                opacity = 1
            }
            nav.style.opacity = opacity;
            nav.style.backgroundColor = "red"
        }
    </script>

onload

        window.onload = function(){
            var input = document.getElementById("input");
            input.onchange = function(event){
                console.log(this.value)
            }
        }
               /* 
        onload 等DOM树以及图片相关资源加载完毕,再执行函数中的代码
         */

四、BOM

1.BOM的介绍

JavaScript基础分为三个部分:

  • ECMAScript:JavaScript的语法标准。包括变量、表达式、运算符、函数、if语句、for语句等。
  • DOM:文档对象模型,操作网页上的元素的API。比如让盒子移动、变色、轮播图等。
  • BOM:浏览器对象模型,操作浏览器部分功能的API。比如让浏览器自动滚动。

BOM:Browser Object Model,浏览器对象模型。
BOM的结构图:
JavaScript基础 - 图8
由上图可知:
window对象是bom的顶层对象,所有对象都是通过它延伸出来的,也可以成为window的子对象
dom是bom的一部分

window对象:

  • window对象是JavaScript中的顶级对象。
  • 全局变量、自定义函数也是window对象的属性和方法
  • window对象下的属性和方法调用时,可以省略window

    2.弹出系统对话框

    比如alert(1)是window.alert(1)的简写
    系统对话框有三种:
    alert();    //弹出警告框
    confirm();    //弹出确认框,确定 返回true,取消 返回false
    prompt();        //弹出提示用户输入的对话框, 返回输入的内容
    

3.打开、关闭窗口

打开窗口

    window.open(url,target,param);
  /*url:要打开的地址
    target:新窗口的位置,可以是 _blank、_self、_parent
    param:新窗口的一些设置
    返回值:新窗口的句柄
    */

关闭窗口

window.close();

4.setTimeout和setInterval

  <script>
        /* 超时调用 间隔一段时间,执行函数,且只执行一次 */
        /* 异步 */
        console.log(1)
        setTimeout(function(){
            console.log("a")
        },1000)
        console.log(2);        //结果1 2 a;由于这个方法要1s时间故先跳过,最后执行
    </script>

   <script>
        /* 间歇调用  间隔一段时间,执行函数 */
        setInterval(function(){
            console.log("b")
        },3000)
    </script>

 <script>
        var btn = document.getElementById("btn");
        var timer = window.setInterval(function(){
            console.log("a")
        },3000)
        /* 清除定时器
        clearInterval()
         */
        console.log(timer)
        btn.onclick = function(){
            clearInterval(timer)
        }
    </script>

5.BOM的内置对象

location对象

window.location可以简写成location。location相当于浏览器地址栏,可以将URL解析成独立的片段
location对象的属性

  • href:跳转
  • hash 返回url中#后面的内容,包含#
  • host 主机名,包括端口
  • hostname 主机名
  • pathname url中的路径部分
  • protocol 协议 一般是http、https
  • search 查询字符串

location.href属性举例:
有时候,当我们访问一个不存在的网页时,会提示5秒后自动跳转到指定页面,此时就可以用到location。

<script>
    setTimeout(function () {
        location.href = "http://www.baidu.com";
    }, 5000);
</script>

navigator对象

window.navigator的一些属性可以获取客户端的一些信息

  • userAgent:系统,浏览器
  • platform:浏览器支持的系统,win/mac/linux
    console.log(navigator.userAgent);
      console.log(navigator.platform);
    
    结果:
    image.png

history对象

1、历史记录管理
2、后退:

  • history.back()
  • history.go(-1):0是刷新

3、前进:

  • history.forward()
  • history.go(1)

用的不多。因为浏览器中已经自带了这些功能的按钮

五、事件对象Event和冒泡

1.绑定事件的两种方式

方式一:onclick

<body>
<button>点我</button>
<script>
    var btn = document.getElementsByTagName("button")[0];

    //这种事件绑定的方法容易被层叠。
    btn.onclick = function () {
        console.log("事件1");    //被事件2覆盖
    }

    btn.onclick = function () {
        console.log("事件2");    //控制台只显示事件2
    }

</script>
</body>

image.png

方式二:addEventListener

addEventListener()里的参数:

  • 参数1:事件名(注意,没有on)
  • 参数2:事件名(执行函数)
  • 参数3:false或者true(冒泡或者捕获) ```javascript

    点击按钮后,上方代码的打印结果:
    

    事件1 事件2

    
    
    <a name="jdHBQ"></a>
    ### 2.事件冒泡和事件捕获
    ![image.png](https://cdn.nlark.com/yuque/0/2019/png/457370/1566996465726-8659d22d-0606-40aa-a37d-d9c5372d4c7e.png#align=left&display=inline&height=286&name=image.png&originHeight=357&originWidth=394&size=52024&status=done&width=315.2)
    <a name="GkYV4"></a>
    #### 事件冒泡
    **事件冒泡:即事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点。**<br />通俗的将就是父元素和子元素绑定了相同的事件,子元素的事件执行,父元素的事件也会触发<br />点击子元素,会先弹出child,再弹出parent
    ```javascript
      parent.onclick = function(){
                alert("parent")
            }
            child.onclick = function(){
                alert("child")
            }
    

    阻止事件冒泡: event.stopPropagation();

      parent.onclick = function(event){
                alert("parent")
                event.stopPropagation()
            }
            child.onclick = function(event){
                alert("child")
                event.stopPropagation()
            }
    

    事件捕获

    事件捕获:不太具体的节点应该更早接收到事件,而具体的节点应该最后接收到事件。
    点击子元素,会先弹出parent,再弹出child

            child.addEventListener('click',function(){
                alert("child")
            },true)
            parent.addEventListener('click',function(){
                alert("parent")
            },true)