JavaScript基础(上)

144 阅读10分钟

初步认识JavaScript

JavaScript是什么

JavaScript的发展历史

JavaScript是一种具有函数优先的轻量级,解释型或即时编译型的编程语言(简称"JS")。他的发明者名为:布兰登-艾克(JS之父,英文全称"Brendan Eich")

浏览器执行JavaScript的执行原理

JavaScript由那三个部分组成

javascript由3个部分组成:

1、ECMAScript,js语言核心部分,描述了该语言的语法和基本对象;

2、文档对象模型(DOM),网页文档操作标准;

3、浏览器对象模型(BOM),客户端和浏览器窗口操作基础。

核心(ECMAScript)

由ECMA-262定义的ECMAScript是一种在国际认可的标准的脚本语言规范,与Web浏览器没有依赖关系。ECMA-262标准主要规定了这门语言由以下组成部分:

1.语法

2.变量和数据类型

3.关键字和保留字

4.操作符

5.控制语句

6.对象

2009年ECMAScript 5.0版正式发布。在很长一段时间,使用javaScript都是按照5.0的标准。2015年ECMAScript 6发布正式版本,官方称为ECMAScript 2015。ECMAScript定义了脚本语言的所有属性、方法和对象。因此抵用web客户端脚本编码时一定要遵循ECMAScript标准。

文档对象模型(DOM)

DOM(文档对象模型)是 HTML 和 XML 的应用程序接口(API)。DOM 将把整个页面规划成由节点层级构成的文档。HTML或XML页面中的每个组成部分都是某种类型的节点,这些节点又包含着不同类型的数据。

浏览器对象模型(BOM)

IE 3.0 和 Netscape Navigator 3.0 提供了一种特性 - BOM(浏览器对象模型),可以对浏览器窗口进行访问和操作。使用 BOM,开发者可以移动窗口、改变状态栏中的文本以及执行其他与页面内容不直接相关的操作。

JavaScript的输入输出语句

方法说明
alert("msg")浏览弹出来提示框
console.log("msg")浏览器的控制台打印输出信息
prompt()浏览器弹出输入框,用户可以经行输入

javaScript里面的注释

单行注释 //

多行注释 /* */

变量

变量的作用

变量实际上就是一个容器他的里面可以放入不同类型的值

变量是在程序在内存中申请的一块用来存放数据的空间

变量的使用

变量的使用分成两部:声明和赋值

声明:var 变量名

声明多个变量:var 变量名1,变量名2 ... 变量名n

赋值:变量名 = 变量值 (= 代表这赋值的意思)

变量的命名规范

1.严格区分大小写
2.必须以字母,下划线,$开3.不能用关键字或者保留字
4.javascript驼峰命名法
5.命名要有一定的意义,不能太随便

数据类型

数据类型简介

JS中的变量不同于Java、C++,Js中的变量数据类型只有程序在运行的过程中,根据等号右边的值来确定的。

var age = 10 //数值型
var name = '牛小牛' //字符串

js中拥有动态类型,同时也意味着相同的变量可以用作不同的数据类型

var x = 6     //数值型
var x = '6'   //字符串

简单数据类型

js将数据类型分成两大类:简单数据类型(Number,String,Boolean,Undefined,Null) 和 复杂数据类型(Object)

基本数据类型:

数据类型说明默认值
Number数字型 包含整数和小数0
Boolean布尔值类型 true、false 等价于 1 0false
String字符串""
Undefined声明了变量但是没有给变量赋值undefined
Null声明了变量a为空值null

数值型Number

var x1 = 10                       //整数

var x2 = 20.5                     //小数

var x3 = 012                      //8进制

var x4 = 0x12                     //16进制

var x5 = Number.MAX_VALUE         //最大值

var x6 = Number.MIN_VALUE         //最小值

isNaN 方法:判断非数字,如果是一个数字返回false,不是一个数字返回true

