文章目录
- javascript
-
- 一、简介
- 二、基础语法
-
- 1. Helloword-编写位置-基本语法-字面量和变量-标识符
- 2.数据类型-基本数据类型(String-Number-Boolean-Null-Undefined)-类型转换
- 3.运算符(算数运算符-一元运算符-逻辑运算符-赋值运算符-关系运算符-相等运算符-三元运算符)
- 4.html页面和 js使用 Unicode编码
- 5.语句 代码块
- 6. 流程控制语句(if-else if-else ;switch-case; while; do-while;for)
- 7.对象
- 8.函数
- 9.作用域
- 10.this(上下文对象)
- 11.构造函数
- 12.原型
- 13.数组
- 14.数组方法
- 15.函数方法call-apply-arguments[callee]
- 16.包装类
- 17.字符串的相关的方法
- 18.正则表达式
- 19.Date
- 20.Math
- 21.`JSON`
- 三、DOM
- 四、事件(Event)
- 五、`BOM`
javascript
一、简介
1.什么是语言
计算机就是一个由人来控制的机器,人让它干嘛,它就得干嘛。
我们要学习的语言就是人和计算机交流的工具,人类通过语言来控制、操作计算机。
编程语言和我们说的中文、英文本质上没有区别,只是语法比较特殊。
语言的发展:
-
纸带机:机器语言
-
汇编语言:符号语言
-
现代语言:高级语言
2.起源
JavaScript诞生于1995年,它的出现主要是用于处理网页中的前端验证。
所谓的前端验证,就是指检查用户输入的内容是否符合一定的规则。
比如:用户名的长度,密码的长度,邮箱的格式等。
3.简史
JavaScript是由网景公司发明,起初命名为LiveScript,后来由于SUN公司的介入更名为了JavaScript。
1996年微软公司在其最新的IE3浏览器中引入了自己对JavaScript的实现JScript。
于是在市面上存在两个版本的JavaScript,一个网景公司的JavaScript和微软的JScript。
为了确保不同的浏览器上运行的JavaScript标准一致,所以几个公司共同定制了JS的标准名命名为ECMAScript。
4.ECMAScript实现
ECMAScript是一个标准,而这个标准需要由各个厂商去实现。
不同的浏览器厂商对该标准会有不同的实现
我们已经知道ECMAScript是JavaScript标准,所以一般情况下这两个词我们认为是一个意思。
但是实际上JavaScript的含义却要更大一些。
一个完整的JavaScript实现应该由以下三个部分构成:
5.JS的特点
- 解释型语言
- JavaScript是一门解释型语言,所谓解释型值语言不需要被编译为机器码在执行,而是直接执行。
- 由于少了编译这一步骤,所以解释型语言开发起来尤为轻松,但是解释型语言运行较慢也是它的劣势。
- 不过解释型语言中使用了JIT技术,使得运行速度得以改善。
- 类似于 C 和 Java 的语法结构
- JavaScript的语法结构与C和Java很像,向for、if、while等语句和Java的基本上是一模一样的。
- 所以有过C和Java基础的同学学习起来会轻松很多。
- 不过JavaScript和与Java的关系也仅仅是看起来像而已。
- 动态语言
- JavaScript是一门动态语言,所谓的动态语言可以暂时理解为在语言中的一切内容都是不确定的。比如一个变量,这一时刻是个整型,下一时刻可能会变成字符串了。
- 不过在补充一句动态语言相比静态语言性能上要差一些,不过由于JavaScript中应用的JIT技术,所以JS可能是运行速度最快的动态语言了
- 基于原型的面向对象
- JavaScript是一门面向对象的语言。
- Java也是一门面向对象的语言,但是与Java不同JavaScript是基于原型的面向对象。
二、基础语法
1. Helloword-编写位置-基本语法-字面量和变量-标识符
prompt() 输入语法
- JavaScript负责页面中的的行为。
- 它是一门运行在浏览器端的脚本语言。
- JS的编写的位置
1.可以编写到标签的指定属性中
<button οnclick="alert('hello');">我是按钮</button>
<a href="javascript:alert('aaa');">超链接</a>
虽然可以写在标签的属性中,但是他们属于结构与行为耦合,不方便维护,不推荐使用
2.可以编写到script标签中 *****
<script type="text/javascript">
//编写js代码
</script>
type:默认值text/javascript可以不写,不写也是这个值。
3.可以将代码编写到外部的js文件中,然后通过标签将其引入 *****
<script type="text/javascript" src="文件路径"></script>
src:当需要引入一个外部的js文件时,使用该属性指向文件的地址
写到外部文件中可以在不同的页面中同时引用,也可以利用到浏览器的缓存机制
script标签一旦用于引入外部文件了,就不能在编写代码了,即使编写了浏览器也会忽略
如果需要则可以在创建一个新的script标签用于编写内部代码
- 输出语句
- alert("要输出的内容");
- 该语句会在浏览器窗口中弹出一个警告框
- document.write("要输出的内容");
- 该内容将会被写到body标签中,并在页面中显示
- console.log("要输出的内容");
- 该内容会被写到开发者工具的控制台中
- 基本的语法
- 注释
- 单行注释
//注释内容
- 多行注释
/*
注释内容
*/
- JS严格区分大小写
- JS中每条语句以分号(;)结尾
- JS中会自动忽略多个空格和换行,所以我们可以利用空格和换行对代码进行格式化。
- 字面量和变量
- 字面量
- 字面量实际上就是一些固定的值,比如 1 2 3 4 true false null NaN "hello"
字面量都是不可以改变的。
- 由于字面量不是很方便使用,所以在JS中很少直接使用字面量
- 变量
- 变量可以用来保存字面量,并且可以保存任意的字面量
- 一般都是通过变量来使用字面量,而不直接使用字面量,而且也可以通过变量来对字面量进行一个描述
- 声明变量
- 使用var关键字来声明一个变量
var a;
var b;
var c;
- 为变量赋值
a = 1;
b = 2;
c = 3;
- 声明和赋值同时进行 *****
var d = 456;
var e = 789;
- 标识符
- 在JS中所有的可以自主命名的内容,都可以认为是一个标识符,
是标识符就应该遵守标识符的规范。
- 比如:变量名、函数名、属性名
- 规范:
1.标识符中可以含有字母、数字、_、$
2.标识符不能以数字开头
3.标识符不能是JS中的关键字和保留字
4.标识符一般采用驼峰命名法
xxxYyyZzz helloWorld
- JS底层保存标识符时实际上是采用的Unicode编码,
所以理论上讲,所有的utf-8中含有的内容都可以作为标识符
关键字
保留字符
其他不建议使用的标识符
2.数据类型-基本数据类型(String-Number-Boolean-Null-Undefined)-类型转换
1.数据类型
- JS中一共分成六种数据类型
- String 字符串
- Number 数值
- Boolean 布尔值
- Null 空值
- Undefined 未定义
- Object 对象
- 其中基本数据类型有
- String 字符串
- JS中的字符串需要使用引号引起来双引号或单引号都行
- 在字符串中使用\作为转义字符
\' ==> '
\" ==> "
\n ==> 换行
\t ==> 制表符
\\ ==> \
\b ==> 空格
\r ==> 回车
- 使用typeof运算符检查字符串时,会返回"string"
var a = 'a'
console.log(typeof a)
- Number 数值
- JS中所有的整数和浮点数都是Number类型
- 特殊的数字
Infinity 正无穷
-Infinity 负无穷
NaN 非法数字(Not A Number)
NaN 是一个特殊的数字,表示Not A Number
使用typeof检查一个NaN也会返回number
- 其他进制的数字的表示:
0b 开头表示二进制,但是不是所有的浏览器都支持
0 开头表示八进制
0x 开头表示十六进制
- 使用typeof检查一个Number类型的数据时,会返回"number"
(包括NaN 和 Infinity)
- JS中可以表示的数字的最大值 Number.MAX_VALUE 1.7976931348623157e+308
Number.MIN_VALUE 大于0的最小值 5e-324
- 如果使用JS进行浮点运算,可能得到一个不精确的结果
所以千万不要使用JS进行对精确度要求比较高的运算
- Boolean 布尔值
- 布尔值主要用来进行逻辑判断,布尔值只有两个
- true 逻辑的真
- false 逻辑的假
- 使用typeof检查一个布尔值时,会返回"boolean"
- Null 空值
- 空值专门用来表示为空的对象,Null类型的值只有一个
- null
- 使用typeof检查一个Null类型的值时会返回"object"
- Undefined 未定义
- 如果声明一个变量但是没有为变量赋值此时变量的值就是undefined
- 该类型的值只有一个 undefined
- 使用typeof检查一个Undefined类型的值时,会返回"undefined"
- 引用数据类型
- Object 对象
- 类型转换
- 类型转换就是指将其他的数据类型,转换为String Number 或 Boolean
- 转换为String
- 方式一(强制类型转换):
- 调用被转换数据的toString()方法
- 例子:
var a = 123;
a = a.toString();
- 注意:这个方法不适用于null和undefined
由于这两个类型的数据中没有方法,所以调用toString()时会报错
- 方式二(强制类型转换):
- 调用String()函数
- 例子:
var a = 123;
a = String(a);
- 原理:对于Number Boolean String都会调用他们的toString()方法来将其转换为字符串,
对于null值,直接转换为字符串"null"。对于undefined直接转换为字符串"undefined"
- 方式三(隐式的类型转换): *****
- 为任意的数据类型 +""
- 例子:
var a = true;
a = a + "";
- 原理:和String()函数一样
- 转换为Number
- 方式一(强制类型转换):
- 调用Number()函数
- 例子:
var s = "123";
s = Number(s);
- 转换的情况:
1.字符串 --> 数字
- 如果字符串是一个合法的数字,则直接转换为对应的数字
- 如果字符串是一个非法的数字,则转换为NaN
- 如果是一个空串或纯空格的字符串,则转换为0
2.布尔值 --> 数字
- true转换为1
- false转换为0
3.空值 --> 数字
- null转换为0
4.未定义 --> 数字
- undefined 转换为NaN
- 方式二(强制类型转换):
- 调用parseInt()或parseFloat()
- 这两个函数专门用来将一个*字符串*转换为数字的
- parseInt()
- 可以将一个字符串中的有效的整数位提取出来,并转换为Number
- 例子:
var a = "123.456px";
a = parseInt(a); //123
- 如果需要可以在parseInt()中指定一个第二个参数,来指定进制
a = "070";
//可以在parseInt()中传递一个第二个参数,来指定数字的进制
a = parseInt(a,10);
- parseFloat()
- 可以将一个字符串中的有效的小数位提取出来,并转换为Number
- 例子:
var a = "123.456px";
a = parseFloat(a); //123.456
- 如果对非String使用parseInt()或parseFloat()
它会先将其转换为String然后在操作
- 方式三(隐式的类型转换):
- 使用一元的+来进行隐式的类型转换
- * / - 隐式转换
- 例子:
var a = "123";
a = +a;
- 原理:和Number()函数一样
- 转换为布尔值
- 方式一(强制类型转换):
- 使用Boolean()函数
- 例子:
var s = "false";
s = Boolean(s); //true
- 转换的情况
字符串 --> 布尔
- 除了空串其余全是true
数值 --> 布尔
- 除了0和NaN其余的全是true
null、undefined ---> 布尔
- 都是false
对象 ---> 布尔
- 都是true
- 方式二(隐式类型转换):
- 为任意的数据类型做两次非运算,即可将其转换为布尔值
- 例子:
var a = "hello";
a = !!a; //true
3.运算符(算数运算符-一元运算符-逻辑运算符-赋值运算符-关系运算符-相等运算符-三元运算符)
1.运算符
- 运算符
- 运算符也称为操作符
- 通过运算符可以对一个或多个值进行运算或操作
- typeof运算符
- 用来检查一个变量的数据类型
- 语法:typeof 变量
- 它会返回一个用于描述类型的字符串作为结果
- 算数运算符
+ 对两个值进行加法运算并返回结果
- 对两个值进行减法运算并返回结果
* 对两个值进行乘法运算并返回结果
/ 对两个值进行除法运算并返回结果
% 对两个值进行取余运算并返回结果
** 次方
- 除了加法以外,对非Number类型的值进行运算时,都会先转换为Number然后在做运算。
- 而做加法运算时,如果是两个字符串进行相加,则会做拼串操作,将两个字符连接为一个字符串。
- 任何值和字符串做加法,都会先转换为字符串,然后再拼串
- 一元运算符
- 一元运算符只需要一个操作数
- 一元的+
- 就是正号,不会对值产生任何影响,但是可以将一个非数字转换为数字
- 例子:
var a = true;
a = +a;
对于非Number类型的值,
它会将先转换为Number,然后在运算
可以对一个其他的数据类型使用+,来将其转换为number
它的原理和Number()函数一样
- 一元的-
- 就是负号,可以对一个数字进行符号位取反
- 例子:
var a = 10;
a = -a;
- 自增
- 自增可以使变量在原值的基础上自增1
- 自增使用 ++
- 自增可以使用 前++(++a)后++(a++)
- 无论是++a 还是 a++都会立即使原变量自增1
不同的是++a和a++的值是不同的,
++a的值是变量的新值(自增后的值)
a++的值是变量的原值(自增前的值)
- 自减
- 自减可以使变量在原值的基础上自减1
- 自减使用 --
- 自减可以使用 前--(--a)后--(a--)
- 无论是--a 还是 a--都会立即使原变量自减1
不同的是--a和a--的值是不同的,
--a的值是变量的新值(自减后的值)
a--的值是变量的原值(自减前的值)
- 逻辑运算符
!
- 非运算可以对一个布尔值进行取反,true变false false边true
- 当对非布尔值使用!时,会先将其转换为布尔值然后再取反
- 我们可以利用!来将其他的数据类型转换为布尔值
&&
- &&可以对符号两侧的值进行与运算
- 只有两端的值都为true时,才会返回true。只要有一个false就会返回false。
- 与是一个短路的与,如果第一个值是false,则不再检查第二个值
- 对于非布尔值,它会将其转换为布尔值然后做运算,并返回原值
- 规则:
1.如果第一个值为false,则返回第一个值
2.如果第一个值为true,则返回第二个值
****3.返回的不一定是布尔值,而是返回表达式结果
||
- ||可以对符号两侧的值进行或运算
- 只有两端都是false时,才会返回false。只要有一个true,就会返回true。
- 或是一个短路的或,如果第一个值是true,则不再检查第二个值
- 对于非布尔值,它会将其转换为布尔值然后做运算,并返回原值
- 规则:
1.如果第一个值为true,则返回第一个值
2.如果第一个值为false,则返回第二个值
&& || 非布尔值的情况
* - 与运算:
* - 如果第一个值为true,则必然返回第二个值
* - 如果第一个值为false,则直接返回第一个值
* - 或运算
* - 如果第一个值为true,则直接返回第一个值
* - 如果第一个值为false,则返回第二个值
- 赋值运算符
=
- 可以将符号右侧的值赋值给左侧变量
+=
- a += 5 相当于 a = a+5
- var str = "hello"; str += "world";
-=
- a -= 5 相当于 a = a-5
*=
- a *= 5 相当于 a = a*5
/=
- a /= 5 相当于 a = a/5
%=
- a %= 5 相当于 a = a%5
- 关系运算符
- 关系运算符用来比较两个值之间的大小关系的
>
>=
<
<=
- 关系运算符的规则和数学中一致,用来比较两个值之间的关系,
如果关系成立则返回true,关系不成立则返回false。
- 如果比较的两个值是非数值,会将其转换为Number然后再比较。
任何值和NaN做任何比较都是false
- 如果比较的两个值都是字符串,此时会比较字符串的Unicode编码,而不会转换为Number。
比较字符编码时是一位一位进行比较
如果两位一样,则比较下一位,所以借用它来对英文进行排序
比较中文时没有意义
如果比较的两个字符串型的数字,可能会得到不可预期的结果
********注意:在比较两个字符串型的数字时,一定一定一定要转型
- 相等运算符
==
- 相等,判断左右两个值是否相等,如果相等返回true,如果不等返回false
- 相等会自动对两个值进行类型转换,如果对不同的类型进行比较,会将其转换为相同的类型然后再比较,
转换后相等它也会返回true
!=
- 不等,判断左右两个值是否不等,如果不等则返回true,如果相等则返回false
- 不等也会做自动的类型转换。
===
- 全等,判断左右两个值是否全等,它和相等类似,只不过它不会进行自动的类型转换,
如果两个值的类型不同,则直接返回false
!==
- 不全等,和不等类似,但是它不会进行自动的类型转换,如果两个值的类型不同,它会直接返回true
特殊的值:
- null和undefined
- 由于undefined衍生自null,所以null == undefined 会返回true。
但是 null === undefined 会返回false。
0 != null 0!= undefined
- NaN
- NaN不与任何值相等,报告它自身 NaN == NaN //false
- 判断一个值是否是NaN
- 使用isNaN()函数
- 三元运算符:
?:
- 语法:条件表达式?语句1:语句2;
- 执行流程:
先对条件表达式求值判断,
如果判断结果为true,则执行语句1,并返回执行结果
如果判断结果为false,则执行语句2,并返回执行结果
- 优先级:
- 和数学中一样,JS中的运算符也是具有优先级的,
比如 先乘除 后加减 先与 后或
- 具体的优先级可以参考优先级的表格,在表格中越靠上的优先级越高,
优先级越高的越优先计算,优先级相同的,从左往右计算。
- 优先级不需要记忆,如果越到拿不准的,使用()来改变优先级。
4.html页面和 js使用 Unicode编码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
/*
* 在字符串中使用转义字符输入Unicode编码
* \u四位编码
*/
console.log("\u2620");
</script>
</head>
<body>
<!--在网页中使用Unicode编码
&#编码; 这里的编码需要的是10进制
-->
<h1 style="font-size: 200px;">☠</h1>
<h1 style="font-size: 200px;">⚀</h1>
</body>
</html>
5.语句 代码块
语句
前边我所说表达式和运算符等内容可以理解成是我们一门语言中的单词,短语。
而语句(statement)就是我们这个语言中一句一句完整的话了。
语句是一个程序的基本单位,JS的程序就是由一条一条语句构成的,每一条语句使用;结尾。
JS中的语句默认是由上至下顺序执行的,但是我们也可以通过一些流程控制语句来控制语句的执行顺序。
代码块
代码块是在大括号 {} 中所写的语句,以此将多条语句的集合视为一条语句来使用。
例如:
{
var a = 123;
a++;
alert(a);
}
我们一般使用代码块将需要一起执行的语句进行分组,需要注意的是,代码块结尾不需要加分号。
es6语法 , let const 变量在代码块里只有局部作用,外面的代码看不到代码块内的let 变量
6. 流程控制语句(if-else if-else ;switch-case; while; do-while;for)
补充知识点
prompt()可以弹出一个提示框,该提示框中会带有一个文本框,
用户可以在文本框中输入一段内容,该函数需要一个字符串作为参数,
该字符串将会作为提示框的提示文字
用户输入的内容将会作为函数的返回值返回,可以定义一个变量来接收该内容
1.流程控制语句
- 程序都是自上向下的顺序执行的,
通过流程控制语句可以改变程序执行的顺序,或者反复的执行某一段的程序。
- 分类:
1.条件判断语句
2.条件分支语句
3.循环语句
条件判断语句
- 条件判断语句也称为if语句
- 语法一:
if(条件表达式){
语句...
}
- 执行流程:
if语句执行时,会先对条件表达式进行求值判断,
如果值为true,则执行if后的语句
如果值为false,则不执行
- 语法二:
if(条件表达式){
语句...
}else{
语句...
}
- 执行流程:
if...else语句执行时,会对条件表达式进行求值判断,
如果值为true,则执行if后的语句
如果值为false,则执行else后的语句
- 语法三:
if(条件表达式){
语句...
}else if(条件表达式){
语句...
}else if(条件表达式){
语句...
}else if(条件表达式){
语句...
}else{
语句...
}
- 执行流程
- if...else if...else语句执行时,会自上至下依次对条件表达式进行求值判断,
如果判断结果为true,则执行当前if后的语句,执行完成后语句结束。
如果判断结果为false,则继续向下判断,直到找到为true的为止。
如果所有的条件表达式都是false,则执行else后的语句
1.条件分支语句
- switch语句
- 语法:
- 这里需要与 case 全等 ===
switch(条件表达式){
case 表达式:
语句...
break;
case 表达式:
语句...
break;
case 表达式:
语句...
break;
default:
语句...
break;
}
- 执行流程:
- switch...case...语句在执行时,会依次将case后的表达式的值和switch后的表达式的值进行全等比较,
如果比较结果为false,则继续向下比较。如果比较结果为true,则从当前case处开始向下执行代码。
如果所有的case判断结果都为false,则从default处开始执行代码。
2.循环语句
- 通过循环语句可以反复执行某些语句多次
- while循环
- 语法:
while(条件表达式){
语句...
}
- 执行流程:
while语句在执行时,会先对条件表达式进行求值判断,
如果判断结果为false,则终止循环
如果判断结果为true,则执行循环体
循环体执行完毕,继续对条件表达式进行求值判断,依此类推
- do...while循环
- 语法:
do{
语句...
}while(条件表达式)
- 执行流程
do...while在执行时,会先执行do后的循环体,然后在对条件表达式进行判断,
如果判断判断结果为false,则终止循环。
如果判断结果为true,则继续执行循环体,依此类推
- 和while的区别:
while:先判断后执行
do...while: 先执行后判断
- do...while可以确保循环体至少执行一次。
- for循环
- 语法:
for(①初始化表达式 ; ②条件表达式 ; ④更新表达式){
③语句...
}
- 执行流程:
首先执行①初始化表达式,初始化一个变量,
然后对②条件表达式进行求值判断,如果为false则终止循环
如果判断结果为true,则执行③循环体
循环体执行完毕,执行④更新表达式,对变量进行更新。
更新表达式执行完毕重复②
- 死循环
while(true){
}
for(;;){
}
1.break-continue
break关键字可以用来退出switch或循环语句
不能在if语句中使用break和continue
break关键字,会立即终止离他最近的那个循环语句
可以为循环语句创建一个label,来标识当前的循环
label:循环语句
使用break语句时,可以在break后跟着一个label,
这样break将会结束指定的循环,而不是最近的
continue关键字可以用来跳过当次循环
同样continue也是默认只会对离他最近的循环循环起作用
continue 也能配合label使用
2.补充 程序计时-开方
console.time("计时器的名字")可以用来开启一个计时器
它需要一个字符串作为参数,这个字符串将会作为计时器的标识
console.timeEnd()用来停止一个计时器,需要一个计时器的名字作为参数
例如:
console.time("test");
console.timeEnd("test");
可以通过Math.sqrt()对一个数进行开方
7.对象
对象分类
1.内建对象
- 由ES标准中定义的对象,在任何的ES的实现中都可以使用
- 比如:Math String Number Boolean Function Object....
2.宿主对象
- 由JS的运行环境提供的对象,目前来讲主要指由浏览器提供的对象
- 比如 BOM DOM
3.自定义对象
- 由开发人员自己创建的对象
1.对象(Object)
- 对象是JS中的引用数据类型
- 对象是一种复合数据类型,在对象中可以保存多个不同数据类型的属性
- 使用typeof检查一个对象时,会返回object
- 创建对象
- 方式一:
- var obj = new Object();
- 方式二:使用对象字面量
- var obj = {};
- 向对象中添加属性
- 语法:
对象.属性名 = 属性值;
对象["属性名"] = 属性值;
- 对象的属性名没有任何要求,不需要遵守标识符的规范,
但是在开发中,尽量按照标识符的要求去写。
- 属性值也可以任意的数据类型。
- 读取对象中的属性
- 语法:
对象.属性名
对象["属性名"]
- 如果读取一个对象中没有的属性,它不会报错,而是返回一个undefined
- 删除对象中的属性
- 语法:
delete 对象.属性名
delete 对象["属性名"]
- 使用in检查对象中是否含有指定属性
- 语法:"属性名" in 对象
- 如果在对象中含有该属性,则返回true
如果没有则返回false
- 使用对象字面量,在创建对象时直接向对象中添加属性
语法:
var obj = {
属性名:属性值,
属性名:属性值,
属性名:属性值,
属性名:属性值
}
- 使用工厂方法创建对象 通过该方法可以大批量的创建对象
使用工厂方法创建的对象,使用的构造函数都是Object
就导致我们无法区分出多种不同类型的对象,后面用构造函数解决
function createPerson(name , age ,gender){
//创建一个新的对象
var obj = new Object();
//向对象中添加属性
obj.name = name;
obj.age = age;
obj.gender = gender;
obj.sayName = function(){
alert(this.name);
};
//将新的对象返回
return obj;
}
- 基本数据类型和引用数据类型
- 基本数据类型
String Number Boolean Null Undefined
- 引用数据类型
Object
- 基本数据类型的数据,变量是直接保存的它的值。
变量与变量之间是互相独立的,修改一个变量不会影响其他的变量。
- 引用数据类型的数据,变量是保存的对象的引用(内存地址)。
如果多个变量指向的是同一个对象,此时修改一个变量的属性,会影响其他的变量。
- 比较两个变量时,对于基本数据类型,比较的就是值,
对于引用数据类型比较的是地址,地址相同才相同
8.函数
1.函数(Function)
- 函数也是一个对象,也具有普通对象的功能
- 函数中可以封装一些代码,在需要的时候可以去调用函数来执行这些代码
- 使用typeof检查一个函数时会返回function
- 创建函数
- 构造函数
//我们在实际开发中很少使用构造函数来创建一个函数对象
//创建一个函数对象
//可以将要封装的代码以字符串的形式传递给构造函数
//var fun = new Function("console.log('Hello 这是我的第一个函数');");
- 函数声明
function 函数名([形参1,形参2...形参N]){
语句...
}
- 函数表达式
var 函数名 = function([形参1,形参2...形参N]){
语句...
//这是匿名函数 function 后面没有函数名
};
- 调用函数
- 语法:函数对象([实参1,实参2...实参N]);
fun() sum() alert() Number() parseInt()
- 当我们调用函数时,函数中封装的代码会按照编写的顺序执行
- 形参和实参
- 形参:形式参数
- 定义函数时,可以在()中定义一个或多个形参,形参之间使用,隔开
定义形参就相当于在函数内声明了对应的变量但是并不赋值,
形参会在调用时才赋值。
- 实参:实际参数
- 调用函数时,可以在()传递实参,传递的实参会赋值给对应的形参,
调用函数时JS解析器不会检查实参的类型和个数,可以传递任意数据类型的值。
如果实参的数量大于形参,多余实参将不会赋值,
如果实参的数量小于形参,则没有对应实参的形参将会赋值undefined
- 返回值,就是函数执行的结果。
- 使用return 来设置函数的返回值。
- 语法:return 值;
- 该值就会成为函数的返回值,可以通过一个变量来接收返回值
- return后边的代码都不会执行,一旦执行到return语句时,函数将会立刻退出。
- return后可以跟任意类型的值,可以是基本数据类型,也可以是一个对象。
- 如果return后不跟值,或者是不写return则函数默认返回undefined。
- break、continue和return
- break
- 退出循环
- continue
- 跳过当次循环
- return
- 退出函数
- 参数,函数的实参也可以是任意的数据类型。
- 方法(method)
- 可以将一个函数设置为一个对象的属性,
当一个对象的属性是一个函数时,
我们称这个函数是该对象的方法。
- 对象.方法名();
- 函数名();
补充 立即执行函数
/*
* 立即执行函数
* 函数定义完,立即被调用,这种函数叫做立即执行函数
* 立即执行函数往往只会执行一次
*/
(function () {
alert("我是一个匿名函数~~~");
})();
(function (a, b) {
console.log("a = " + a);
console.log("b = " + b);
})(123, 456);
(function () {
alert("我是一个匿名函数~~~");
}());
(function (a, b) {
console.log("a = " + a);
console.log("b = " + b);
}(123, 456));
9.作用域
作用域
- 作用域简单来说就是一个变量的作用范围。
- 在JS中作用域分成两种:
1.全局作用域
- 直接在script标签中编写的代码都运行在全局作用域中
- 全局作用域在打开页面时创建,在页面关闭时销毁。
- 全局作用域中有一个全局对象window,window对象由浏览器提供,
可以在页面中直接使用,它代表的是整个的浏览器的窗口。
- 在全局作用域中创建的变量都会作为window对象的属性保存
在全局作用域中创建的函数都会作为window对象的方法保存
- 在全局作用域中创建的变量和函数可以在页面的任意位置访问。
在函数作用域中也可以访问到全局作用域的变量。
- 尽量不要在全局中创建变量
2.函数作用域
- 函数作用域是函数执行时创建的作用域,每次调用函数都会创建一个新的函数作用域。
- 函数作用域在函数执行时创建,在函数执行结束时销毁。
- 在函数作用域中创建的变量,不能在全局中访问。
- 当在函数作用域中使用一个变量时,它会先在自身作用域中寻找,
如果找到了则直接使用,如果没有找到则到上一级作用域中寻找,
如果找到了则使用,找不到则继续向上找,一直会
- 变量的声明提前
- 在全局作用域中,使用var关键字声明的变量会在所有的代码执行之前被声明,但是不会赋值。
所以我们可以在变量声明前使用变量。但是不使用var关键字声明的变量不会被声明提前。
- 在函数作用域中,也具有该特性,使用var关键字声明的变量会在函数所有的代码执行前被声明,
****如果没有使用var关键字声明变量,则变量会变成全局变量,不使用var关键字声明的变量不会被声明提前。
- 函数的声明提前
- 在全局作用域中,使用函数声明创建的函数(function fun(){}),会在所有的代码执行之前被创建,
也就是我们可以在函数声明前去调用函数,但是使用函数表达式(var fun = function(){})创建的函数没有该特性
- 在函数作用域中,使用函数声明创建的函数,会在所有的函数中的代码执行之前就被创建好了。
10.this(上下文对象)
- 我们每次调用函数时,解析器都会将一个上下文对象作为隐含的参数传递进函数。
使用this来引用上下文对象,根据函数的调用形式不同,this的值也不同。
- this的不同的情况:
1.以函数的形式调用时,this是window
2.以方法的形式调用时,this就是调用方法的对象
3.以构造函数的形式调用时,this就是新创建的对象
4.使用call和apply调用时,this是指定的那个对象
5.在全局作用域中this代表window
目前以我自己知识量对this指向的总结
1.**以函数的形式调用时,this是window**
2.以方法的形式调用时,this就是调用方法的对象
3.以构造函数的形式调用时,this就是新创建的对象
函数箭头函数没有自己的this对象,看他所在作用域的this。
bind 可以绑定 普通函数的this对象,不可以绑定箭头函数的
箭头函数内部的this指向是固定的,相比之下,普通函数的this指向是可变的。
**普通函数**只有作为某**对象方法**时,内部this是这个对象,其余全是window ,构造函数作为普通函数使用 this 指向 window
构造函数new方式使用,this就是新创建的对象。
如下代码 输出的this 指向 window
var test = {
id: 1,
fun: function (fun1) {
fun1()
}
}
var obj = {
id: 2,
fun: function () {
test.fun(function () { console.log(this); })
}
}
obj.fun()
补充:
4.使用call和apply调用时,this是指定的那个对象,不可以改变箭头函数的this指向
5.在全局作用域中this代表window
- call()
- apply()
- 这两个方法都是函数对象的方法需要通过函数对象来调用
- 通过两个方法可以直接调用函数,并且可以通过第一个实参来指定函数中this
- 不同的是call是直接传递函数的实参而apply需要将实参封装到一个数组中传递
- call()方法可以将实参在对象之后依次传递
- apply()方法需要将实参封装到一个数组中统一传递
11.构造函数
- 构造函数是专门用来创建对象的函数
- 一个构造函数我们也可以称为一个类
- 通过一个构造函数创建的对象,我们称该对象时这个构造函数的实例
- 通过同一个构造函数创建的对象,我们称为一类对象
- 构造函数就是一个普通的函数,只是他的调用方式不同,
如果直接调用,它就是一个普通函数
如果使用new来调用,则它就是一个构造函数
- 例子:
function Person(){
}
- 构造函数的执行流程:
1.创建一个新的对象
2.将新的对象作为函数的上下文对象(this)
3.执行函数中的代码
4.将新建的对象返回
-
- instanceof 用来检查一个对象是否是一个类的实例
- 语法:对象 instanceof 构造函数
- 如果该对象时构造函数的实例,则返回true,否则返回false
- Object是所有对象的祖先,所以任何对象和Object做instanceof都会返回true
/*
* 创建一个Person构造函数
* - 在Person构造函数中,为每一个对象都添加了一个sayName方法,
* 目前我们的方法是在构造函数内部创建的,
* 也就是构造函数每执行一次就会创建一个新的sayName方法
* 也是所有实例的sayName都是唯一的。
* 这样就导致了构造函数执行一次就会创建一个新的方法,
* 执行10000次就会创建10000个新的方法,而10000个方法都是一摸一样的
* 这是完全没有必要,完全可以使所有的对象共享同一个方法
*/
function Person(name , age , gender){
this.name = name;
this.age = age;
this.gender = gender;
//向对象中添加一个方法
this.sayName = function(){
alert("Hello大家好,我是:"+this.name);
}
}
//将sayName方法在全局作用域中定义
/*
* 将函数定义在全局作用域,污染了全局作用域的命名空间
* 而且定义在全局作用域中也很不安全
*/
function Person(name , age , gender){
this.name = name;
this.age = age;
this.gender = gender;
//向对象中添加一个方法
this.sayName = fun;
}
function fun(){
alert("Hello大家好,我是:"+this.name);
};
//向原型中添加sayName方法 √
Person.prototype.sayName = function(){
alert("Hello大家好,我是:"+this.name);
};
1.枚举对象中的属性
for...in
语法:
for(var 属性名 in 对象){
}
for...in语句的循环体会执行多次,对象中有几个属性就会执行几次(包括自己在构造函数在原型对象中添加的属性),
每次将一个属性名赋值给我们定义的变量,我们可以通过它来获取对象中的属性
如果是数组,对应的属性名是从0开始的索引
for...of语句在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句
12.原型
1.原型(prototype)
- 创建一个函数以后,**解析器**都会**默认在函数中添加一个数prototype**
prototype属性指向的是一个对象,这个对象我们称为原型对象。
如果函数作为普通函数调用prototype没有任何作用
- 当函数以构造函数的形式调用时,它所创建的对象中都会有一个隐含的属性,
指向该构造函数的原型对象,我们可以通过__proto__来访问该属性
- 原型对象就相当于一个公共的区域,凡是通过同一个构造函数创建的对象他们通常都可以访问到相同的原型对象。
我们可以将对象中共有的属性和方法统一添加到原型对象中,
这样我们只需要添加一次,就可以使所有的对象都可以使用。
- 当我们去访问对象的一个属性或调用对象的一个方法时,它会先自身中寻找,
如果在自身中找到了,则直接使用。
如果没有找到,则去原型对象中寻找,如果找到了则使用,
如果没有找到,则去原型的原型中寻找,依此类推。直到找到Object的原型为止,Object的原型的原型为null,
如果依然没有找到则返回undefined
- 以后我们创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中,
这样不用分别为每一个对象添加,也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法了
- hasOwnProperty()
- 这个方法可以用来检查对象自身中是否含有某个属性(原型身上的不算)
- 语法:对象.hasOwnProperty("属性名")
1.补充 toString
当我们直接在页面中打印一个对象时,事件上是输出的对象的toString()方法的返回值
如果我们希望在输出对象时不输出[object Object],可以为对象添加一个toString()方法
一般加在构造函数prototype上
2.垃圾回收(GC)
- 就像人生活的时间长了会产生垃圾一样,程序运行过程中也会产生垃圾
这些垃圾积攒过多以后,会导致程序运行的速度过慢,
所以我们需要一个垃圾回收的机制,来处理程序运行过程中产生垃圾
- 当一个对象没有任何的变量或属性对它进行引用,此时我们将永远无法操作该对象,
此时这种对象就是一个垃圾,这种对象过多会占用大量的内存空间,导致程序运行变慢,
所以这种垃圾必须进行清理。
- 在JS中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁,
我们不需要也不能进行垃圾回收的操作
- **我们需要做的只是要将不再使用的对象设置null即可**
13.数组
数组(Array)
- 数组也是一个对象,是一个用来存储数据的对象
和Object类似,但是它的存储效率比普通对象要高
数组中的元素可以是任意的数据类型
数组中也可以放数组,生成多维数组
- 数组中保存的内容我们称为元素
- 数组使用索引(index)来操作元素
- 索引指由0开始的整数
- 数组的操作:
- 创建数组
- var arr = new Array();
- var arr = [];
- 向数组中添加元素
- 语法;
数组对象[索引] = 值;
arr[0] = 123;
arr[1] = "hello";
- 创建数组时直接添加元素
- 语法:
var arr = [元素1,元素2....元素N];
var arr = new Array(1, 'a', null);
new Array(3) 创建长度为3的空数组
- 例子:
var arr = [123,"hello",true,null];
- 获取和修改数组的长度
- 使用length属性来操作数组的长度
- 获取长度:
数组.length
- length获取到的是数组的最大索引+1
- 对于连续的数组,length获取到的就是数组中元素的个数
- 修改数组的长度
数组.length = 新长度
- 如果修改后的length大于原长度,则多出的部分会空出来
- 如果修改后的length小于原长度,则原数组中多出的元素会被删除
- 向数组的最后添加元素
数组[数组.length] = 值;
- 数组的方法
- push()
- 用来向数组的末尾添加一个或多个元素,并返回数组新的长度
- 语法:数组.push(元素1,元素2,元素N)
- pop()
- 用来删除数组的最后一个元素,并返回被删除的元素
- unshift()
- 向数组的前边添加一个或多个元素,并返回数组的新的长度
- shift()
- 删除数组的前边的一个元素,并返回被删除的元素
- slice()
- 可以从一个数组中截取指定的元素
- 该方法不会影响原数组,而是将截取到的内容封装为一个新的数组并返回
- 参数:
1.截取开始位置的索引(包括开始位置)
2.截取结束位置的索引(不包括结束位置)
- 第二个参数可以省略不写,如果不写则一直截取到最后
- 参数可以传递一个负值,如果是负值,则从后往前数
- splice()
- 可以用来删除数组中指定元素,并使用新的元素替换
该方法会将删除的元素封装到新数组中返回
- 参数:
1.删除开始位置的索引
2.删除的个数
3.三个以后,都是替换的元素,这些元素将会插入到开始位置索引的前边
- 遍历数组
- 遍历数组就是将数组中元素都获取到
- 一般情况我们都是使用for循环来遍历数组:
for(var i=0 ; i<数组.length ; i++){
//数组[i]
}
- 使用forEach()方法来遍历数组(不兼容IE8)
数组.forEach(function(value , index , obj){
});
forEach()方法需要一个回调函数作为参数,
数组中有几个元素,回调函数就会被调用几次,
每次调用时,都会将遍历到的信息以实参的形式传递进来,
我们可以定义形参来获取这些信息。
value:正在遍历的元素
index:正在遍历元素的索引
obj:被遍历对象
14.数组方法
reverse()
- reverse() 方法将数组中元素的位置颠倒,并返回该数组。数组的第一个元素会变成最后一个,数组的最后一个元素变成第一个。该方法会改变原数组。
concat()
- 可以连接两个或多个数组,它不会影响原数组,而是新数组作为返回值返回
该方法不会对原数组产生影响
join()
- 可以将一个数组转换为一个字符串
- 参数:
需要一个字符串作为参数,这个字符串将会作为连接符来连接数组中的元素
如果不指定连接符则默认使用','
sort()
- 可以对一个数组中的内容进行排序,默认是按照'Unicode编码'进行排序
调用以后,会直接修改原数组。
- 即使数组是数字数组,也默认Unicode 编码排序
- 可以自己指定排序的规则,需要一个回调函数作为参数:
function(a,b){
//升序排列
//return a-b;
//降序排列
return b-a;
}
方法 | 描述 |
---|---|
push() | 将新元素添加到数组的末尾,并返回新的长度。 |
pop() | 删除数组的最后一个元素,并返回该元素。 |
shift() | 删除数组的第一个元素,并返回该元素。 |
unshift() | 将新元素添加到数组的开头,并返回新的长度。 |
forEach() | 为每个数组元素调用函数。 |
slice() | 选择数组的一部分,并返回新数组。 |
splice() | 从数组中添加/删除元素。 |
concat() | 连接两个或多个数组,并返回已连接数组的副本。 |
reverse() | 反转数组中元素的顺序。 |
join() | 将数组的所有元素连接成一个字符串。 |
sort() | 对数组的元素进行排序。 |
copyWithin() | 将数组中的数组元素复制到指定位置或从指定位置复制。 |
entries() | 返回键/值对数组迭代对象。 |
every() | 检查数组中的每个元素是否通过测试。 |
fill() | 用静态值填充数组中的元素。 |
filter() | 使用数组中通过测试的每个元素创建新数组。 |
find() | 返回数组中第一个通过测试的元素的值。 |
findIndex() | 返回数组中通过测试的第一个元素的索引。 |
from() | 从对象创建数组。 |
includes() | 检查数组是否包含指定的元素。 |
indexOf() | 在数组中搜索元素并返回其位置。 |
isArray() | 检查对象是否为数组。 |
keys() | 返回 Array Iteration 对象,包含原始数组的键. |
lastIndexOf() | 在数组中搜索元素,从末尾开始,并返回其位置。 |
map() | 使用为每个数组元素调用函数的结果创建新数组。 |
reduce() | 将数组的值减为单个值(从左到右)。 |
reduceRight() | 将数组的值减为单个值(从右到左)。 |
some() | 检查数组中的任何元素是否通过测试。 |
toString() | 将数组转换为字符串,并返回结果。 |
valueOf() | 返回数组的原始值。 |
15.函数方法call-apply-arguments[callee]
- call()
- apply()
- 这两个方法都是函数对象的方法需要通过函数对象来调用
- 通过两个方法可以直接调用函数,并且可以通过第一个实参来指定函数中this
- 不同的是call是直接传递函数的实参而apply需要将实参封装到一个数组中传递
- call()方法可以将实参在对象之后依次传递
- apply()方法需要将实参封装到一个数组中统一传递
- arguments
- arguments和this类似,都是函数中的隐含的参数
- arguments是一个*类数组元素*,它用来封装函数执行过程中的实参
所以即使不定义形参,也可以通过arguments来使用实参
- arguments中有一个属性callee表示当前执行的函数对象
1.补充:闭包
闭包(closure)
- 闭包是JS一个非常重要的特性,这意味着当前作用域总是能够访问外部作用域中的
变量。因为函数是JS中唯一拥有自身作用域的结构,因此闭包的创建依赖于函数。
- 也可以将闭包的特征理解为,其相关的局部变量在函数调用结束之后将会继续存在。
16.包装类
- 在JS中为我们提供了三个包装类:
String() Boolean() Number()
- 通过这三个包装类可以创建基本数据类型的对象
例子:
var num = new Number(2);
var str = new String("hello");
var bool = new Boolean(true);
- 但是在实际应用中千万不要这么干。
- 当我们去操作一个基本数据类型的属性和方法时,
解析器会临时将其转换为对应的包装类,然后再去操作属性和方法,
操作完成以后再将这个临时对象进行销毁。
17.字符串的相关的方法
在底层字符串是以字符数组的形式保存的
//console.log(str.length);
//console.log(str[5]);
length
- 获取字符串的长度
charAt()
- 根据索引获取指定的字符
charCodeAt()
- 根据索引获取指定的字符编码
String.fromCharCode()
- 根据字符编码获取字符
concat()
- 可以用来连接两个或多个字符串
- 作用和+一样
indexOf()
lastIndexOf()
- 从一个字符串中检索指定内容
- 需要一个字符串作为参数,这个字符串就是要检索的内容,
如果找到该内容,则会返回其第一次出现的索引,如果没有找到则返回-1。
- 可以指定一个第二个参数,来表示开始查找的位置 ,不能指定负数
- indexOf()是从前向后找
- lastIndexOf()是从后向前找
slice()
- 可以从一个字符串中截取指定的内容,并将截取到内容返回,不会影响原变量
- 参数:
第一个:截取开始的位置(包括开始)
第二个:截取结束的位置(不包括结束)
- 可以省略第二个参数,如果省略则一直截取到最后
- 可以传负数,如果是负数则从后往前数
substr()
- 和slice()基本一致,不同的是它第二个参数不是索引,而是截取的数量
substring()
- 和slice()基本一致,不同的是它不能接受负值作为参数,如果设置一个负值,则会自动修正为0,
substring()中如果第二个参数小于第一个,自动调整位置
toLowerCase() toLocaleLowerCase()
- 将字符串转换为小写并返回
toUpperCase() toLocaleUpperCase()
- 将字符串转换为大写并返回
split()
- 可以根据指定内容将一个字符串拆分为一个数组
- 参数:
- 需要一个字符串作为参数,将会根据字符串去拆分数组
可以接收一个正则表达式,此时会根据正则表达式去拆分数组
方法 | 描述 |
---|---|
anchor() | 创建 HTML 锚。 |
big() | 用大号字体显示字符串。 |
blink() | 显示闪动字符串。 |
bold() | 使用粗体显示字符串。 |
charAt() | 返回在指定位置的字符。 |
charCodeAt() | 返回在指定的位置的字符的 Unicode 编码。 |
concat() | 连接字符串。 |
fixed() | 以打字机文本显示字符串。 |
fontcolor() | 使用指定的颜色来显示字符串。 |
fontsize() | 使用指定的尺寸来显示字符串。 |
fromCharCode() | 从字符编码创建一个字符串。 |
indexOf() | 检索字符串。 |
italics() | 使用斜体显示字符串。 |
lastIndexOf() | 从后向前搜索字符串。 |
link() | 将字符串显示为链接。 |
localeCompare() | 用本地特定的顺序来比较两个字符串。 |
match() | 找到一个或多个正则表达式的匹配。 |
replace() | 替换与正则表达式匹配的子串。 |
search() | 检索与正则表达式相匹配的值。 |
slice() | 提取字符串的片断,并在新的字符串中返回被提取的部分。 |
small() | 使用小字号来显示字符串。 |
split() | 把字符串分割为字符串数组。 |
strike() | 使用删除线来显示字符串。 |
sub() | 把字符串显示为下标。 |
substr() | 从起始索引号提取字符串中指定数目的字符。 |
substring() | 提取字符串中两个指定的索引号之间的字符。 |
sup() | 把字符串显示为上标。 |
toLocaleLowerCase() | 把字符串转换为小写。 |
toLocaleUpperCase() | 把字符串转换为大写。 |
toLowerCase() | 把字符串转换为小写。 |
toUpperCase() | 把字符串转换为大写。 |
toSource() | 代表对象的源代码。 |
toString() | 返回字符串。 |
valueOf() | 返回某个字符串对象的原始值。 |
18.正则表达式
方法 | 描述 |
---|---|
exec |
一个在字符串中执行查找匹配的RegExp方法,它返回一个数组(只有索引为零的值)(未匹配到则返回 null)【一次查一个 迭代使用】。 |
test |
一个在字符串中测试是否匹配的RegExp方法,它返回 true 或 false。 |
match |
一个在字符串中执行查找匹配的String方法,它返回一个数组,在未匹配到时会返回 null。 |
matchAll |
一个在字符串中执行查找所有匹配的String方法,它返回一个迭代器(iterator)。 |
search |
一个在字符串中测试匹配的String方法,它返回匹配到的位置索引,或者在失败时返回-1。 |
replace |
一个在字符串中执行查找匹配的String方法,并且使用替换字符串替换掉匹配到的子字符串。 |
split |
一个使用正则表达式或者一个固定字符串分隔一个字符串,并将分隔后的子字符串存储到数组中的 String 方法。 |
- 正则用来定义一些字符串的规则,程序可以根据这些规则来判断一个字符串是否符合规则,
也可以将一个字符串中符合规则的内容提取出来。
- 创建正则表达式
- var reg = new RegExp("正则","匹配模式");
- var reg = /正则表达式/匹配模式
下面这是两两等价 注意一下
var reg = /\./
var reg = RegExp('\\.')
var reg = /\\/
var reg = RegExp('\\\\')
- 语法:
匹配模式:
i:忽略大小写
g:全局匹配模式
- 设置匹配模式时,可以都不设置,也可以设置1个,也可以全设置,设置时没有顺序要求
正则语法
| 或
[] 或
[^ ] 除了
[a-z] 小写字母
[A-Z] 大写字母
[A-z] 任意字母
[0-9] 任意数字
- 语法:
- 量词
{n} 正好n次
{m,n} m-n次
{m,} 至少m次
+ 至少1次 {1,}
? 0次或1次 {0,1}
* 0次或多次 {0,}
- 转义字符
\ 在正则表达式中使用\作为转义字符
\. 表示.
\\ 表示\
. 表示任意字符
\w
- 相当于[A-z0-9_]
\