JavaScript
ECMAScript
由网景提交代码给 ECMA 形成了一套ECMAScript标准 (ECMA-262) 它规定了语言的语法 语句 规范 语法规范 和 标准库
JavaScript注释
单行注释
//单行注释 快捷键CTRL+/
多行注释
/* 多行注释 */ 快捷键ctrl+shift+a
变量
定义
存放数据的空间
声明
var 变量名;
同时声明多个变量: var 变量名1, var 变量名2, var 变量名3;
只声明,不赋值 undefined
不声明也不赋值,直接引用 报错
不声明,只赋值 输出值
赋值
声明后赋值:变量名=xxx;
边声明边赋值: var 变量名=xxx;
命名规范
由字母,数字,下划线 ,$组成
数字不能在变量开头
严格区分大小写
不能是关键字,保留字 变量名要有意义 驼峰命名法
变量提升
JavaScript 仅提升声明,而不提升初始化。
会把当前上下文中所有带VAR/FUNCTION关键字的进行提前声明或者定义
eg: console.log(a)
上面代码会去找当前上下文为a的变量,找不到则根据作用域去找,
知道找到最顶层,找不到就报错,下面报错是指未定义。
console.log(a) // undefined
var a = 3; // 可以隐式的理解为 var a; console.log(a); a = 3;
数据类型
简单数据类型
也叫基本数据类型,在内存种占据固定大小的空间,因此被保存在栈内存中
Number
数字型,包含整数,浮点数
八进制:数字前面加0
十六进制:数字前面加0x
特殊值:Infinity 无穷大
NaN 非数字
isNaN()函数:判断非数字
String
字符型,赋值时需带引号,js推荐使用单引号
Boolean
布尔型 true false 1 0
Undefined
未赋值
Null
值为空,空指针
复杂数据类型
Object
通过Object自定义对象,
对象是一组数据和功能的集合
引用类型的值是对象,保存在堆内存中
包含引用类型值的变量实际上包含的并不是对象本身,
而是指向对象的一个指针
从一个变量向另一个变量复制引用类型的值,复制的其实是指针,
因此两个变量最终都指向同一个对象
运算符
算术运算符
一元运算符
只有一个数参与运算
++
自增,可以出现在变量的前面或后面, ++在前先自增再运算,++在后先运算再自增
–
自减,可以出现在变量的前面和后面, --在前先自减再运算,–在后先运算再自减
一元+
任意类型转换为数字型
一元-
正数变为负数
toFixed()函数
固定小数点后的位数
eg: n.toFixed(2)返回小数点后有两位的字符串
二元运算符
符号前后有两个数的运算符
取余运算符
% A % B A除以B取余数
幂函数
A ** B A 的 B次方
eg:2 ** 3=8
关系运算符
用于判断两个数值之间的大小关系
关系运算的结果会返回一个布尔值
所有会返回布尔值的表达式都叫布尔表达式
>
<
>=
字符串比较
如果关系运算符左右两边的内容是字符串类型, JavaScript会将它转换为数字类型Unicode编码
Unicode编码
数字 48-57 大写字母65-90 小写字母97-122
<=
赋值运算符
将右边的值赋给左边的变量 右结合
=
+=
-=
*=
/=
%=
逻辑运算符
ECMAScript中,所有的数据类型都可以被转换成
boolean类型,number类型,string类型
NaN undefined null 转布尔类型的结果都是false
逻辑与 &&
都为true ,结果为true
逻辑或 ||
一个为true就为true
逻辑非 !
任意非0的数值转换为布尔类型都是true
!NaN true !undefined true !null true
作用:快速将其他数值类型转为布尔类型
eg: !!null !!35
短路逻辑
当逻辑表达式的一个值能决定结果时,不对另一个值进行求值
应用场景
-
设定默认值
-
确认应用
字符串连接符
当 +号两边有任意一边是字符串时,
+号是字符链接符
当+号被看作字符连接符时,
JS引擎会自动将另外一边不是字符串的数据转换成字符串类型,
再进行连接
true false null undefined NaN这些值转换成字符串类型,原样转换
任意对象转换为字符串,其结果都是’[object Object]’
作用
使用空字符串和字符连接符,可以快速转换字符串类型
条件运算符
也叫三元运算符/三目运算符
语法
表达式1 ? 表达式2 :表达式3;
//当表达式1的结果是true 条件运算符的结果为表达式2
//当表达式1的结果为false 条件运算符的结果为表达式3
//当表达式1不是布尔表达式时,JS引擎会将其自动转换为布尔表达式
typeof运算符
作用
判断数据类型
ECMAScript是弱类型语言
在声明变量时没有对数据类型进行约束
需要一种手段来查看数据类型
相等操作符
相等比较运算符
比较两个值之前,
如果有布尔类型的值,先将布尔类型的值转换成数值型
比较时,如果有一个值是数值,另一个值是字符串,
则将字符串转换成数值
//特殊:
null==undefined //true
'NaN'=='NaN' //true
'NaN'==NaN //false
NaN == NaN //false
//NaN和任何值比较,都是false
undefined ==undefined //true
undefined=='undefined' //false
==
不相等比较运算符
比较两个值之前,
如果有布尔类型的值,先将布尔类型的值转换成数值型
比较时,如果有一个值是数值,另一个值是字符串,
则将字符串转换成数值
NaN != NaN //true
!=
全等运算符 ===
不全等运算符 !==
逗号操作符
在用于赋值时,逗号运算符总会返回表达式的最后一项
运算符优先级
1.小括号
()
2.一元运算符
++
–
!
3.算术运算符
3.1幂运算符
**
3.2
*
3.2
/
3.2
%
3.3
+
3.3
-
4.关系运算符
-
>
-
>=
-
<
-
<=
5.相等运算符
-
==
-
!=
-
===
-
!==
6.逻辑运算符
6.1
&&
6.2
||
7.赋值运算符
=
8.逗号运算符
,
JavaScript书写方式
行内式
<input type="button" value="点我试试" onclick="alert("Hello World&")>//不推荐使用
内部式
<script>
alert('Hello World~!');
</script>
外部式
<script src="my.js"></script>`
书写美观,在js代码量较多的情况下使用
数据类型转换
隐式类型转换
代码在执行过程中为保证运行结果正确减少错误情况
会进行自动的数据转换
在代码执行过程中,运算时发生的数据类型转换
叫做隐式类型转换
特殊
undefined转换成数字型的结果是NaN
一元自增和一元自减不允许出现在值的前后
任意对象(Object)转换成数字都是NaN
强制类型转换
用户主动使用一些函数进行数据类型转换
Number()
将一个string解析成number ,
若改字符串无法解析则转化为NaN
转换结果与一元+的转换效果相同
可以使用一元+代替这个函数
parseFloat()
将一个string解析成一个浮点数(带有小数点的数)
如果没有可解析的部分 返回NaN
parseFloat('3.14') //3.14
parseFloat('3.14a38493') //3.14
parseFloat('3a.14') //3
parseInt()
将一个string解析成一个整数 如果没有可解析的部分, 返回NaN
toString()
转换成字符串
语法: value.toString();
//null 和undefined 没有toString方法
作用
转换进制数 number类型的数据使用toString函数,可以转换进制数 value.toString(2) //把value转换成2进制数
Boolean()
将值转换为布尔型
流程控制
流程图
-
圆形
开始结束
-
箭头
程序流程
-
菱形
逻辑判断
-
矩形
加工步骤
-
平行四边形
数据
分支结构
if
JS引擎在执行if语句时,先判断布尔表达式的结果,
结果为true执行大括号中的代码
if-else
if可以单独使用,else不可以单独使用
if-else只有一条语句时,可以使用三目运算符代替
switch-case
是一种特殊的分支结构 决定了程序的某个入口开始执行
一般情况指的是某个范围中的特定值
语法
//中括号表示可选
switch(变量) {
case 常量:
代码;
[break];
case 常量:
代码;
[break];
[default:]
}
switch在入口选择方面
判断的是相等(强判断 全等比较)
从某个入口开始执行代码,直到遇见break关键字为止
如果case后面没有break关键字,将继续向下穿透执行
循环结构
循环必须要有一个出口
如果小括号里放置的不是布尔表达式,则会自动转换为布尔类型
循环结构中的变量可以被外部访问
循环体不是函数,而是流程控制语句
for
语法: for(表达式1;表达式2;表达式3){ }
表达式1:循环初始条件
表达式2:布尔表达式,判断什么时候可以跳出循环
表达式3:赋值语句,改变循环条件
明确知道循环次数时使用
当使用,号书写多个循环判断条件时,最后一个条件为循环条件
while
语法 while(布尔表达式){ 需要重复执行的代码; }
JS引擎执行到一个while语句时,
会先判断while语句小括号中布尔表达式的结果
结果是true 执行一次大括号中的语句
执行结束后,继续判断布尔表达式
直到布尔表达式false为止
结果是false 则不执行大括号中的语句
直接结束循环结构
在无法明确循环次数时推荐使用while
do-while
语法
do{ 需要执行的循环代码; }while(布尔表达式);
先执行一次再判断
在无法明确循环次数且至少要执行一次时推荐使用do-while
函数
严格模式下,函数的函数名和参数名命名不可以为eval或arguments 方法和函数是同一种东西 函数是一个功能的整体
概念
表示一个特定的功能
由一个或多个语句块构成
相较于其他代码
具有相对的独立性
eg: isNaN() alert() prompt() console.log()
作用
提供过程的封装和细节的隐藏
返回值
即函数的执行结果
每个函数只有一个返回值
函数的返回值可以是任意数据类型
执行返回值语句后 函数将中止执行
创建
ECMAScript为函数提供了构造函数
命名规范:可以使用字母、数字、下划线、$
不可以使用关键字、保留字
不可以以数字开头
命名有语义 驼峰命名法
(普通函数,小驼峰命名法 ,构造函数, 大驼峰命名法)
声明式
function 函数名(参数列表){ //语句块; }
声明式函数在变量提升时,会将整个函数体提升到顶端,
函数提升比变量提升的优先级高;
赋值式
又叫字面量式,
函数表达式 将一个匿名函数赋值给一个变量或对象的属性
var 变量名=function(){ }
赋值式函数在进行函数提升时,
和变量提升一致,只会提升变量的声明,不会提升变量的赋值(即不会提升函数体
因此赋值式函数只能在赋值的下面调用,否则会报错
函数构造
箭头函数
调用
函数不会自动执行,需要进行调用
调用函数的语法: 函数名(参数列表);
参数
在创建函数时,可以为函数添加参数
在创建函数时 有一个小括号 叫做参数列表
可以在这个参数列表中 添加一些名称(参数)
参数命名方式和变量相同
参数的本质就是函数内部的局部变量
创建参数相当于声明了一个变量
只能在当前函数中使用
在声明函数时 参数列表中的参数叫做形式参数
在调用函数时,参数列表中的参数叫做实际参数
ECMAScript函数不介意传递进来参数的个数或者数据类型。
因为ECMAScript中的参数在内部是用一个数组来表示的。
作用
让函数的使用更加灵活多样
参数的声明
参数
传参
调用函数时 写的实参叫做传递参数
传参的本质是赋值
函数的参数传递是按值传递
调用函数时写在参数列表中的实参变量,其实传递的是变量的值
arguments对象
是函数中的内置对象
它的作用是用来存储实际参数的
在函数体内可以通过argument对象来访问这个参数数组
arguments.length获得传进来的参数个数
arguments[n]访问参数列表的第n+1个值
它存储的参数是有序的
arguments为每一个参数 都提供了一个编号
(所以) 索引(index)是以数值进行编号
从0开始编号 0是第一个参数 1是第二个参数
arguments.callee返回当前函数的引用
arguments.callee===当前函数 通常在递归时使用
递归
递归是函数在执行过程中的自调用
递归的本质是一个循环
递归的出口设置比较麻烦(没有出口会导致栈溢出)
递归通常处理的是相同或相近的功能
它是一种效率极低的遍历方式
应用场景
遍历树结构(html,目录,对象)
匿名函数
匿名函数,就是定义时未直接指定名称的函数
function(num1,num2){
console.log(num1+num2);
}
应用
回调函数,将一个函数作为另一个函数的参数叫做回调函数
function fn(num1,num2){
console.log(num1()+num2());
}
fn(function(){
return 1;
}
function(){
return 2;
});
写法1:(
//自调函数,自执行函数,一次性函数,定义一个匿名函数
function(num1,num2){
console.log(num1+num2);
} )(100,200);
写法2:!function(){
}();
写法3:~function(){
}();
优点
因为非匿名函数在定义时,就已经创建和函数对象和作用域链对象。
所以,即使未调用,也占内存空间。
匿名函数仅在调用时,才临时创建函数对象和作用域链对象。
调用完,立刻释放。
所以,匿名函数比非匿名函数更节省内存空间。
有效隔离作用域 避免作用域污染(原则 作用域越小越好)
匿名函数仅在执行时 临时创建作用域链对象
匿名函数没有名字,不存在声明提前,
临时创建作用域链,执行结束后自动销毁,比实名函数更节约内容空间
功能
计算
this关键字
this关键字出现在函数中 谁调用函数指向谁
JS执行过程
1.预编译
1.词法分析
2.语法分析
2.预编译
查找所有的函数声明和变量声明
先将声明式的函数提前创建
等待调用
将变量的声明提前创建
并赋值为undefined
3.代码执行
JS引擎按照从上到下的顺序执行
作用域
ECMAScript采用的作用域是静态作用域(在定义变量或函数时 就已经决定了 作用域)
ECMAScript(传统作用域 分为两类)
- 全局作用域
定义好的变量或函数 在任意位置都可以访问 - 函数作用域
定义好的变量或函数 仅在当前函数中可用
作用域链
在JS中,函数也是对象,
实际上,JS里一切都是对象,
函数对象和其他对象一样,拥有可以通过代码访问的属性和一系列仅供JS引擎访问的内部属性。
其中一个内部属性是[[Scope]],
该内部属性包含了函数被创建的作用域中对象的集合,
这个集合被称为函数的作用域链,它决定了哪些数据能被函数访问。
作用域的集合就是作用域链
当代码在一个环境中执行时,会创建变量对象的一个作用域链。
作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。
全局执行环境的变量对象始终都是作用域链中的最后一个对象。
栈
一种数据结构 用于存储数据
存储特点是 LIFO(Last in First Out)
栈只有一个入口和出口在栈的顶部
数据的存取都在栈的顶部
事件
当用户与web页面进行交互时,
解释器就会创建相应的event对象以描述事件信息
常见的事件:
- 鼠标点击
- 鼠标移动
- 键盘按下
- 键盘弹起
- 窗口滚动
JS中获得的元素都是以对象的形式存在的,
可以通过对象.属性名 的语法获得属性值、
通过对象.属性名=值修改或设置属性值
class在JS中是关键字,不能用做命名,
访问元素的class属性时 使用className
事件与函数的关系
事件的触发需要满足以下条件 事件源 监听的事件 事件处理函数
window.onload
窗口(浏览器窗口)(资源)加载完毕 执行一个函数
//事件处理函数的特点是 不需要用户调用
//只要对应的事件被触发 就会自动执行
//函数表达式
window.onload=function(){
console.log(1);
}
鼠标常见事件
onclick()
鼠标点击
onmouseenter()
鼠标进入元素 类似mouseover()
onmouseleave()
鼠标离开元素 类似mouseout()
ondbclick()
鼠标左键双击
键盘常见事件
onkeydown
键盘按下
onkeyup
键盘弹起
表单常见事件
onsubmit
表单提交事件
onfocus
输入框获得焦点
onblur
输入框失去焦点
oninput
输入事件
引用类型
对象是一类数据和功能的集合
对象Object是ECMAScript提供的一个内置的 引用数据类型
它的本质是一组数据(属性)和功能(方法)的集合
给对象不存在的属性进行赋值是添加属性
给对象已存在的属性进