字符串String

被 '' 或者 "" 包裹起来的都是字符串类型,推荐使用单引号

var x1 = '牛小牛'

获取字符串的长度:可以通过length属性获取

var str = 'hello world'
var len = str.length

任何数据类型和String 进行拼接都会变成String

var str1 = '12' + 12                //1212
var str2 = true + '12'              //true12

布尔型 Boolean

Boolean类型只有两种 true 和 false

如果说Boolean类型参加运算其中:true 当做1 来算 false当作0来算

Undefined 和 null

Undefined如果说一个变量被声明了但是没有赋值那么就是undefined 未定义的数据类型

null就是空值,在参与运算的时候当作0

变量数据检测 typeof

typeof 关键字 用来检测数据的类型

var str = 'hello world'
var len = str.length
alert( typeof len)
alert(typeof "132")

数据类型的转换

转字符串

方法说明案例
toString()转字符串var num = 1; alert(num.toString())
String() 强制转换转成字符串var num = 1; alert(String(num))
+ 进行拼接和字符串进行拼接的都是字符串var num = 1; alert(num + ' ')

转数字型

方法说明案例
parseInt(String)函数将String类型转换成整数类型parseInt('777')
parseFloat将String类型转换成小数类型parseFloat('777.777')
Number()强制类型转换将String类型转换成整数类型Number('12')
隐式转换利用算数运算符进行隐式转换'12' - 0

转换成boolean

方法说明案例
Boolean函数其他类型转成布尔型parseInt('true')

代表空、否定的值都会被转换成false 例如 '',0,NaN,null,Undefined。剩下的值都会转换成true

流程控制

流程控制中的三大结构:顺序结构、分支结构、循环结构

