1.ECMAScript
1.初识JavaScript
1.初识JavaScript
1.1 JavaScript 是什么
-
布兰登艾奇(BrendanEich,1961年~)
-
神奇的大哥在1995年利用10天完成JavaScript设计
-
网景公司最初命名为LiveScript,后来在与Sun合作之后将其改名为JavaScript.
-
JavaScript是世界上最流行的语言之一,是一种运行在客户端的脚本语言(Script 是脚本的意思)。
-
脚本语言:不需要编译,运行过程中由js 解释器(js 引)逐行来进行解释并执行
-
现在也可以基于Node.js 技术进行服务器端编程
1.2 JavaScript 的作用
-
表单动态校验(密码强度检测) ( JS 产生最初的目的)
-
网页特效
-
服务端开发(Nodejs)
-
桌面程序(Electron)
-
App(Cordova)
-
控制硬件-物联网(Ruff)
-
游戏开发(cocos2d-js)
1.3 HTML/CSS/JS 的关系
HTML/CSS 标记语言--描述类语言
-
HTML决定网页结构和内容(决定看到什么),相当于人的身体
-
CSS决定网页呈现给用户的模样(决定好不好看)相当于给人穿衣服、化妆
JS 脚本语言--编程类语言
-
实现业务逻辑和页面控制(决定功能),相当于人的各种动作
1.4浏览器执行JS简介
浏览器分成两部分:渲染引擎和JS引擎
-
渲染引擎:用来解析HTML与CSS,俗称内核,比如chrome 浏览器的 blink,老版本的webkit
-
JS引擎:也称为JS解释器。用来读取网页中的JavaScript代码,对其外理后运行,比如chrome 浏览器的V8
浏览器本身并不会执行JS代码,而是通过内置JavaScript引警(解程器)来执行JS 代码。JS引警执行代码时逐行解释每一句源码(转换为机器语言),然后由计算机去执行,所以JvaScript语言归为脚本语言,会逐行解释执行。
1.5 JS的组成
1.ECMAScript
ECMAScript是由ECMA国际( 原欧洲计算机制造商协会)进行标准化的一门编程语言,这种语言在万维网上应用广泛,它往往被称为JavaScript或JScript,但实际上后两者是ECMAScript语言的实现和扩展
ECMAScript: ECMAScript规定了JS的编程语法和基础核心知识,是所有浏览器厂商共同遵守的一套JS语法工业标准。
2.DOM-文档对象模型
文档对象模型(DocumentObjectModel,简称DOM),是W3C组织推荐的处理扩展标记语言的标准编程接口。通过 DOM提供的接口可以对页面上的各种元素进行操作(大小、位置、颜色等)
3.BOM-浏览器对象模型
BOM(Browser ObjectModel,简称BOM)是指浏览器对象模型,它提供了独立于内容的、可以与浏览器窗口进行互动的对象结构。通过BOM可以操作浏览器窗口,比如弹出框、控制浏览器跳转、获取分辨率等.
1.6 JS初体验
JS有3种书写位置,分别为行内、内嵌和外部
1.行内JS
<input type="button"value="点我试试"οnclick="alert('Hello World')"/>
-
可以将单行或少量JS 代码写在HTML标签的事件属性中(以on 开头的属性),如:onclick。
-
注意单双引号的使用:在HTML中我们推荐使用双引号,JS 中我们推荐使用单引号
-
可读性差,在html中编写JS大量代码时,不方便阅读;
-
引号易错,引号多层嵌套匹配时,非常容易弄混;
-
特殊情况下使用
2.内嵌JS
<script> alert("Hello world~!"); </script>
-
可以将多行JS代码写到
<script>
标签中 -
内嵌JS是学习时常用的方式
3.外部JS文件
<script src="my.js"></script>
-
利于HTML页面代码结构化,把大段JS代码独立到HTML页面之外,既美观,也方便文件级别的复用
-
引用外部JS文件的script标签中间不可以写代码
-
适合JS代码量比较大的情况
2. JavaScript注释
2.1 单行注释
为了提高代码的可读性,JS与CSS一样,也提供了注释功能。JS中的注释主要有两种,分别是单行注释和多行注释。 单行注释的注释方式如下:
// 我是一行文字,不想被 JS引擎 执行,所以 注释起来
// 用来注释单行文字( 快捷键 ctrl + / )
2.2 多行注释
多行注释的注释方式如下:
/* 获取用户年龄和姓名 并通过提示框显示出来 */
/* */ 用来注释多行文字( 默认快捷键 alt + shift + a )
3.JavaScript 输入输出语句
为了方便信息的输入输出,JS中提供了一些输入输出语句,其常用的语句如下
注意:alert() 主要用来显示消息给用户,console.log() 用来给程序员自己看运行时的消息。
2.变量
1.变量概述
1.什么是变量
白话:变量就是一个装东西的盒子
通俗:变量是用于存放数据的容器。我们通过变量名获取数据,甚至数据可以修改
2.变量在内存中的存储
本质:变量是程序在内存中申请的一块用来存放数据的空间
类似我们酒店的房间,一个房间就可以看做是一个变量
2.变量的使用
1.声明变量
// 声明变量 var age; // 声明一个名称为age的变量
-
var是一个JS关键字,用来声明变量(variable 变量的意思)。使用该关健字声明变量后,计算机会自动为变量分配内存空间,不需要程序员管
-
age 是程序员定义的变量名,我们要通过变量名来访问内存中分配的空间
2.赋值
age = 10; // 给 age 这个变量赋值为 10
-
= 用来把右边的值赋给左边的变量空间中 此处代表赋值的意思
-
变量值是程序员保存到变量空间里的值
3. 变量的初始化
var age = 18; // 声明变量同时赋值为 18
声明一个变量并赋值, 我们称之为变量的初始化
3. 变量语法扩展
1.更新变量
个变量被重新复喊值后,它原有的值就会被覆盖,变量值将以最后一次赋的值为准
var age = 18; age = 81; //最后的结果就是81因为18被覆盖掉了
2.同时声明多个变量
同时声明多个变量时,只需要写一个var,多个变量名之间使用英文逗号隔开
var age = 10,name ='zs',sex = 2;
3.声明变量特殊情况
4.变量命名规范
-
由字母(A-Za-z)、数字(0-9)、下划线()、美元符号(S)组成,如 : usrAgenum01,name
-
严格区分大小写。varapp;和var App;是两个变量
-
不能以数字开头。 18age 是错误的
-
不能是关键字、保留字。例如 :var、for、while
-
变量名必须有意义。MMD BBDnl -age
-
遵守驼峰命名法。首字母小写,后面单词的首字母需要大写。 myfirstName
5.小结
-
为什么需要变量?
因为我们一些数据需要保存,所以需要变量
-
变量是什么?
变量就是一个容器,用来存放数据的。方便我们以后使用里面的数据
-
变量的本质是什么?
变量是内存里的一块空间,用来存储数据
-
变量怎么使用的?
我们使用变量的时候,一定要声明变量,然后赋值
声明变量本质是去内存申请空间。
-
什么是变量的初始化?
声明变量并赋值我们称之为变量的初始化
3.数据类型
1.数据类型简介
1.1为什么需要数据类型
在计算机中,不同的数据所需占用的存储空间是不同的,为了便于把数据分成所需内存大小不同的数据,充分利用存储空间,于是定义了不同的数据类型
简单来说,数据类型就是数据的类别型号。比如姓名“张三”,年龄18,这些数据的类型是不一样的.
1.2变量的数据类型
变量是用来存储值的所在处,它们有名字和数据类型。变量的数据类型决定了如何将代表这些值的位存储到计算机的内存中。JavaScript 是一种弱类型或者说动态语言。这意味着不用提前声明变量的类型,在程序运行过程中,类型会被自动确定。
var age = 10;//这是一个数字型 var areYouok =‘是的’: //这是一个字符串
在代码运行时,变量的数据类型是由JS引擎根据 = 右边变量值的数据类型来判断的,运行完毕之后,变量就确定了数据类型
JavaScript拥有动态类型,同时也意味看相同的变量可用作不同的类型 :
var X = 6;//x为数字 var x = "Bill";//x为字符串
1.3 数据类型的分类
JS 把数据类型分为两类:
-
简单数据类型 (Number,String,Boolean,Undefined,Null)
-
复杂数据类型 (object)
2.简单数据类型
2.1简单数据类型(基本数据类型)
JavaScript中的简单数据类型及其说明如下
2.2 数字型 Number
JavaScript数字类型既可以用来保存整数值,也可以保存小数(浮点数)
var age = 21; //整数 var Age = 21.3747; // 小数
1.数字型进制
最常见的进制有二进制、八进制、十进制、十六进制。
// 1八进制数字序列范围:0~7 var num1 = 07; // 对应十进制的7 var num2 = 019; // 对应十进制的19 var num3 = 08;// 对应十进制的8 // 2.十六进制数字序列范国 :0~9以及A~F var num = 0xA;
在JS中八进制前面加0,十六进制前面加0x
2.数字型范围
JavaScript中数值的最大和最小值
alert(Numloer.MAX_VALUE);// 17976931348623157e+308 alert(Number.MIN_VALUE); // 5e-324
-
最大值:Number.MAX _VALUE,这个值为:17976931348623157e+308。
-
最小值:Number.MIN _VALUE,这个值为:5e-32
3.数字型三个特殊值
alert(Infinity); // Infinity alert(-Infinity); // -Infinity alert (NaN) ;// NaN
-
Infinity,代表无穷大,大于任何数值
-
-Infinity,代表无穷小,小于任何数值
-
NaN,Notanumber,代表一个非数值
4.isNaN0
用来判断一个变量是否为非数字的类型,返回true 或者false
var usrAge = 21; var isok = isNaN(userAge); console.log(isNun); // false ,21 不是一个非数字 var usrName = "andy" ; console.log(isNan(userName)); // true ,"andy"是一个非数字
2.3 字符串型 String
1.字符串引号嵌套
JS 可以用单引号嵌套双引号,或者用双引号嵌套单引号(外双内单,外单内双)
var strMsg =‘我是”高帅富”程序猿 ’; // 可以用‘ ’包含" “ var strMsg2 =“我是‘高帅富’程序猿”; // 也可以用” “包含’‘ // 常见错误 var badquotes =’what on earth?"; // 报错,不能单双引号搭配
2.字符串转义符
类似HTML里面的特殊字符,字符串中也有特殊字符,我们称之为转义符
转义符都是\开头的,常用的转义符及其说明如下
3.字符串长度
字符串是由若干字符组成的,这些字符的数量就是字符串的长度。通过字符串的length 属性可以获取整个字符串的长度。
var strMsg ="我是帅气多金的程序猿!"; alert(strMsg.length); // 显示11
4.字符串拼接
-
多个字符串之间可以使用 + 进行拼接,其拼接方式为字符串 + 任何类型 = 拼接之后的新字符串
-
拼接前会把与字符串相加的任何类型转成字符串,再拼接成一个新的字符串
//1.1 字符串”相加” alert(‘hello’+‘world'); // hello world //1.2 数值字符串”相加” alert(‘100' +‘100’); // 100100 //1.3 数值字符 + 数值 alert(‘11' + 12) // 1112
+号总结口诀: 数值相加,字符相连
5.字符串拼接加强
console.log(‘我’+ 18);//只要有字符就会相连 var age = 18; // console.log('我age岁啦’ );//这样不行 console.log(‘我 ’+ age); // 我18 console.log('我'+ age +‘岁啦’) ; // 我18岁啦
-
我们经常会将字符串和变量来拼接,因为变量可以很方便地修改里面的值
-
变量是不能添加引号的,因为加引号的变量会变成字符串
-
如果变量两侧都有字符串拼接,口诀“引引加加”,删掉数字,变量写加中间
2.4 布尔型 Boolean
布尔类型有两个值:true和false,其中 true 表示真(对),而false 表示假(错)
布尔型和数字型相加的时候,true的值为1,false 的值为 0
console.log(true + 1); // 2 console.log(false + 1); // 1
2.5 Undefined 和Null
一个声明后没有被赋值的变量会有一个默认值undefined(如果进行相连或者相加时,注意结果)
var variable; console.log(variable); // udefined console.log(‘你好’+ variable); // 你好undefined console.log(11 + variable); // NaN console.log(true + variable); //NaN
一个声明变早给null 值,里面存的值为空(学习对象时,我们继研究nulD)
var vari = null; console.log('你好'+ vari); // 你好nul1 console.log(11 + vari) ; //11 console.log(true + vari); // 1
3.获取变量数据类型
3.1获取检测变量的数据类型
typeof可用来获取检测变量的数据类型
var num = 18; console.log(typeof num) // 结果 number
不同类型的返回值
3.2 字面量
字面量是在源代码中一个固定值的表示法,通俗来说,就是字面量表示如何表达这个值.
-
数字字面量: 8 9 10
-
字符串字面量:'程序员',"大前端"
-
布尔字面量:true,false
4.数据类型转换
4.1什么是数据类型转换
使用表单、prompt获取过来的数据默认是字符串类型的,此时就不能直接简单的进行加法运算,而需要转换变量的数据类型。通俗来说,就是把一种数据类型的变量转换成另外一种数据类型
我们通常会实现3种方式的转换:
-
转换为字符串类型
-
转换为数字型
-
转为布尔型
4.2转换为字符串
-
toString()和String() 使用方式不一样。
-
三种转换方式,我们更喜欢用第三种加号拼接字符串转换方式,这一种方式也称之为隐式转换
4.3转换为数字型(重点)
-
注意parselnt和 parseFloat单词的大小写,这2个是重点
-
隐式转换是我们在进行算数运算的时候,JS自动转换了数据类型
4.4转换为布尔型
-
代表空、否定的值会被转换为 false,如”、0、NaN、null、undefined
-
其余值都会被转换为true
console.log(Boolean(' ')); // false console.log(Boolean(0)); // false console.log(Boolean(NaN)); // false console.log(Boolean(null)); // false console.log(Boolean(undefined)); // false console.log(Boolean('小白'));// true console.log(Boolean(12)); // true
4.运算符
1.运算符的分类
运算符(operator)也被称为操作符,是用于实现赋值、比较和执行算数运算等功能的符号。
JavaScript中常用的运算符有:
-
算数运算符
-
递增和递减运算符
-
比较运算符
-
逻辑运算符
-
赋值运算符
2算数运算符
1.算术运算符概述
概念:算术运算使用的符号,用于执行两个变量或值的算术运算
2.浮点数的精度问题
浮点数值的最高精度是17 位小数,但在进行算术计算时其精确度远远不如整数
var result = 0.1 + 0.2;// 结果不是 0.3,而是:0.30000000000000004 console.log(0.07* 100); // 结果不是 7, 而是:7.000000000000001
所以:不要直接判断两个浮点数是否相等!
3.表达式和返回值
表达式:是由数字、运算符、变量等以能求得数值的有意义排列方法所得的组合
简单理解:是由数字、运算符、变量等组成的式子
表达式最终都会有一个结果,返回给开发者,称为返回值
3.递增和递减运算符
1.递增和递减运算符概述
如果需要反复给数字变量添加或减去1,可以使用递增( ++和递减( - -) 运算符来完成
在JavaScript中,递增(++)和递减( -- )既可以放在变量前面,也可以放在变量后面,放在变量前面时我们可以称为前舌递增(涕减)运算符,放在变量后面时,我们可以称为后递增(递减 运算符
注意: 递增和递减运算符必须和变量配合使用
2.递增运算符
1.前置递增运算符
++num 前置递增,就是自加1,类似于num = num + 1,但是++num 写起来更简单
使用口诀: 先自加,后返回值
2.后置递增运算符
num++ 后置递增,就是自加1,类似于num = num +1,但是num++ 写起来更简单
使用口诀:先返回原值,后自加
4.比较运算符
4.1比较运算符概述
概念:比较运算符(关系运算符)是两个数据进行比较时所使用的运算符,比较运算后,会返回一个布尔值(true /false)作为比较运算的结果
-
等号比较
console.log(18 =='18' ); console.log(18 ==='18');
5.逻辑运算符
1.逻辑运算符概述
概念:逻辑运算符是用来进行布尔值运算的运算符,其返回值也是布尔值。后面开发中经常用于多个条件的判断
2.逻辑与&&
两边都是 true才返回 true,否则返回 false
3.逻辑或 ||
两边都是 true才返回 true,否则返回 false
4.逻辑非 !
逻辑非(!)也叫作取反符,用来取一个布尔值相反的值,如 true 的相反值是 false
var isOk = !true; console.log(isOk); // false
5. 短路运算(逻辑中断)
短路运算的原理:当有多个表式(值)时左边的表达式值可以确定结果时,就不再继运算右边的表达式的值
6.逻辑与
语法:表达式1 && 表达式2
如果第一个表达式的值为真,则返回表达式2
如果第一个表达式的值为假,则返回表达式1
console.log( 123 && 456 ); // 456 console.log( 0 && 456 ); // 0 console.log( 123 && 456&& 789 ); // 789
7.逻辑或
语法: 表达式1||表达式2
如果第一个表达式的值为真,则返回表达式1
如果第一个表达式的值为假,则返回表达式2
console.log( 123 || 456 );// 123 console.log( 0 || 456 ); //456 console.log( 123 || 456 || 789 ); // 123
6.赋值运算符
概念:用来把数据赋值给变量的运算符。
7.运算符优先级
-
一元运算符里面的逻辑非优先级很高
-
逻辑与比逻辑或优先级高
5.流程控制
1 流程控制概念
在一个程序执行的过程中,各条代码的执行顺序对程序的结果是有直接影响的。很多时候我们要通过控制代码的执行 顺序来实现我们要完成的功能。
简单理解:流程控制就是来控制代码按照一定结构顺序来执行
流程控制主要有三种结构,分别是顺序结构、分支结构和循环结构,代表三种代码执行的顺序。
2.顺序流程控制
顺序结构是程序中最简单、最基本的流程控制,它没有特定的语法结构,程序会按照代码的先后顺序,依次执行, 程序中大多数的代码都是这样执行的。
3.分支流程控制
-
分支结构
由上到下执行代码的过程中,根据不同的条件,执行不同的路径代码(执行代码多选一的过程),从而得到 不同的结果
JS 语言提供了两种分支结构语句:if 语句、switch 语句
-
if 语句
-
语法结构
// 条件成立执行代码,否则什么也不做 if (条件表达式) { // 条件成立执行的代码语句 }
语句可以理解为一个行为,循环语句和分支语句就是典型的语句。一个程序由很多个语句组成,一般情况下, 会分割成一个一个的语句。
-
-
if else语句(双分支语句)
-
语法结构
// 条件成立 执行 if 里面代码,否则执行else 里面的代码 if (条件表达式) { // [如果] 条件成立执行的代码 } else { // [否则] 执行的代码 }
-
-
if else if 语句(多分支语句)
-
语法结构
// 适合于检查多重条件。 if (条件表达式1) { 语句1; } else if (条件表达式2) { 语句2; } else if (条件表达式3) { 语句3; .... } else { // 上述条件都不成立执行此处代码 }
-
4.三元表达式
-
语法结构
表达式1 ? 表达式2 : 表达式3;
-
执行思路
-
如果表达式1为 true ,则返回表达式2的值,如果表达式1为 false,则返回表达式3的值
-
简单理解: 就类似于 if else (双分支) 的简写
-
5 switch分支流程控制
-
语法结构
switch 语句也是多分支语句,它用于基于不同的条件来执行不同的代码。当要针对变量设置一系列的特定值 的选项时,就可以使用 switch。
switch( 表达式 ){ case value1: // 表达式 等于 value1 时要执行的代码 break; case value2: // 表达式 等于 value2 时要执行的代码 break; default: // 表达式 不等于任何一个 value 时要执行的代码 }
-
switch :开关 转换 , case :小例子 选项
-
关键字 switch 后面括号内可以是表达式或值, 通常是一个变量
-
关键字 case , 后跟一个选项的表达式或值,后面跟一个冒号
-
switch 表达式的值会与结构中的 case 的值做比较
-
如果存在匹配全等(===) ,则与该 case 关联的代码块会被执行,并在遇到 break 时停止,整个 switch 语句代 码执行结束
-
如果所有的 case 的值都和表达式的值不匹配,则执行 default 里的代码
注意: 执行case 里面的语句时,如果没有break,则继续执行下一个case里面的语句.
-
switch 语句和 if else if 语句的区别
-
一般情况下,它们两个语句可以相互替换
-
switch...case 语句通常处理 case为比较确定值的情况, 而 if…else…语句更加灵活,常用于范围判断(大 于、等于某个范围)
-
switch 语句进行条件判断后直接执行到程序的条件语句,效率更高。而if…else 语句有几种条件,就得 判断多少次。
-
当分支比较少时,if… else语句的执行效率比 switch语句高。
-
当分支比较多时,switch语句的执行效率比较高,而且结构更清晰。
-
6.数组
1.数组的概念
问:之前学习的数据类型,只能存储一个值。如果我们想存储班级中所有学生的姓名,那么该如何存储呢?
答:可以使用数组(Array)。数组可以把一组相关的数据一起存放,并提供方便的访问(获取)方式。
问:什么是数组呢?
答:数组是指一组数据的集合,其中的每个数据被称作元素,在数组中可以存放任意类型的元素。数组是一 种将一组数据存储在单个变量名下的优雅方式。
// 普通变量一次只能存储一个值 var num = 10; // 数组一次可以存储多个值 var arr = [1,2,3,4,5];
2.创建数组
2.1 数组的创建方式
JS 中创建数组有两种方式:
-
利用 new 创建数组
-
利用数组字面量创建数组
2.2 利用 new 创建数组
var 数组名 = new Array() ; var arr = new Array(); // 创建一个新的空数组
-
注意 Array () ,A 要大写
2.3利用数组字面量创建数组
//1.使用数组字面量方式创建空的数组 var 数组名 = []; //2.使用数组字面量方式创建带初始值的数组 var 数组名 = ['小白 ','小黑' ,'大黄','瑞奇'];
-
数组的字面量是方括号[]
-
声明数组并赋值称为数组的初始化
-
这种字面量方式也是我们以后最多使用的方式
2.4 数组元素的类型
数组中可以存放任意类型的数据,例如字符串,数字,布尔值等。
var arrStus = ['小白',12,true,28.9];
3. 获取数组元素
3.1 数组的索引
索引 (下标) :用来访问数组元素的序号(数组下标从 0 开始)。
数组可以通过索引来访问、设置、修改对应的数组元素,我们可以通过“数组名[索引]”的形式来获取数组中的 元素。
这里的访问就是获取得到的意思
// 定义数组 var arrStus = [1,2,3]; // 获取数组中的第2个元素 alert(arrStus[1]);
4.遍历数组
4.1数组的长度
使用“数组名.length”可以访问数组元素的数量(数组长度)
var arrStus = [1,2,3]; alert(arrStus.length); // 3
注意:
① 此处数组的长度是数组元素的个数 ,不要和数组的索引号混淆。
② 当我们数组里面的元素个数发生了变化,这个 length 属性跟着一起变化。
5.数组中新增元素
5.1 通过修改length 长度新增数组元素
-
可以通过修改length长度来实现数组扩容的目的
-
length 属性是可读写的
var arr = ['red',green',"blue",pink"]; arr.length = 7; console.log(arr); console.log(arr[4]) console.log(arr[5]): console.log(arr[6]);
其中索引号是4,5,6的空间没有给值,就是声明变量未给值,默认值就是undefined.
5.2 通过修改数组索引新增数组元素
-
可以通过修改数组索引的方式追加数组元素
-
不能直接给数组名赋值,否则会覆盖掉以前的数据
var arr = ['red','green','blue','pink']; arr[4] = 'hotpink'; console.log(arr) ;
这种方式也是我们最常用的一种方式
7.函数
1.函数的使用
函数在使用时分为两步:声明函数和调用函数
1.声明函数
//声明函数 function 函数名(){ //函数体代码 }
function 是声明函数的关键字,必须小写
由于函数一般是为了实现某个功能才定义的,所以通常我们将函数名命名为动词,比如 getSum
2.调用函数
// 调用函数 函名(); // 通过调用函名来执行函数体代码
调用的时候千万不要忘记添加小括号
口诀:函数不调用,自己不执行。
注意: 声明函数本身并不会执行代码,只有调用函数时才会执行函数体代码.
3.函数的返回值
函数没有 return 返回 undefined
函数都是有返回值的
1.如果有return则返回 return 后面的值
2.如果没有return 则返回undefined
4.arguments的使用
当我们不确定有多少个参数传递的时候,可以用arguments来获取。在JavaScript中,arguments实际上它是当前函数的一个内置对象。所有函数都内置了一个arguments对象,arguments对象中存储了传递的所有实参
arguments展示形式是一个伪数组,因此可以进行遍历。伪数组具有以下特点:
具有length 居性
按索引方式储存数据
不具有数组的push,pop等方法
8.作用域
1.作用域
1.1 作用域概述
通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字 的作用域。作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。 JavaScript(es6前)中的作用域有两种:
-
全局作用域
-
局部作用域(函数作用域)
1.2 全局作用域
作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js 文件。
1.3 局部作用域
作用于函数内的代码环境,就是局部作用域。 因为跟函数有关系,所以也称为函数作用域
1.4 JS没有块级作用域
块作用域由 { } 包括。
在其他编程语言中(如 java、c#等),在 if 语句、循环语句中创建的变量,仅仅只能在本 if 语句、本循环语 句中使用,如下面的Java代码:
java有块级作用域:
if(true){ int num = 123; system.out.print(num); // 123 } system.out.print(num); // 报错
以上java代码会报错,是因为代码中 { } 即一块作用域,其中声明的变量 num,在 “{ }” 之外不能使用;
而与之类似的JavaScript代码,则不会报错: Js中没有块级作用域(在ES6之前)
if(true){ var num = 123; console.log(123); //123 } console.log(123); //123
2.变量的作用域
在JavaScript中,根据作用域的不同,变量可以分为两种:
-
全局变量
-
局部变量
2.1 全局变量
在全局作用域下声明的变量叫做全局变量(在函数外部定义的变量)。
-
全局变量在代码的任何位置都可以使用
-
在全局作用域下 var 声明的变量 是全局变量
-
特殊情况下,在函数内不使用 var 声明的变量也是全局变量(不建议使用)
2.2 局部变量
在局部作用域下声明的变量叫做局部变量(在函数内部定义的变量)
-
局部变量只能在该函数内部使用
-
在函数内部 var 声明的变量是局部变量
-
函数的形参实际上就是局部变量
2.3 全局变量和局部变量的区别
-
全局变量:在任何一个地方都可以使用,只有在浏览器关闭时才会被销毁,因此比较占内存
-
局部变量:只在函数内部使用,当其所在的代码块被执行时,会被初始化;当代码块运行结束后,就会被销 毁,因此更节省内存空间
3.作用域链
只要是代码都一个作用域中,写在函数内部的局部作用域,未写在任何函数内部即在全局作用域中;
如果函数中还有 函数,那么在这个作用域中就又可以诞生一个作用域;
根据在内部函数可以访问外部函数变量的这种机制,用 链式查找决定哪些数据能被内部函数访问,就称作作用域链
4.预解析
4.1 预解析的相关概念
JavaScript 代码是由浏览器中的 JavaScript 解析器来执行的。JavaScript 解析器在运行 JavaScript 代码的时候分为两 步:预解析和代码执行。
-
预解析:在当前作用域下, JS 代码执行之前,浏览器会默认把带有 var 和 function 声明的变量在内存中进行提 前声明或者定义。
-
代码执行: 从上到下执行JS语句。 预解析会把变量和函数的声明在代码执行之前执行完成。
4.2 变量预解析
-
预解析也叫做变量、函数提升。
-
变量提升(变量预解析): 变量的声明会被提升到当前作用域的最上面,变量的赋值不会提升。
console.log(num); // 结果是多少? var num = 10; // ?
结果:undefined
注意:变量提升只提升声明,不提升赋值
4.3 函数预解析
函数提升: 函数的声明会被提升到当前作用域的最上面,但是不会调用函数。
fn(); function fn() { console.log('打印'); }
结果:控制台打印字符串 --- ”打印“
注意:函数声明代表函数整体,所以函数提升后,函数名代表整个函数,但是函数并没有被调用!
4.4 函数表达式声明函数问题
函数表达式创建函数,会执行变量提升,此时接收函数的变量名无法正确的调用:
fn(); var fn = function() { console.log('想不到吧'); }
结果:报错提示 ”fn is not a function"
解释:该段代码执行之前,会做变量声明提升,fn在提升之后的值是undefined;而fn调用是在fn被赋值为函数体之 前,此时fn的值是undefined,所以无法正确调用
9.对象
1.对象的相关概念
-
什么是对象?
-
在 JavaScript 中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串、数值、数 组、函数等。
-
对象是由属性和方法组成的。
-
-
属性:事物的特征,在对象中用属性来表示(常用名词)
-
方法:事物的行为,在对象中用方法来表示(常用动词)
-
为什么需要对象?
-
保存一个值时,可以使用变量,保存多个值(一组值)时,可以使用数组。
如果要保存一个人的完整信息呢? 例如,将“张三疯”的个人的信息保存在数组中的方式为:
var arr = [‘张三疯’, ‘男', 128,154];
上述例子中用数组保存数据的缺点是:数据只能通过索引值访问,开发者需要清晰的清除所有的数据的排行才能准 确地获取数据,而当数据量庞大时,不可能做到记忆所有数据的索引值。
为了让更好地存储一组数据,对象应运而生:对象中为每项数据设置了属性名称,可以访问数据更语义化,数据结 构清晰,表意明显,方便开发者使用。
使用对象记录上组数据为:
var obj = { "name":"张三疯", "sex":"男", "age":128, "height":154 }
-
2 创建对象的三种方式
1.利用字面量创建对象
使用对象字面量创建对象:
就是花括号 { } 里面包含了表达这个具体事物(对象)的属性和方法;{ } 里面采取键值对的形式表示
-
键:相当于属性名
-
值:相当于属性值,可以是任意类型的值(数字类型、字符串类型、布尔类型,函数类型等)
代码如下:
var star = { name : 'pink', age : 18, sex : '男', sayHi : function(){ alert('大家好啊~'); } };
上述代码中 star即是创建的对象。
-
对象的使用
-
对象的属性
-
对象中存储具体数据的 "键值对"中的 "键"称为对象的属性,即对象中存储具体数据的项
-
-
对象的方法
-
对象中存储函数的 "键值对"中的 "键"称为对象的方法,即对象中存储函数的项
-
-
访问对象的属性
-
对象里面的属性调用 : 对象.属性名 ,这个小点 . 就理解为“ 的 ”
-
对象里面属性的另一种调用方式 : 对象[‘属性名’],注意方括号里面的属性必须加引号
示例代码如下:
console.log(star.name) // 调用名字属性 console.log(star['name']) // 调用名字属性
-
-
调用对象的方法
-
对象里面的方法调用:对象.方法名() ,注意这个方法名字后面一定加括号
示例代码如下:
star.sayHi(); // 调用 sayHi 方法,注意,一定不要忘记带后面的括号
-
-
变量、属性、函数、方法总结
属性是对象的一部分,而变量不是对象的一部分,变量是单独存储数据的容器
-
变量:单独声明赋值,单独存在
-
属性:对象里面的变量称为属性,不需要声明,用来描述该对象的特征
-
2.利用 new object 创建对象
-
创建空对象
var andy = new Obect();
通过内置构造函数Object创建对象,此时andy变量已经保存了创建出来的空对象
-
给空对象添加属性和方法
-
通过对象操作属性和方法的方式,来为对象增加属性和方法
-
示例代码如下:
andy.name = 'pink'; andy.age = 18; andy.sex = '男'; andy.sayHi = function(){ alert('大家好啊~'); }
-
注意:
-
Object() :第一个字母大写
-
new Object() :需要 new 关键字
-
使用的格式:对象.属性 = 值;
-
3.利用构造函数创建对象
-
构造函数
-
构造函数:是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与 new 运算符一起使用。我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。
-
构造函数的封装格式:
function 构造函数名(形参1,形参2,形参3) { this.属性名1 = 参数1; this.属性名2 = 参数2; this.属性名3 = 参数3; this.方法名 = 函数体; }
-
构造函数的调用格式
var obj = new 构造函数名(实参1,实参2,实参3)
-
以上代码中,obj即接收到构造函数创建出来的对象。
-
注意事项
-
-
构造函数约定首字母大写。
-
函数内的属性和方法前面需要添加 this ,表示当前对象的属性和方法。
-
构造函数中不需要 return 返回结果。
-
当我们创建对象的时候,必须用 new 来调用构造函数。
-
-
其他
-
构造函数,如 Stars(),抽象了对象的公共部分,封装到了函数里面,它泛指某一大类(class)
-
创建对象,如 new Stars(),特指某一个,通过 new 关键字创建对象的过程我们也称为对象实例化
-
-
-
-
new关键字的作用
-
-
在构造函数代码开始执行之前,创建一个空对象;
-
修改this的指向,把this指向创建出来的空对象;
-
执行函数的代码
-
在函数完成之后,返回this---即创建出来的对象
-
-
3.遍历对象
for...in 语句用于对数组或者对象的属性进行循环操作。 其语法如下:
for (变量 in 对象名字) { // 在此执行代码 }
语法中的变量是自定义的,它需要符合命名规范,通常我们会将这个变量写为 k 或者 key
for (var k in obj) { console.log(k); // 这里的 k 是属性名 console.log(obj[k]); // 这里的 obj[k] 是属性值 }
4.内置对象
1. 内置对象
-
JavaScript 中的对象分为3种:自定义对象 、内置对象、 浏览器对象
-
前面两种对象是JS 基础 内容,属于 ECMAScript; 第三个浏览器对象属于我们JS 独有的, 我们JS API 讲解
-
内置对象就是指 JS 语言自带的一些对象,这些对象供开发者使用,并提供了一些常用的或是最基本而必要的功能(属性和方法)
-
内置对象最大的优点就是帮助我们快速开发
-
JavaScript 提供了多个内置对象:Math、 Date 、Array、String等
2.Math对象
2.1Math 概述
Math 对象不是构造函数,它具有数学常数和函数的属性和方法。跟数学相关的运算(求绝对值,取整、最大值等)可以使用Math 中的成员
Math.PI //圆周率 Math.floor()// 向下取整 Math.ceil()// 向上取整 Math .round()// 四五入版 就近取整注意 -3.5结果是-3 Math.abs ()// 绝对值 Math.max()/Math.min() // 求最大和最小值
注意:上面的方法必须带括号
2.2 random
random() 方法可以随机返回一个小数,其取值范围是 [0,1),左闭右开 0 <= x < 1
得到一个两数之间的随机整数,包括两个数在内
function getRandom(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }
3.日期对象
3.1 Date 概述
-
Date 对象和 Math 对象不一样,他是一个构造函数,所以我们需要实例化后才能使用
-
Date 实例用来处理日期和时间
4.2 Date()方法的使用
1.获取当前时间必须实例化
var now = new Date () ; console.log(now);
2.Date()构造函数的参数
如果括号里面有时间,就返回参数里面的时间。例如日期格式字符串为'2019-5-1'可以写成new Date('2019-5-1')或者new Date('2019/5/1')
-
如果Date()不写参数,就返回当前时间
-
如果Date()里面写参数,就返回括号里面输入的时间
4.3日期格式化
我们想要2019-8-8 8:8:8格式的日期,要怎么办?
需要获取日期指定的部分,所以我们要手动的得到这种格式
4.4 获取日期的总的毫秒形式
Date 对象是基于1970年1月1日(世界标准时间)起的毫秒数
为什么计算机起始时间从1970年开始?
我们经常利用总的毫秒数来计算时间,因为它更精确
// 实例化Date对象 var now = new Date(); // 1. 用于获取对象的原始值 console.log(date.valueOf()) console.log(date.getTime()) // 2. 简单写可以这么做 var now = + new Date(); // 3. HTML5中提供的方法,有兼容性问题 var now = Date.now();
4. 数组对象
1.数组对象的创建
创建数组的两种方式
1.利用数组字面量
var arr = [1,2,3]; console.log(arr[0]);
2.利用new Array()
// var arr1 = new Array(); // 创建了一个空的数组 // var arr1 = new Array(2); // 这个2 示 组的长度为 2 里面有2个空的数组元素 var arr1 = new Array(2,3); // 等价于 [2,3] 这样写表示 里面有2个数组元素 是 2和3 console.log(arr1);
2.检测是否为数组
-
instanceof 运算符,可以判断一个对象是否属于某种类型
-
Array.isArray()用于判断一个对象是否为数组,isArray() 是 HTML5 中提供的方法
var arr = [1, 23]; var obj = {}; console.log(arr instanceof Array); // true console.log(obj instanceof Array); // false console.log(Array.isArray(arr)); // true console.log(Array.isArray(obj)); // false
3.添加删除数组元素的方法
1.push()
在我们数组的末尾 添加一个或者多个数组元素push 推
var arr = [1,2,3]; // arr.push(4,'pink'); console.log(arr.push(4,'pink')); console.log(arr);
(1) push 是可以给数组追加新的元素
(2) push() 参数直接写 数组元素就可以了
(3) push完毕之后,返回的结果是 新数组的长度
(4) 原数组也会发生变化
2.unshift
在我们数组的开头 添加一个或者多个数组元素
console.log(arr.unshift('red', purple')); console.log(arr);
(1) unshift是可以给数组前面追加新的元素
(2)unshift() 参数直写 数组元素就可以了
(3)unshift完毕之后,返回的结果是 新数组的长度
(4)原数组也会发生变化
4.数组排序
var arr = [1, 64, 9, 6]; arr.sort(function(a, b) { return b - a; // 降a序 // return a - b; // 升序 }); console.log(arr);
5.数组索引方法
6.数组转换为字符串
7.其他方法
5.字符串对象
1.基本包装类型
为了方便操作基本数据类型,JavaScript还提供了三个特殊的引用类型:String、Number和Boolean。
基本包装类型就是把简单数据类型包装成为复杂数据类型,这样基本数据类型就有了属性和方法
//下面代码有什么问题? var str = 'andy'; console.log(str.length);
按道理基本教据类型是没有属性和方法的,而对象才有属性和方法,但上面代码却可以执行,这是因为js 会把基本数据类型包装为复杂数据类型,其执行过程如下 :
//1.生成临时变量,把简单类型包装为复杂数据类型 var temp = new string('andy'); //2.赋值给我们声明的学符变量 str = temp; // 3.销毁临时变量 temp = null;
2.字符串的不可变
指的是里面的值不可变,虽然看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间
var str = 'abc'; str = 'hello'; // 当重新给 str 赋值的时候,常量'abc'不会被修改,依然在内存中 // 重新给字符串赋值,会重新在内存中开辟空间,这个特点就是字符串的不可变 // 由于字符串的不可变,在大量拼接字符串的时候会有效率问题 var str = ''; for (var i = 0; i < 100000; i++) { str += i; } console.log(str); // 这个结果需要花费大量时间来显示,因为需要不断的开辟新的空间
3.根据字符返回位置
字符串所有的方法,都不会修改字符串本身(字符串是不可变的),操作完成会返回一个新的字符串
4.根据位置返回字符
5.字符串操作方法
6.replace()方法
replace() 方法用于在字符串中用一些字符替换另一些字符。 其使用格式如下:
replace(被替换的字符串, 要替换为的字符串);
7.split()方法
split()方法用于切分字符串,它可以将字符串切分为数组。在切分完毕之后,返回的是一个新数组。 例如下面代码:
var str = 'a,b,c,d'; console.log(str.split(',')); // 返回的是一个数组 [a, b, c, d]
10.简单类型与复杂类型
1. 简单类型与复杂类型
简单类型又叫做基本数据类型或者值类型,复杂类型又叫做引用类型。
-
值类型:简单数据类型/基本数据类型,在存储时变量中存储的是值本身,因此叫做值类型
string ,number,boolean,undefined,null
-
引用类型:复杂数据类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用数据类型
通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等
2. 堆和栈
堆栈空间分配区别:
1、栈(操作系统):由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;
简单数据类型存放到栈里面
2、堆(操作系统):存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。
复杂数据类型存放到堆里面
注意:JavaScript中没有堆栈的概念,通过堆栈的方式,可以让大家更容易理解代码的一些执行方式,便于将来学习其他语言。
3. 简单类型的内存分配
-
值类型(简单数据类型): string ,number,boolean,undefined,null
-
值类型变量的数据直接存放在变量(栈空间)中
4. 复杂类型的内存分配
-
引用类型(复杂数据类型):通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等
-
引用类型变量(栈空间)里存放的是地址,真正的对象实例存放在堆空间中
5. 简单类型传参
函数的形参也可以看做是一个变量,当我们把一个值类型变量作为参数传给函数的形参时,其实是把变量在栈 空间里的值复制了一份给形参,那么在方法内部对形参做任何修改,都不会影响到的外部变量。
function fn(a) { a++; console.log(a); } var x = 10; fn(x); console.log(x)
6. 复杂类型传参
函数的形参也可以看做是一个变量,当我们把引用类型变量传给形参时,其实是把变量在栈空间里保存的堆地 址复制给了形参,形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象。
function Person(name) { this.name = name; } function f1(x) { // x = p console.log(x.name); // 2. 这个输出什么 ? x.name = "张学友"; console.log(x.name); // 3. 这个输出什么 ? } var p = new Person("刘德华"); console.log(p.name); // 1. 这个输出什么 ? f1(p); console.log(p.name); // 4. 这个输出什么 ?
2.DOM
1.DOM 简介
1.1 什么是 DOM
文档对象横型(DocumentObject Model,简称DOM),是W3C组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。
W3C已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容、结构和样式
1.2 DOM树
-
文档:一个页面就是一个文档,DOM 中使用 document表示
-
元素:页面中的所有标签都是元素,DOM中使用element 表示
-
节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM中使用node 表示
DOM 把以上内容都看做是对象
2.获取元素
2.1如何获取页面元素
DOM在我们实际开发中主要用来操作元素
我们如何来获取页面中的元素呢?获取页面中的元索可以使用以下几种方式
-
根据ID 获取
-
根据标签名获取
-
通过HTML5新增的方法获取
-
特殊元素获取
2.2根据ID获取
使用getElementByld()方法可以获取带有ID 的元素对象
document.getElementById('id');
2.3 根据标签名获取
使用 getElementsByTagName()方法可以返回带有指定标签名的对象的集合
document.getElementsByTagName('标签名');
注意
-
因为得到的是一个对象的集合,所以我们想要操作里面的元素就需要遍历,
-
得到元素对象是动态的
还可以获取某个元素(父元素)内部所有指定标签名的子元素
element.getElementsByTagName('标签名');
注意:父元素必须是单个对象(必须指明是哪一个元素对象).获取的时候不包括父元素自己
2.4 通过HTML5新增的方法获取
document.getElementsByclassName(类名');// 根据类名返回元素对象集合 document .querySelector (选择器);// 根据指定选择器返回第一个元素对象 document.querySelectorA11(选择器');// 根据指定选择器返回
注意: querySelector 和 querySelectorAll里面的选择器需要加符号,比如:document.querySelector('#nav');
1.getElementsByclassName 根据类名获得某些元素集合
var boxs = document .getElementsByClassName( ' box'); console.log(boxs);
2.queryselector 返回指定选择器的第一个元素对象 切记 里面的选择器需要加符号 box #nav
var firstBox = document.querySelector(' .box'); console.log(firstBox); var nav = document.querySelector('#nav'); console.log(nav); var li = document.queryselector('li'); console.log(li);
3.queryselectorA1L()返回指定选择器的所有元素对象集合
var al1Box = document.querySelectorAl1('box'); console.log(al1Box); var lis = document.querySelectorAl1('li'); console.log(lis);
2.5 获取特殊元素( body,html)
获取body元素
doucumnet.body // 返回body元素对象
获取html元素
document .documentElement // 这html元素对象
3.事件基础
3.1事件概述
JavaScript使我们有能力创建动态页面,而事件是可以被JavaScript侦测到的行为
简单理解:触发--- 响应机制
网页中的每个元素都可以产生某些可以触发 JavaScript的事件,例如,我们可以在用户点击某按钮时产生一/事件,然后去执行某些操作。
3.2 事件三要素
事件是有三部分组成
-
事件源
-
事件类型
-
事件处理程序
我们也称为事件三要素
(1) 事件源 事件被触发的对象 谁
(2) 事件类型 如何触发 什么事件 比如鼠标点击(onclick) 还是鼠标经过 还是键盘按下
(3) 事件处理程序 通过一个函数赋值的方式 完成
3.3 执行事件的步骤
1.获取事件源
var div = document.querySelector( 'div');
2.绑定事件 注册事件
div.onclick
3.添加事件处理程序( 采取函数赋值形式)
div.onclick = function() { console.log("我被选中了); }
常见的鼠标事件
4.操作元素
JavaScript的DOM操作可以改变网页内容、结构和样式,我们可以利用DOM操作元素来改变元素里面的内容、属性等。注意以下都是属性
4.1改变元素内容
element.innerText//识别HTML标签
从起始位置到终止位置的内容,但它去除 htlm 标签,同时空格和换行也会去掉
element.innerHTML//不识别HTML标签
起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行
4.2 常用元素的属性操作
-
innerText、innerHTML 改变元表内容
-
src、href
-
id、alt、title
4.3 表单元素的属性操作
利用 DOM可以操作如下表单元素的属性:
type、value、 checked、selected、disabled
4.4 样式属性操作
我们可以通过JS 修改元素的大小、颜色、位置等样式
-
element.style 行内样式操作
-
element.className 类名样式操作
注意
-
Js 里面的样式采取驼峰命名法 比如 fontSize、 backgroundColor
-
Js 修改 style 样式操作,产生的是行内样式,css 权重比较高
-
如果样式修改较多,可以采取提作类名方式更改元素样式
-
class因为是个保留字,因此使用className来操作元素类名属性
-
className会直接更改元素的类名,会覆盖原先的类名
操作元素总结
4.5 排他思想
如果有同一组元素,我们想要某一个元素实现某种样式,需要用到循环的排他思想算法
-
所有元素全部清除样式(干掉其他人)
-
给当前元素设置样式(留下我自己)
-
注意顺序不能颠倒,首先干掉其他人,再设置自己
4.6 自定义属性的操作
1.获取属性值
-
element.属性 获取属性值
-
element.getAttribute('属性' );
区别:
-
element.属性 获取内属性值(元素本身自带的属性)
-
element.getAttribute(属性); 主要获得自定义的属性 (标准) 我们程序员自定义的属性
2.设置属性值
-
element.属性 = '值' 设置内置属性值
-
element.setAttribute('属性','值');
区别 :
-
element.属性 设置内置属性值
-
element.setAttribute('属性'); 主要设置自定义的属性 (标准)
3. 移除属性
-
element.removeAttribute('属性');
4.7 H5自定义属性
自定义属性目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中.
自定义属性获取是通过getAttribute('属性') 获取
但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性
H5给我们新增了自定义属性:
1.设置H5自定义属性
H5规定自定义属性data-开头做为属性名并且赋值
比如 <div data-index="1"></div>
或者使用JS 设置
element.setAttribute( 'data-index',2)
2.获取H5自定义属性
-
兼容性获取
element.getAttribute('data-index');
-
H5新增
element.dataset.index
或者element.dataset[' index']
ie 11才开始支持
5.节点操作
5.1为什么学节点操作
获取元素通常使用两种方式:
1.利用 DOM 提供的方法获取元素
-
document.getElementByld()
-
document.getElementsByTagName()
-
document.querySelector 等
-
逻辑性不强、繁琐
2.利用节点层级关系获取元素
-
利用父子兄节点关系获取元素
-
逻辑性强,但是兼容性稍差
这两种方式都可以获取元素节点,我们后面都会使用,但是节点操作更简单
5.2节点概述
网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM中,节点使用nde 来表示HTMLDOM树中的所有节点均可通过JavaScript进行访问所有HTML元素(节点)均可被修改,也可以创建或删除。
一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。
-
元素节点nodeType为1
-
属性节点 nodeType 为2
-
文本节点 nodeType 为3(文本节点包含文字、空格、换行等)我们在实际开发中,节点操作主要操作的是元素节点
5.3节点层级
利用 DOM树可以把节点划分为不同的层级关系,常见的是父子兄层级关系
1.父级节点
node .parentNode
-
parentNode属性可返回某节点的父节点,注意是最近的一个父节点
-
如果指定的节点没有父节点则返回nul!
2.子节点
1.parentNode.childNodes (标准)
parentNode.childnodes 返回包含指定节点的子节点的集合,该集合为即时更新的集合。
注意 : 返回值里面包含了所有的子节点,包括元素节点,文本节点等
如果只想要获得里面的元素节点,则需要专门处理。所以我们一般不提倡使用childNodes
var ul = document. querySelector(‘ul’); for(var i = 0; i < ul.childNodes.length;i++) { if (ul.childNodes[i].nodeType == 1) { // ul.childNodes[i] 是元素节点 console.log(ul.childNodes[i]); } }
2.parentNode.children(非标准)
parentNode.children 是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返 回 (这个是我们重点掌握的)。 虽然children 是一个非标准,但是得到了各个浏览器的支持,因此我们可以放心使用
3.parentNode .firstChild
firstChild返回第一个子节点,找不到则返回null。同样,也是包含所有的节点。
4.parentNode .lastchild
lastChild 返回最后一个子节点,找不到则返回null。同样,也是包含所有的节点
5.parentNode.firstElementchild
firstElementchild 返回第一个子元素节点,找不到返回null
6.parentNode.lastElementChild
lastElementchild返回最后一个子元素节点,找不到则返回null
注意:这两个方法有兼容性问题,IE9 以上才支持
-
实际开发中,firstchild 和 lastchild 包含其他节点,操作不方便,而 firstElementchild 和lastElementchild 又有兼容性问题,那么我们如何获取第一个子元素节点或最后一个子元素节点呢?
-
解决方案:
-
如果想要第一个子元素节点,可以使用
parentNode.chilren[0]
-
如果想要最后一个子元素节点,可以使用
parentNode.chilren[parentNode.chilren.length-1]
3.兄弟节点
1.node .nextSibling
nextSibling 返回当前元素的下一个兄弟节点,找不到则返回nu11。同样,也是包含所有的节点。
2.node.previousSibling
previousSibling 返回当前元素上一个兄弟节点,找不到则返回nu11。同样,也是包含所有的节点
3.node.nextElementSibling
nextElementSibling返回当前元素下一个兄弟元素节点,找不到则返回null。
4.node.previousElementSibling
previousElementSibling返回当前元素上一个兄弟节点,找不到则返回null.
注意: 这两个方法有兼容性问题, IE9 以上才支持.
问:如何解决兼容性问题?
答:自己封装一个兼容性的函数
function getNextElementSibling(element) { var el = element; while (el = el.nextSibling) { if (el.nodeType === 1) { return el; } } return null; }
5.4 创建节点
document.createElement('tagName')
document.createBlement() 方法创建由 tagName 指定的 HTML元素因为这些元素原先不存在是根据我们的需求动态生成的,所以我们也称为动态创建元素节点。
5.5 添加节点
1.node.appendchild(child)
node.appendchild()方法将一个节点添加到指定父节点的子节点列表末尾。类似于css 里面的after 伪元素
2.node.insertBefore(child,指定元素)
node.insertBefore()方法将一个节点添加到父节点的指定子节点前面。类似于 css里面的 before伪元素。
5.6 删除节点
node.removechild(child)
node.removechild() 方法从DOM 中删除一个子节点,返回删除的节点
5.7 复制节点
node.cloneNode()
node.cloneNode() 方法返回调用该方法的节点的一个副本。
注意:
-
如果括号参数为空或者为 false ,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点。
-
如果括号参数为 true ,则是深度拷贝,会复制节点本身以及里面所有的子节点。
5.8 替换节点
parentNode.replaceChild(newChild, oldChild);
用指定的节点替换当前节点的一个子节点,并返回被替换掉的节点
5.9 三种动态创建元素区别
-
document.write()
-
element.innerHTMl
-
document.createElement ()
区别
-
document.write 是直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘
-
innerHTML 是将内容写入某个 DOM 节点,不会导致页面全部重绘
-
innerHTML创建多个元素效率更高(不要拼按字符串,采取数组形式拼接),结构稍微复杂
-
createElement()创建多个元素效率稍低一点点,但是结构更清晰
总结:不同浏览器下,innerHTML 效率要比 creatElement 高
6.DOM 重点核心
文档对象模型( DocumentObjectModel,简称 DOM),是W3C组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。
W3C已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容、结构和样式
-
对于JavaScript,为了能够使JavaScript操作HTML,JavaScript就有了一套自己的dom编程接口。
-
对于HTML,dom使得html形成一棵dom树包含文档、元素、节点
我们获取过来的DOM元素是一个对象(object),所以称为文档对象模型
关于dom操作,我们主要针对于元素的操作。主要有创建、增、删、改、查、属性操作、事件操作.
6.1 创建
-
document.write
-
innerHTML
-
createElement
6.2 增
-
appendChild
-
insertBefore
6.3 删
-
removeChild
6.4 改
主要修改dom的元素属性,dom元素的内容、属性,表单的值等
-
修改元素属性:src、href、 title等
-
修改普通元素内容:innerHTML、innerText
-
修改表单元素:value、type、disabled等
-
修改元素样式:style、className
6.5 查
主要获取查询dom的元素
-
DOM提供的API方法: getElementByld、getElementsByTagName 古老用法不太推荐
-
H5提供的新方法: querySelector、querySelectorAll 提倡
-
利用节点操作获取元素:父(parentNode)、子children)、兄(previousElementSibling.nextElementSibling)提倡
6.6 属性操作
主要针对于自定义属性
-
setAttribute:设置dom的属性值
-
getAttribute:得到dom的属性值
-
removeAttribute移除属性
6.7事件操作
给元素注册事件,采取 事件源.事件类型=事件处理程序
7.事件高级
1.注册事件(绑定事件)
1.1 注册事件概述
给元素添加事件,称为注册事件或者绑定事件
注册事件有两种方式:传统方式和方法监听注册方式
传统注册方式
-
利用 on 开头的事件onclick
-
<button οnclick="alert(hi~)"></button>
-
btn.onclick = function(){}
-
特点:注册事件的唯一性
-
同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数
方法监听注册方式
-
w3c标准推荐方式
-
addEventListener()它是一个方法
-
IE9之前的IE不支持此方法,可使用attachEvent()代替
-
特点:同一个元素同一个事件可以注册多个监听器
-
按注册顺序依次执行
1.2 addEventListener 事件监听方式
eventTarget.addEventListener(type, listener[, useCapture])
eventTarget.addEventListener()方法将指定的监听器注册到 eventTarget(目标对象)上,当该对 象触发指定的事件时,就会执行事件处理函数。
该方法接收三个参数:
-
type:事件类型字符串,比如 click 、mouseover ,注意这里不要带 on
-
listener:事件处理函数,事件发生时,会调用该监听函数
-
useCapture:可选参数,是一个布尔值,默认是 false。
1.3 attachEvent 事件监听方式
eventTarget.attachEvent(eventNameWithOn, callback)
eventTarget.attachEvent()方法将指定的监听器注册到 eventTarget(目标对象) 上,当该对象触 发指定的事件时,指定的回调函数就会被执行。
该方法接收两个参数:
-
eventNameWithOn:事件类型字符串,比如 onclick 、onmouseover ,这里要带 on
-
callback: 事件处理函数,当目标触发事件时回调函数被调用
注意:IE8 及早期版本支持
1.4 注册事件兼容性解决方案
function addEventListener(element, eventName, fn) { // 判断当前浏览器是否支持 addEventListener 方法 if (element.addEventListener) { element.addEventListener(eventName, fn); // 第三个参数 默认是false } else if (element.attachEvent) { element.attachEvent('on' + eventName, fn); } else { // 相当于 element.onclick = fn; element['on' + eventName] = fn; }
兼容性处理的原则: 首先照顾大多数浏览器,再处理特殊浏览器
2.删除事件(解绑事件)
2.1删除事件的方式
1.传统注册方式
eventTarget.onclick = nu11;
2.方法监听注册方式
-
eventTarget.removeEventListener(type, listener[,useCapture]);
-
eventTarget.detachEvent(eventNameWithOn, callback) ;
2.2 删除事件兼容性解决方案
function removeEventListener(element, eventName, fn) { // 判断当前浏览器是否支持 removeEventListener 方法 if (element.removeEventListener) { element.removeEventListener(eventName, fn); // 第三个参数 默认是false } else if (element.detachEvent) { element.detachEvent('on' + eventName, fn); } else { element['on' + eventName] = null; }
3.DOM 事件流
事件流描述的是从页面中接收事件的顺序
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM 事件流
比如我们给一个div注册了点击事件:
DOM事件流分为3个阶段:
-
捕获阶段
-
当前目标阶段
-
冒泡阶
-
事件冒泡:IE 最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到到DOM最顶层节点的过程。
-
事件捕获:网景最早提出,由DOM 最顶层节点开始,然后逐级向下传播到到最具体的元素接收的过程
注意
-
Js代码中只能执行捕获或者冒泡其中的一个阶段
-
onclick和 attachEvent 只能得到冒泡阶段
-
addEventiistener(type,listener[useCapture])第三个参数是true,表示在事件捕获阶段调用事件处理程序;如果是 false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序。
-
实际开发中我们很少使用事件捕获,我们更关注事件冒泡
-
有些事件是没有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave
-
事件冒泡有时候会带来麻烦,有时候又会帮助很巧妙的做某些事件
4.事件对象
4.1什么是事件对象
eventTarget.onclick = function (event) {} eventTarget.addEventristener('click',function(event) (}) //这个 event 就是事件对象,我们还喜欢的写成 e 或者 evt
官方解释:event对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态
简单理解:事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象event,它有很多属性和方法
比如:
-
谁绑定了这个事件
-
鼠标触发事件的话,会得到鼠标的相关信息,如鼠标位置
-
键盘触发事件的话,会得到键盘的相关信息,如按了哪个键
4.2事件对象的使用语法
eventTarget.onclick = function (event) { // 这个 event 就是事件对象,我们还喜欢的写成 e 或者 evt eventTarget.addEventListener ('click' function (event) { // 这个 event 就是事件对象,我们还喜欢的写成 e 或者 evt }
这个event 是个形参,系统帮我们设定为事件对象,不需要传递实参过去
当我们注册事件时,event对象就会被系统自动创建,并依次传递给事件监听器(事件处理函数)
4.3事件对象的兼容性方案
事件对象本身的获取存在兼容问题:
-
标准浏览器中是浏览器给方法传递的参数,只需要定义形参 e 就可以获取到。
-
在 IE6~8 中,浏览器不会给方法传递参数,如果需要的话,需要到 window.event 中获取查找。
解决: e = e || window.event;
4.4事件对象的常见属性和方法
e.target 和 this 的区别:
-
this 是事件绑定的元素, 这个函数的调用者(绑定这个事件的元素)
-
e.target 是事件触发的元素。
5.阻止事件冒泡
5.1阻止事件冒泡的两种方式
事件冒泡:开始时由最具体的元素接收,然后逐级向上传播到到DOM最顶层节点
事件冒泡本身的特性,会带来的坏处,也会带来的好处,需要我们灵活掌握.
阻止事件冒泡
标准写法:利用事件对象里面的 stopPropagation()方法
e.stopPropagation ()
非标准写法:IE6-8 利用事件对象cancelBubble属性
e.cancelBubble = true;
5.2阻止事件冒泡的兼容性解决方案
if(e && e.stopPropagation){ e.stopPropagation(); }else{ window.event.cancelBubble = true; }
6.事件委托(代理、委派)
事件委托
事件委托也称为事件代理,在jQuery里面称为事件委派
事件委托的原理
不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点
以上案例:给注册点击事件,然后利用事件对象的target 来找到当前点击的,因为点击li,事件会冒泡到u上ul有注册事件,就会触发事件监听器
事件委托的作用
我们只操作了一次DOM,提高了程序的性能
7.常用的鼠标事件
7.1常用的鼠标事件
1.禁止鼠标右键菜单
contextmenu主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单
document .addEventListener('contextmenu', function(e) ( e.preventDefault (); )}
2.禁止标选中(selectstart 开始选中)
document.addEventlistener('selectstart',function (e) { e.preventDefault () ; )}
7.2鼠标事件对象
event对象代表事件的状态,跟事件相关的一系列信息的集合。现阶段我们主要是用鼠标事件对象MouseEvent 和键盘事件对象 KeyboardEvent.
8.常用的键盘事件
8.1常用键盘事件
事件除了使用鼠标触发,还可以使用键盘触发
注意
-
如果使用addEventListener 不需要加on
-
onkeypress和前面2个的区别是,它不识别功能键,比如左右箭头,shift等.
-
三个事件的执行顺序是: eydown -- keypress --- keyup
8.2键盘事件对象
注意: onkeydown和 onkeyup 不区分字母大小写,onkeypress 区分字母大小写.
在我们实际开发中,我们更多的使用keydown和keyup,它能识别所有的键(包括功能键)
Keypress 不识别功能键,但是keyCode属性能区分大小写,返回不同的ASCII值
3.BOM
1.BOM 概述
1.1什么是BOM
BOM(BrowserObject Model)即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是window。
BOM由一系列相关的对象构成,并且每个对象都提供了很多方法与属性
BOM缺乏标准,JavaScript语法的标准化组织是ECMA,DOM的标准化组织是W3C,BOM最初是Netscape浏览器标准的一部分。
DOM
-
文档对象模型
-
DOM就是把[文档]当做一个[对象]来看待
-
DOM的顶级对象是document
-
DOM主要学习的是提作页面元素
-
DOM是W3C标准规范
BOM
-
浏览器对象模型
-
把[浏览器]当做一个[对象]来看待
-
BOM的顶级对象是window
-
BOM学习的是浏览器窗口交互的一些对象
-
BOM 是浏览器厂商在各自浏览器上定义的,兼容性较差
1.2BOM 的构成
BOM比DOM更大,它包含DOM
window 对象是浏览器的顶级对象,它具有双重角色
-
它是JS访问浏览器窗口的一个接口。
-
它是一个全局对象。定义在全局作用域中的变量、函数都会变成window对象的属性和方法在调用的时候可以省略window,前面学习的对话框都属于window对象方法,如alert0、prompt0等.
注意: window下的一个特殊属性 window.name
2.window 对象的常见事件
2.1窗口加载事件
window.onload = function (){} 或者 window.addEventListener("load",function(){});
window.onload是窗口(页面)加载事件当文档内容完全加载完成会触发该事件(包括图像、脚本文件、CSS文件等),就调用的处理函数。
注意
-
有了window.onload就可以把JS代码写到页面元素的上方,因为 onload是等页面内容全部加载完毕再去执行处理函数。
-
window.onload传统注册事件方式只能写一次,如果有多个,会以最后一个window.onload为准
-
如果使用addEventListener 则没有限制
document.addEventListener('DOMContentLoaded',function(){})
DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等等。
Ie9以上才支持
如果页面的图片很多的话, 从用户访问到onload触发可能需要较长的时间, 交互效果就不能实现,必然影响用 户的体验,此时用 DOMContentLoaded 事件比较合适。
2.2调整窗口大小事件
window.onresize = function()} window.addEventListener ("resize", function() {});
window.onresize 是调整窗口大小加载事件当触发时就调用的处理函数
注意:
-
只要窗口大小发生像素变化,就会发这个事件
-
我们经常利用这个事件完成响应式布局。windowinnerWidth 当前屏幕的宽度
3.定时器
3.1两种定时器
window 对象给我们提供了2个非常好用的方法-定时器
-
setTimeout()
-
setlnterval()
3.2 setTimeout()定时器
window.setTimeout(调用函数,[延迟的毫秒数]);
setTimeout()方法用于设置一个定时器,该定时器在定时器到期后执行调用函数
注意 :
-
window 可以省略
-
这个调用函数可以直接写函数,或者写函数名或者采取字符串'函数名()'三种形式。第三种不推荐
-
延迟的毫秒数省略默认是0,如果写,必须是毫秒
-
因为定时器可能有很多,所以我们经常给定时器赋值一个标识符
setTimeout()这个调用函数我们也称为回调函数 callback
普通函数是按照代码顺序直接调用。
而这个函数,需要等待时间,时间到了才去调用这个函数,因此称为回调函数
简单理解:回调,就是回头调用的意思。上一件事干完,再回头再调用这个函数以
前我们讲的 element.οnclick=function(){} 或者 elementaddEventListener(“click”,fn); 里面的函数也是回调函数。
3.3停止 setTimeout() 定时器
window.clearTimeout (timeoutID)
clearTimeout()方法取消了先前通过调用 setTimeout()建立的定时器
注意:
-
window 可以省略
-
里面的参数就是定时器的标识符
3.4 setInterval()定时器
window.setInterval(回调函数。[间隔的毫秒数]);
setlnterval0方法重复调用一个函数,每隔这个时间,就去调用一次回调函数
注意
-
window 可以省略
-
这个调用函数可以直接写函数,或者写函数名或者采取字符串'函数名()’三种形式
-
间隔的毫秒数省略默认是0,如果写,必须是毫秒,表示每隔多少毫秒就自动调用这个函数。
-
因为定时器可能有很多,所以我们经常给定时器赋值一个标识符
3.5 停止 setlnterval() 定时器
window.clearInterval(intervalID):
clearInterval()法取消了先前通过调用 setInterval()建立的定时器
注意
-
window 可以省略
-
里面的参数就是定时器的标识符
3.6 this
this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,一般情况下this的最终指向的是那个调用它的对象
现阶段,我们先了解一下几个this指向
-
全局作用域或者普通函数中this指向全局对象window(注意定时器里面的this指向window)
-
方法调用中谁调用this指向谁
-
构造函数中this指向构造函数的实例
4.JS 执行机制
4.1 JS是单线程
JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。这是因为Javascript这门脚本语言诞生的使命所致-JavaScript是为处理页面中用户的交互,以及操作DOM而诞生的。比如我们对某个 DOM 元素进行添加和删除操作,不能同时进行。应该先进行添加,之后再删除。
单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。这样所导致的问题是:如果JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉
一个问题:以下代码执行的结果是什么?
console.log(1); setTimeout(function () { console.log(3); }, 1000); console.log(2);
4.2 同步和异步
为了解决这个问题,利用多核CPU的计算能力,HTML5提出Web Worker 标准,允许JavaScript脚本创建多个线程。于是,JS中出现了同步和异步
同步
前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。比如做饭的同步做法:我们要烧水煮饭,等水开了( 10分钟之后),再去切菜,炒菜。
异步
你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事情。比如做饭的异步做法,我们在烧水的同时,利用这10分钟,去切菜,炒菜
同步任务
同步任务都在主线程上执行,形成一个执行栈
异步任务
JS的异步是通过回调函数实现的
一般而言,异步任务有以下三种类型:
1、普通事件,如click、resize等
2、资源加载,如load、error等
3、定时器,包括setlnterval、setTimeout等
异步任务相关回调函数添加到任务队列中(任务队列也称为消息队列)
4.3 JS执行机制
-
先执行执行栈中的同步任务
-
异步任务(回函)放入任务队列中
-
一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。
5 location 对象
5.1 什么是location 对象
window 对象给我们提供了一个location 属性用于获取或设置窗体的URL,并且可以用于解析URL,因为这个属性返回的是一个对象,所以我们将这个属性也称为location 对象
5.2 URL
统一资源定位符(Uniform Resource Locator, URL) 是互联网上标准资源的地址,互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它
URL 的一般语法格式为:
protocol://host[:port]/path/[?query]#fragment
5.3 location 对象的属性
5.4 location 对象的方法
6.navigator 对象
navigator对象包含有关浏览器的信息,它有很多属性,我们最常用的是userAgent,该属性可以返回由客户机发送服务器的user-agent头部的值
下面前端代码可以判断用户那个终端打开页面,实现跳转
if((navigator.userAgent.match(/ (phonelpadlpod] iphoneliPod|ios|iPad |Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|windows phone) /i))){ window.location .href ="";//手机 } else { window.location.href = "";//电脑 }
7.history 对象
window 对象给我们提供了一个history 对象,与浏览器历史记录进行交互该对象包含用户(在浏览器窗口中)访问过的 URL。