文章目录
一、JS的组成部分
JavaScript是由ECMAScript、文档对象模型(Document Object Model:DOM)、浏览器对象模型
(Brower Object Model:BOM)三部分构成。
- ECMAScript,描述了该语言的基础语法和基本对象(包含内置对象),JavaScript的核心,描述了语言
的基本语法(变量、运算符、表达式、流程控制语句等)和数据类型(数字、字符串、布尔、array、函
数、对象(obj、[]、{}、null)、未定义),ECMAScript是一套标准.
- 文档对象模型(DOM),描述处理网页内容的方法和接口。通过 DOM,可以访问所有的 HTML 元
素,连同它们所包含的文本和属性,可以对其中的内容进行修改和删除,同时也可以创建新的元
素;DOM(文档对象模型)是 HTML 和 XML 的应用程序接口(API)。DOM 将把整个页面规划成
由节点层级构成的文档。HTML 或 XML 页面的每个部分都是一个节点的衍生物。
- 浏览器对象模型(BOM),描述与浏览器进行交互的方法和接口。BOM提供了独立于内容而与浏
览器窗口进行交互的对象,例如可以移动,调整浏览器大小的window对象,可以用于导航的
location对象与history对象,可以获取浏览器,操作系统与用户屏幕信息的navigator与screen对象。
二、JS的引入方式
HTML 中的脚本必须位于 标签之间。
脚本可被放置在 HTML 页面的 和 部分中。
引入JavaScript需要使用script标签:
script 标签用于定义客户端脚本,script 元素即可包含脚本语句,又可通过 src 属性指向外部脚
本文件。
如果想在页面上使用JavaScript,必须使用 script 标签,把JavaScript源码放入 script 和
/script 之间。
script 标签属性:
type:指定脚本的类型。
src:指定外部脚本的url。
script 和 /script 会告诉 JavaScript 在何处开始和结束。
script 和 /script 之间的代码行包含了 JavaScript:
<script>
//定义JS代码
</script>
//引入外部JS文件
<script src="url"></script>
浏览器会解释并执行位于 之间的 JavaScript 代码。
那些老旧的实例可能会在
了。
JavaScript 是所有现代浏览器以及 HTML5 中的默认脚本语言。
2…1 行内引入JavaScript
在标签事件属性中填写JavaScript代码或调用函数时,调用函数时不是 事件=函数名, 而是 事件=函数名
+()
<button onclick="alert('我是一个警告框')" type="button">点击这里</button>
<head>
<script>
function myfunction(){
document.getElementById("demo").innerHTML="onclick事件触发";
}
</script>
</head>
<body>
<h1 id="demo">一个段落</h1>
<button onclick="myfunction()" type="button">点击这里</button>
</body>
2.2内部引入JavaScript
您可以在 HTML 文档中放入不限数量的脚本。
脚本可位于 HTML 的 或 部分中,或者同时存在于两个部分中。
通常的做法是把函数放入 部分中,或者放在页面底部。这样就可以把它们安置到同一处位置,
不会干扰页面的内容。
<!DOCTYPE html>
<html>
<head>
<script>
function myFunction(){
document.getElementById("demo").innerHTML="我的第一个 JavaScript 函
数";
}
</script>
</head>
<body>
<h1>我的 Web 页面</h1>
<p id="demo">一个段落</p>
<button type="button" onclick="myFunction()">尝试一下</button>
</body>
</html>
<!DOCTYPE html>
<html>
<body>
<h1>我的 Web 页面</h1>
<p id="demo">一个段落</p>
<button type="button" onclick="myFunction()">尝试一下</button>
<script>
function myFunction(){
document.getElementById("demo").innerHTML="我的第一个 JavaScript 函
数";
}
</script>
</body>
</html>
2.3 外部引入JavaScript
也可以把脚本保存到外部文件中。外部文件通常包含被多个网页使用的代码。
外部 JavaScript 文件的文件扩展名是 .js。
如需使用外部文件,请在
<!DOCTYPE html>
<html>
<body>
<script src="myScript.js"></script>
</body>
</html>
如果把JS源代码直接写在某个具体的页面上时(通常放在 标签下),这样的成为内部的JavaScript。
但是当 JS 代码越来越庞大的时候,我们最好把它独立另存为一个JS文件,扩展名为.js,然后在页面上引
入即可,这样的称为外部的JS文件,它具有维护性高、可缓存(加载一次,无需加载)、方便未来扩展、复
用性高等特点。
三、JS三种输出
3.1向文档写入内容
输出文字。
除了直接输出文字外,它还支持带有HTML标签的输出内容。
比如直接输出一个标题
比如在输出内容中加入br换行标签
比如输入一张图片
…等等
<!DOCTYPE html>
<html>
<body>
<h1>我的第一个 Web 页面</h1>
<p>我的第一个段落。</p>
<script>
document.write("<h1>我是H1的内容</h1>");
</script>
</body>
</html>
如果在文档已完成加载后执行 document.write,整个 HTML 页面将被覆盖。
<!DOCTYPE html>
<html>
<body>
<h1>我的第一个 Web 页面</h1>
<p>我的第一个段落。</p>
<button onclick="myFunction()">点我</button>
<script>
function myFunction() {
document.write(Date());
}
</script>
</body>
</html>
3.2警告框
**alert()**方法:
alert()方法会弹出警告框。
可以添加多个alert();他们会按照顺序依次执行。
<!DOCTYPE html>
<html>
<body>
<h1>我的第一个页面</h1>
<p>我的第一个段落。</p>
<script>
window.alert(5 + 6);
</script>
</body>
</html>
3.3控制台
console.log():
写入到浏览器的控制台。
如果您的浏览器支持调试,你可以使用 console.log() 方法在浏览器中显示 JavaScript 值。
浏览器中使用 F12 来启用调试模式, 在调试窗口中点击 “Console” 菜单。
<!DOCTYPE html>
<html>
<body>
<h1>我的第一个 Web 页面</h1>
<script>
a = 5;
b = 6;
c = a + b;
console.log(c);
</script>
</body>
</html>
四、JavaScript注释及注意事项
单行注释:
// 单行注释内容
var name = 'hm';
多行注释:
/* 多行注释内容 */
/*
var age = 18;
var name = 'zs';
console.log(name, age);
*/
文档注释
/** 文档注释内容 */
注意事项:
- 字母的大小写,Name和name是两个不同的标识符。
- 空格和换行。这一点和CSS代码规则类似:多余的空格会被忽略,可以将一行代码分成多行写。
- 分号作为一个语句的结束标志,分号之后是新语句的开始。虽然省略不写通常也是没有问题的,但
还是建议大家写上。
五、JavaScript变量和数据类型
5.1标识符
所谓标识符,就是指变量、函数、属性的名字,或者函数的参数(凡是可以自己起名字的地方,都叫标
识符)。
标识符命名规范(包括函数名,变量等):
由字母、数字、下划线、$符号组成;
不能以数字开头
命名不能是系统的关键字或保留字:比如new ,if,class…;关键字:赋予特殊含义的单词
区分大小写
命名最好用有意义的名称(见名之意)。比如说name,people…
驼峰原则: 首字母小写,多个单词组成,从第二个单词的首字母开始都大写; 比如: getNameById();
常量命名: 全部大写,多个单词组成,每个单词之间由下划线分割;APPLICATION_NAME
需要注意的是ECMAScript 中的一切,包括变量、函数名和操作符(typeof、instanceof、void等)都是严
格区分大小写的。例如:text 和Text 表示两种不同的变量。
5.2变量
可以发生改变的量就是变量,变量可以看做是存储数据的容器。比如一个瓶子,它既可以装入酱油、
醋;也可以装入茅台和二锅头…。
变量是计算机内存中存储数据的标识符,根据变量名称可以获取到内存中存储的数据
使用变量可以方便的获取或者修改内存中的数据。
**在我们平时开发中,使用最多的并不是固定的数据, **而是会变换的数据。
- 比如购物车商品的数量、价格的计算等等;
- 比如一首歌曲播放的时间、进度条、歌词的展示等等;
- 比如微信聊天中消息条数、时间、语音的长度、头像、名称等等;
- 比如游戏中技能的冷却时间、血量、蓝量、buff时间、金币的数量等等;
5.3变量的命名
可以给变量起一个简短名称,这个名称就是变量名。比如 x,或者更有描述性的名称,比如 age、name
等。变量名对大小写敏感(y 和 Y 是两个不同的变量)且必须以字母或下划线开始。可以通过其名称来引
用一个变量,以此显示或改变它的值。
5.4变量的声明
在 JavaScript 中创建变量通常称为“声明”变量,使用关键字 var来声明变量。
向变量赋值,使用等号;可以在声明变量时对其赋值,也可以先声明后赋值。
可以在一条语句中声明很多变量。该语句以 var 开头,并使用逗号分隔变量即可
// 声明一个变量count:
var count;
// 声明一个变量username:
var username;
在以上声明之后,变量并没有值,仅仅只是变量声明,不过可以在声明它们时向变量赋值,”=”是赋值符
号,变量名在赋值符号符号的左边,而需要向变量赋的值在赋值符号的右侧。
// 变量声明并赋值
var count = 5;
var username= "Volvo";
也可以先声明后赋值。
// 先声明后赋值
var count ;
count=100;
var username;
username = “zhangsan”;
注释:在为变量赋文本值时,请为该值加引号(单引号或双引号都可以)。
如果所赋值的变量还未进行过声明,该变量会自动声明。
// 这些语句:
x = 5; carname = "Volvo";
// 与这些语句的效果相同:
var x = 5; var carname = "Volvo";
如果再次声明了 JavaScript 变量,该变量也不会丢失其原始值。
var x = 5;
var x; // 5
在以上语句执行后,变量 x 的值仍然是 5。在重新声明该变量时,x 的值不会被重置或清除。 但是如果
是在下面这种情况下,JavaScript 变量的值会改变
var x = 5;
var x = 7;
此时页面输出的值为7。
JavaScript也允许一次定义多个变量:
var a,b,v;
还可以在定义变量的同时给变量赋初始值:
var a=12,b,c=34;
如果一个变量没有赋值,它的值是undefined(未定义)。
5.5变量在内存中的存储
var name = "zhangsan";
var age = 18;
5.6变量的简单使用
1、小明今年20岁,小胡比小明大15岁,请问小胡今年多大?
<script>
//1、声明一个变量,用来存储小明的年龄
var xiaoming_age = 20;
//2、声明一个变量,用来存储小胡的年龄
var xiaohu_age;
//3、通过小明的年龄运算给小胡赋值
xiaohu_age = xiaoming_age + 15;
//4、输出小胡的名字
alert("小胡的年龄是:"+xiaohu_age);
</script>
2、在淘宝网购物,一件衣服55.4元,如果买4件衣服,共花多少钱?
<script>
//1、声明一个变量,用来存储衣服单价
var price = 55.4;
//2、声明一个变量,用来存储衣服的数量
var count = 4;
//3、计算得出总价格,并使用变量存储总价格
var money = price * count;
alert("衣服的总价格是:"+money);
</script>
3、思维题交换两个变量的值不使用临时变量,交换两个数值变量的值
var n1 = 5;
var n2 = 6;
n1 = n1 + n2; // 5 + 6 = 11
n2 = n1 - n2; // 11 - 6 = 5;
n1 = n1 - n2; // 11 - 5 = 6;
console.log(n1, n2);
5.7 数据类型
Javascript脚本语言同其他语言一样,有它自身的基本数据类型,表达式和算术运算符及程序的基本程序
框架。
Javascript提供了五种原始的数据类型和两种特殊数据类型用来处理数据和文字。
而变量提供存放信息的地方,表达式则可以完成较复杂的信息处理。
值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、空(Null)、未定义(Undefined)、Symbol。
引用数据类型(对象类型):对象(Object)、数组(Array)、函数(Function),还有两个特殊的对象:正则(RegExp)和日期(Date)
5.8 字符串
字符串是存储字符(比如 “Bill Gates”)的变量。
字符串可以是引号中的任意文本。您可以使用单引号或双引号;
变量字符串:如:var text=“HTML5视频教程”
可以使用"+"进行字符串的连接
在 JavaScript 中,字符串使用单引号或者双引号来起始或者结束。那么如何输出单引号或者双引号呢?
就要用到转义字符。
JavaScript中常用的转义字符**(转义就是转变原有的意思)**:
代码 | 输出 |
---|---|
\’ | 单引号 |
\" | 双引号 |
\\ | 反斜杠 |
\n | 换行 |
\r | 回车 |
\t | tab(制表符) |
\b | 退格符 |
\f | 换页符 |
字符串长度
length属性用来获取字符串的长度。
var str = 'Hello World';
console.log(str.length);
字符串拼接
字符串拼接使用 + 连接。
console.log(11 + 11);
console.log('hello' + ' world');
console.log('100' + '100');
console.log('11' + 11);
console.log('male:' + true);
- 两边只要有一个是字符串,那么+就是字符串拼接功能。
- 两边如果都是数字,那么就是算术功能。
5.9 **数值(**Number)
JavaScript 只有一种数值类型。数值可以带小数点,也可以不带。极大或极小的数字可以通过科学(指
数)计数法来书写:3e4。
数值可以通过运算符进行计算。
浮点数值的最高精度是16位小数,但是在进行算术计算时其精度远远不如整数。例如,0.1加0.2的结果
不是0.3, 而是0.30000000000000004。这个舍入误差会导致无法测试特定的浮点数值。
数字可以写成十进制、八进制、十六进制。
八进制在js中表示是第一位一定要是0,后面就是八进制字数序列(0~7)
十六进制字面量前两位必须是0x,后面跟十六进制数字(09及AF)。字母A~F不区分大小写。
**温馨提示:**科学(指数)计数法、八进制、十六进制表示的数字在输出时统统会转换成十进制。
数值字面量:数值的固定值的表示法。
5.10 布尔(Boolean)
Boolean(布尔)类型用于表示真假:
比如是否毕业. 是否有身份证. 是否购买车票. 是否成年人;
比如开发中,我们会判断一个账号是否登录、是否是管理员、是否具备某个权限、是否拥有某个英
雄、皮肤等;
Boolean **类型仅包含两个值:**true 和 false:
就两个值,一个是true,一个false,true表示真 false表示假
前面,讲的string或number数据类型,对应的值有无数个
5.11数组**(**Array)
2.4.4.1、为什么需要数组?
之前学习的数据类型,只能存储一个值(比如:Number/String。我们想存储班级中所有学生的姓名,此
时该如何存储?
2.4.4.2、数组的概念
所谓数组,就是将多个元素(通常是同一类型)按一定顺序排列放到一个集合中,那么这个集合我们就
称之为数组。
2.4.4.3、数组的定义及使用
数组是一个有序的列表,可以在数组中存放任意的数据,并且数组的长度可以动态的调整。
使用关键字new创建或[]
创建数组的方式:
var 数组名=[数组值…值N];
var 数组名= new Array(值1…值N);
var 数组名= new Array();
可以通过数组的下标来访问数组的元素:
数组元素的顺序从0开始
数组名[0]=值;
数组名[1]=值; …
/**
JavaScript数组的创建方式:
1. 构造函数创建
var 数组名 = new Array(); -- 得到一个空数组
var 数组名 = new Array(数组); -- 创建指定长度的数组
var 数组名 = new Array(值1,值2,值3...) 创建数组并赋予值
2. 快捷创建
var 数组名 = [];
var 数组名 = [值1,值2,值3....];
JavaScript数组的属性:
length属性 用来获取数组的长度
JavaScript数组的特点:
JS数组可以存储任意数据类型
JS数组自动扩容,不是固定长度
注意事项:
当JS变量只有声明没有赋值的时候,去调用,那么undefined
当JS根本没有这个变量的时候,去调用,那么报错 arr is not defined
*/
var arr1 = new Array();
document.write("数组1的长度为:" + arr1.length + "<br>");
var arr2 = new Array(5);
document.write("数组2的长度为:" + arr2.length + "<br>");
//给数组存储数据: 通过下标来存储数据
//语法: 数组名[下标] = 值;
arr2[0] = 10;
arr2[1] = 20;
arr2[2] = 30;
arr2[3] = 40;
arr2[4] = 50;
arr2[10] = 100;
//调用数组里面的值
//语法: 数组名[下标]
document.write("下标1的值是:" + arr2[1] + "<br>");
document.write("下标20的值是:" + arr2[20] + "<br>");
document.write("数组2的长度为:" + arr2.length + "<br>");
var arr3 = new Array(5,"Hello",true,44.22);
document.write("数组3的长度为:" + arr3.length + "<br>");
var arr4 = []; //创建一个空数组 类似于 new Array();
var arr5 = [1,3,5,7]; //创建数组并赋值
var arr6 = [7];
document.write("数组6的长度为:" + arr6.length + "<br>");
// 补充 :数组 的长度 可以动态改变
var scores = []; // 空数组
console.log(scores.length);
// 清空数组
scores.length = 0;
console.log(scores);
六、JS运算符和表达式
6.1基本概念
JavaScript描述了一组用于操作数据值的运算符,包括一元运算符(++ --)、逻辑运算符、算术运算符、关
系运算符、三目运算符及赋值运算符。ECMAScript 中的运算符适用于很多值,包括字符串、数值、布尔
值、对象等。
-
**表达式:**表达式由一个或多个操作数通过操作符组合而成,就是由数据和运算符组成的一个式子。
例如:x+y;x/10; x+23/2+y; x%y等都是表达式。
-
操作数: 表达式中的变量成为操作数;
-
运算符: 表达式中起运算作用的符号称为运算符;
6.2算数运算符
算术运算符即算术运算符号。是完成基本的算术运算 (arithmetic operators) 符号,就是用来处理四则运
算的符号。
算数运算符分为以下:
运算符 | 运算规则 | 范例 | 结果 |
---|---|---|---|
+ | 连接字符串 | “中” + “国” | “中国” |
+ | 加法 | 1 + 1 | 2 |
- | 减法 | 5 - 3 | 2 |
* | 乘法 | 2 * 3 | 6 |
/ | 除法 | 6 / 3 | 2 |
% | 取余 | 8 % 3 | 2 |
** | 幂运算 | 5 ** 2 | 25 |
加法运算
var box = 1 + 2; //等于3
var box = 1 + NaN; //NaN,只要有一个NaN 就为NaN
var box = Infinity + Infinity; //Infinity
var box = -Infinity + -Infinity; //-Infinity
var box = Infinity + -Infinity; //NaN,正无穷和负无穷相加等NaN
var box = 100 + '100';//100100,字符串连接符,有字符串就不是加法
var box = '您的年龄是:' + 10 + 20; //您的年龄是:1020,被转换成字符串
var box = 10 + 20 + '是您的年龄'; //30 是您的年龄,没有被转成字符串
var box = '您的年龄是:' + (10 + 20); //您的年龄是:30,没有被转成字符串
其中NaN是not a number的缩写,表示不是一个数;infinity是无穷大的数。
任意数据类型的数值和字符串做 “+”运算,得到的肯定是字符串。
减法运算
var box = 100 - 70; //等于30
var box = -100 - 70 ;//等于-170
var box = -100 - -70; //-30,一般写成-100 - (-70)比较清晰
var box = 1 - NaN; //NaN,只要有一个NaN 就为NaN
var box = Infinity - Infinity; //NaN
var box = -Infinity - -Infinity;//NaN
var box = 100 - true; //99,true 转成数值为1
var box = 100 -false; //100,false转成数值为0
var box = 100 - ''; //100,''转成了0
var box = 100 - '70'; //30,'70'转成了数值70
var box = 100 - null; //100,null 转成了0
var box = 100 - 'Lee'; //NaN,Lee 转成了NaN
乘法运算
var box = 100 * 70; //7000
var box = 100 * NaN; //NaN,只要有一个NaN 即为NaN
var box = Infinity * Infinity; //Infinity
var box = -Infinity * Infinity ; //-Infinity
var box = -Infinity * -Infinity ; //Infinity
var box = 100 * true; //100,true 转成数值为1
var box = 100 * ''; //0,''转成了0
var box = 100 * null; //0,null 转成了0
var box = 100 * 'Lee'; //NaN,Lee 转成了NaN
除法运算
var box = 100 / 70; //1.42....
var box = 100 / NaN; //NaN
var box = Infinity / Infinity; //NaN
var box = -Infinity / Infinity ; //NaN
var box = -Infinity / -Infinity; //NaN
var box = 100 / true; //100,true 转成1
var box = 100 / ''; //Infinity,
var box = 100 / null; //Infinity,
var box = 100 / 'Lee'; //NaN
取余运算
var box = 10 % 3; //1,余数为1
var box = 100 % NaN; //NaN
var box = Infinity % Infinity; //NaN
var box = -Infinity % Infinity ; //NaN
var box = -Infinity % -Infinity; //NaN
var box = 100 % true; //0
var box = 100 % ''; //NaN
var box = 100 % null; //NaN
var box = 100 % 'Lee'; //NaN
JS算数运算符优先级
-
任意数据类型和字符串进行加法运算,都是字符串的拼接
-
任意数据类型和NaN进行四则运算,结果都是NaN
-
当true和false参与运算,true转换为1,false转换为0
-
除+运算外,数值类型字符串参与运算,都转换为数值;但是非数值类型字符参与运算,结果都是NaN
-
除+运算外,空字符串转换为0,null转换为0
-
0可以作为除数,得到结果都是无穷大
-
0参与取余运算,得到结果都是NaN
6.3一元运算符
递增和递减运算符概述
-
如果需要反复给数字变量添加或减去1,可以使用递增(++)和递减( – )运算符来完成。
-
在 JavaScript 中,递增(++)和递减( – )既可以放在变量前面,也可以放在变量后面。放在变量
前面时,我们可以称为前置递增(递减)运算符,放在变量后面时,我们可以称为后置递增(递
减)运算符。
-
递增和递减运算符必须和变量配合使用
递增运算符
- 前置递增运算符
- ++num 前置递增,就是自加1,类似于 num = num + 1,但是 ++num 写起来更简单。
- num++ 后置递增,就是自加1,类似于 num = num + 1,但是 num++ 写起来更简单。
- 使用口诀:++在前,整体是一个新值,++在后,整体是一人旧值
前置++
var num1 = 5;
++ num1; // num1 = 6;
var num2 = 6;
console.log(num1 + ++ num2); // 13
后置++
var num1 = 5;
num1 ++; // num1 = 6
var num2 = 6
console.log(num1 + num2 ++); // 12
前置和后置的区别
在没有赋值操作,前置和后置是一样的。但在赋值操作时,如果递增或递减运算符前置,那么前置的运算符会先累加或累减再赋值,如果是后置运算符则先赋值再累加或累减。运算的时候也是一样;
6.4赋值运算符
用来把数据赋值给变量的运算符。前面我们使用的 = 其实也是一个运算符,被称之为 赋值(assignments )运算符。
运算符 | 运算规则 | 范例 | 结果 |
---|---|---|---|
= | 赋值 | a = 5 | 5 |
+= | 加后赋值 | a = 5;a += 1 | 6 |
-= | 减后赋值 | a = 5; a-= 1 | 4 |
*= | 乘后赋值 | a = 5; a*= 1 | 5 |
/= | 除后赋值 | a = 5; a/= 1 | 5 |
%= | 取模后赋值 | a = 5 ;a%= 2 | 1 |
**= | 幂后赋值 | a = 5; a**= 2 | 25 |
在JavaScript中,赋值运算符是“=”,其含义就是把赋值运算符的右边的数值或表达式的值赋给赋值运算符的左边的变量或表达式。
var t=5; // 其意义就是把数值5赋给变量t;
var k=x+y+5; // 其意义就是把表达式x+y+5最后的值赋给变量k。
var box = 100;
box += 100; // 200,+=代替box+100
6.5关系运算符
比较运算符(关系运算符)是两个数据进行比较时所使用的运算符,比较运算后,会返回一个布尔值(true / false)作为比较运算的结果。
运算符 | 运算规则 | 范例 | 结果 |
---|---|---|---|
== | 比较值 | “1” == 1 | true |
=== | 比较数据类型和值 | “1” === 1 | false |
!= | 不等于 | 4 != 3 | true |
> | 大于 | 2 > 3 | false |
< | 小于 | 3 < 6 | true |
>= | 大于等于 | 3 >=4 | false |
<= | 小于等于 | 4 <= 6 | true |
比较原则
- 若一个是数值字符串,一个是数值,字符串会自动转换成数值进行比较。
- 若两个都是数值字符串,则比较首个数字的大小。
- 布尔值的false和true会转换成0和1。
- 两个操作数都是数值,则数值比较。
- 两个操作数都是字符串,则比较两个字符串对应的字符编码值。
-
字符转ascii码:用charCodeAt();
在相等和不等的比较上,如果操作数是非数值,则遵循以下规则:
-
一个操作数是布尔值,则比较之前将其转换为数值,false 转成0,true 转成1;
-
一个操作数是字符串,则比较之前将其转成为数值再比较;
-
不需要任何转换的情况下,null 和undefined 是相等的;
-
一个操作数是NaN,则==返回false,!=返回true;并且NaN 和自身不等;
-
在全等和全不等的判断上,比如值和类型都相等,才返回true,否则返回false。
特殊值对比表
表达式 值
null == undefined true
'NaN' == NaN false
5 == NaN false
NaN == NaN false
false == 0 true
true == 1 true
true == 2 false
undefined == 0 false
null == 0 false
'100' == 100 true
'100' === 100 false
相等运算符 == :判断两个操作数是否相等。不同的数据类型会自动转换为相等的数据类型再做比较。
等同运算符=== :全等(值和类型),严格意义的相等,两个操作数的值和他们的类型必须完全一致。
var result = '55' == 55; // true
var result = '55' === 55; // false 值相等,类型不相等
var result = 55 === 55; // true
6.6逻辑运算符
逻辑运算符通常用于布尔值的操作,一般和关系运算符配合使用,有三个逻辑运算符:逻辑与(AND)、逻辑或(OR)、逻辑非(NOT)。
运算符 | 运算规则 | 范例 | 结果 |
---|---|---|---|
&& | 与 同时为真 | false && true | false |
|| | 或 一个为真 | false || true | true |
! | 非 取反 | !false | true |
-
逻辑与运算符属于短路操作,顾名思义,如果第一个操作数返回是false,第二个数不管是true 还是
false 都返回的false。
-
和逻辑与运算符相似,逻辑或运算符也是短路操作。当第一操作数的求值结果为true,就不会对第
二个操作数求值了。
-
逻辑非运算符可以用于任何值。无论这个值是什么数据类型,这个运算符都会返回一个布尔值。它
的流程是:先将这个值转换成布尔值,然后取反。
注:JavaScript虽说也有& 和 |,但是这里不是做逻辑运算符,而是位运算符
区别主要是:以&和&&为例 当第一个条件为假时 &会判断第二个 而&&不会继续判断 提升运算效率
6.7三元运算符
三目运算符,又叫三元条件运算符
三元条件运算符其实就是后面将要学到的if 语句的简写形式。
根据条件在两个语句中执行其中的一个,使用符号 ?:
语法如下:条件表达式?语句1:语句2
参数说明:
- 条件表达式,结果会被作为布尔值处理
- 语句1:如果条件表达式返回true则执行
- 语句2:如果条件表达式返回false则执行
var box = 5 > 4 ? '对' : '错'; //对,5>4 返回true 则把'对'赋值给box,反之,把错赋给box。
// 判断一个年龄是否成年, 当年龄超过18 返回 成年 否则返回未成年
var age = 19;
// console.log( age >= 18 ? '成年' : '未成年' );
var msg = age >= 18 ? '成年' : '未成年';
console.log(msg);
6.8运算符的优先级
运算符优先级描述了在计算表达式时执行运算 的顺序。先执行具有较高优先级的运算,然后执行较低优先级的运算。例如,先执行相乘,再执行相加。运算符比较多,可以合理使用()来改变表达式的优先级。()的用法和数学中的()用法相同,()内的会优先计算。
运算符 | 描述 |
---|---|
. 【】 () | 字段访问,数组下标,函数调用以及表达式分组 |
++ – ~ ! delete new typeof void | 一元运算符,返回数据类型,对象创建,未定义值 |
* / % | 乘法,除法,取模 |
+ - + | 加法,减法,字符串连接 |
<< >> >>> | 移位 |
< <= > >= instanceof | 小于,小于等于,大于,大于等于,instanceof |
== != === !=== | 等于,不等于,严格等于,非严格等于 |
& | 按位与 |
^ | 按位异或 |
| | 按位或 |
&& | 逻辑与 |
|| | 逻辑或 |
?: | 条件 |
== oP= | 赋值,运算赋值 |
, | 多重求值 |
七、流程控制语句
7.1语句的定义
在ECMAScript 中,所有的代码都是由语句来构成的。
一行代码就是一条简单语句。形式上可以是单行语句,或者由一对大括号“{}”括起来的复合语句,复合
语句包含若干条简单语句,它可以作为一个单行语句处理。复合语句也称为语句块。
单行语句:一行代码简单语句
复合语句:由一对大括号“{}”括起来的若干条简单语句,也叫语句块
7.2流程控制语句分类
任何复杂的程序逻辑都可以通过”顺序”、”条件(分支)”和”循环”三种基本的程序结构来实现。
- 顺序程序结构就是从上往下顺序执行语句;程序默认就是由上到下顺序执行的
- 条件(分支)程序结构就是根据不同的情况执行不同的语句;
- 循环程序结构就是某些语句要循环执行多次。
条件语句(分支语句)
if单分支语句
if-else双分支语句
if - else if多分支语句
switch开关语句
循环语句
for循环语句
while循环语句
do-while循环语句
for/in循环语句 (增强for循环、foreach循环)
7.3条件语句
if语句即条件判断语句,一共有三种格式:
- 单分支的条件语句;
- 双分支的条件语句;
- 多分支的条件语句。
条件语句用于基于不同的条件来执行不同的动作。
单分支的条件语句
if(){} 语句 - 只有当指定条件为 true 时,使用该语句来执行代码:
if (/* 条件表达式 */) {
// 执行语句
}
注意:
- 放在if之后的括号里的返回值为boolean类型的表达式或boolean值,即这个表达式的返回值只能是true或false。
- 如果表达式的值为true,则执行语句;如果表达式的值为false,则什么也不执行。
- 花括号括起来的语句块可以只有一行语句,也可以由多行代码构成。一个语句块通常被当成一个整体来执行。 如果语句块只有一行语句时,则可以省略花括号,因为单行语句本身就是一个整体,无须花括号来把它们定义成一个整体。建议都加花括号;
双分支的条件语句
if()…else 语句 - 当条件为 true 时执行语句1,当条件为 false 时执行语句2
if (/* 条件表达式 */){
// 成立执行语句
} else {
// 否则执行语句
}
if (条件表达式){
语句1;
}else {
语句2;
}
注意:
- 放在if之后的括号里的返回值为boolean类型的表达式或boolean值,即这个表达式的返回值只能是true或false。
- 如果if表达式的值为true,则执行语句1;如果表达式的值为false,则执行语句2。
多分支的条件语句
if()…else if()…else 语句 - 使用该语句来选择多个代码块之一来执行
if (/* 条件1 */){
// 成立执行语句
} else if (/* 条件2 */){
// 成立执行语句
} else if (/* 条件3 */){
// 成立执行语句
} else {
// 最后默认执行语句
}
语法:
if (条件表达式) {
语句1;
} else if (条件表达式) {
语句2;
} ...
else{
语句n;
}
注:
if语句()中的表达式会自动转换成布尔值。满足条件即执行对应语句,然后语句就结束;如果都不满足,则执行else语句块;当然else语句块可以不存在
switch多条件选择语句
switch语句又称开关语句,它与多重if语句类似,前者用于等值判断,后者用于区间值和等值判断。
switch语句的作用是根据表达式的值,跳转到不同的语句。switch 语句用于基于不同的条件来执行不同的动作。
语法:
switch (expression) {
case 常量1:
语句;
break;
case 常量2:
语句;
break;
case 常量3:
语句;
break;
…
case 常量n:
语句;
break;
default:
语句;
break;
}
switch多条件选择语句:
首先设置表达式,随后表达式的值会与结构中的每个case 的常量表达式做比较。如果存在匹配,则与该
case 关联的代码块会被执行。
使用 break 来阻止代码自动地向下一个 case 运行。default 关键词来规定匹配不存在时做的事情,也就
是说,当没有匹配的值时,执行default下的语句。
switch 语句在比较值时使用的是全等操作符, 因此不会发生类型转换(例如,字符串’10’ 不等于数值
10)
工作原理:
- 首先设置表达式 n(通常是一个变量)。
- 随后表达式的值会与结构中的每个 case 的值做比较。
- 如果存在匹配,则与该 case 关联的代码块会被执行。
- 请使用 break 来阻止代码自动地向下一个 case 运行。
- default 关键词来规定匹配不存在时做的事情;相当于if里的else
**注意: **
1、每个case语句下的break语句一般不可以省略,break语句表示退出switch语句,如果省略,则会继续执行下一个case语句中的代码,直到遇到break语句跳出switch语句。
2、default语句可以出现在switch语句中任何地方,如果放在最后,其中的break语句可省略。default语句也可省略。
**3、每个case语句没有先后顺序之分,但建议按照常量表达式的值从小到大的顺序。 **
4、switch语句用于等值判断,也就是说表达式的结果是个具体的值;而多重if选择结果的表达式的值
是个区间,比如大于100而小于200。
输入一个数字,打印对应的星期
var day = 10;
switch (day) {
case 1:
console.log('星期一');
break;
case 2:
console.log('星期二');
break;
case 3:
console.log('星期三');
break;
case 4:
console.log('星期四');
break;
case 5:
console.log('星期五');
break;
case 6:
console.log('星期六');
break;
case 7:
console.log('星期日');
break;
default:
console.log('输入的值不在星期范围内');
break;
}
7.4循环语句
如果希望一遍又一遍地运行相同的代码,那么使用循环是很方便的。比如在页面上输出100遍“我爱HTML5编程”,如果不用循环,document.write(“我爱HTML5编程”);要写100遍。如果用循环则代码这样写即可:
for(var i=1;i<=100;i++){
document.write("我爱HTML5编程<br/>");
}
循环程序的结构有三要素:循环的初始值、循环条件(循环的结束值)和循环的迭代,所谓循环的迭代就是如何从初始值到结束值,比如是每次加1还是每次加2,诸如此类等。当然,一个循环程序还有包含一个循环体。
while循环语句
while循环会在指定条件为真时循环执行代码块,它是一种先判断,后运行的循环语句,也就是说,必须满足条件了之后,方可运行循环体。用于不太确定循环次数的场合。
语法:
// 当循环条件为true时,执行循环体,
// 当循环条件为false时,结束循环。
while (循环条件) {
//循环体
}
打印100以内 7的倍数
// 打印100以内 7的倍数
var i = 1;
while (i <= 100) {
// 判断当前的i是否是7的倍数
if (i % 7 === 0) {
console.log(i);
}
// i自身+1
i++;
}
do…while循环
do…while 循环是 while 循环的变体,在检查条件是否为真之前,该循环会至少执行一次do下的代码块(循环体),然后如果条件为真的话,就会重复这个循环,否则退出该循环体。常用于至少执行一次循环体,再判断要不要继续循环的场合。
语法:
do {
// 循环体;
} while (循环条件);
代码示例:
// 初始化变量
var i = 1;
var sum = 0;
do {
sum += i;//循环体
i++;//自增
} while (i <= 100);//循环条件
求100以内所有3的倍数的和
// 求100以内所有3的倍数的和
var i = 1;
var sum = 0;
do {
// 循环体
// 判断是否是3的倍数,如果是3的倍数累加
if (i % 3 === 0) {
sum += i;
}
// i自身+1
i++;
} while (i <= 100);
console.log(sum);
for语句
for 语句是应用最广泛、功能最强的一种循环语句。大部分情况下,for 循环可以代替 while 循环、dowhile 循环。
for 语句是一种在程序执行前就要先判断条件表达式是否为真的循环语句。假如条件表达式的结果为假,那么它的循环语句根本不会执行。for 语句通常使用在知道循环次数的循环中。
while和do…while一般用来解决无法确认次数的循环。for循环一般在循环次数确定的时候比较方便。
for 语句语法格式:
for(条件表达式1; 条件表达式2; 条件表达式3) {
语句块;
}
for 循环中 3 个条件表达式的含义如下:
表达式 | 形式 | 功能 | 举例 |
---|---|---|---|
条件表达式1 | 赋值语句 | 循环结构的初始部分,为循环变量赋初值 | var i = 1 |
条件表达式2 | 条件语句 | 循环结构的循环条件 | i > 40 |
条件表达式3 | 迭代语句,通常使用++或–运算符 | 循环结构的迭代部分,通常用来修改循环变量的值 | i++ |
for 关键字后面括号中的 3 个条件表达式必须用“;”隔开。for 循环中的这 3 部分以及大括号中使循环体必需的 4 个组成部分完美地结合在一起,简单明了。
for 循环语句执行的过程为:
- 首先执行条件表达式 1 进行初始化
- 然后判断条件表达式 2 的值是否为true,如果为 true,则执行循环体语句块;否则直接退出循环。
- 最后执行表达式 3,改变循环变量的值,至此完成一次循环。接下来进行下一次循环,直到条件表达式 2 的值为 false,才结束循环
for in语句
for…in 语句用于遍历数组或者对象的属性(通常我们使用for/in 语句循环遍历对象的属性,在数组中可以遍历数组中的所有元素)。
for…in 循环中的代码每执行一次,就会对数组的元素或者对象的属性进行一次操作。
for…in遍历数组
// 定义一个数组
var arr = [13,21,34,42,53,63];
// 普通for循环遍历
for(var i = 0;i < arr.length;i++){
console.log(arr[i]);
}
// 使用for..in遍历数组
for(var i in arr){
console.log(arr[i]);
}
for…in遍历对象
// 创建一个对象
var person = {
name : "jack",
age : 12,
height: 178
}
//列举对象属性名及其值
for(var pro in person){
console.log(pro+" "+person[pro])
}
在JavaScript语言中,支持循环语句的相互嵌套,即在一个循环语句中嵌套另一个循环语句,也就是说,for循环语句可以嵌套for语句,也可以嵌套while循环语句,或者do…while循环语句,其他的循环语句也是一样的。
需要注意的是,break和continue语句用在循环嵌套中,这两条语句只对离它最近的循环语句有效。比如:如果break语句用在内层的循环语句中,则只退出内层的循环,对外层循环没有影响。
打印正方形
// 使用拼字符串的方法的原因
// console.log 输出重复内容的问题
// console.log 默认输出内容介绍后有换行
var start = '';
for (var i = 0; i < 10; i++) {
for (var j = 0; j < 10; j++) {
start += '* ';
}
start += '\n';
}
console.log(start);
打印直角三角形
var start = '';
for (var i = 0; i < 10; i++) {
for (var j = i; j < 10; j++) {
start += '* ';
}
start += '\n';
}
console.log(start);
打印9*9乘法表
var str = '';
for (var i = 1; i <= 9; i++) {
for (var j = i; j <=9; j++) {
str += i + ' * ' + j + ' = ' + i * j + '\t';
}
str += '\n';
}
console.log(str);
7.5跳转语句
break:立即跳出整个循环,即循环结束,开始执行循环后面的内容(直接跳到大括号)
continue:立即跳出当前循环,继续下一次循环(跳到i++的地方)
continue 语句只能用在循环中;break能用在循环或 switch 中。
求整数1~100的累加值,但要求碰到个位为3的数则停止累加
var sum = 0;
for (var i = 1; i <= 100; i++) {
if (i % 10 === 3) {
// 如果找到个位为3的数字 ,继续执行下一次循环
continue;
}
sum += i;
}
console.log(sum);
7.6调试
过去调试JavaScript的方式
- alert()
- console.log()
断点调试
断点调试是指自己在程序的某一行设置一个断点,调试时,程序运行到这一行就会停住,然后你可以一步一步往下调试,调试过程中可以看各个变量当前的值,出错的话,调试到出错的代码行即显示错误,停下。
调试步骤
浏览器中按F12–>sources–>找到需要调试的文件–>在程序的某一行设置断点
三
八、JS函数
为什么要有函数 ?
如果要在多个地方求1-100之间所有数的和,应该怎么做?
8.1函数的概念
函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块。通俗来讲:把一段相对独立的具有特定功能的代码块封装起来,形成一个独立实体,就是函数,起个名字(函数名)。函数的作用就是封装一段代码,将来可以重复使用。
函数的语法
函数声明
function 函数名(参数列表){
// 函数体
}
函数表达式
var fn = function () {
// 函数体
}
特点:
函数声明的时候,函数体并不会执行,只要当函数被调用的时候才会执行。
函数一般都用来干一件事情,函数名称一般使用动词
8.2 JS声明式函数的应用
函数的应用分为两步,一是先声明一个函数,再调用该函数。
声明函数:
- 声明无参函数语法
- 声明有参函数的语法
- 声明带有返回值的函数
函数的调用
调用函数的语法:
函数名();
特点:
- 函数体只有在调用的时候才会执行,调用需要()进行调用。
- 可以调用多次(重复使用)
在JavaScript中,调用函数时,如果没有返回值,就直接用函数方法名()调用。如果有参数,则必须给每个参数赋值,函数方法名(参数值),如果还有返回值,可以用一个变量来存储这个值。
// 声明无参函数:无参函数就是在函数名的小括号中不定义任何参数。
function sayHello() {
console.log("吃了没?");
}
// 调用无参函数
sayHello();
求1-100之间所有数的和
function getSum() {
var sum = 0;
for (var i = 0; i < 100; i++) {
sum += i;
}
console.log(sum);
}
// 调用
getSum();
函数的参数
为什么要有参数
function getSum() {
var sum = 0;
for (var i = 1; i <= 100; i++) {
sum += i;
}
console.log();
}
虽然上面代码可以重复调用,但是只能计算1-100之间的值。
如果想要计算n-m之间所有数的和,应该怎么办呢?
语法
函数内部是一个封闭的环境,可以通过参数的方式,把外部的值传递给函数内部。
带参数的函数声明语法:
function 函数名(var1, var2...) {
// 函数体
}
上面的var1,var2就是参数,它代表一个不确定的值,这个值要参与函数代码块的运算,在调用函数时,可以给这些参数赋值。也可以在函数中定义多个参数,每个参数之间逗号 (,) 分隔。当声明函数时,参数相当于作为变量来声明。
变量和参数必须以一致的顺序出现。第一个变量就是第一个被传递的参数的给定的值,以此类推。
带参数的函数调用:
函数名(实参1, 实参2, 实参3);
形参1 = 实参1
形参2 = 实参2
形参和实参
- 形式参数:在声明一个函数的时候,为了函数的功能更加灵活,有些值是固定不了的,对于这些固定不了的值。我们可以给函数设置参数。这个参数没有具体的值,仅仅起到一个占位置的作用,我们通常称之为形式参数,也叫形参。
- 实际参数:如果函数在声明时,设置了形参,那么在函数调用的时候就需要传入对应的参数,我们把传入的参数叫做实际参数,也叫实参。
需要注意的是,同一个函数,形参和实参是一一对应的。
如何区分实参和形参?
- 出现的地方不一样,一个是在函数的声明中,一个出现在函数的调用中。
- 代表的意义不一样,一个是声明一个变量,一个是该变量的值。
// 定义变量x和y
var x = 5, y = 6;
// 调用fn函数,把x和y传递到函数里面
fn(x,y);
function fn(a, b) {
console.log(a + b);
}
// x,y实参,有具体的值。函数执行的时候会把x,y复制一份给函数内部的a和b,函数内部的值是复制的新值,无法修改外部的x,y
判断一个数是否是素数(又叫质数,只能被1和自身整数的数)
function jdugePrimeNumber(number) {
// 假设number是质数
var isPrime = true;
for (var i = 2; i < number; i++) {
// 判断是否有能被number整数的数
if (number % i === 0) {
// 如果此处执行了。说明不是质数
isPrime = false;
break;
}
}
if (isPrime) {
console.log('质数');
} else {
console.log('不是质数');
}
}
jdugePrimeNumber(13);
函数的返回值
当函数执行完的时候,并不是所有时候都要把结果打印。我们期望函数给我一些反馈(比如计算的结果返回进行后续的运算),这个时候可以让函数返回一些东西,也就是返回值。函数通过return返回一个返回值。
语法如下:
//声明一个带返回值的函数
function 函数名(形参1, 形参2, 形参3...) {
//函数体
return 返回值;
}
//可以通过变量来接收这个返回值
var 变量 = 函数名(实参1, 实参2, 实参3...);
示范:利用函数计算两个数相乘后的值,并返回。
//1、声明一个带参数的方法
function myFunction(a,b) {
return a*b;
}
//2、调用带参的方法
var mul=myFunction(5,6);
// - 求1!+2!+3!+....+n! n!
function getJieCheng(n) {
var result = 1;
for (var i = 1; i <= n; i++) {
// result *= i;
result = result * i;
}
return result;
}
function getSum(n) {
// 求1-n之间每一个数的阶乘的累加
var sum = 0;
for (var i = 1; i <= n; i++) {
// 累加的是每一个数的阶乘
sum += getJieCheng(i);
}
return sum;
}
返回值详解:
- 如果函数没有显式的使用 return语句 ,那么函数有默认的返回值:undefined。
- 如果函数使用 return语句,那么跟在return后面的值,就成了函数的返回值。
- 如果函数使用 return语句,但是return后面没有任何值,那么函数的返回值也是:undefined。
- 函数使用return语句后,这个函数会在执行完 return 语句之后停止并立即退出,也就是说return后
- 面的所有其他代码都不会再执行。
- 推荐的做法是要么让函数始终都返回一个值,要么永远都不要返回值。
函数是一种数据类型
function fn() {}
console.log(typeof fn);
函数作为参数:因为函数也是一种类型,可以把函数作为另一个函数的参数,在另一个函数中调用
函数做为返回值:因为函数是一种类型,所以可以把函数可以作为返回值从函数内部返回。
function fn(b) {
var a = 10;
return function () {
alert(a+b);
}
}
fn(15)();
arguments对象(动态参数,伪数组,包含了所有实参)
JavaScript中,arguments对象是比较特别的一个对象,实际上是当前函数的一个内置属性。也就是说所有函数都内置了一个arguments对象,arguments对象中存储了传递的所有的实参。arguments是一个伪数组,因此就可以进行遍历。
示例代码:
// 求任意个数的最大值
function getMax() {
var max = arguments[0];
for (var i = 1; i < arguments.length; i++) {
if (max < arguments[i]) {
max = arguments[i];
}
}
return max;
}
var max = getMax(5, 10, 1, 5, 100);
console.log(max);
…数组名 (剩余参数,包含了所有没有形参接受的实参,真数组,可使用数组的方法)
// 求任意个数的最大值
function getMax(...arr) {
var max = arr[0];
for (var i = 1; i < arr.length; i++) {
if (max < arr[i]) {
max = arr[i];
}
}
return max;
}
var max = getMax(5, 10, 1, 5, 100);
console.log(max);
动态参数和剩余参数的区别
- 都是当实参数量不确定时使用,ES6的箭头函数中没有arguments对象,只能用剩余参数…数组名
- 动态参数是伪数组,而剩余参数是真数组
8.3JavaScript函数作用域
变量从作用域的角度划分,分为两种:
- 局部变量
- 全局变量
什么是作用域?
变量可以起作用的范围
局部变量
在JavaScript函数内部声明的变量是局部变量,所以只能在函数内部访问它,该变量的作用域是局部的。可以在不同的函数中使用名称相同的局部变量,因为只有声明过该变量的函数才能识别出该变量。只要函数运行完毕,局部变量就会被删除。
function sayHello(){
//该变量声明在一个函数内部,name就是一个局部变量,
//局部变量只可以在本函数内调用
var name="H5";
alert("Hello "+name);
}
全局变量
在函数外声明的变量是全局变量,网页上的所有脚本和函数都能访问它
//声明一个全局变量,任何函数都可以使用它
var name="H5";
function sayHello(){
alert("Hello "+name);
}
//调用函数
sayHello();
需要注意的是,如果没有使用var声明变量,该变量将被自动作为全局变量声明,不推荐使用。
比如这条语句:carname=“Volvo”;将声明一个全局变量 carname,即使它在函数内部声明。
变量的生命周期
JavaScript 变量的生命期从它们被声明的时间开始。
局部变量会在退出作用域之后会销毁。
全局变量会在关闭网页或浏览器才会销毁。
局部变量和全局变量的区别
-
声明位置不同:局部变量声明在函数内部。全局变量声明在函数外部。
-
作用域不一样:局部变量只在某一个局部范围有效,比如函数内部。全局变量在整个页面有效,网页上的所有脚本和函数都能访问它。
-
生命周期不一样:局部变量会在函数运行以后被删除,全局变量会在页面关闭后被删除。
块级作用域
任何一对花括号({和})中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见
的,我们称之为块级作用域。
在es5之前没有块级作用域的的概念,只有函数作用域,现阶段可以认为JavaScript没有块级作用域。
作用域链
只有函数可以制造作用域结构, 那么只要是代码,就至少有一个作用域, 即全局作用域。凡是代码中有函数,那么这个函数就构成另一个作用域。如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域。
将这样的所有的作用域列出来,可以有一个结构: 函数内指向函数外的链式结构。就称作作用域链。
就近原则,自己作用域找不到就往父级找,找不到继续往上找
8.4匿名函数
匿名函数,就是没有名字的函数。
一般的有名函数:
function myFun( a,b ){
console.info( a+b );
}
myFun( 10 , 30 ); // 输出40
匿名函数: 有关键词 function, 有小括号,有大括号,就是没有函数名。
function(a,b){
console.info( a+b );
}
想要执行它,怎么执行?没有名字,怎么调用?
方式一:把它放进一个变量里,这个变量就相当于一个函数名了。没有名字的匿名函数,变成有“名”函数了,我们把这种方式称之为函数字面量(函数表达式)。
var myFun = function( a,b ){
console.info( a+b);
};
myFun( 10,30 );
**方式二:**干脆不要名字,直接执行~!-- 这么做可以在内部形成局部变量和局部函数,防止全局污染。个人常用的直接执行匿名函数的方式!
(匿名函数)();
(匿名函数());
//注意: 使用改写法一定要注意添加分号
(function(a,b){
console.info( a+b );
})(10,30);
(function(a,b){
console.info( a+b );
}(10,30));
**方式三:**利用事件去调用。
var btn = document.getElementById("btn"); // 找到页面某个标签
// 添加事件
btn.onclick = function(){
console.info("你点了我!");
}
**方法四:**作为对象的方法调用
var myObj = {
name : "John",
sayHello:function(){
console.info("Hello,"+ this.name );
}
};
myObj.sayHello();
**方法五:**作为另一个函数的参数。
**函数也可以作为另一个函数的参数的。**当然有名函数也可以做参数。
function myFun(fn){
fn();
}
myFun(function(){
console.info("这个匿名函数是个参数");
});
8.5构造函数(快速创建多个相同属性对象的函数)
通过 new 函数名() 来实例化对象的函数叫构造函数。任何的函数都可以作为构造函数存在。之所以有构造函数与普通函数之分,主要从功能上进行区别的,构造函数的主要 功能为 初始化对象,特点是和new一起使用。new就是在创建对象,从无到有,构造函数就是在为初始化的对象添加属性和方法。构造函数定义时首字母大写(规范)。
对new理解:new 申请内存, 创建对象,当调用new时,后台会隐式执行new Object()创建对象。所以,通过new创建的字符串、数字是引用类型,而是非值类型。
1、常用的构造函数:
1. var arr = []; 为 var arr = new Array(); 的语法糖。
2. var obj = {} 为 var obj = new Object(); 的语法糖
3. var date = new Date();
4. ...
2、自定义构造函数:
- 构造函数名首字母要大写
- 构造函数的作用就是用来创建对象的,
- 功能上: 普通函数是用来执行某个行为;构造函数是用来创建对象的
- 语法上: 基本没有差别
- 从函数体: 普通函数的函数体里面就是要执行的逻辑代码; 构造函数的函数体里面是用来初始化对象成员以及对象方法的;
function Person(id,name,age) {
//this关键字: 表示的当前对象
this.id = id; //对象的属性
this.name = name;
this.age = age;
this.eat = function () { //对象方法
alert(this.name+"的吃饭行为");
}
}
//直接通过函数名() 调用的是普通函数
//使用构造函数,必须结合new来使用
//Person()就算是构造函数,它也属于函数的一种
var p1 = new Person(1001,"张三",12); //创建一个Person对象
var p2 = new Person(1002,"李四",12);
document.write("p1的name是:"+p1.name+"<br>");
p1.eat();
8.5回调函数
字面上的理解,回调函数就是一个参数,将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数。这个过程就叫做回调。
其实也很好理解对吧,回调,回调,就是回头调用的意思。主函数的事先干完,回头再调用传进来的那个函数。
function modifyArray(arr, callback) {
// 对 arr 做一些操作
arr.push(100);
// 执行传进来的 callback 函数
callback();
}
var arr = [1, 2, 3, 4, 5];
modifyArray(arr, function() {
console.log("array has been modified", arr);
});
上面的代码中,我们先定义了主函数和回调函数,然后再去调用主函数,将回调函数传进去。定义主函数的时候,我们让代码先去执行callback()回调函数,但输出结果却是后输出回调函数的内容。
这就说明了主函数不用等待回调函数执行完,可以接着执行自己的代码。所以一般回调函数都用在耗时操作上面。比如ajax请求,比如处理文件等。
8.6预解析
代码段是指一个script标签就是一个代码段。JS代码在执行时,是一个代码段一个代码段执行
<!-- 代码段是彼此独立的,上面的代码段报错了,不会影响下面的代码段 -->
<!-- 1个script标签就是一个代码段 -->
<script>
// 在一个代码段中就可以写JS代码
var a = 110;
// 上面代码段不能使用下面的代码段中定义的数据
console.log(b); // ReferenceError: b is not defined
</script>
<!-- 一个网页中可以有多个代码段 -->
<script>
var b = 220;
// 可以在下面的代码段中使用上面的代码段中的数据
console.log(a);
</script>
JavaScript代码的执行是由浏览器中的JavaScript解析器来执行的。JavaScript解析器执行JavaScript代码的时候,分为两个过程:预解析过程和代码执行过程。
什么是预解析?
- 浏览器在执行JS代码的时候会分成两部分操作:预解析以及逐行执行代码
- 也就是说浏览器不会直接执行代码, 而是加工处理之后再执行,
- 这个加工处理的过程, 我们就称之为预解析
预解析过程:
- 把变量的声明提升到当前作用域的最前面,只会提升声明,不会提升赋值。
- 把函数的声明提升到当前作用域的最前面,只会提升声明,不会提升调用。
- 先提升var,再提升function。
变量提升
ES5 提升有变量提升和函数提升。
原则:
1、所有声明都会被提升到作用域的最顶上;
2、同一个变量声明只进行一次,并且因此其他声明都会被忽略;
3、函数声明的优先级优于变量声明,且函数声明会连带定义一起被提升。
变量提升:
把变量声明提升到函数的顶部,但是变量赋值不会提升。
console.log(a);
var a = 10;
//输出为undefined
//与上例等价
var a;
console.log(a);
a = 10;
注意:变量未声明,直接使用,输出‘变量 is not defined。
函数提升:
函数提升会将函数声明连带定义一起提升。在JavaScript中函数的创建方式有三种:函数声明、函数表达式(函数字面量)、函数构造法(动态的,匿名的)。只有函数声明创建的函数会执行函数提升,字面量定义的函数(实质为变量+匿名函数)会执行变量提升。
test1();
function test1(){
console.log("可以被提升");
}
test2();
var test2 = function(){
console.log("不可以被提升");
}
console.log(test2);
var test2 = function(){
console.log("不可以被提升");
}
函数和变量同时提升:
console.log(test3);
function test3(){console.log('func');}
var test3 = 'Mary';
防止全局污染
全局污染问题
JavaScript 可以随意定义保存所有应用资源的全局变量。
但全局变量可以削弱程序灵活性,增大了模块之间的耦合性。在多人协作时,如果定义过多的全局变量有可能造成全局变量冲突,也就是全局变量污染问题。
解决全局污染
// 方式1: 定义全局变量命名空间,只创建一个全局变量,并定义该变量为当前应用容器,把其他全局变量追
加在该命名空间下。
//my就是一个全局变量,我们可以把my这个全局变量当成一个命名空间,然后把其他的所有全局变量都放在它下
面;
var my={}; //唯一的全局变量
my.name={
big_name:"zhangsan",
small_name:"lisi"
};
my.work={
school_work:"study",
family_work:"we are"
};
// alert(my.name.small_name);
// 方式2: 利用匿名函数将脚本包裹起来
(function(){
var temp = {};
//把两个变量赋值给temp
//temp.school_work = "study";
//temp.small_name = "李四";
small_name = "李四";
temp.getName = function(){
return small_name;
}
//把tmep赋值给全局变量test
window.test = temp;
}())
// alert(test.getName());
加var的变量和不加var的变量
加var的变量和不加var的变量有什么区别
- 加var的变量在预编译期间会提升,不加var的变量在预编译期间不会提升
<script>
// 加var的变量在预编译期间会提升,不加var的变量在预编译期间不会提升。
// console.log(a); // undefined
// var a = 110;
console.log(b); // ReferenceError: b is not defined
b = 120;
</script>
- 不管有没有加var,创建的全局变量,都会放到GO中的,也就是可以通过window.xx。
<script>
// 不管有没有加var,创建的全局变量,都会放到GO中的,也就是可以通过window.xx。
var a = 110;
b = 120;
console.log(window.a); // 110
console.log(window.b); // 120
</script>
- 加var的变量,可能是全局变量,也可能是局部变量,不加var的变量,只能是全局变量。
- 加var的局部变量,不会作用window的属性
<script>
function fn(){
var a = 110;
}
fn();
console.log(window.a);
</script>
不加var创建的变量
- 不建议使用。 项目中尽量不要使用全局变量。在项目中,不要使用没有加var的变量。
8.7IIFE
Immediately Invoked Function Expression(立即调用函数表达式)
<script>
function fn(){
console.log("fn...");
}
// 之前:先定义函数 再去调用函数
fn();
// 思考:在定义函数时,能不能直接去调用
// 答:IIFE
</script>
<script>
function fn(){
console.log("fn...");
}()
</script>
- 正确的IIFE,如下:
<script>
// IIFE写法一
(function fn() {
console.log("fn...");
})()
</script>
<script>
// IIFE写法二
(function fn() {
console.log("fn...");
}())
</script>
<script>
// IIFE写法三
+function fn() {
console.log("fn...");
}()
</script>
<script>
// IIFE写法四
-function fn() {
console.log("fn...");
}()
</script>
<script>
// IIFE写法五
!function fn() {
console.log("fn...");
}()
</script>
- 注意问题:
<script>
let obj = {
name:"wc",
age:100
}
(function(){
console.log("mn...");
})();
let obj = {
name:"wc",
age:100
};
(function(){
console.log("mn...");
})();
</script>
- 为了防止,你前面的代码没有加分号,通常写一个IIFE,都会在前面加上分号,如下:
<script>
let obj = {
name:"wc",
age:100
}
// 在写IIFE时,直接以分号开头
;(function(){
console.log("mn...");
})();
</script>
九、JavaScript对象
9.1类和对象的概念
为什么要有对象
function printPerson(name, age, sex....) {
}
// 函数的参数如果特别多的话,可以使用对象简化
function printPerson(person) {
console.log(person.name);
……
}
什么是对象
所谓对象就是真实世界中的实体,对象与实体是一一对应的,也就是说现实世界中每一个实体都是一个对象为。
比如一只狗,那么它的属性有名称、品种、颜色、体重;行为有吠叫、摇摆、跑等。,它是一种具体的存在,可以发现身边很多对象,汽车,狗,人等,这些对象都有一个属性和行
JavaScript中的对象
**JavaScript语言没有“类”,而改用构造函数(constructor)作为对象的模板。**前面说过,“对象”是单个实物的抽象。所以,通常需要一个模板,表示某一类实物的共同特征,然后“对象”根据这个模板生成。所谓构造函数”,就是专门用来生成“对象”的函数。它提供模板,作为对象的基本结构。比如var date1=new Date()是通过调用Date的构造函数Date()(这里可以理解为一个类)来创建一个日期对象。一个构造函数,可以生成多个对象,这些对象都有相同的属性和行为,但是属性值可以不同。在 JavaScript 中,不会创建类,也不会通过类来创建对象(就像在其他面向对象的语言中那样),JavaScript 基于 prototype(原型),而不是基于类的。
在Javascript没有类和接口,只有对象,而根据ECMAscript的定义,对象是“无序属性的集合,其属性包含基本值,对象或者函数”。
需要注意的是,在ECMAscrip6.0中,已经使用class来定义类了。
对象object是JavaScript的核心概念,也是最重要的数据类型。JavaScript的所有数据都可以被视为对象。对象是一个容器,封装了属性(propert)和方法(method)。所谓属性,就是对象的静态状态;所谓方法,就是对象的动态行为。
JavaScript的对象是无序属性的集合。
其属性可以包含基本值、对象或函数。对象就是一组没有顺序的值。我们可以把JavaScript中的对象想象成键值对,其中值可以是数据和函数。
对象的行为和特征
特征—属性:事物的特征在对象中用属性来表示。
行为—方法:事物的行为在对象中用方法来表示。
在JavaScript中,其中一种定义对象的方法如下:
var o = {
p: "Hello World",
sayHello:function(){
return p;
}
};
上面代码中,定义了一个对象o,这个对象内部包含2个键值对:p和sayHello,其中p键值对是描述静态属性的;sayHello键值对是描述对象的动态行为的。属性名与属性值之间用冒号分隔。
p是对象的属性名,字符串“Hello World”是对象的属性值。sayHello是对象的另一个属性名,属性值是function(){return p; }。
如果对象内部包含多个属性对,每个属性对之间用逗号分隔。 需要注意的是,上面的代码后台隐式调用了new Object()这个构造函数创建了一个对象o,再通过键值对定义静态属性动态行为。
对象又分内置对象和自定义对象,其中内置对象是指JavaScript中已经定义好的,比如我们之后学的Date、Array、Math、String等,这些内置对象提供了许多方法和属性,只管调用和使用即可,比如Math对象中的PI和E是属性,pow(x,y)、sin(x)、sqrt(x)等方法。
9.2 对象的使用
对象的创建方式
- 对象字面量
var hero = {
name: '黄忠',
weapon: '弓箭',
equipment: ['头盔', '靴子', '盔甲'],
blood: 100,
attack: function () {
console.log(this.name + ':射箭');
},
run: function () {
console.log(this.name + ': 加速跑');
}
}
console.log(hero.name);
console.log(hero.equipment);
hero.attack();
hero.run();
- new Object()创建对象
// Object 是一个构造函数
// new 的方式来调用构造函数
// new Object() 调用构造函数 会在内存中创建一个对象
var hero = new Object(); // 创建了一个空的对象
// 打印一个不存在的属性 输出 undefined
// console.log(hero.name);
// 属性
// JavaScript的动态特性
hero.name = '关羽';
hero.weapon = '青龙偃月刀';
hero.equipment = ['头盔', '靴子', '赤兔马'];
hero.blood = 100;
// 方法
hero.attack = function () {
console.log(this.name + ': 射箭');
}
hero.run = function () {
console.log(this.name + ': 加速跑')
}
- 工厂函数创建对象
function createHero(name, weapon, equipment, blood) {
var hero = new Object(); //返回一个空的对象
// 属性
hero.name = name;
hero.weapon = weapon;
hero.equipment = equipment;
hero.blood = blood;
// 方法
hero.attack = function () {
console.log(this.name + ':攻击');
}
hero.run = function () {
console.log(this.name + ':加速跑');
}
return hero;
}
var hero1 = createHero('黄忠', '弓箭', ['头盔', '靴子'], 100);
var hero2 = createHero('刘备', '剑', ['头盔', '盔甲'], 100);
- 自定义构造函数
function Hero(name, weapon, equipment, blood) {
// this 动态的给对象增加成员
// this 指向了当前对象
this.name = name;
this.weapon = weapon;
this.equipment = equipment;
this.blood = blood;
this.attack = function () {
console.log(this.name + ':攻击');
}
this.run = function () {
console.log(this.name + ': 加速跑');
}
}
var hero1 = new Hero('黄忠', '弓箭', ['头盔', '靴子'], 100);
var hero2 = new Hero('刘备', '剑', ['头盔', '盔甲'], 100);
this代表的是当前对象。
但是构造函数方有个缺点,就是对象的方法放在了构造函数内部,这样每创建一个方法就会需要多占用
一些内存,所以js给构造函数设计了一个prototype属性,用来存放对象的方法:
function Student(name,age,id){
this.name=name;
this.age=age;
this.id=id;
}
Student.prototype={
work:function(skill){
alert(this.name+"做"+skill+"开发相关的工作");
},
classId:"Java1班"
}
var stu1=new Student("李明",18,20151515);//得到的就是字面量对象
var stu2=new Student("王磊",18,20141000);//得到的就是字面量对象
console.log(stu2.work==stu1.work);//ture,节省了内存空间
stu1.work("Java");
stu2.work("PHP");
console.log(stu1.classId);//20151515
console.log(stu2.classId);//20141000
属性和方法
如果一个变量属于一个对象所有,那么该变量就可以称之为该对象的一个属性,属性一般是名词,用来描述事物的特征。
如果一个函数属于一个对象所有,那么该函数就可以称之为该对象的一个方法,方法是动词,描述事物的行为和功能。
关键字详解
new关键字
- 构造函数用于创建一类对象,首字母要大写。
- 构造函数要和new一起使用才有意义。
// Student 自定义构造函数
// 属性:name age sex score
// 方法:sayHi
function Student(name, age, sex, score) {
// 属性
this.name = name;
this.age = age;
this.sex = sex;
this.score = score;
// 方法
this.sayHi = function () {
console.log(this.name + ': hello');
}
}
var stu1 = new Student('lilei', 18, '男', 100);
var stu2 = new Student('hanmeimei', 17, '女', 100);
new在执行时会做四件事情
- new会在内存中创建一个新的空对象
- new 会让this指向这个新的对象
- 执行构造函数 目的:给这个新对象加属性和方法
- new会返回这个新对象
this详解
JavaScript中的this指向问题,有时候会让人难以捉摸,随着学习的深入,我们可以逐渐了解
现在我们需要掌握函数内部的this几个特点
- 函数在定义的时候this是不确定的,只有在调用的时候才可以确定
- 一般函数直接执行,内部this指向全局window
- 函数作为一个对象的方法,被该对象所调用,那么this指向的是该对象
- 构造函数中的this其实是一个隐式对象,类似一个初始化的模型,所有方法和属性都挂载到了这个隐式对象身上,后续通过new关键字来调用,从而实现实例化
对象的使用方法
对象属性的使用:
1、可以用点符号访问对象属性值
2、也可以通过数组的方式,即用[“属性名称”]
对象方法的使用:
可以使用对象名.方法名()来调用
遍历对象的属性
var obj = {
name: '张三',
age: 18,
sex: true,
sayHi: function () {
console.log(this.name);
}
};
for(var key in obj) {
console.log(key + "==" + obj[key]);
}
删除对象的属性
function fun() {
this.name = 'mm';
}
var obj = new fun();
console.log(obj.name); // mm
delete obj.name;
console.log(obj.name); // undefined
简单类型和复杂类型的区别
基本类型又叫做值类型,复杂类型又叫做引用类型
值类型:简单数据类型,基本数据类型,在存储时,变量中存储的是值本身,因此叫做值类型。
引用类型:复杂数据类型,在存储是,变量中存储的仅仅是地址(引用),因此叫做引用数据类型。
堆和栈
堆栈空间分配区别:
1、栈(操作系统):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。
2、堆(操作系统): 存储复杂类型(对象),一般由程序员分配释放, 若程序员不释放,由垃圾回收机制回收。
**注意:**JavaScript中没有堆和栈的概念,此处我们用堆和栈来讲解,目的方便理解和方便以后的学习。
栈
var a = 1;
var b = "1";
堆
const p1 = {};
const p2 = {};
const p3 = {};
十、JS内置对象
JavaScript中的对象分为3种:内置对象、自定义对象、浏览器对象
JavaScript 提供多个内置对象:Math/Array/Date…
对象只是带有属性和方法的特殊数据类型。
学习一个内置对象的使用,只要学会其常用的成员的使用(通过查文档学习)
可以通过MDN/W3C来查询
内置对象的方法很多,我们只需要知道内置对象提供的常用方法,使用的时候查询文档。
Mozilla 开发者网络(MDN)提供有关开放网络技术(Open Web)的信息,包括 HTML、CSS 和万维网及 HTML5 应用的 API。
MDN:https://developer.mozilla.org/zh-CN/
如何学习一个方法?
- 方法的功能
- 参数的意义和类型
- 返回值意义和类型
- demo进行测试
10.1Array对象
Array构造函数
// new关键字创建空数组
var arr = new Array();
// new关键字创建包含元素的数组
var arr = new Array(值1,值2.....值N);
// new关键字创建指定元素个数的数组
var arr = new Array(数值);
// 也可以使用[]直接创建数组
var arr = [];
var arr = [值1,值2.....值N];
// 可以使用length属性获取数组的长度;并且可以给一个数组长度赋值。
检测一个对象是否是数组:
- instanceof
- Array.isArray() HTML5中提供的方法,有兼容性问题
Array对象方法(常用)
方法 | 描述 |
---|---|
push(要添加的数据) | 尾部添加元素 |
pop() | 尾部删除元素 |
unshift(要添加的数据) | 头部添加元素 |
shift() | 头部删除元素 |
delete运算符 | 删除指定元素的内容 |
splice(起始位置,截取个数,要插入的数据) | 删除、替换、插入元素,会更改原数组; |
toString() | 将数组转换为字符串,返回新数组 |
join(分隔符) | 将数组转换为字符串,返回新数组 |
reverse() | 反转数组 |
concat(其他数组名) | 合并数组,返回新数组 |
slice(start下标,end下标) | 截取数组,包含start,不包含end,省略end截取至末尾,返回新数组 |
sort(回调函数) | 数组排序 |
- push()
var arr = [1,2,3,4,5]
arr.push(6)
console.log(arr); //[1, 2, 3, 4, 5, 6]
- pop()
var arr = [1,2,3,4,5]
arr.pop()
console.log(arr); //[1, 2, 3, 4]
- unshift()
var arr = [1,2,3,4,5]
arr.unshift(0)
console.log(arr); // [0, 1, 2, 3, 4, 5]
- shift()
var arr = [1,2,3,4,5]
arr.shift
console.log(arr); //[1, 2, 3, 4, 5]
- delete运算符
var arr = [1,2,3,4,5]
delete arr[0]
console.log(arr); // […, 2, 3, 4, 5]
- splice()
var arr = [1,2,3,4,5]
arr.splice(2,2)
console.log(arr); //[1, 2, 5]
var arr = [1,2,4,5]
arr.splice(2,0,3)
console.log(arr); //[1, 2, 3, 4, 5]
- toString()
var arr = [1,2,3,4,5]
var newStr = arr.toString()
console.log(newStr); //1,2,3,4,5
- join() (和toString的区别主要是join可以指定分隔符的样式)
var arr = [1,2,3,4,5]
var newStr = arr.join(`|`)
console.log(newStr); //1|2|3|4|5
- reverse()
var arr = [1,2,3,4,5]
arr.reverse()
console.log(arr); //[5, 4, 3, 2, 1]
- concat()
var arr = [1,2,3,4,5]
var newarr = [6,7,8,9]
var rs = arr.concat(newarr)
console.log(rs); //[1, 2, 3, 4, 5, 6, 7, 8, 9]
- slice()
var arr = [1,2,3,4,5]
var newarr = arr.slice(1,4)
console.log(newarr); //[2, 3, 4]
- sort()
var arr = [1,21,13,54,25]
arr.sort(function(a,b){
return a - b //升序
})
console.log(arr); //[1, 13, 21, 25, 54]
var arr = [1, 21, 13, 54, 25]
arr.sort(function (a, b) {
return b - a //降序
})
console.log(arr); //[54, 25, 21, 13, 1]
Array对象应用
将一个字符串数组输出为|分割的形式,比如“刘备|张飞|关羽”。使用两种方式实现
function myJoin(array, seperator) {
if (array.length == 0){
return '';
}
var str = array[0];
for (var i = 1; i < array.length; i++) {
str += seperator + array[i];
}
return str;
}
var array = [6, 3, 5, 6, 7, 8, 0];
console.log(myJoin(array, '-'));
console.log(array.join('-'))
将一个字符串数组的元素的顺序进行反转。使用两种种方式实现。
function myReverse(arr) {
if (!arr || arr.length == 0) {
return [];
}
for (var i = 0; i < arr.length / 2; i++) {
var tmp = arr[i];
arr[i] = arr[this.length - i - 1];
arr[arr.length - i - 1] = tmp;
}
return arr;
}
var array = ['a', 'b', 'c'];
console.log(myReverse(array));
console.log(array.reverse());
10.2Date对象
Date是JavaScript的内置对象,系统在Date对象中封装了与日期和时间相关的属性和方法。
Date使用UTC1970年1月1日0时开始经过的毫秒数来存储时间。
Date构造函数
// 无参数的情况下返回值为当前时间。不同浏览器显示的时间格式会有细微差异
var date= new Date();
// 参数为毫秒值,距1970年1月1日(世界标准时间)起的毫秒数
var date = new Date(milliseconds);
// 参数为日期字符串
var date = new Date(dateString);
// 必选值:year, month, day;
var date = new Date(year, month, day, hours, minutes, seconds, milliseconds);
Date对象方法(常用)
方法 | 描述 |
---|---|
getDate() | 从 Date 对象返回一个月中的某一天 (1 ~ 31)。 |
getDay() | 从 Date 对象返回一周中的某一天 (0 ~ 6)。 |
getFullYear() | 从 Date 对象以四位数字返回年份。 |
getHours() | 返回 Date 对象的小时 (0 ~ 23)。 |
getMilliseconds() | 返回 Date 对象的毫秒(0 ~ 999)。 |
getMinutes() | 返回 Date 对象的分钟 (0 ~ 59)。 |
getMonth() | 从 Date 对象返回月份 (0 ~ 11)。 |
getSeconds() | 返回 Date 对象的秒数 (0 ~ 59)。 |
getTime() | 返回 1970 年 1 月 1 日至今的毫秒数。 |
Date.now() | 返回1970年1月1日午夜到指定日期的毫秒数(HTML5中提供的方法,有兼容性问题) |
Date对象解析相关方法:
Date.parse()返回1970年1月1日午夜到指定日期(字符串)的毫秒数。
Date.parse()参数支持的时间格式如下:
1/24/2021;得到 Sun Jan 24 2021 10:10:10 GMT+0800
格式不正确会返回 无效的时间
写一个函数,格式化日期对象,返回yyyy-MM-dd HH:mm:ss的形式
function formatDate(d) {
//如果date不是日期对象,返回
if (!d instanceof Date) {
return;
}
var year = d.getFullYear(),
month = d.getMonth() + 1,
date = d.getDate(),
hour = d.getHours(),
minute = d.getMinutes(),
second = d.getSeconds();
month = month < 10 ? '0' + month : month;
date = date < 10 ? '0' + date : date;
hour = hour < 10 ? '0' + hour : hour;
minute = minute < 10 ? '0' + minute : minute;
second = second < 10 ? '0' + second : second;
return year + '-' + month + '-' + date + ' ' + hour + ':' + minute + ':' +
second;
}
10.3 String对象
字符串是非常重要的数据类型,除了基本字符串外,JavaScript还提供了字符串的引用类型–字符串对象。
字符串对象提供了字符串检索、替换、连接等方法…
字符串的不可变
var str = 'abc';
str = 'hello';
// 当重新给str赋值的时候,常量'abc'不会被修改,依然在内存中
// 重新给字符串赋值,会重新在内存中开辟空间,这个特点就是字符串的不可变
// 由于字符串的不可变,在大量拼接字符串的时候会有效率问题
String构造函数
可以通过new 关键字创建字符串对象
var str=”hello”; // 字符串字面量
var str=new String(); // 字符串对象
注:创建出来的类型虽说不同,但是对于内置的方法和属性都是可以使用的。
length 属性返回字符串的长度(字符数)。
String对象方法(现阶段常用)
方法 | 描述 |
---|---|
charAt(index) | 返回在指定位置的字符。 |
charCodeAt() | 返回在指定的位置的字符的 Unicode 编码。 |
concat([string1,string2…) | 连接字符串。返回新字符串 |
slice(start,end) | 提取字符串n到m之间的片断(不包括m位置的字符串),并在新的字符串中返回新字符串。 |
substring(star,end) | 和slice作用一样,不同点在于slice参数可以是负数,substring设置负数视为0 |
split(separator,limit) | 将字符串分割成数组,separator指定以什么符号分割,limit指定数组最大长度,返回新数组 |
indexOf(subString[,startIndex]) | sbString指定要查找的字符,startIndex指定开始寻找位置下标,返回该字符的下标,如果没有找到该字符,则返回-1 |
lastIndexOf(subString[,startIndex]) | 返回指定字符串在字符串最后出现的位置。 |
replace(rgExp, replaceText) | 替换字符,返回新字符串 |
- charAt(index)
var str = "这是一个字符串"
console.log(str.charAt(1)); //是
- charCodeAt()
var str = "这是一个字符串"
console.log(str.charCodeAt(1)); //26159
- concat([string1,string2…)
var str1 = "我爱"
var str2 = "中华"
var str3 = "人名共和国"
var rs = str1.concat(str2,str3)
console.log(rs); //我爱中华人名共和国
- slice()
var str = "这是一个字符串"
var newStr = str.slice(1,3)
console.log(newStr); //是一
- substring()
var str = "这是一个字符串"
var newStr = str.substring(1,3)
console.log(newStr); //是一
- split()
var str = "这是一个字符串"
var newArr = str.split("")
console.log(newArr); //['这', '是', '一', '个', '字', '符', '串']
- indexOf()
var str = "这是一个字符串"
var index = str.indexOf("字")
console.log(index); //4
- lastIndexOf()
var str = "这是一个字符串,一直熊"
var index = str.lastIndexOf("一")
console.log(index);
- replace()
var str = "这是一个字符串,一直熊"
str = str.replace("这","啦")
console.log(str); //啦是一个字符串,一直熊
把字符串中所有的o替换成!
var s = 'abcoefoxyozzopp';
var index = -1;
do {
index = s.indexOf('o', index + 1);
if (index !== -1) {
// 替换
s = s.replace('o', '!');
}
} while (index !== -1);
console.log(s);
10.4 Math对象
Math对象不是构造函数,它具有数学常数和函数的属性和方法,都是以静态成员的方式提供。
跟数学相关的运算来找Math中的成员(求绝对值,取整)。
Math 对象并不像 Date 和 String 那样是对象的类,因此没有构造函数 Math()
方法名/属性名 | 描述 |
---|---|
Math.PI | 返回圆周率(约等于3.14159)。 |
Math.ceil(x) | 向上取整 |
Math.floor(x) | 向下取整 |
Math.round(x) | 四舍五入 |
Math.random() | 随机数,返回包含0不包含1的随机数 |
Math.max(x,y) | 返回 x 和 y 中的最高值。 |
Math.min(x,y) | 返回 x 和 y 中的最低值。 |
Math.abs(x) | 返回x的绝对值。 |
- Math.PI
var PI = Math.PI
console.log(PI); //3.141592653589793
- Math.ceil(x)
var num1 = 3
var num2 = 3.1
var num3 = 3.7
console.log(Math.ceil(num1)); //3
console.log(Math.ceil(num2)); //4
console.log(Math.ceil(num3)); //4
- Math.floor(x)
var num1 = 3
var num2 = 3.1
var num3 = 3.7
console.log(Math.floor(num1)); //3
console.log(Math.floor(num2)); //3
console.log(Math.floor(num3)); //3
- Math.round(x)
var num1 = 3
var num2 = 3.1
var num3 = 3.7
console.log(Math.round(num1)); //3
console.log(Math.round(num2)); //3
console.log(Math.round(num3)); //4
- Math.random()
var r = Math.random()
console.log(r); //0.8418179422200389
注意:求min - max的随机数公式为
Math.floor(Math.random() * (max - min) + min)
- Math.max(x,y)
- Math.min(x,y)
var max = Math.max(5,6)
var min = Math.min(5,6)
console.log(max); //6
console.log(min); //5
- Math.abs()
console.log(Math.abs(-10)); //10
10.5全局对象
1、parseInt
- parseInt() 函数可解析一个字符串,并返回一个整数。
2、parseFloat方法
- parseFloat()函数可解析一个字符串,并返回一个浮点数。
- 该函数指定字符串中的首个字符是否是数字。如果是,则对字符串进行解析,直到到达数字的末端为止,然后以数字返回该数字,而不是作为字符串。
- 如果参数字符串的第一个字符不能被解析成为数字,则 parseFloat 返回 NaN。
3、isNaN()方法
-
isNaN(x):函数用于检查其参数是否是非数字值。
-
参数x是要检测的值,如果x是特殊的非数字值NaN(或者能被转换为这样的值),返回的值就是true。如果 x 是其他值,则返回 false。
-
isNaN()函数可用于判断其参数是否是NaN,该值表示一个非法的数字(比如被 0 除后得到的结果),如果把NaN与任何值(包括其自身)相比得到的结果均是false,所以要判断某个值是否是NaN,不能使用 == 或 === 运算符。正因为如此,isNaN() 函数是必需的。
提示:isNaN()函数通常用于检测parseFloat()和parseInt()的结果,以判断它们表示的是否是合法的数字。当然也可以用isNaN()函数来检测算数错误,比如用0作除数的情况。
var loginName = parseInt('amigo1121');
if (isNaN(loginName)) {
//如果loginName不是数值,执行如下语句
alert("parseInt('amigo1121')的结果是: " + loginName);
} else {
alert("parseInt('amigo1121')的结果是数值!");
}
10.6基本包装类型
为了方便操作简单数据类型,JavaScript还提供了三个特殊的简单类型类型:String/Number/Boolean
// 下面代码的问题?
// s1是基本类型,基本类型是没有方法的
var s1 = 'zhangsan';
var s2 = s1.substring(5);
// 当调用s1.substring(5)的时候,先把s1包装成String类型的临时对象,再调用substring方法,最
后销毁临时对象, 相当于:
var s1 = new String('zhangsan');
var s2 = s1.substring(5);
s1 = null;
// 创建基本包装类型的对象
var num = 18; //数值,基本类型
var num = Number('18'); //类型转换
var num = new Number(18); //基本包装类型,对象
// Number和Boolean基本包装类型基本不用,使用的话可能会引起歧义。例如:
var b1 = new Boolean(false);
var b2 = b1 && true; // 结果是什么