语法if:if(条件){//执行代码}

语法if-else: if(条件){ //code }else{ //code }

三元操作表达式:判断条件? 真*执行:假*执行

switch语法格式:

switch(表达式){
    case1:
     语句1;
     break;
     
    case2:
     语句2;
     break;
     
     ...
     
     default:
      语句...
}

循环结构

在Js中有三种循环结构分别是:for while do...while

for循环格式:

for(var 变量;条件;操作){
   循环体
}

while循环格式:

while(条件){
  //循环体
}

do-while 循环格式:

do{
  //循环体
}while(条件);

break:跳出循环

continue: 跳出当前循环,会进入到下一次循环中去

数组

为什么要使用数组

为了一次性可以存储更多的数据。

数组创建的方式有哪几种

数组的创建可以通过字面量的方式或者new 的方式创建

创建数组的语法1:var 变量名 = []

创建数组的语法2:var 变量名 = new Array()

数组里面的元素可以是任意类型。

数组的遍历

在进行数组遍历之前要知道数组里面的元素是如何进行获取的,数组的索引下标是从0开始的。

var arr = ['小黑','小红','小路','小黄']

0: 小黑
1: 小红
2: 小路
3: 小黄

数组的遍历:一上面的数组为例

for(var i=0;i<arr.length;i++){
    console.log(arr[i])
}

函数

函数的使用分成两步骤:声明和使用

声明调用格式:

//正常写法
function 函数名(){
    //函数体
}

//简写
函数名(){
    //函数体
}

//匿名函数
var fun = function(){
   //函数体
}

//调用,注意这里的fun是变量名不是函数名
fun()


方法名()
    //函数声明
    function sayHi(){
        alert("Hello world")
    }
    //调用
    sayHi()

函数的参数

声明:

function 函数名(形参1,形参2 ... 形参n){
    //函数体
}

调用:

函数名(实参1,实参2 ... 实参n)

函数形参实参个数匹配问题:

        function getSum(num1,num2){
            console.log(num1 + num2)
        }
        //实参类型和形参的个数一致,正常输出结果
        getSum(1,2)
        //实参多余形参的个数,会取到形参的个数
        getSum(1,2,3)
        //小于形参的个数,形参可以被看成不用声明的变量 num2是一个变量但是没有接受值结果就是undefined
        getSum(1)

函数的返回值 return

return 语句除了可以对值进行返回以外,return还可以终止函数,return后面的语句都不执行。return只可以返回一个值

function 函数名(){
    return val
}

如果说函数没有返回值,则返回的是undefined

arguments 参数

当我们不确定有多少个参数的时候,可以使用arguments

    function fn(){
        console.log(arguments)
        console.log(arguments.length)
    }
    fn(1,2,3);
    //他是一个伪数组,并不是真正意义身上的数组
    //有数组的length属性
    //按照索引的方式进行存储
    //没有数组的pop push方法等等

作用域

javaScript中的作用域:简单来说就是变量在某个范围内起效果,目的是为了解决变量名的冲突

在es6之前:全局作用域 和 局部作用域

全局作用域:整个script标签,或者是一个单独的Js文件

局部作用域:指的就是函数内部的作用域,出了这个函数这个变量就失效了

javaScript中的两种作用域

全局作用域


    <script>
        var a = 1
    </script>

局部作用域

    <script>
        function a(num1){
            var a = 1
        }
    </script>

区分全局变量和局部变量

全局变量指的是在整个script 标签下的变量,全局变量只有当浏览器关闭以后才会销毁

局部变量指的是函数的形参、函数内部的变量。局部变量当函数执行完毕就进行销毁

作用域链

在函数中套用另外一个函数,就会生成两个作用域,看下面的例子

    <script>
        function father(){
            var number = 10
            function son(){
                console.log(number)
            }
        }
    </script>

作用域链:内部函数访问外部函数的变量,采取的是链式查找的方式来决定取那个值,这种结构称之为作用域链

javaScript 预解析

javaScript 代码是由浏览器的javaScript解析器来执行的。javascript解析器在运行JavaScript代码的时候分成两部:预解析和执行

解析器运行js分成那几步

Js引擎运行Js分成两步:预解析和执行

预解析:js引擎会把js里面所有的var 还有function 提升到当前作用域前面

代码执行:按照顺序从上往下执行

变量预解析:只做变量提升,不做赋值操作

        console.log(num);
        var num = 10;
        以上代码相当于
        var num;
        console.log(num);
        var num = 10;

函数预解析

        fun();
        var fun = function(){
            console.log(22);
        }
        //相当于执行了以下代码
        var fun;
        fun();
        var fun = function(){
            console.log(22);
        }
        

对象

什么是对象

对象是一个具体的对象。在javaScript中 , 对象是一个相关属性和方法的集合,所有的事物都是对象,比如字符串、数值、数组、函数等等。

对象的创建方式

创建对象的三种方式

方式1、 利用字面量创建

var obj = {
    uname:'张三',
    age:'18',
    sex:'男',
    sayHello(){
       console.log('hello world')
    }
}
// 对象里面的属性或者方式采用键值对的方式 属性名:属性值
// 多个方法或者属性是用逗号隔开的
// 方法冒号后面跟一个匿名函数

//对象的使用
对象名.属性
对象名.方法
对象名['属性名']

方式2、 利用new Object的方式进行创建

var obj = new Object();

//如何追加属性和方法

obj.name = '张三'
obj.age = 18
obj.sex = '男'
obj.sayHi = function(){
}

方式3、利用构造函数创建

//构造函数创建的语法格式
function 构造函数名(){
    this.属性 = 值;
    this.方法 = function(){}
}

示例1:

//创建构造函数
function Star(uname,age,sex){
  this.name = uname,
  this.age = age,
  tis.sex = sex
}

//调用
new Star('刘德华'15,'男')


//1.构造函数首字母不用大写
//2.构造函数不需要return,就可以返回结果
//3.调用函数必须使用new
//4.必须使用this.属性

new关键子的执行过程

1、在内存种创建一个空的对象

2、让this指向这个新的对象

3、执行构造函数里面的代码,给这个新对象添加属性和方法

4、返回这个新的对象

对象的遍历

对象的遍历可以通过for ... in 循环

    var obj = {
    uname:'张三',
    age:'18',
    sex:'男',
    sayHello(){
       console.log('hello world')
        }
    }
    for(var k in obj){
        console.log(k);         //属性名
        console.log(obj[k])     //属性值
    }

内置对象

javaScript里面的对象分成三大类:自定义对象、内置对象、浏览器对象

javaScript中常见的内置对象 Math、Date、Array 等等,

在这里只是简绍常见的内置对象:

Math对象

String对象

Array对象

Date对象

内置对象参考API:developer.mozilla.org/zh-CN/docs/…

DOM对象

文档对象模型DOM(Document Object Model 简称DOM),是w3c组织推荐的处理可扩展标记语言的标准编程接口。

可以通过DOM接口改变网页的内容、结构、样式等信息

DOM树

image.png

文档:一个页面就是一个文档,DOM中使用document表示

元素:页面中的所有标签都是元素,DOM中使用element表示

节点:网页中的所有内容都是节点(标签、属性、文本、注释),DOM中使用Node表示

元素的获取

getElementById("id")

获取到的是一个对象元素

    <div id="time">2022-01-22</div>
    <script>
        var timerObj = document.getElementById('time')
        console.log(timerObj);
        console.log(typeof timerObj)
    </script>

getElementsByTagName("元素名称")

通过标签元素进行获取元素,返回一组对象集合,如果没有相应的元素返回一个空的伪数组。

   <ul>
        <li>牛小牛学 javaScript</li>
        <li>牛小牛学 javaScript</li>
        <li>牛小牛学 javaScript</li>
        <li>牛小牛学 javaScript</li>
        <li>牛小牛学 javaScript</li>
    </ul>
    
    <script>
        var collectionList = document.getElementsByTagName('li')
        console.log(collectionList);
    </script>

getElementsByClassName("类元素")

根据类名进行获取,返回一组对象集合,如果没有相应的元素返回一个空的伪数组

    <div class="box">box01</div>
    <div class="box">box02</div>
    <script>
        var classObj = document.getElementsByClassName('box')
        console.log(classObj)
    </script>

querySelector("选择器")

返回指定选择器的第一个元素对象 里面的选择器需要加符号



    <div id="time">2022-01-22</div>

    <ul>
        <li>牛小牛学 javaScript</li>
        <li>牛小牛学 javaScript</li>
        <li>牛小牛学 javaScript</li>
        <li>牛小牛学 javaScript</li>
        <li>牛小牛学 javaScript</li>
    </ul>

    <div class="box">box01</div>
    <div class="box">box02</div>

  <script>
        var classBox = document.querySelector('.box')
        var idSelect = document.querySelector('#time')
        var liSelect = document.querySelector('li')

        console.log(classBox);
        console.log(idSelect);
        console.log(liSelect);
  </script>

querySelectorAll("选择器")

    <div id="time">2022-01-22</div>

    <ul>
        <li>牛小牛学 javaScript</li>
        <li>牛小牛学 javaScript</li>
        <li>牛小牛学 javaScript</li>
        <li>牛小牛学 javaScript</li>
        <li>牛小牛学 javaScript</li>
    </ul>

    <div class="box">box01</div>
    <div class="box">box02</div>
    
    <script>
        var classAll = document.querySelectorAll('.box')
        var idSelectAll = document.querySelectorAll('#time')
        var liSelectAll = document.querySelectorAll('li')

        console.log(classAll);
        console.log(idSelectAll);
        console.log(liSelectAll);
    </script>

body的获取方式

    var bodyEle = document.body
    console.log(bodyEle);

Html根元素的获取方式

    var htmlEle = document.documentElement
    console.log(htmlEle);

事件基础

什么是事件:可以被javaScript侦测到的行为,动作

事件的三要素: 事件源、事件类型、事件处理程序

案例:

<body>
    <!-- 事件的三要素: 事件源、事件类型、事件处理程序 -->
    <button id="btn">牛小牛</button>

    <script>
        /*
            可以被javaScript侦测到的行为,动作
        */
        
        //1.事件源
        var btn = document.getElementById("btn")
        //2.事件类型
        btn.onclick = function(){
            //3.事件处理程序
            alert("正在学习中.....")
        }
    </script>
</body>

通过事件操作内容

小案例:

<body>
    <button>点击我</button>
    <div>我的名字是:</div>
    <script>
        var btn = document.querySelector('button')
        var divObj = document.querySelector('div')

        btn.onclick = function(){
            divObj.innerText = divObj.innerText + '牛小牛'
        }
    </script>
</body>

image.png

image.png

innerText 和 innerHtml之间的区别

innerText是不识别html标签的,他会去除掉空格和换行

innerHTML 是识别html标签的并且不会去除空格和换行

节点操作

主要是利用父子兄弟节点的关系来对元素进行获取

获取元素的父节点

通过 element.parentNode

    <div class="parentNode">
        <p class="son">p text</p>
    </div>

    <script>
        var pNode = document.querySelector('.son')
        var father = pNode.parentNode;
        console.log(father);
    </script>

parentNode 返回的是最近的一个父节点,如果没有指定的父节点则返回null

操作子节点

方式一: 通过 element.childNodes

<ul id="father">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
</ul>

<script>
    var fatherNode = document.querySelector('#father')
    var sonNode = fatherNode.childNodes
    console.log(sonNode);
</script>

image.png

element.childNodes 会获取到所有的子节点包含元素节点文本节点等等

方式二:通过 element.children

    <ul id="father">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>

    <script>
        var fatherNode = document.querySelector('#father')
        var childrenNode = fatherNode.children
        console.log(childrenNode);
    </script>

image.png

节点操作获取第一个和最后一个元素

<body>
    <ol id="ol">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ol>

    <script>
        var father = document.getElementById("ol")
        /*firestNode 获取到第一个子节点,不管是文本节点还是元素节点*/
        var firestNode = father.firstChild
        var lastNode = father.lastChild
        
        /*firstElementChild 返回第一个子元素节点 IE 9 以上兼容*/
        var firestNode1 = father.firstElementChild
        var lastNode1 = father.lastElementChild

        console.log(firestNode);
        console.log(lastNode);
        console.log(firestNode1);
        console.log(lastNode1);
    </script>
</body>

image.png

获取兄弟元素信息

<body>
    <div>我是div</div>
    <span>我是span</span>

    <script>
        var divEle = document.querySelector('div')
        //nextSibling 下一个兄弟节点,包含元素节点或者文本节点等等
        var nextEle =  divEle.nextSibling 
        var preEle = divEle.previousSibling

        //nextElementSibling 得到下一个兄弟元素节点
        var nextEle1 = divEle.previousElementSibling
        var preEle1 = divEle.nextElementSibling

        console.log(nextEle);
        console.log(preEle);
        console.log(nextEle1);
        console.log(preEle1);

    </script>
</body>

image.png

节点的创建操作以及追加操作

创建节点的方式: document.createElement("tagName") document.createElement("tagName") 方法创建是由tagName指定的HTML元素。因为这些元素原先不存在,是根据我们的需求动态生成的,所以我们也称之为动态创建元素节点。

元素的追加操作:

node.appendChild("追加的节点")

node.insertBefore(要追加的元素,目标元素的位置)

<body>
    <div>
        <p>我是 p</p>
    </div>

    <script>
          //创建一个节点
          var p = document.createElement("p")
          //添加一个节点 appendChild 这个方法类似于元素的追加
          var node = document.querySelector('div')
          node.appendChild(p)
          //将创建的元素追加到指定的位置 node.insertBefore(要追加的元素,目标元素的位置)
          var span = document.createElement("span")
          node.insertBefore(span,node.children[0])

    </script>
</body>

image.png

节点的删除操作

删除节点操作:node.removeChild(要删除的节点)

<body>
    <button>删除</button>
    <ul>
        <li>熊大</li>
        <li>熊二</li>
        <li>熊三</li>
    </ul>
    <script> 
        var btn = document.querySelector('button')

        var ul = document.querySelector('ul')

        btn.onclick = function(){
            ul.removeChild(ul.firstElementChild)
        }
    </script>
</body>

节点的拷贝

节点拷贝:node.cloneNode()

    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
    </ul>

    <script>
        /*节点的克隆操作*/
        var ul = document.querySelector('ul')
        // cloneNode(true) 深拷贝,拷贝标签和内容  cloneNode() 浅拷贝
        var lili = ul.children[0].cloneNode(true)
        ul.appendChild(lili)
    </script>

事件高级

事件的注册方式

给元素添加事件,称之为注册事件或者事件绑定

注册事件有两种方式:传统方式和方法监听的方式

传统的注册方式:利用 on 开头的事件 "onClick",特点:注册事件的唯一性,同一个元素同一个事件只能处理一个函数,最后注册的函数会覆盖掉前面注册的函数

<body>
    <button onclick="alert('Hii ~')">按钮一</button>
    <button>按钮二</button>

    <script>
        var btns = document.querySelectorAll('button')
        btns[1].onclick = function(){
            alert('Hi ~')
        }
        btns[1].onclick = function(){
            alert('Hi 牛小牛 ~')
        }
    </script>
</body>

使用监听注册方式

addEventListener 事件监听方式(非标准:IE9 以上才支持)

<body>
    <button onclick="alert('Hii ~')">按钮一</button>
    <button>按钮二</button>
    <button>按钮三</button>
    <script>
        var btns = document.querySelectorAll('button')
        /*
            1、传统的事件注册方式
        */
        btns[1].onclick = function(){
            alert('Hi ~')
        }
        btns[1].onclick = function(){
            alert('Hi 牛小牛 ~')
        }
        /*
            1、注册监听器事件addEventListener IE 9 以上才支持

            (1)里面的事件类型是字符串,事件的名称不要加on
            (2)同一个元素,同一个事件是可以添加多个监听器的
        */
        btns[2].addEventListener('click',function(){
            alert('我是小牛')
        })
        btns[2].addEventListener('click',function(){
            alert('我是大牛')
        })
    </script>
</body>

attatchEvent 事件监听方式 支持 IE8以及以前的版本

这个方法接收两个参数:

  • eventNameWithOn:事件类型字符串,比如onClick、onmouseover,这里要带on

  • callback:事件处理函数,当目标触发事件时候回调函数被调用

在以上代码中添加如下内容

    btns[3].attatchEvent('onclick',function(){
        alert('我是Attatch')
    })

删除事件的两种方式(事件解绑)

<style>
    div{
        width: 200px;
        height: 200px;
        background-color: pink;
    }
</style>

<body>

    <div>1</div>
    <div>2</div>
    <div>3</div>


    <script>
        var divs = document.getElementsByTagName('div')
        /*方式一、 事件解绑*/
        divs[0].onclick = function(){
            alert(11)
            divs[0].onclick = null
        }


        /*方式二、 事件解绑 */
        divs[1].addEventListener('click',fn)

        function fn(){
            alert('div2')
            divs[1].removeEventListener('click',fn)
        }

        /*方式三、事件解绑 */
        divs[2].attatchEvent('onclick',fn1)
        function fn1(){
            alert('div2')
            divs[1].detachEvent('click',fn1)
        }
    </script>
</body>

DOM事件流的三个阶段

事件冒泡

事件委托