初步认识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 0 | false |
| 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(表达式){
case 值1:
语句1;
break;
case 值2:
语句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树
文档:一个页面就是一个文档,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>
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>
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>
节点操作获取第一个和最后一个元素
<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>
获取兄弟元素信息
<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>
节点的创建操作以及追加操作
创建节点的方式: 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>
节点的删除操作
删除节点操作: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>