add file:Bootstrap
This commit is contained in:
@@ -1,826 +0,0 @@
|
||||
|
||||
|
||||
> 本文最初发表于[博客园](https://www.cnblogs.com/smyhvae/p/8303507.html),并在[GitHub](https://github.com/smyhvae/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。
|
||||
|
||||
> 以下是正文。
|
||||
|
||||
## JavaScript简介
|
||||
|
||||
Web前端有三层:
|
||||
|
||||
- HTML:从语义的角度,描述页面**结构**
|
||||
|
||||
- CSS:从审美的角度,描述**样式**(美化页面)
|
||||
|
||||
- JavaScript:从交互的角度,描述**行为**(提升用户体验)
|
||||
|
||||
|
||||
JavaScript是世界上用的最多的**脚本语言**。
|
||||
|
||||
补充:
|
||||
|
||||
- 编译执行:把代码编译成CPU认识的语言(文件),然后整体的执行。
|
||||
|
||||
|
||||
- **脚本语言:不需要编译**,直接在运行时**边解析边执行**的语言。
|
||||
|
||||
- 弱类型语言:简单定义一个变量,可以有多种数据类型。(var temp)
|
||||
|
||||
|
||||
### JavaScript历史背景介绍
|
||||
|
||||
布兰登 • 艾奇(Brendan Eich,1961年~),1995年在网景公司,发明的JavaScript。
|
||||
|
||||
一开始JavaScript叫做LiveScript,但是由于当时Java这个语言特别火,所以为了傍大牌,就改名为JavaScript。如同“北大”和“北大青鸟”的关系。“北大青鸟”就是傍“北大”大牌。
|
||||
|
||||
同时期还有其他的网页语言,比如VBScript、JScript等等,但是后来都被JavaScript打败了,所以现在的浏览器中,只运行一种脚本语言就是JavaScript。
|
||||
|
||||
### JavaScript和ECMAScript的关系
|
||||
|
||||
ECMAScript是一种由Ecma国际(前身为欧洲计算机制造商协会,英文名称是European Computer Manufacturers Association)制定的标准。
|
||||
|
||||
JavaScript是由公司开发而成的,问题是不便于其他的公司拓展和使用。所以欧洲的这个ECMA的组织,牵头制定JavaScript的标准,取名为ECMAScript。
|
||||
|
||||
简单来说,**ECMAScript不是一门语言,而是一个标准**。符合这个标准的比较常见的有:JavaScript、Action Script(Flash中用的语言)。就是说,你JavaScript学完了,Flash中的程序也就轻而易举了。
|
||||
|
||||
ECMAScript在2015年6月,发布了ECMAScript 6版本,语言的能力更强(也包含了很多新特性)。但是,浏览器的厂商不能那么快去追上这个标准。
|
||||
|
||||
### JavaScript的发展:蒸蒸日上
|
||||
|
||||
2003年之前,JavaScript被认为“牛皮鲜”,用来制作页面上的广告,弹窗、漂浮的广告。什么东西让人烦,什么东西就是JavaScript开发的。所以浏览器就推出了屏蔽广告功能。
|
||||
|
||||
2004年,JavaScript命运开始改变,那一年,**谷歌公司开始带头使用Ajax技术**,Ajax技术就是JavaScript的一个应用。并且,那时候人们逐渐开始提升用户体验了。Ajax有一些应用场景。比如,当我们在百度搜索框搜文字时,输入框下方的智能提示,可以通过Ajax实现。比如,当我们注册网易邮箱时,能够及时发现用户名是否被占用,而不用调到另外一个页面。
|
||||
|
||||
2007年乔布斯发布了第一款iPhone,这一年开始,用户就多了上网的途径,就是用移动设备上网。
|
||||
**JavaScript在移动页面中,也是不可或缺的**。并且这一年,互联网开始标准化,按照W3C规则三层分离,JavaScript越来越被重视。
|
||||
|
||||
2010年,人们更加了解**HTML5技术**,**HTML5推出了一个东西叫做Canvas**(画布),工程师可以在Canvas上进行游戏制作,利用的就是JavaScript。
|
||||
|
||||
2011年,**Node.js诞生**,使JavaScript能够开发服务器程序了。
|
||||
|
||||
如今,**WebApp**已经非常流行,就是用**网页技术开发手机应用**。手机系统有iOS、安卓。比如公司要开发一个“携程网”App,就需要招聘三队人马,比如iOS工程师10人,安卓工程师10人,前端工程师10人。共30人,开发成本大;而且如果要改版,要改3个版本。现在,假设公司都用web技术,用html+css+javascript技术就可以开发App。也易于迭代(网页一改变,所有的终端都变了)。
|
||||
|
||||
虽然目前WebApp在功能和性能上的体验远不如Native App,但是“WebApp慢慢取代Native App”很有可能是未来的趋势。
|
||||
|
||||
### JavaScript入门易学性
|
||||
|
||||
- JavaScript对初学者比较友好。
|
||||
|
||||
- JavaScript是有界面效果的(比如C语言只有白底黑字)。
|
||||
|
||||
- JavaScript是**弱变量类型**的语言,变量只需要用var来声明。而Java中变量的声明,要根据变量的类型来定义。
|
||||
|
||||
比如Java中需要定义如下变量:
|
||||
|
||||
```java
|
||||
int a;
|
||||
float a;
|
||||
double a;
|
||||
String a;
|
||||
boolean a;
|
||||
```
|
||||
|
||||
而JavaScript中,只用定义一个变量:
|
||||
|
||||
```JavaScript
|
||||
var a;
|
||||
```
|
||||
|
||||
- JavaScript不用关心其他的一些事情(比如内存的释放、指针等),更关心自己的业务。
|
||||
|
||||
### 浏览器工作原理
|
||||
|
||||
|
||||
20180124_1700.png
|
||||
|
||||
1、User Interface 用户界面,我们所看到的浏览器
|
||||
|
||||
2、Browser engine 浏览器引擎,用来查询和操作渲染引擎
|
||||
|
||||
3、Rendering engine 用来显示请求的内容,负责解析HTML、CSS
|
||||
|
||||
4、Networking 网络,负责发送网络请求
|
||||
|
||||
5、JavaScript Interpreter(解析者) JavaScript解析器,负责执行JavaScript的代码
|
||||
|
||||
6、UI Backend UI后端,用来绘制类似组合框和弹出窗口
|
||||
|
||||
7、Data Persistence(持久化) 数据持久化,数据存储 cookie、HTML5中的sessionStorage
|
||||
|
||||
|
||||
|
||||
参考链接:<https://www.2cto.com/kf/201202/118111.html>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### JavaScript是前台语言
|
||||
|
||||
JavaScript是前台语言,而不是后台语言。
|
||||
|
||||
JavaScript运行在用户的终端网页上,而不是服务器上,所以我们称为“**前台语言**”。JavaScript就是一个简单的制作页面效果的语言,就是服务于页面的交互效果、美化、绚丽、不能操作数据库。
|
||||
|
||||
**后台语言**是运行在服务器上的,比如PHP、ASP、JSP等等,这些语言都能够操作数据库,都能够对数据库进行“增删改查”操作。Node.js除外。
|
||||
|
||||
### JavaScript的组成
|
||||
|
||||
JavaScript基础分为三个部分:
|
||||
|
||||
- ECMAScript:JavaScript的语法标准。包括变量、表达式、运算符、函数、if语句、for语句等。
|
||||
|
||||
- **DOM**:操作**网页上的元素**的API。比如让盒子移动、变色、轮播图等。
|
||||
|
||||
- **BOM**:操作**浏览器部分功能**的API。比如让浏览器自动滚动。
|
||||
|
||||
PS:JS机械重复性的劳动几乎为0,基本都是创造性的劳动。而不像HTML、CSS中margin、padding都是机械重复劳动。
|
||||
|
||||
### JavaScript的特点
|
||||
|
||||
(1)简单易用:可以使用任何文本编辑工具编写,只需要浏览器就可以执行程序。
|
||||
|
||||
(2)解释执行(**解释语言**):事先不编译、逐行执行、无需进行严格的变量声明。
|
||||
|
||||
(3)基于对象:内置大量现成对象,编写少量程序可以完成目标
|
||||
|
||||
## 开始写第一行JavaScript代码
|
||||
|
||||
### JavaScript代码的书写位置
|
||||
|
||||
(1)内嵌的方式:
|
||||
|
||||
页面中,我们可以在`<body>`标签里放入`<script type=”text/javascript”></script>`标签对儿,并在`<script>`里书写JavaScript程序:
|
||||
|
||||
```
|
||||
<script type="text/javascript">
|
||||
|
||||
</script>
|
||||
```
|
||||
|
||||
text表示纯文本,因为JavaScript也是一个纯文本的语言。
|
||||
|
||||
PS:在Sublime Text里,输入`<sc`后,按tab键,可以自动补齐。
|
||||
|
||||
(2)外链式:引入外部JavaScript文件(放到body标签里,可以和内嵌的js代码并列)
|
||||
|
||||
```
|
||||
<script src="tool.js"></script>
|
||||
```
|
||||
|
||||
|
||||
### alert语句
|
||||
|
||||
我们要学习的第一个语句,就是alert语句。
|
||||
|
||||
```
|
||||
<script type="text/javascript">
|
||||
alert("生命壹号");
|
||||
</script>
|
||||
```
|
||||
|
||||
**alert**(英文翻译为“警报”)的用途:**弹出“警告框”**。
|
||||
|
||||
`alert("")`警告框的效果如下:
|
||||
|
||||

|
||||
|
||||
这个警告框,在IE浏览器中长这样:
|
||||
|
||||

|
||||
|
||||
上面的代码中,如果写了两个alert()语句的话,网页的效果是:弹出第一个警告框,点击确定后,继续弹出第二个警告框。
|
||||
|
||||
### 语法规则
|
||||
|
||||
学习程序,是有规律可循的,就是程序是有相同的部分,这些部分就是一种规定,不能更改,我们成为:语法。
|
||||
|
||||
(1)JavaScript对换行、缩进、空格不敏感。
|
||||
|
||||
也就是说:
|
||||
|
||||
代码一:
|
||||
|
||||
```
|
||||
<script type="text/javascript">
|
||||
alert("今天蓝天白云");
|
||||
alert("我很高兴");
|
||||
</script>
|
||||
```
|
||||
|
||||
等价于代码二:
|
||||
|
||||
```
|
||||
<script type="text/javascript">
|
||||
alert("今天蓝天白云");alert("我很高兴");
|
||||
</script>
|
||||
```
|
||||
|
||||
备注:每一条语句末尾要加上分号,虽然分号不是必须加的,但是为了程序今后要压缩,如果不加分号,压缩之后将不能运行。
|
||||
|
||||
(2)所有的符号,都是英语的。比如**括号**、引号、分号。
|
||||
|
||||
如果你用的是搜狗拼音,**建议不要用shift切换中英文**(可以在搜狗软件里进行设置),不然很容易输入中文的分号;建议用ctrl+space切换中英文输入法。
|
||||
|
||||
### 注释
|
||||
|
||||
我们不要把html、CSS、JavaScript三者的注释格式搞混淆了。
|
||||
|
||||
(1)**html的注释:**
|
||||
|
||||
```html
|
||||
<!-- 我是注释 -->
|
||||
```
|
||||
|
||||
(2)**CSS的注释:**
|
||||
|
||||
```html
|
||||
<style type="text/css">
|
||||
|
||||
/*
|
||||
我是注释
|
||||
*/
|
||||
|
||||
p{
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
color: red;
|
||||
}
|
||||
|
||||
</style>
|
||||
```
|
||||
|
||||
注意:CSS只有`/* */`这种注释,没有`//`这种注释。而且注释要写在`<style>`标签里面才算生效哦。
|
||||
|
||||
(3)**JavaScript的注释:**
|
||||
|
||||
单行注释:
|
||||
|
||||
```
|
||||
// 我是注释
|
||||
```
|
||||
|
||||
多行注释:
|
||||
|
||||
```
|
||||
/*
|
||||
多行注释1
|
||||
多行注释2
|
||||
*/
|
||||
```
|
||||
|
||||
备注:sublime中,单行注释的快捷键是`ctrl+/`,多行注释的快捷键是`ctrl+shift+/`。
|
||||
|
||||
## Javascript 网页中输出信息的写法
|
||||
|
||||
### 弹出警告框:alert("")
|
||||
|
||||
我们在上一段讲到了alert语句,这里不再赘述。
|
||||
|
||||
### 控制台输出:console.log("")
|
||||
|
||||
`console.log("")`表示在控制台中输出。console表示“控制台”,log表示“输出”。
|
||||
|
||||
控制台在Chrome浏览器的F12中。控制台是工程师、程序员调试程序的地方。程序员经常使用这条语句输出一些东西,来测试程序是否正确。
|
||||
|
||||
`console.log("")`效果如下:
|
||||
|
||||

|
||||
|
||||
普通人是不会在意控制台的,但是有些网站另藏玄机。有个很有意思的地方是,百度首页的控制台,悄悄地放了一段招聘信息:
|
||||
|
||||

|
||||
|
||||
毕竟做前端的人是经常使用控制台的。
|
||||
|
||||
接下来,我们开始学习JavaScript语法。
|
||||
|
||||
### 用户输入:prompt()语句
|
||||
|
||||
`prompt()`就是专门用来弹出能够让用户输入的对话框。用得少,测试的时候可能会用。
|
||||
|
||||
JS代码如下:
|
||||
|
||||
```javascript
|
||||
var a = prompt("请随便输入点什么东西吧");
|
||||
console.log(a);
|
||||
```
|
||||
|
||||
上方代码中,用户输入的内容,将被传递到变量 a 里面。
|
||||
|
||||
效果如下:
|
||||
|
||||

|
||||
|
||||
**prompt()语句中,用户不管输入什么内容,都是字符串。**
|
||||
|
||||
**alert和prompt的区别:**
|
||||
|
||||
```javascript
|
||||
alert("从前有座山"); //直接使用,不需要变量
|
||||
var a = prompt("请输入一个数字"); // 必须用一个变量,来接收用户输入的值
|
||||
```
|
||||
|
||||
## 字面量:数字和字符串
|
||||
|
||||
“字面量”即**常量**,是固定值。看见什么,它就是什么。
|
||||
|
||||
简单的直接量有2种:数字、字符串。
|
||||
|
||||
(1)数值的直接量的表达非常简单,写上去就行了,不需要任何的符号。例如:
|
||||
|
||||
```javascript
|
||||
1 alert(886); //886是数字,所以不需要加引号。
|
||||
```
|
||||
|
||||
(2)字符串也很简单,但一定要加上引号。可以是单词、句子等。
|
||||
|
||||
温馨提示:100是数字,"100"是字符串。
|
||||
|
||||
|
||||
## 变量
|
||||
|
||||
### 变量的定义和赋值
|
||||
|
||||
变量举例如下:
|
||||
|
||||
```javascript
|
||||
var a = 100;
|
||||
```
|
||||
|
||||
如下图所示:
|
||||
|
||||

|
||||
|
||||
var是英语“variant”变量的缩写。后面要加一个空格,空格后面的东西就是“变量名”,
|
||||
|
||||
- 定义变量:var就是一个**关键字**,用来定义变量。所谓关键字,就是有特殊功能的小词语。关键字后面一定要有空格隔开。
|
||||
|
||||
- 变量的赋值:等号表示**赋值**,将等号右边的值,赋给左边的变量。
|
||||
|
||||
- 变量名:我们可以给变量任意的取名字。
|
||||
|
||||
PS:**在JavaScript中,永远都是用var来定义变量**,这和C、Java等语言不同。
|
||||
|
||||
变量要先定义,才能使用。比如,我们不设置变量,直接输出:
|
||||
|
||||
```html
|
||||
<script type="text/javascript">
|
||||
console.log(a);
|
||||
</script>
|
||||
```
|
||||
|
||||
控制台将会报错:
|
||||
|
||||

|
||||
|
||||
正确写法:
|
||||
|
||||
```javascript
|
||||
var a; // 定义
|
||||
a = 100; //赋值
|
||||
console.log(a); //输出100
|
||||
```
|
||||
|
||||
有经验的程序员,会把定义和赋值写在一起:
|
||||
|
||||
```javascript
|
||||
var a = 100; //定义,并且赋值100
|
||||
console.log(a); //输出100
|
||||
```
|
||||
|
||||
### 变量的命名规范
|
||||
|
||||
变量名有命名规范:只能由英语字母、数字、下划线、美元符号$构成,且不能以数字开头,并且不能是JavaScript保留字。
|
||||
|
||||
下列的单词,叫做保留字,就是说不允许当做变量名,不用记:
|
||||
|
||||
```
|
||||
abstract、boolean、byte、char、class、const、debugger、double、enum、export、extends、final、float、goto
|
||||
implements、import、int、interface、long、native、package、private、protected、public、short、static、super、synchronized、throws、transient、volatile
|
||||
```
|
||||
|
||||
大写字母是可以使用的,并且大小写敏感。也就是说A和a是两个变量。
|
||||
|
||||
```javascript
|
||||
var A = 250; //变量1
|
||||
var a = 888; //变量2
|
||||
```
|
||||
|
||||
|
||||
我们来整理一下变量的命名规则:
|
||||
|
||||
驼峰命名规则:getElementById/matherAndFather/aaaOrBbbAndCcc
|
||||
|
||||
|
||||
1.变量命名必须以字母或是下标符号”_”或者”$”为开头。
|
||||
2.变量名长度不能超过255个字符。
|
||||
3.变量名中不允许使用空格,首个字不能为数字。
|
||||
4.不用使用脚本语言中保留的关键字及保留符号作为变量名。
|
||||
5.变量名区分大小写。(javascript是区分大小写的语言)
|
||||
6.汉语可以作为变量名。但是不建议使用,因为 low
|
||||
|
||||
|
||||
## 变量的类型
|
||||
|
||||
变量里面能够存储数字、字符串等。变量会自动的根据存储内容的类型不同,来决定自己的类型。
|
||||
|
||||
|
||||
- **简单数据类型(值类型)**:字符串 String、数字 Number、布尔 Boolean、未定义 undefined、空 null。
|
||||
|
||||
- **复杂数据类型(引用类型)**:Object、function、Array、Date、RegExp、Error...
|
||||
|
||||
|
||||
简单数据类型:参数赋值的时候,传数值
|
||||
|
||||
复杂数据类型:参数赋值的时候,传地址(修改的同一片内存空间)
|
||||
|
||||
|
||||
### 数值型:number
|
||||
|
||||
如果一个变量中,存放了数字,那么这个变量就是数值型的。
|
||||
|
||||
```javascript
|
||||
var a = 100; //定义了一个变量a,并且赋值100
|
||||
console.log(typeof a); //输出a变量的类型
|
||||
```
|
||||
|
||||
上方代码的输出结果为:
|
||||
|
||||
```
|
||||
number
|
||||
```
|
||||
|
||||
**typeof()**表示“**获取变量的类型**”,语法为:
|
||||
|
||||
```
|
||||
typeof 变量
|
||||
```
|
||||
|
||||
**在JavaScript中,只要是数,就是数值型(number)的**。无论整浮、浮点数(即小数)、无论大小、无论正负,都是number类型的。
|
||||
|
||||
**数值范围:**
|
||||
|
||||
由于内存的限制,ECMAScript 并不能保存世界上所有的数值。
|
||||
- 最小值:Number.MIN_VALUE,这个值为: 5e-324
|
||||
|
||||
- 最大值:Number.MAX_VALUE,这个值为: 1.7976931348623157e+308
|
||||
|
||||
- 无穷大:Infinity
|
||||
|
||||
- 无穷小:-Infinity
|
||||
|
||||
|
||||
**NaN和isNaN()函数:**
|
||||
|
||||
(1)NaN:Not a Number,非数值。
|
||||
|
||||
```
|
||||
console.log(“abc”/18); //结果是NaN
|
||||
```
|
||||
|
||||
Undefined和任何数值计算为NaN。NaN 与任何值都不相等,包括 NaN 本身。
|
||||
|
||||
(2)isNaN() :任何不能被转换为数值的值都会导致这个函数返回 true。
|
||||
|
||||
|
||||
```
|
||||
isNaN(NaN);// true
|
||||
isNaN(“blue”); // true
|
||||
isNaN(123); // false
|
||||
|
||||
```
|
||||
|
||||
|
||||
### undefined和null
|
||||
|
||||
|
||||
null和undefined有最大的相似性。看看null == undefined的结果(true)也就更加能说明这点。
|
||||
|
||||
但是null ===undefined的结果(false)。不过相似归相似,还是有区别的,就是和数字运算时,10 + null结果为:10;10 + undefined结果为:NaN。
|
||||
|
||||
|
||||
- 任何数据类型和undefined运算都是NaN;
|
||||
|
||||
- 任何值和null运算,null可看做0运算。
|
||||
|
||||
|
||||
|
||||
|
||||
### 字符串型:string
|
||||
|
||||
现有如下代码:
|
||||
|
||||
```javascript
|
||||
var a = "abcde";
|
||||
var b = "传智播客";
|
||||
var c = "123123";
|
||||
var d = "哈哈哈哈哈";
|
||||
var e = ""; //空字符串
|
||||
|
||||
console.log(typeof a);
|
||||
console.log(typeof b);
|
||||
console.log(typeof c);
|
||||
console.log(typeof d);
|
||||
console.log(typeof e);
|
||||
```
|
||||
|
||||
控制台输出如下:
|
||||
|
||||
```
|
||||
sting
|
||||
sting
|
||||
sting
|
||||
sting
|
||||
sting
|
||||
```
|
||||
|
||||
### 连字符和加号的区别
|
||||
|
||||
键盘上的`+`可能是连字符,也可能是数字的加号。如下:
|
||||
|
||||
```
|
||||
console.log("我" + "爱" + "你"); //连字符,把三个独立的汉字,连接在一起了
|
||||
console.log("我+爱+你"); //原样输出
|
||||
console.log(1+2+3); //输出6
|
||||
```
|
||||
|
||||
输出:
|
||||
|
||||
```
|
||||
我爱你
|
||||
我+爱+你
|
||||
6
|
||||
```
|
||||
|
||||
**总结**:如果加号两边**都是**数值,此时是加。否则,就是连字符(用来连接字符串)。
|
||||
|
||||
举例1:
|
||||
|
||||
```javascript
|
||||
var a = "1";
|
||||
var b = 2;
|
||||
console.log(a + b);
|
||||
```
|
||||
|
||||
控制台输出:
|
||||
|
||||
```
|
||||
12
|
||||
```
|
||||
|
||||
举例2:
|
||||
|
||||
```
|
||||
var a = 1;
|
||||
var b = 2;
|
||||
console.log("a" + b); //"a"就不是变量了!所以就是"a"+2 输出a2
|
||||
|
||||
```
|
||||
|
||||
控制台输出:
|
||||
|
||||
```
|
||||
a2
|
||||
```
|
||||
|
||||
于是我们明白了,在变量中加入字符串进行连接,可以被同化为字符串。
|
||||
|
||||
|
||||
## 变量值的传递(赋值)
|
||||
|
||||
语句:
|
||||
|
||||
```
|
||||
a = b;
|
||||
```
|
||||
|
||||
把b的值赋给a,b不变。
|
||||
|
||||
将等号右边的值,赋给左边的变量;等号右边的变量,值不变。
|
||||
|
||||
来做几个题目。
|
||||
|
||||
举例1:
|
||||
|
||||
```
|
||||
//a b c
|
||||
var a = 1; //1
|
||||
var b = 2; //1 2
|
||||
var c = 3; //1 2 3
|
||||
a = b + c; //5 2 3
|
||||
b = c - a; //5 -2 3
|
||||
c = a * b; //5 -2 -10
|
||||
console.log(a);
|
||||
console.log(b);
|
||||
console.log(c);
|
||||
```
|
||||
|
||||
输出:
|
||||
|
||||
```
|
||||
5
|
||||
-2
|
||||
-10
|
||||
```
|
||||
|
||||
举例2:
|
||||
|
||||
```
|
||||
//a b c
|
||||
var a = 1;
|
||||
var b = 2;
|
||||
var c = 3; //1 2 3
|
||||
a = a + b; //3 2 3
|
||||
b = b + a; //3 5 3
|
||||
c = c + b; //3 5 8
|
||||
console.log(a); //3
|
||||
console.log(b); //5
|
||||
console.log(c); //8
|
||||
```
|
||||
|
||||
输出:
|
||||
|
||||
```
|
||||
3
|
||||
5
|
||||
8
|
||||
```
|
||||
|
||||
举例3:
|
||||
|
||||
```
|
||||
//a b
|
||||
var a = "1";
|
||||
var b = 2; //"1" 2
|
||||
a = a + b; //"12" 2
|
||||
b = b + a; //"12" "212"
|
||||
console.log(a); //输出12
|
||||
console.log(b); //输出212
|
||||
```
|
||||
|
||||
输出:
|
||||
|
||||
```
|
||||
12
|
||||
212
|
||||
```
|
||||
|
||||
举例4:
|
||||
|
||||
```
|
||||
//a b
|
||||
var a = "1";
|
||||
var b = 2;
|
||||
a = b + a; //"21" 2
|
||||
b = b + a; //"21" "221"
|
||||
console.log(a); //21
|
||||
console.log(b) //221
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
效果:
|
||||
|
||||
```
|
||||
21
|
||||
221
|
||||
|
||||
```
|
||||
|
||||
举例5:(这个例子比较特殊,字符串减去数字)
|
||||
|
||||
```
|
||||
var a = "3";
|
||||
var b = 2;
|
||||
console.log(a-b);
|
||||
```
|
||||
|
||||
|
||||
效果:(注意,字符串 - 数值 = 数值)
|
||||
|
||||
```
|
||||
1
|
||||
```
|
||||
|
||||
|
||||
## 数据类型转换
|
||||
|
||||
### 用户的输入
|
||||
|
||||
我们在上面的内容里讲过,`prompt()`就是专门用来弹出能够让用户输入的对话框。重要的是:用户不管输入什么,都是字符串。
|
||||
|
||||
### `parseInt()`:字符串转数字
|
||||
|
||||
**parseInt()可以将字符串转数字**。parse表示“转换”,Int表示“整数”(注意`Int`的拼写)。例如:
|
||||
|
||||
字符串转数字的方法:
|
||||
|
||||
```
|
||||
parseInt(“5”);
|
||||
```
|
||||
|
||||
得到的结果是数字5。
|
||||
|
||||
**parseInt()还具有以下特性**:
|
||||
|
||||
(1)带有自动净化的功能;**只保留字符串最开头的数字**,后面的中文自动消失。例如:
|
||||
|
||||
```
|
||||
console.log(parseInt("2017年在公众号上写了6篇文章");
|
||||
```
|
||||
|
||||
控制台输出:
|
||||
|
||||
```
|
||||
2017
|
||||
```
|
||||
|
||||
(2)自动带有截断小数的功能:**取整,不四舍五入**。
|
||||
|
||||
例1:
|
||||
|
||||
|
||||
```
|
||||
var a = parseInt(5.8) + parseInt(4.7);
|
||||
console.log(a);
|
||||
```
|
||||
|
||||
控制台输出:
|
||||
|
||||
```
|
||||
9
|
||||
```
|
||||
|
||||
例2:
|
||||
|
||||
```
|
||||
var a = parseInt(5.8 + 4.7);
|
||||
console.log(a);
|
||||
```
|
||||
|
||||
控制台输出:
|
||||
|
||||
```
|
||||
10
|
||||
```
|
||||
|
||||
(3)带两个参数时,表示进制转换。
|
||||
|
||||
|
||||
### 字符串转为浮点数(小数):`parseFloat()`:
|
||||
|
||||
道理同上。
|
||||
|
||||
|
||||
### 隐式转换
|
||||
|
||||
我们知道,`"2"+1`得到的结果其实是字符串,但是`"2"-1`得到的结果却是数值1,这是因为计算机自动帮我们进行了“**隐式转换**”。
|
||||
|
||||
|
||||
也就是说,`-`、`*`、`/`、`%``这几个符号会自动进行隐式转换。例如:
|
||||
|
||||
```javascript
|
||||
var a = "4" + 3 - 6;
|
||||
console.log(a);
|
||||
```
|
||||
|
||||
输出结果:
|
||||
|
||||
```
|
||||
37
|
||||
```
|
||||
|
||||
虽然程序可以对`-`、`*`、`/`、`%``这几个符号自动进行“隐式转换”;但作为程序员,我们最好自己完成转换,方便程序的可读性。
|
||||
|
||||
|
||||
### 4.1 任何简单类型转换成String
|
||||
|
||||
(1)方法1:变量+“” 或者 变量+“abc”
|
||||
|
||||
(2)方法2:
|
||||
|
||||
```
|
||||
String(变量)
|
||||
```
|
||||
|
||||
(3)方法三:
|
||||
|
||||
```
|
||||
变量.toSting()
|
||||
```
|
||||
|
||||
注意:undefined和null无toString方法,所以它们不能用方法三。
|
||||
|
||||
Null和undefined无toString方法。
|
||||
|
||||
|
||||
|
||||
## 我的公众号
|
||||
|
||||
想学习<font color=#0000ff>**代码之外的软技能**</font>?不妨关注我的微信公众号:**生命团队**(id:`vitateam`)。
|
||||
|
||||
扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外:
|
||||
|
||||

|
||||
|
||||
@@ -1,228 +0,0 @@
|
||||
|
||||
> 本文首发于[博客园](https://www.cnblogs.com/smyhvae/p/8306146.html),并在[GitHub](https://github.com/smyhvae/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。
|
||||
|
||||
> 以下是正文。
|
||||
|
||||
我们在[上一篇文章](http://www.cnblogs.com/smyhvae/p/8303507.html)里讲到了JS中**变量**的概念,本篇文章讲一下**运算符**和表达式。
|
||||
|
||||
|
||||
比如说`+`、`*`、`/`、`(` 都是**运算符**,而`(3+5)/2`则是**表达式**。
|
||||
|
||||
运算符有很多分类:数学运算符、逻辑运算符、自增运算符、赋值运算等。
|
||||
|
||||
## 数学运算符
|
||||
|
||||
常见的数学运算符有以下几种:
|
||||
|
||||

|
||||
|
||||
|
||||
**求余的举例**:
|
||||
|
||||
假设用户输入345,怎么分别得到3、4、5这三个数呢?
|
||||
|
||||
**答案**:
|
||||
|
||||
```
|
||||
得到3的方法:345 除以100,得到3.45然后取整,得到3。即:parseInt(345/100)
|
||||
|
||||
得到4的方法:345 除以100,余数是45,除以10,得到4.5,取整。即:parseInt(345 % 100 / 10)
|
||||
|
||||
得到5的方法:345 除以10,余数就是5。即:345 % 10
|
||||
```
|
||||
|
||||
### 数学运算符的运算规则
|
||||
|
||||
(1)先算乘除、后算加减。
|
||||
|
||||
(2)小括号:能够影响计算顺序,且可以嵌套。没有中括号、没有大括号,只有小括号。
|
||||
|
||||
(3)百分号:取余。只关心余数。
|
||||
|
||||
举例1:(取余)
|
||||
|
||||
```
|
||||
console.log(3 % 5);
|
||||
```
|
||||
|
||||
输出结果为3。
|
||||
|
||||
举例2:(运算符优先级)
|
||||
|
||||
```
|
||||
var a = 1 + 2 * 3 % 4 / 3;
|
||||
```
|
||||
|
||||
结果分析:
|
||||
|
||||
原式 = 1 + 6 % 4 / 3 = 1 + 2 / 3 = 1.66666666666666
|
||||
|
||||
### 乘方
|
||||
|
||||
如果想计算 `a 的 b 次方`,可以使用如下函数:
|
||||
|
||||
```
|
||||
Math.pow(a, b);
|
||||
```
|
||||
|
||||
Math的中文是“数学”,pow是“power 幂”。
|
||||
|
||||
**举例1:**
|
||||
|
||||

|
||||
|
||||
代码实现:
|
||||
|
||||
```
|
||||
var a = Math.pow(3, Math.pow(2, 2));
|
||||
console.log(a);
|
||||
```
|
||||
|
||||
**举例2:**
|
||||
|
||||

|
||||
|
||||
代码实现:
|
||||
|
||||
```
|
||||
var a = Math.pow(Math.pow(3, 2), 4);
|
||||
console.log(a);
|
||||
```
|
||||
|
||||
### 开方
|
||||
|
||||
如果想计算数值a的开二次方,可以使用如下函数:
|
||||
|
||||
```
|
||||
Math.sqrt(a);
|
||||
```
|
||||
|
||||
sqrt即“square 开方”。比如:
|
||||
|
||||
```
|
||||
var a = Math.sqrt(36);
|
||||
```
|
||||
|
||||
## 布尔值、关系运算符、逻辑运算符
|
||||
|
||||
### 布尔值
|
||||
|
||||
我们在上一篇文章中学习到的变量类型中包括:数值型、字符串型。今天再来学习一个类型:**布尔类型**。
|
||||
|
||||
布尔类型的值,就两个:true、false。
|
||||
|
||||
布尔值直接使用就可以了,千万不要加上引号。
|
||||
|
||||
代码:
|
||||
|
||||
```javascript
|
||||
var a = true;
|
||||
console.log(typeof a);
|
||||
```
|
||||
|
||||
控制台输出结果:
|
||||
|
||||
```
|
||||
boolean
|
||||
```
|
||||
|
||||
### 关系运算符
|
||||
|
||||
关系运算符有很多种,比如:
|
||||
|
||||
```
|
||||
> 大于号
|
||||
< 小于号
|
||||
>= 大于或等于
|
||||
<= 小于或等于
|
||||
== 等于
|
||||
=== 全等于
|
||||
!= 不等于
|
||||
!== 不全等于
|
||||
```
|
||||
|
||||
关系运算符,得到的结果都是布尔值:要么是true,要么是false。
|
||||
|
||||
**`==`符号的强调**:
|
||||
|
||||
注意`==`这个符号,它是**判断是否等于**,而不是赋值。
|
||||
|
||||
(1)`== `这个符号,还可以验证字符串是否相同。例如:
|
||||
|
||||
```
|
||||
console.log("我爱你中国" == "我爱你中国"); //输出结果为true
|
||||
```
|
||||
|
||||
(3)`== `这个符号并不严谨,会将不同类型的东西,转为相同类型进行比较。例如:
|
||||
|
||||
```
|
||||
console.log("6" == 6); //true
|
||||
```
|
||||
|
||||
如果要保证**完全等于**,我们就要用三个等号`===`。例如:
|
||||
|
||||
|
||||
```
|
||||
console.log("6" === 6); //false
|
||||
console.log(6 === 6); //true
|
||||
```
|
||||
|
||||
上述内容分析出:
|
||||
|
||||
- `==`两个等号,不严谨,"6"和6是true。
|
||||
|
||||
- `===`三个等号,严谨,"6"和6是false。
|
||||
|
||||
另外还有:**`==`的反面是`!=`,`===`的反面是`!==`。**。例如:
|
||||
|
||||
```
|
||||
console.log(3 != 8); //true
|
||||
console.log(3 != "3"); //false,因为3=="3"是true,所以反过来就是false。
|
||||
console.log(3 !== "3"); //true,应为3==="3"是false,所以反过来是true。
|
||||
```
|
||||
|
||||
### 逻辑运算符
|
||||
|
||||
逻辑运算符有三个:
|
||||
|
||||
- && 与(且):两个都为真,结果才为真
|
||||
|
||||
- || 或
|
||||
|
||||
- ! 非:只要有一个是真,结果就是真
|
||||
|
||||
能参与逻辑运算的,都是布尔值,得到的答案仍然是布尔值。
|
||||
|
||||
**连比的写法:**
|
||||
|
||||
来看看逻辑运算符连比的写法。
|
||||
|
||||
举例1:
|
||||
|
||||
```
|
||||
console.log(3 < 2 && 2 < 4);
|
||||
```
|
||||
|
||||
输出结果为false。
|
||||
|
||||
举例2:(判断一个人的年龄是否在18~60岁之间)
|
||||
|
||||
```
|
||||
var a = prompt("请输入您的年龄");
|
||||
alert(a>=18 && a<= 65);
|
||||
```
|
||||
|
||||
## 数据类型转换
|
||||
|
||||
暂略。
|
||||
|
||||
## 我的公众号
|
||||
|
||||
想学习<font color=#0000ff>**代码之外的软技能**</font>?不妨关注我的微信公众号:**生命团队**(id:`vitateam`)。
|
||||
|
||||
扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
@@ -1,382 +0,0 @@
|
||||
|
||||
|
||||
> 本文首发于[博客园](http://www.cnblogs.com/smyhvae/p/8310295.html),并在[GitHub](https://github.com/smyhvae/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。
|
||||
|
||||
> 以下是正文。
|
||||
|
||||
## if语句
|
||||
|
||||
### 最基本的if语句
|
||||
|
||||
if语句的结构体:(格式)
|
||||
|
||||
```javascript
|
||||
if (条件表达式) {
|
||||
// 条件为真时,做的事情
|
||||
|
||||
} else {
|
||||
// 条件为假时,做的事情
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
if语句也成为“选择语句”、“条件判断语句”。
|
||||
|
||||
### 多分支的if语句
|
||||
|
||||
格式:
|
||||
|
||||
```javascript
|
||||
if (条件表达式1) {
|
||||
// 条件1为真时,做的事情
|
||||
|
||||
} else if (条件表达式2) {
|
||||
// 条件1不满足,条件2满足时,做的事情
|
||||
|
||||
} else if (条件表达式3) {
|
||||
// 条件1、2不满足,条件3满足时,做的事情
|
||||
|
||||
} else {
|
||||
// 条件1、2、3都不满足时,做的事情
|
||||
}
|
||||
```
|
||||
|
||||
以上所有的语句体中,只执行其中一个。
|
||||
|
||||
做个题目:
|
||||
|
||||
```
|
||||
根据BMI(身体质量指数)显示一个人的体型。
|
||||
BMI指数,就是体重、身高的一个计算公式。公式是:
|
||||
BMI =体重÷身高的平方
|
||||
|
||||
比如,老师的体重是81.6公斤,身高是1.71米。
|
||||
那么老师的BMI就是 81.6 ÷ 1.712 等于 27.906022365856163
|
||||
|
||||
过轻:低于18.5
|
||||
正常:18.5-24.99999999
|
||||
过重:25-27.9999999
|
||||
肥胖:28-32
|
||||
非常肥胖, 高于32
|
||||
|
||||
用JavaScript开发一个程序,让用户先输入自己的体重,然后输入自己的身高(弹出两次prompt框)。
|
||||
计算它的BMI,根据上表,弹出用户的身体情况。比如“过轻” 、 “正常” 、“过重” 、 “肥胖” 、“非常肥胖”。
|
||||
```
|
||||
|
||||
答案:
|
||||
|
||||
写法1:
|
||||
|
||||
```javascript
|
||||
//第一步,输入身高和体重
|
||||
var height = parseFloat(prompt("请输入身高,单位是米"));
|
||||
var weight = parseFloat(prompt("请输入体重,单位是公斤"));
|
||||
//第二步,计算BMI指数
|
||||
var BMI = weight / Math.pow(height, 2);
|
||||
//第三步,if语句来判断。注意跳楼现象
|
||||
if (BMI < 18.5) {
|
||||
alert("偏瘦");
|
||||
} else if (BMI < 25) {
|
||||
alert("正常");
|
||||
} else if (BMI < 28) {
|
||||
alert("过重");
|
||||
} else if (BMI <= 32) {
|
||||
alert("肥胖");
|
||||
} else {
|
||||
alert("非常肥胖");
|
||||
}
|
||||
```
|
||||
|
||||
写法2:
|
||||
|
||||
```javascript
|
||||
//第一步,输入身高和体重
|
||||
var height = parseFloat(prompt("请输入身高,单位是米"));
|
||||
var weight = parseFloat(prompt("请输入体重,单位是公斤"));
|
||||
//第二步,计算BMI指数
|
||||
var BMI = weight / Math.pow(height, 2);
|
||||
//第三步,if语句来判断。注意跳楼现象
|
||||
if (BMI > 32) {
|
||||
alert("非常肥胖");
|
||||
} else if (BMI >= 28) {
|
||||
alert("肥胖");
|
||||
} else if (BMI >= 25) {
|
||||
alert("过重");
|
||||
} else if (BMI >= 18.5) {
|
||||
alert("正常")
|
||||
} else {
|
||||
alert("偏瘦");
|
||||
}
|
||||
```
|
||||
|
||||
### if语句的嵌套
|
||||
|
||||
我们通过下面这个例子来引出if语句的嵌套。
|
||||
|
||||
```
|
||||
一个加油站为了鼓励车主多加油,所以加的多有优惠。
|
||||
92号汽油,每升6元;如果大于等于20升,那么每升5.9;
|
||||
97号汽油,每升7元;如果大于等于30升,那么每升6.95
|
||||
编写JS程序,用户输入自己的汽油编号,然后输入自己加多少升,弹出价格。
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
代码实现如下:
|
||||
|
||||
```javascript
|
||||
//第一步,输入
|
||||
var bianhao = parseInt(prompt("您想加什么油?填写92或者97"));
|
||||
var sheng = parseFloat(prompt("您想加多少升?"));
|
||||
|
||||
//第二步,判断
|
||||
if (bianhao == 92) {
|
||||
//编号是92的时候做的事情
|
||||
if (sheng >= 20) {
|
||||
var price = sheng * 5.9;
|
||||
} else {
|
||||
var price = sheng * 6;
|
||||
}
|
||||
} else if (bianhao == 97) {
|
||||
//编号是97的时候做的事情
|
||||
if (sheng >= 30) {
|
||||
var price = sheng * 6.95;
|
||||
} else {
|
||||
var price = sheng * 7;
|
||||
}
|
||||
} else {
|
||||
alert("对不起,没有这个编号的汽油!");
|
||||
}
|
||||
|
||||
alert("价格是" + price);
|
||||
```
|
||||
|
||||
### if语句的几个小知识点
|
||||
|
||||
(1)else部分可以省略。例如:
|
||||
|
||||
```javascript
|
||||
var a = 10;
|
||||
if(a > 20){
|
||||
alert("这个数字大于20");
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
没有else部分,则代表没有“否则”。如果条件表达式不满足了,那么就什么都不做。
|
||||
|
||||
(1)如果要做的事情只有一句话,那么大括号就可以省略。例如:
|
||||
|
||||
```javascript
|
||||
var a = 2;
|
||||
if(a > 5) alert("这个数字大于5");
|
||||
alert("哈哈");
|
||||
|
||||
```
|
||||
|
||||
弹出的内容是“哈哈”。
|
||||
|
||||
## for循环
|
||||
|
||||
### for循环的结构
|
||||
|
||||
for循环举例:
|
||||
|
||||
```javascript
|
||||
for (var i = 1; i <= 100; i++) {
|
||||
console.log(i);
|
||||
}
|
||||
```
|
||||
|
||||
上方代码的解释:
|
||||
|
||||

|
||||
|
||||
|
||||
### for循环遍历
|
||||
|
||||
|
||||
```javascript
|
||||
for (var i = 1; i < 13; i = i + 4) {
|
||||
console.log(i);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
上方代码的遍历步骤:
|
||||
|
||||
```
|
||||
程序一运行,将执行var i = 1;这条语句, 所以i的值是1。
|
||||
然后程序会验证一下i < 13是否满足,1<13是真,所以执行一次循环体(就是大括号里面的语句)。
|
||||
执行完循环体之后,会执行i=i+4这条语句,所以i的值,是5。
|
||||
|
||||
程序会会验证一下i < 13是否满足,5<13是真,所以执行一次循环体(就是大括号里面的语句)。
|
||||
执行完循环体之后,会执行i=i+4这条语句,所以i的值,是9。
|
||||
|
||||
程序会会验证一下i < 13是否满足,9<13是真,所以执行一次循环体(就是大括号里面的语句)。
|
||||
执行完循环体之后,会执行i=i+4这条语句,所以i的值,是13。
|
||||
|
||||
程序会会验证一下i < 13是否满足,13<13是假,所以不执行循环体了,将退出循环。
|
||||
|
||||
最终输出输出结果为:1、5、9
|
||||
```
|
||||
|
||||
接下来做几个题目。
|
||||
|
||||
题目1:
|
||||
|
||||
```javascript
|
||||
for (var i = 1; i < 10; i = i + 3) {
|
||||
i = i + 1;
|
||||
console.log(i);
|
||||
}
|
||||
```
|
||||
|
||||
输出结果:2、6、10
|
||||
|
||||
题目2:
|
||||
|
||||
```javascript
|
||||
for (var i = 1; i <= 10; i++) {
|
||||
|
||||
}
|
||||
console.log(i);
|
||||
```
|
||||
|
||||
输出结果:11
|
||||
|
||||
题目3:
|
||||
|
||||
```javascript
|
||||
for(var i = 1; i < 7; i = i + 3){
|
||||
|
||||
}
|
||||
console.log(i);
|
||||
```
|
||||
|
||||
输出结果:7
|
||||
|
||||
题目4:
|
||||
|
||||
```javascript
|
||||
for (var i = 1; i > 0; i++) {
|
||||
console.log(i);
|
||||
}
|
||||
```
|
||||
|
||||
死循环。
|
||||
|
||||
## 算法题练习
|
||||
|
||||
暂略。
|
||||
|
||||
## 函数
|
||||
|
||||
函数:就是将一些语句进行**封装**,然后通过**调用**的形式,执行这些语句。
|
||||
|
||||
**函数的作用:**
|
||||
|
||||
- 将大量重复的语句写在函数里,以后需要这些语句的时候,可以直接调用函数,避免重复劳动。
|
||||
|
||||
- 简化编程,让编程模块化。
|
||||
|
||||
先来看个例子:
|
||||
|
||||
```javascript
|
||||
console.log("你好");
|
||||
sayHello(); //调用函数
|
||||
//定义函数:
|
||||
function sayHello(){
|
||||
console.log("欢迎");
|
||||
console.log("welcome");
|
||||
}
|
||||
```
|
||||
|
||||
### 第一步:函数的定义
|
||||
|
||||
函数定义的语法:
|
||||
|
||||
```javascript
|
||||
function sum(a, b){
|
||||
return a+b;
|
||||
}
|
||||
```
|
||||
|
||||
解释如下:
|
||||
|
||||
- function:是一个关键字。中文是“函数”、“功能”。
|
||||
|
||||
- 函数名字:命名规定和变量的命名规定一样。只能是字母、数字、下划线、美元符号,不能以数字开头。
|
||||
|
||||
- 参数:后面有一对小括号,里面是放参数用的。
|
||||
|
||||
- 大括号里面,是这个函数的语句。
|
||||
|
||||
PS:方法写完之后,我们在方法的前面输入`/**`,然后回车,会发现,注释的格式会自动补齐。
|
||||
|
||||
|
||||
### 第二步:函数的调用
|
||||
|
||||
函数调用的语法:
|
||||
|
||||
```javascript
|
||||
函数名字();
|
||||
```
|
||||
|
||||
### 函数的参数:形参和实参
|
||||
|
||||
函数的参数包括形参和实参。来看下面的图就懂了:
|
||||
|
||||
|
||||

|
||||
|
||||
注意:实际参数和形式参数的个数,要相同。
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
sum(3,4);
|
||||
sum("3",4);
|
||||
sum("Hello","World");
|
||||
|
||||
//函数:求和
|
||||
function sum(a, b) {
|
||||
console.log(a + b);
|
||||
}
|
||||
```
|
||||
|
||||
控制台输出结果:
|
||||
|
||||
```
|
||||
7
|
||||
34
|
||||
helloworld
|
||||
```
|
||||
|
||||
### 函数的返回值
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
console.log(sum(3, 4));
|
||||
|
||||
//函数:求和
|
||||
function sum(a, b) {
|
||||
return a + b;
|
||||
}
|
||||
```
|
||||
|
||||
return的作用是结束方法。
|
||||
|
||||
## 我的公众号
|
||||
|
||||
想学习<font color=#0000ff>**代码之外的软技能**</font>?不妨关注我的微信公众号:**生命团队**(id:`vitateam`)。
|
||||
|
||||
扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,613 +0,0 @@
|
||||
|
||||
|
||||
> 本文最初发表于[博客园](https://www.cnblogs.com/smyhvae/p/8359654.html),并在[GitHub](https://github.com/smyhvae/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。
|
||||
|
||||
> 以下是正文。
|
||||
|
||||
|
||||
## 数组的定义
|
||||
|
||||
之前学习的数据类型,只能存储一个值(字符串为一个值)。如果我们想存储多个值,就可以使用数组。
|
||||
|
||||
### 数组的定义
|
||||
|
||||
(1)字面量定义。举例:
|
||||
|
||||
```
|
||||
var arr = [1,2,3];
|
||||
```
|
||||
|
||||
(2)对象定义(数组的构造函数)。格式:
|
||||
|
||||
```
|
||||
var arr = new Array(参数);
|
||||
```
|
||||
|
||||
参数位置是一个数值时,表示数组长度;多个数值时,表示数组中的元素。
|
||||
|
||||
### 数组的操作
|
||||
|
||||
1、求数组的长度:
|
||||
|
||||
```
|
||||
数组的长度 = 数组名.length;
|
||||
```
|
||||
|
||||
可以通过修改数组的长度来改变数组中元素的个数,如果改小了,数组将从后面删除元素。(伪数组arguments的长度可以修改,但是不能修改里面的元素,后面单独讲)
|
||||
|
||||
2、获取数组中的元素:
|
||||
|
||||
```
|
||||
数组中的指定元素 = 数组名[索引值];
|
||||
```
|
||||
|
||||
数组的索引代表的是数组中的元素在数组中的位置,从0开始。
|
||||
|
||||
如果索引值有误(比如元素没那么多),系统不报错,而是会给定值为undefined。
|
||||
|
||||
### 遍历数组(重要)
|
||||
|
||||
遍历数组即:获取并操作数组中的每一个元素。
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
var arr = ["生命壹号","许嵩","永不止步"];
|
||||
for(var i = 0;i<arr.length;i++){
|
||||
console.log(arr[i]); // arr[i]代表的是数组中的每一个元素i
|
||||
}
|
||||
|
||||
console.log(arr);
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||

|
||||
|
||||
## 数组Array的常用方法
|
||||
|
||||
Array数组是属于**内置对象**,我们可以在下面的网站上查询各种方法。
|
||||
|
||||
- MDN(开发者网站):<https://developer.mozilla.org/zh-CN/>
|
||||
|
||||
Array有各种api接口(Application Programming Interface,应用程序编程接口),下面分别介绍。
|
||||
|
||||
(1)判断是否为数组:instanceof
|
||||
|
||||
```javascript
|
||||
布尔类型值 = A instanceof B;
|
||||
```
|
||||
|
||||
解释:判断A是否为B类型(instanceof 是一个关键字)。
|
||||
|
||||
在数组里,这种方法已经用的不多了,因为有下面这种方法。
|
||||
|
||||
(2)判断是否为数组:isArray()
|
||||
|
||||
```javascript
|
||||
布尔类型值 = Array.isArray(被检测的值) ;
|
||||
```
|
||||
|
||||
PS:属于HTML5中新增的方法。
|
||||
|
||||
(3)转换数组:toString()
|
||||
|
||||
```javascript
|
||||
字符串 = 数组.toString();
|
||||
```
|
||||
|
||||
解释:把数组转换成字符串,每一项用`,`分割。
|
||||
|
||||
(4)返回数组本身:valueOf()
|
||||
|
||||
```javascript
|
||||
数组本身 = 数组.valueOf();
|
||||
```
|
||||
|
||||
这个方法的意义不大。因为我们指直接写数组对象的名字,就已经是数组本身了。
|
||||
|
||||
(5)将数组中的元素用符号连接成字符串:join()
|
||||
|
||||
```javascript
|
||||
字符串 = 数组.join(参数);
|
||||
```
|
||||
|
||||
参数决定用什么符号进行连接。如果不写参数,则和toString()的效果一致。
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
var arr = ["生命壹号","许嵩","棒棒哒"];
|
||||
|
||||
console.log(arr.join()); //无参数
|
||||
console.log(arr.join(" ")); //用空格进行连接
|
||||
console.log(arr.join("")); //用空字符串进行连接
|
||||
console.log(arr.join("&")); //用符号"&"进行连接
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||
```
|
||||
生命壹号,许嵩,棒棒哒
|
||||
|
||||
生命壹号 许嵩 棒棒哒
|
||||
|
||||
生命壹号许嵩棒棒哒
|
||||
|
||||
生命壹号&许嵩&棒棒哒
|
||||
```
|
||||
|
||||
join方法有一定的实际用途:当我们需要把一堆字符串进行连接时,我们可以把他们转换成数组,然后调用数组的join()方法。这样做有个好处是:内存不会溢出。
|
||||
|
||||
|
||||
## 伪数组:arguments
|
||||
|
||||
arguments代表的是实参。有个讲究的地方是:arguments**只在函数中使用**。
|
||||
|
||||
(1)返回函数**实参**的个数:arguments.length
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
fn(2,4);
|
||||
fn(2,4,6);
|
||||
fn(2,4,6,8);
|
||||
|
||||
function fn(a,b) {
|
||||
console.log(arguments);
|
||||
console.log(fn.length); //获取形参的个数
|
||||
console.log(arguments.length); //获取实参的个数
|
||||
|
||||
console.log("----------------");
|
||||
}
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||

|
||||
|
||||
(2)返回正在执行的函数:arguments.callee
|
||||
|
||||
在使用函数**递归**调用时,推荐使用arguments.callee代替函数名本身。
|
||||
|
||||
(3)之所以说arguments是伪数组,是因为:**arguments可以修改元素,但不能改变数组的长短**。举例:
|
||||
|
||||
```javascript
|
||||
fn(2,4);
|
||||
fn(2,4,6);
|
||||
fn(2,4,6,8);
|
||||
|
||||
function fn(a,b) {
|
||||
arguments[0] = 99; //将实参的第一个数改为99
|
||||
arguments.push(8); //此方法不通过,因为无法增加元素
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## 数组的添加和删除
|
||||
|
||||
(1)push():在数组**最后面**插入项,返回数组的长度
|
||||
|
||||
```javascript
|
||||
数组改后的长度 = 数组.push(元素);
|
||||
```
|
||||
|
||||
(2)pop():取出数组中的**最后一个**元素,返回被删除的元素
|
||||
|
||||
```javascript
|
||||
被删除的元素 = 数组.pop();
|
||||
```
|
||||
|
||||
(3)unshift():在数组**最前面**插入项,返回数组的长度
|
||||
|
||||
数组改后的长度 = 数组.unshift(元素);
|
||||
|
||||
(4)shift():取出数组中的**第一个**元素,返回被删除的元素
|
||||
|
||||
```javascript
|
||||
被删除的元素 = 数组.shift();
|
||||
```
|
||||
|
||||
## 数组的反转和排序
|
||||
|
||||
(1)reverse():翻转数组(返回值是反转后的数组,而且**原数组也已经被反转了**)
|
||||
|
||||
```
|
||||
反转后的数组 = 数组.reverse();
|
||||
```
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
var arr = ["a","b","c","d","e","f"];
|
||||
|
||||
console.log(arr); //反转前打印
|
||||
console.log(arr.reverse()); //反转
|
||||
console.log(arr); //反转后打印
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||

|
||||
|
||||
注意:反转后,打印原来的数组发现,原来的数组已经被反转了。
|
||||
|
||||
(2)sort():给数组排序,返回排序后的数组(排序的规则看参数)
|
||||
|
||||
```
|
||||
从小到大排序后的数组 = 数组.sort(function(a,b){
|
||||
return a-b;
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
- 无参:按照数组元素的**首字符对应的Unicode编码值**,从小到大排列数组元素。
|
||||
|
||||
- 带参:必须为函数(回调函数:callback)。这个回调函数中带有两个参数,代表数组中的前后元素。
|
||||
- 如果返回值(a-b)为负数,a排b前面。
|
||||
- 如果返回值(a-b)等于0,不动。
|
||||
- 如果返回值(a-b)为正数,a排b后面。
|
||||
|
||||
上面的这个带参的排序,其实是调用了底层的**冒泡排序**,小的排前面,大的排后面。
|
||||
|
||||
PS:sort方法的功能非常强大,能对数字和字母进行排列。
|
||||
|
||||
## 数组的一些其他方法
|
||||
|
||||
(1)concat() :把参数拼接到当前数组(原数组不会被修改)
|
||||
|
||||
```javascript
|
||||
新数组 = 数组1.concat(数组2);
|
||||
|
||||
```
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
var arr1 = [1,2,3];
|
||||
var arr2 = ["a","b","c","d","e","f"];
|
||||
|
||||
console.log(arr1.concat(arr2)); //把参数拼接到当前数组
|
||||
console.log(arr1);
|
||||
console.log(arr2);
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||

|
||||
|
||||
从打印结果中可以看到,原数组(数组1、数组2)并没有被修改。
|
||||
|
||||
(2)slice():从当前数组中截取一个新的数组(不影响原来的数组)
|
||||
|
||||
```javascript
|
||||
新数组 = 原数组.slice(开始位置index,结束位置index); //注意:索引值包括左边的,不包括右边的
|
||||
```
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
var arr = ["a","b","c","d","e","f"];
|
||||
|
||||
console.log(arr.slice(2)); //从第二个值开始截取
|
||||
console.log(arr.slice(2,4)); //截取从第二个到第四个之间的值(不包括第四个值)
|
||||
console.log(arr.slice(-2)); //截取最后两个值
|
||||
console.log(arr.slice(4,2)); //空
|
||||
|
||||
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||

|
||||
|
||||
(3)splice():删除当前数组的某些元素(原数组会被改变)
|
||||
|
||||
```javascript
|
||||
新数组 = 数组1.splice(起始索引index,需要操作的个数,弥补的值);
|
||||
```
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
var arr11 = ["a","b","c","d","e","f"];
|
||||
var arr12 = arr11.splice(1); //从第一个位置开始,删除元素
|
||||
console.log("原数组:"+arr11);
|
||||
console.log("新数组:"+arr12);
|
||||
console.log("-----------");
|
||||
|
||||
var arr21 = ["a","b","c","d","e","f"];
|
||||
var arr22 = arr21.splice(1,3); //从第一个元素开始删除,一共删除3个元素
|
||||
console.log(arr21);
|
||||
console.log(arr22);
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||

|
||||
|
||||
PS:第三个参数很少用,这里先不讲。
|
||||
|
||||
(3)获取数据的索引:indexOf()、lastIndexOf()
|
||||
|
||||
- indexOf():从前往后索引
|
||||
|
||||
- lastIndexOf() :从后往前索引
|
||||
|
||||
```javascript
|
||||
索引值 = 数组.indexOf/lastIndexOf(数组中的元素内容);
|
||||
```
|
||||
|
||||
PS:如果没找到返回-1。
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
var arr = ["a","b","c","d","e","d","c"];
|
||||
|
||||
console.log(arr.indexOf("c")); //从前往后,找"c"在哪个位置
|
||||
console.log(arr.lastIndexOf("d")); //从前往后,找"d"在哪个位置
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||

|
||||
|
||||
## 数组迭代方法
|
||||
|
||||
数组迭代方法包括:every()、filter()、forEach()、map()、some()
|
||||
|
||||
PS:这几个方法**不会修改原数组**。
|
||||
|
||||
语法格式:
|
||||
|
||||
```
|
||||
数组/boolean/无 = 数组.every/filter/forEach/map/some(
|
||||
function(element,index,arr){
|
||||
程序和返回值;
|
||||
```
|
||||
|
||||
有了这几种方法,就可以替代一些for循环了。下面依次来介绍。
|
||||
|
||||
### every()方法
|
||||
|
||||
解释:对数组中每一项运行回调函数,如果都返回true,every就返回true;如果有一项返回false,则停止遍历,此方法返回false。
|
||||
|
||||
注意:every()方法的返回值是boolean值,参数是回调函数。
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
var arr1 = ["千古", "宿敌", "南山忆", "素颜"];
|
||||
var bool1 = arr1.every(function (element, index, array) {
|
||||
if (element.length > 2) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
console.log(bool1); //输出结果:false。只要有一个元素的长度是超过两个字符的,就返回false
|
||||
|
||||
var arr2 = ["千古", "宿敌", "南山", "素颜"];
|
||||
var bool2 = arr2.every(function (element, index, array) {
|
||||
if (element.length > 2) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
console.log(bool2); //输出结果:true。因为每个元素的长度都是两个字符。
|
||||
```
|
||||
|
||||
### some()方法
|
||||
|
||||
解释:对数组中每一项运行回调函数,只要有一项返回true,则停止遍历,此方法返回true。
|
||||
|
||||
### filter()方法
|
||||
|
||||
解释:对数组中每一项运行回调函数,该函数返回结果是true的项,将组成新的数组(返回值就是这个新的数组)。
|
||||
|
||||
```javascript
|
||||
var arr1 = ["千古", "宿敌", "南山忆", "素颜"];
|
||||
|
||||
var arr2 = arr1.filter(function (element, index, array) {
|
||||
if (element.length > 2) { //arr1中的元素,如果是长度超过2个字符的,我就把它放到arr2中去
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
console.log(arr1);
|
||||
console.log(arr2);
|
||||
|
||||
```
|
||||
|
||||
结果:
|
||||
|
||||

|
||||
|
||||
### forEach()方法
|
||||
|
||||
解释:遍历数组。
|
||||
|
||||
注意:无返回值,纯粹操作数组中的元素,所以应用场景并不多。
|
||||
|
||||
### map()方法
|
||||
|
||||
解释:对数组中每一项运行回调函数,返回该函数的结果,组成的新数组(返回值就是这个新的数组)。
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
var arr1 = ["千古", "宿敌", "南山忆", "素颜"];
|
||||
|
||||
var arr2 = arr1.map(function (element, index, array) {
|
||||
return element + "vae"; //给arr1中所有的元素增加字符串"vae",放到arr2中。
|
||||
});
|
||||
|
||||
console.log(arr1);
|
||||
console.log(arr2);
|
||||
```
|
||||
|
||||
结果:
|
||||
|
||||

|
||||
|
||||
## 清空数组
|
||||
|
||||
清空数组,有以下几种方式:
|
||||
|
||||
```javascript
|
||||
var array = [1,2,3,4,5,6];
|
||||
|
||||
array.splice(0); //方式1:删除数组中所有项目
|
||||
array.length = 0; //方式1:length属性可以赋值,在其它语言中length是只读
|
||||
array = []; //方式3:推荐
|
||||
```
|
||||
|
||||
## 数组练习
|
||||
|
||||
### 练习1
|
||||
|
||||
**问题**:将一个字符串数组输出为`|`分割的形式,比如“千古|宿敌|素颜”。使用两种方式实现。
|
||||
|
||||
答案:
|
||||
|
||||
方式1:(不推荐)
|
||||
|
||||
```javascript
|
||||
var arr = ["千古","宿敌","素颜"];
|
||||
var str = arr[0];
|
||||
var separator = "|";
|
||||
for(var i = 1;i< arr.length;i++) {
|
||||
str += separator+arr[i]; //从第1个数组元素开始,每个元素前面加上符号"|"
|
||||
}
|
||||
|
||||
console.log(str);
|
||||
```
|
||||
|
||||
输出结果:
|
||||
|
||||

|
||||
|
||||
不推荐这种方式,因为:由于字符串的不变性,str拼接过多的话,容易导致内存溢出(很多个str都堆放在栈里)。
|
||||
|
||||
方式2:(推荐。通过array数组自带的api来实现)
|
||||
|
||||
```javascript
|
||||
var arr = ["千古","宿敌","素颜"];
|
||||
|
||||
console.log(arr.join("|"));
|
||||
```
|
||||
|
||||
结果:
|
||||
|
||||

|
||||
|
||||
### 练习2
|
||||
|
||||
题目:将一个字符串数组的元素的顺序进行反转,使用两种种方式实现。提示:第i个和第length-i-1个进行交换。
|
||||
|
||||
答案:
|
||||
|
||||
方式1:
|
||||
|
||||
```javascript
|
||||
function reverse(array) {
|
||||
var newArr = [];
|
||||
for (var i = array.length - 1; i >= 0; i--) {
|
||||
newArr[newArr.length] = array[i];
|
||||
}
|
||||
return newArr;
|
||||
}
|
||||
```
|
||||
|
||||
方式2:(算法里比较常见的方式)
|
||||
|
||||
```javascript
|
||||
function reverse(array){
|
||||
for(var i=0;i<array.length/2;i++){
|
||||
var temp = array[i];
|
||||
array[i] = array[array.length-1-i];
|
||||
array[array.length-1-i] = temp;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
```
|
||||
|
||||
方式3:(数组自带的reverse方法)
|
||||
|
||||
现在我们学习了数组自带的api,我们就可以直接使用reverse()方法。
|
||||
|
||||
### 练习3
|
||||
|
||||
问题:针对工资的数组[1500,1200,2000,2100,1800],把工资超过2000的删除。
|
||||
|
||||
答案:
|
||||
|
||||
```javascript
|
||||
var arr1 = [1500, 1200, 2000, 2100, 1800];
|
||||
|
||||
var arr2 = arr1.filter(function (ele, index, array) {
|
||||
if (ele < 2000) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
console.log(arr1);
|
||||
console.log(arr2);
|
||||
```
|
||||
|
||||
结果:
|
||||
|
||||

|
||||
|
||||
### 练习4
|
||||
|
||||
问题:找到数组["c","a","z","a","x","a"]中每一个元素出现的次数。
|
||||
|
||||
分析:这道题建议用json数据来做,因为我们想知道a出现了几次,c出现了几次,x出现了几次。恰好`k:v .. k:v`这种键值对的形式就比数组方便很多了。
|
||||
|
||||
键值对的形式:用key代表数组中的元素,用value代表元素出现的次数。
|
||||
|
||||
略难,答案暂略。
|
||||
|
||||
### 练习5
|
||||
|
||||
问题:编写一个方法去掉一个数组中的重复元素。
|
||||
|
||||
分析:创建一个新数组,循环遍历,只要新数组中有老数组的值,就不用再添加了。
|
||||
|
||||
答案:
|
||||
|
||||
```javascript
|
||||
// 编写一个方法 去掉一个数组的重复元素
|
||||
var arr = [1,2,3,4,5,2,3,4];
|
||||
console.log(arr);
|
||||
var aaa = fn(arr);
|
||||
console.log(aaa);
|
||||
//思路:创建一个新数组,循环遍历,只要新数组中有老数组的值,就不用再添加了。
|
||||
function fn(array){
|
||||
var newArr = [];
|
||||
for(var i=0;i<array.length;i++){
|
||||
//开闭原则
|
||||
var bool = true;
|
||||
//每次都要判断新数组中是否有旧数组中的值。
|
||||
for(var j=0;j<newArr.length;j++){
|
||||
if(array[i] === newArr[j]){
|
||||
bool = false;
|
||||
}
|
||||
}
|
||||
if(bool){
|
||||
newArr[newArr.length] = array[i];
|
||||
}
|
||||
}
|
||||
return newArr;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## 我的公众号
|
||||
|
||||
想学习<font color=#0000ff>**代码之外的软技能**</font>?不妨关注我的微信公众号:**生命团队**(id:`vitateam`)。
|
||||
|
||||
扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外:
|
||||
|
||||

|
||||
@@ -1,226 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
## 函数
|
||||
|
||||
函数:就是将一些语句进行**封装**,然后通过**调用**的形式,执行这些语句。
|
||||
|
||||
**函数的作用:**
|
||||
|
||||
- 将大量重复的语句写在函数里,以后需要这些语句的时候,可以直接调用函数,避免重复劳动。
|
||||
|
||||
- 简化编程,让编程模块化。
|
||||
|
||||
先来看个例子:
|
||||
|
||||
```javascript
|
||||
console.log("你好");
|
||||
sayHello(); //调用函数
|
||||
//定义函数:
|
||||
function sayHello(){
|
||||
console.log("欢迎");
|
||||
console.log("welcome");
|
||||
}
|
||||
```
|
||||
|
||||
**1、第一步:函数的定义**
|
||||
|
||||
函数定义的语法:
|
||||
|
||||
```javascript
|
||||
function sum(a, b){
|
||||
return a+b;
|
||||
}
|
||||
```
|
||||
|
||||
解释如下:
|
||||
|
||||
- function:是一个关键字。中文是“函数”、“功能”。
|
||||
|
||||
- 函数名字:命名规定和变量的命名规定一样。只能是字母、数字、下划线、美元符号,不能以数字开头。
|
||||
|
||||
- 参数:后面有一对小括号,里面是放参数用的。
|
||||
|
||||
- 大括号里面,是这个函数的语句。
|
||||
|
||||
PS:方法写完之后,我们在方法的前面输入`/**`,然后回车,会发现,注释的格式会自动补齐。
|
||||
|
||||
|
||||
**2、第二步:函数的调用**
|
||||
|
||||
函数调用的语法:
|
||||
|
||||
```javascript
|
||||
函数名字();
|
||||
```
|
||||
|
||||
### 函数的参数:形参和实参
|
||||
|
||||
函数的参数包括形参和实参。来看下面的图就懂了:
|
||||
|
||||
|
||||

|
||||
|
||||
注意:实际参数和形式参数的个数,要相同。
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
sum(3,4);
|
||||
sum("3",4);
|
||||
sum("Hello","World");
|
||||
|
||||
//函数:求和
|
||||
function sum(a, b) {
|
||||
console.log(a + b);
|
||||
}
|
||||
```
|
||||
|
||||
控制台输出结果:
|
||||
|
||||
```
|
||||
7
|
||||
34
|
||||
helloworld
|
||||
```
|
||||
|
||||
### 函数的返回值
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
console.log(sum(3, 4));
|
||||
//函数:求和
|
||||
function sum(a, b) {
|
||||
return a + b;
|
||||
}
|
||||
```
|
||||
|
||||
return的作用是结束方法。
|
||||
|
||||
注意:
|
||||
|
||||
1. 如果函数没有显示的使用 return语句 ,那么函数有默认的返回值:undefined
|
||||
|
||||
2. 如果函数使用 return语句,那么跟再return后面的值,就成了函数的返回值
|
||||
|
||||
3. 如果函数使用 return语句,但是return后面没有任何值,那么函数的返回值 也是:undefined
|
||||
|
||||
4. 函数使用return语句后,这个函数会在执行完 return 语句之后停止并立即退 出,也就是说return后面的所有其他代码都不会再执行。
|
||||
|
||||
### 1.6 函数名、函数体和函数加载问题(重要,请记住)
|
||||
|
||||
我们要记住:**函数名 == 整个函数**。举例:
|
||||
|
||||
```javascript
|
||||
console.log(fn) == console.log(function fn(){alert(1)});
|
||||
|
||||
//定义fn方法
|
||||
function fn(){
|
||||
alert(1)
|
||||
};
|
||||
```
|
||||
|
||||
我们知道,当我们在调用一个函数时,通常使用`函数()`这种格式;但此时,我们是直接使用`函数`这种格式,它的作用相当于整个函数。
|
||||
|
||||
**函数的加载问题**:JS加载的时候,只加载函数名,不加载函数体。所以如果想使用内部的成员变量,需要调用函数。
|
||||
|
||||
|
||||
### 回调函数
|
||||
|
||||
我们知道,当函数自己调用自己时,称之为递归。本段来讲一下回调。
|
||||
|
||||
回调:**函数作为参数**,进行传递和使用,称之为**回调**。
|
||||
|
||||
举个最简单的例子:
|
||||
|
||||
```javascript
|
||||
fn(test); //回调test这个函数
|
||||
|
||||
function test() {
|
||||
console.log("我是被回调的函数")
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
输出结果:我是被回调的函数。
|
||||
|
||||
|
||||
**什么情况下使用回调函数:**
|
||||
|
||||
回调函数一般是用于**定义一个规则**。因为我们无法通过传递一个变量来传递规则。
|
||||
|
||||
换而言之:当我们需要**传递规则的时候,必须使用回调**。规则的传递只能通过函数来实现,无法通过变量实现。
|
||||
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
console.log(fn(12,3,test1)); //注意第三个参数是函数名
|
||||
console.log(fn(12,3,test2)); //注意第三个参数是函数名
|
||||
|
||||
//定义一个通用规则(包含加减乘数的抽象函数)
|
||||
fn(num1,num2,demo) {
|
||||
return demo(num1,num2);
|
||||
}
|
||||
|
||||
//定义四个规则:加减乘除
|
||||
function test1(a,b) {
|
||||
return a+b;
|
||||
}
|
||||
function test2(a,b) {
|
||||
return a-b;
|
||||
}
|
||||
function test3(a,b) {
|
||||
return a*b;
|
||||
}
|
||||
function test4(a,b) {
|
||||
return a/b;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
打印结果:
|
||||
|
||||
```
|
||||
15
|
||||
9
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,962 +0,0 @@
|
||||
|
||||
|
||||
## 面向对象的概念
|
||||
|
||||
**对象的作用是:封装信息**。比如Student类里可以封装学生的姓名、年龄、成绩等。
|
||||
|
||||
那为什么不用数组封装信息呢?首先,数组只能存放同一种类型的数据;其次,要功过
|
||||
|
||||
对象具有**特征**(属性)和**行为**(方法)。
|
||||
|
||||
面向对象:可以创建自定义的类型、很好的支持继承和多态。
|
||||
|
||||
面向对象的特征:封装、继承、多态。
|
||||
|
||||
## 创建自定义对象
|
||||
|
||||
### 创建单个自定义对象
|
||||
|
||||
创建一个空白的对象,举例:
|
||||
|
||||
```
|
||||
var student= new Object();
|
||||
```
|
||||
|
||||
完整的举例如下:
|
||||
|
||||
```javascript
|
||||
//调用对象
|
||||
console.log(student); //调用对象的方法
|
||||
student.sayHi(); //调用对象的方法
|
||||
|
||||
|
||||
//(1)创建一个空白的对象
|
||||
var student= new Object();
|
||||
|
||||
// (2)定义对象的属性
|
||||
student.name = "生命壹号";
|
||||
student.age = 26;
|
||||
// (3)定义对象的方法
|
||||
student.sayHi = function () {
|
||||
console.log(this.name + "今年的岁数是" + this.age); //如果要调用自己的name,可以使用this
|
||||
}
|
||||
```
|
||||
|
||||
输出如下:
|
||||
|
||||
20180125_1059.png
|
||||
|
||||
### 引入:创建多个自定义对象
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
var stu1 = createStudent("生命壹号");
|
||||
console.log(stu1);
|
||||
stu1.sayHi();
|
||||
|
||||
console.log("------------------");
|
||||
|
||||
var stu2 = createStudent("许嵩");
|
||||
console.log(stu2);
|
||||
stu2.sayHi();
|
||||
|
||||
|
||||
// 创建一个函数
|
||||
function createStudent(name) {
|
||||
var student = new Object();
|
||||
student.name = name; //第一个name指的是student对象定义的变量。第二个name指的是createStudent函数的参数。二者不一样
|
||||
student.sayHi = function () {
|
||||
console.log(this.name + "厉害了");
|
||||
}
|
||||
return student;
|
||||
}
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||
20180125_1121.png
|
||||
|
||||
上方代码中,注意`student.name = name;`中这两个name是不同的。另外,注意this指的是student的this。
|
||||
|
||||
### new和this
|
||||
|
||||
**this:**
|
||||
|
||||
1、this只出现在函数中。
|
||||
|
||||
2、谁调用函数,this就指的是谁。
|
||||
|
||||
3、new People(); People中的this代指被创建的对象实例。
|
||||
|
||||
|
||||
**new之后:**
|
||||
|
||||
(1)开辟内存空间,存储新创建的对象。new Object()
|
||||
|
||||
(2)**把this设置为当前对象**
|
||||
|
||||
(3)执行内部代码,设置对象属性和方法
|
||||
|
||||
(4)返回新创建的对象
|
||||
|
||||
因为this指的是new一个Object之后的对象实例。于是,下面这段代码:
|
||||
|
||||
```javascript
|
||||
// 创建一个函数
|
||||
function createStudent(name) {
|
||||
var student = new Object();
|
||||
student.name = name; //第一个name指的是student对象定义的变量。第二个name指的是createStudent函数的参数。二者不一样
|
||||
}
|
||||
```
|
||||
|
||||
可以改进为:
|
||||
|
||||
```javascript
|
||||
// 创建一个函数
|
||||
function Student(name) {
|
||||
this.name = name; //this指的是构造函数中的对象实例
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
注意上方代码中的注释。
|
||||
|
||||
于是,便得出了接下来的代码。
|
||||
|
||||
**利用构造函数自定义对象:**(改进版)
|
||||
|
||||
```javascript
|
||||
//利用构造函数自定义对象
|
||||
var stu1 = new Student("smyh");
|
||||
console.log(stu1);
|
||||
stu1.sayHi();
|
||||
|
||||
var stu2 = new Student("vae");
|
||||
console.log(stu2);
|
||||
stu2.sayHi();
|
||||
|
||||
|
||||
// 创建一个构造函数
|
||||
function Student(name) {
|
||||
this.name = name; //this指的是构造函数中的对象实例
|
||||
this.sayHi = function () {
|
||||
console.log(this.name + "厉害了");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||
20180125_1350.png
|
||||
|
||||
|
||||
|
||||
### 属性绑定
|
||||
|
||||
暂略。
|
||||
|
||||
|
||||
### 对象字面量
|
||||
|
||||
|
||||
**对象的字面量**就是一个{}。里面的属性和方法均是**键值对**。
|
||||
|
||||
例如:
|
||||
|
||||
```javascript
|
||||
var o = {
|
||||
name: "生命壹号",
|
||||
age: 26,
|
||||
isBoy: true,
|
||||
sayHi: function() {
|
||||
console.log(this.name);
|
||||
}
|
||||
};
|
||||
|
||||
console.log(o);
|
||||
```
|
||||
|
||||
控制台输出:
|
||||
|
||||
20180125_1834.png
|
||||
|
||||
### json的介绍
|
||||
|
||||
> 对象字面量和json比较像,这里我们对json做一个简单介绍。
|
||||
|
||||
JSON:JavaScript Object Notation(JavaScript对象表示形式)。
|
||||
|
||||
JSON和对象字面量的区别:JSON的属性必须用双引号引号引起来,对象字面量可以省略。
|
||||
|
||||
json举例:
|
||||
|
||||
```
|
||||
{
|
||||
"name" : "zs",
|
||||
"age" : 18,
|
||||
"sex" : true,
|
||||
"sayHi" : function() {
|
||||
console.log(this.name);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
注:json里一般放常量、数组、对象等,但很少放function。
|
||||
|
||||
另外,对象和json没有长度,json.length的打印结果是undefined。于是乎,自然也就不能用for循环遍历(因为便利时需要获取长度length)。
|
||||
|
||||
**json遍历的方法:**
|
||||
|
||||
json 采用 `for...in...`进行遍历,和数组的遍历方式不同。如下:
|
||||
|
||||
|
||||
```html
|
||||
<script>
|
||||
var myJson = {
|
||||
"name": "smyhvae",
|
||||
"aaa": 111,
|
||||
"bbb": 222
|
||||
};
|
||||
|
||||
//json遍历的方法:for...in...
|
||||
for (var key in myJson) {
|
||||
console.log(key); //获取 键
|
||||
console.log(myJson[key]); //获取 值(第二种属性绑定和获取值的方法)
|
||||
console.log("------");
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||
20180203_1518.png
|
||||
|
||||
|
||||
## 类和对象
|
||||
|
||||
函数并没有创建对象的能力,类才有。
|
||||
|
||||
|
||||
```javascript
|
||||
class Customer {
|
||||
//属性
|
||||
public String Name;
|
||||
public String Age;
|
||||
public String Money;
|
||||
|
||||
//方法
|
||||
public void Buy (String id,int num,double price) {
|
||||
self.money -= num * price; //记录订单
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## 内置对象
|
||||
|
||||
内置对象就是指这个语言自带的一些对象,供开发者使用,这些对象提供了一些常用的或是最基本而必要的功能。
|
||||
|
||||
**javascript的内置对象**:
|
||||
|
||||
20180201_2330.jpg
|
||||
|
||||
|
||||
## 内置对象:Date
|
||||
|
||||
### Date对象的声明
|
||||
|
||||
写法一:
|
||||
|
||||
```javascript
|
||||
var date1 = new Date();
|
||||
console.log(date1);
|
||||
```
|
||||
|
||||
写法二:(兼容性最强)
|
||||
|
||||
```javascript
|
||||
var date2 = new Date("2017/09/06 09:00:00");
|
||||
console.log(date2);
|
||||
```
|
||||
|
||||
写法三和写法四:(不常用)
|
||||
|
||||
```javascript
|
||||
var date3 = new Date('Wed Jan 27 2017 12:00:00 GMT+0800 (中国标准时间)'); //写法三
|
||||
|
||||
var date4 = new Date(2017, 1, 27); //写法四
|
||||
```
|
||||
|
||||
以上四种写法的打印结果是:
|
||||
|
||||
20180202_1040.png
|
||||
|
||||
|
||||
### Date对象的方法:获取日期和时间
|
||||
|
||||
|
||||
Date对象 有如下方法:
|
||||
|
||||
- `getDate()` 获取日 1-31
|
||||
|
||||
- `getDay()` **获取星期 0-6**(0代表周日)
|
||||
|
||||
- `getMonth() ` **获取月 0-11**(1月从0开始)
|
||||
|
||||
- `getFullYear() ` 获取完整年份(浏览器都支持)
|
||||
|
||||
- `getHours() ` 获取小时 0-23
|
||||
|
||||
- `getMinutes() ` 获取分钟 0-59
|
||||
|
||||
- `getSeconds()` 获取秒 0-59
|
||||
|
||||
- `getMilliseconds()` 获取毫秒 (1s = 1000ms)
|
||||
|
||||
- `getTime ()` **返回累计毫秒数**(从1970/1/1午夜)
|
||||
|
||||
为何累计毫秒数是从1970/1/1开始算起呢?
|
||||
|
||||
打印结果举例:
|
||||
|
||||
20180202_1056.png
|
||||
|
||||
### 返回距离1970/01/01毫秒数
|
||||
|
||||
也就是返回:此刻时间 减去 1970/01/01 的毫秒数。
|
||||
|
||||
代码实现:
|
||||
|
||||
```javascript
|
||||
var date1 = Date.now();
|
||||
var date2 = +new Date();
|
||||
var date3 = new Date().getTime();
|
||||
var date4 = new Date().valueOf();
|
||||
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||
20180202_1100.png
|
||||
|
||||
|
||||
### 举例:模拟日历
|
||||
|
||||
要求每天打开这个页面都能定时显示当前的日期。
|
||||
|
||||
代码实现:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<title></title>
|
||||
<style>
|
||||
div {
|
||||
width: 800px;
|
||||
margin: 200px auto;
|
||||
color: red;
|
||||
text-align: center;
|
||||
font: 600 30px/30px "simsun";
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div></div>
|
||||
|
||||
<script>
|
||||
//模拟日历
|
||||
//需求:每天打开这个页面都能定时显示年月日和星期几
|
||||
|
||||
//1.创建一个当前日期的日期对象
|
||||
var date = new Date();
|
||||
//2.然后获取其中的年、月、日和星期
|
||||
var year = date.getFullYear();
|
||||
var month = date.getMonth();
|
||||
var hao = date.getDate();
|
||||
var week = date.getDay();
|
||||
// console.log(year+" "+month+" "+hao+" "+week);
|
||||
//3.赋值给div
|
||||
var arr = ["星期日","星期一","星期二","星期三","星期四","星期五","星期六"];
|
||||
var div = document.getElementsByTagName("div")[0];
|
||||
div.innerText = "今天是:"+year+"年"+(month+1)+"月"+hao+"日 "+arr[week];
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
```
|
||||
|
||||
实现效果:
|
||||
|
||||
20180202_1110.png
|
||||
|
||||
|
||||
### 举例:发布会倒计时
|
||||
|
||||
实现思路:
|
||||
|
||||
设置一个定时器,每间隔1毫秒就自动刷新一次div的内容。
|
||||
|
||||
代码实现:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<title></title>
|
||||
<style>
|
||||
div {
|
||||
width: 1210px;
|
||||
margin: 200px auto;
|
||||
color: red;
|
||||
text-align: center;
|
||||
font: 600 30px/30px "simsun";
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div></div>
|
||||
|
||||
<script>
|
||||
var div = document.getElementsByTagName("div")[0];
|
||||
var timer = setInterval(fn, 1);
|
||||
|
||||
function fn() {
|
||||
var nowtime = new Date();
|
||||
var future = new Date("2019/02/03 11:20:00");
|
||||
var timeSum = future.getTime() - nowtime.getTime(); //获取时间差:发布会时间减去此刻的毫秒值
|
||||
var day = parseInt(timeSum / 1000 / 60 / 60 / 24);
|
||||
var hour = parseInt(timeSum / 1000 / 60 / 60 % 24);
|
||||
var minu = parseInt(timeSum / 1000 / 60 % 60);
|
||||
var sec = parseInt(timeSum / 1000 % 60);
|
||||
var millsec = parseInt(timeSum % 1000);
|
||||
|
||||
//问题处理:所有的时间小于10的时候,在前面自动补0,毫秒值要补双0(比如如,把 8 秒改成 08 秒)
|
||||
day = day < 10 ? "0" + day : day; //day小于10吗?如果小于,就补0;如果不小于,就是day本身
|
||||
hour = hour < 10 ? "0" + hour : hour;
|
||||
minu = minu < 10 ? "0" + minu : minu;
|
||||
sec = sec < 10 ? "0" + sec : sec;
|
||||
if (millsec < 10) {
|
||||
millsec = "00" + millsec;
|
||||
} else if (millsec < 100) {
|
||||
millsec = "0" + millsec;
|
||||
}
|
||||
// console.log(day);
|
||||
// console.log(parseInt(timeSum/1000/60/60/24));
|
||||
if (timeSum < 0) {
|
||||
div.innerHTML = "距离苹果发布会还有00天00小时00分00秒000毫秒";
|
||||
clearInterval(timer);
|
||||
return;
|
||||
}
|
||||
div.innerHTML = "距离苹果发布会还有" + day + "天" + hour + "小时" + minu + "分" + sec + "秒" + millsec + "毫秒";
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
```
|
||||
|
||||
|
||||
实现效果:
|
||||
|
||||
20180202_1130.gif
|
||||
|
||||
|
||||
## 内置对象String
|
||||
|
||||
### 简单数据类型、复杂数据类型
|
||||
|
||||
**1、简单数据类型:**
|
||||
|
||||
注意,之前学习的简单数据类型`string`是**无法绑定属性和方法**的。比如说:
|
||||
|
||||
|
||||
```javascript
|
||||
var str = "smyhvae";
|
||||
|
||||
str.aaa = 12;
|
||||
console.log(typeof str); //打印结果为:string
|
||||
console.log(str.aaa); //打印结果为:undefined
|
||||
```
|
||||
|
||||
上方代码中,当我们尝试打印`str.aaa`的时候,会发现打印结果为:undefined。
|
||||
|
||||
当然,我们可以打印str.length、srt.indexOf("m")等等。因为这两个方法的底层做了数据类型转换。
|
||||
|
||||
|
||||
**2、复杂数据类型:**
|
||||
|
||||
复杂数据类型`String`是可以绑定属性和方法的。如下:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
```javascript
|
||||
var strObj = new String("smyhvae");
|
||||
strObj.aaa = 123;
|
||||
console.log(strObj);
|
||||
console.log(typeof strObj); //打印结果:Object
|
||||
console.log(strObj.aaa);
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||
20180202_1351.png
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
|
||||
同理,内置对象Number也有一些自带的方法,比如:
|
||||
|
||||
- Number.MAX_VALUE;
|
||||
|
||||
- Number.MIN_VALUE;
|
||||
|
||||
内置对象Boolean也有一些自带的方法,但是用的不多。
|
||||
|
||||
|
||||
下面讲一下内置对象String的常见方法。
|
||||
|
||||
|
||||
### charAt/charCodeAt:1.2.1 给索引查字符
|
||||
|
||||
|
||||
```javascript
|
||||
字符 = Str.charAt(索引值);
|
||||
```
|
||||
|
||||
解释:获取相应位置的字符。
|
||||
|
||||
字符串中第一个字符的下标是 0。如果参数 index 不在 0 与 string.length 之间,该方法将返回一个空字符串。
|
||||
|
||||
|
||||
|
||||
|
||||
```javascript
|
||||
字符编码 = Str.charCodeAt(索引值);
|
||||
```
|
||||
|
||||
解释: 获取相应位置的Unicode字符编码。
|
||||
|
||||
|
||||
举例1:
|
||||
|
||||
```javascript
|
||||
var str = new String("smyhvae");
|
||||
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
console.log(str.charAt(i));
|
||||
}
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||
20180202_1401.png
|
||||
|
||||
上面这个例子一般不用。一般打印数组和json的时候用索引,打印String不建议用索引。
|
||||
|
||||
举例2:打印字符串的占位长度
|
||||
|
||||
提示:一个英文占一个位置,一个中文占两个位置。
|
||||
|
||||
思路:判断该字符是否在0-127之间(在的话是英文,不在是非英文)。
|
||||
|
||||
代码实现:
|
||||
|
||||
```html
|
||||
<script>
|
||||
// sort(); 底层用到了charCodeAt();
|
||||
|
||||
var str = "I love my country!我你爱中国!";
|
||||
|
||||
//需求:求一个字符串占有几个字符位。
|
||||
//思路;如果是英文,站一个字符位,如果不是英文占两个字符位。
|
||||
//技术点:判断该字符是否在0-127之间。(在的话是英文,不在是非英文)
|
||||
alert(getZFWlength(str));
|
||||
alert(str.length);
|
||||
|
||||
//定义方法:字符位
|
||||
function getZFWlength(string) {
|
||||
//定义一个计数器
|
||||
var count = 0;
|
||||
for (var i = 0; i < string.length; i++) {
|
||||
//对每一位字符串进行判断,如果Unicode编码在0-127,计数器+1;否则+2
|
||||
if (string.charCodeAt(i) < 128 && string.charCodeAt(i) >= 0) {
|
||||
count++;
|
||||
} else {
|
||||
count += 2;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||
```
|
||||
30
|
||||
24
|
||||
```
|
||||
|
||||
从打印结果可以看出:字符串的长度是24,但是却占了30个字符位(一个中文占两个字符位)。
|
||||
|
||||
另外,sort()方法其实底层也是用到了charCodeAt(),因为用到了Unicode编码。
|
||||
|
||||
|
||||
### indexOf/lastIndexOf:给字符查索引
|
||||
|
||||
```javascript
|
||||
索引值 = str.indexOf/(想要查询的字符);
|
||||
|
||||
```
|
||||
|
||||
解释:从前向后索引字符串的位置。
|
||||
|
||||
因此可以得出一个技巧:**如果获取的索引值为0,说明字符串是以查询的参数为开头的**。
|
||||
|
||||
同理,lastIndexOf()是从后向前寻找。
|
||||
|
||||
```javascript
|
||||
var str = "abcdea";
|
||||
|
||||
//给字符查索引(索引值为0,说明字符串以查询的参数为开头)
|
||||
console.log(str.indexOf("c"));
|
||||
console.log(str.lastIndexOf("c"));
|
||||
|
||||
console.log(str.indexOf("a"));
|
||||
console.log(str.lastIndexOf("a"));
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||
20180202_1420.png
|
||||
|
||||
### concat:字符串的链接
|
||||
|
||||
|
||||
```javascript
|
||||
新字符串 = str1.concat(str2); 链接两个字符串
|
||||
```
|
||||
|
||||
这种方法基本不用,直接两个字符串相加就好。
|
||||
|
||||
### 字符串的截取(重要)
|
||||
|
||||
字符串的截取有好几个方法,下面分别讲解。
|
||||
|
||||
1、 slice()方法:
|
||||
|
||||
格式:
|
||||
|
||||
```javascript
|
||||
字符串 = str.slice(索引1,索引2); //两个参数都是索引值。
|
||||
```
|
||||
|
||||
上面的参数,包左不包右。如下:
|
||||
|
||||
|
||||
- (2,5) 表示正常,包左不包右。
|
||||
|
||||
- (2) 表示**从指定的索引位置开始,剪到最后**。
|
||||
|
||||
- (-3) 表示从倒数第几个开始,剪到最后.
|
||||
|
||||
- (5,2) 表示前面的大,后面的小,返回值为空。
|
||||
|
||||
2、substr()方法:
|
||||
|
||||
格式:
|
||||
|
||||
```javascript
|
||||
字符串 = srt.substr(索引值, 长度);
|
||||
```
|
||||
|
||||
参数解释:
|
||||
|
||||
- (2,4):从索引值为2的字符开始,截取4个字符。
|
||||
|
||||
- (1):从指定位置开始,截取到最后。
|
||||
|
||||
- (-3):从倒数第几个开始,剪到最后.
|
||||
|
||||
- 不包括前大后小的情况。
|
||||
|
||||
### 一些特殊方法
|
||||
|
||||
**1、trim()**:去除字符串前后的空白。
|
||||
|
||||
代码举例:
|
||||
|
||||
```javascript
|
||||
//去除前后的空格,trim();
|
||||
var str1 = " a b c ";
|
||||
console.log(str1);
|
||||
console.log(str1.trim());
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||
20180202_1455.png
|
||||
|
||||
2、**replace()**:替换。
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
//replace()方法:替换
|
||||
var str2 = "Today is fine day,today is fine day !!!"
|
||||
console.log(str2);
|
||||
console.log(str2.replace("today","tomorrow")); //只能替换第一个today
|
||||
console.log(str2.replace(/today/gi,"tomorrow")); //这里用到了正则,才能替换所有的today
|
||||
```
|
||||
|
||||
3、split():字符串变数组。
|
||||
|
||||
|
||||
```javascript
|
||||
//split()方法:字符串变数组
|
||||
var str3 = "生命壹号|许嵩|smyhvae";
|
||||
|
||||
console.log(str3);
|
||||
console.log(str3.split()); // 无参数,表示:把字符串作为一个元素添加到数组中。
|
||||
console.log(str3.split("")); //参数为空字符串,则表示:分隔字符串中每一个字符,分别添加到数组中
|
||||
console.log(str3.split("|")); //参数为指定字符,表示:此字符将不会出现在数组的任意一个元素中
|
||||
console.log(str3.split("许")); //同理
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||
20180202_1503.png
|
||||
|
||||
|
||||
### 大小写转换
|
||||
|
||||
举例:
|
||||
|
||||
|
||||
```javascript
|
||||
var str = "abcdEFG";
|
||||
|
||||
//转换成小写
|
||||
console.log(str.toLowerCase());
|
||||
//转换成大写
|
||||
console.log(str.toUpperCase());
|
||||
```
|
||||
|
||||
|
||||
|
||||
## html方法
|
||||
|
||||
- anchor() 创建a链接
|
||||
|
||||
- big()
|
||||
|
||||
- sub()
|
||||
|
||||
- sup()
|
||||
|
||||
- link()
|
||||
|
||||
- bold()
|
||||
|
||||
注意,str.link() 返回值是字符串。
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
var str = "你好";
|
||||
|
||||
console.log(str.anchor())
|
||||
console.log(str.big())
|
||||
console.log(str.sub())
|
||||
console.log(str.sup())
|
||||
console.log(str.link("http://www.baidu.com"));
|
||||
console.log(str.bold())
|
||||
```
|
||||
|
||||
20180202_1536.png
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 字符串练习
|
||||
|
||||
**练习1:**"smyhvaevaesmyh"查找字符串中所有m出现的位置。
|
||||
|
||||
代码实现:
|
||||
|
||||
|
||||
```javascript
|
||||
var str2 = "abcoefoxyozzopp";
|
||||
for(var i=0;i<str2.length;i++){
|
||||
//如果指定位置的符号=== "o"
|
||||
//str2[i]
|
||||
if( str2.charAt(i)==="o"){
|
||||
console.log(i);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
**练习2:**判断一个字符串中出现次数最多的字符,统计这个次数
|
||||
|
||||
|
||||
```html
|
||||
<script>
|
||||
var str2 = "smyhvaevaesmyhvae";
|
||||
|
||||
//定义一个json,然后判断json中是够有该属性,如果有该属性,那么值+1;否则创建一个该属性,并赋值为1;
|
||||
var json = {};
|
||||
for (var i = 0; i < str2.length; i++) {
|
||||
//判断:如果有该属性,那么值+1;否则创建一个该属性,并赋值为1;
|
||||
var key = str2.charAt(i);
|
||||
if (json[key] === undefined) {
|
||||
json[key] = 1;
|
||||
} else {
|
||||
json[key] += 1;
|
||||
}
|
||||
}
|
||||
console.log(json);
|
||||
|
||||
|
||||
console.log("----------------");
|
||||
//获取json中属性值最大的选项
|
||||
var maxKey = "";
|
||||
var maxValue = 0;
|
||||
for (var k in json) {
|
||||
// if(maxKey == ""){
|
||||
// maxKey = k;
|
||||
// maxValue = json[k];
|
||||
// }else{
|
||||
if (json[k] > maxValue) {
|
||||
maxKey = k;
|
||||
maxValue = json[k];
|
||||
}
|
||||
// }
|
||||
}
|
||||
console.log(maxKey);
|
||||
console.log(maxValue);
|
||||
|
||||
|
||||
</script>
|
||||
```
|
||||
|
||||
|
||||
打印结果:
|
||||
|
||||
20180202_1540.png
|
||||
|
||||
|
||||
## 内置对象 Math
|
||||
|
||||
内置对象 Math的常见方法:
|
||||
|
||||
- Math.abs(); **取绝对值**
|
||||
|
||||
- Math.floor(); **向下取整**(向小取)
|
||||
|
||||
- Math.ceil(); **向上取整**(向大取)
|
||||
|
||||
- Math.round(); 四舍五入取整(正数四舍五入,负数五舍六入)
|
||||
|
||||
- Math.random(); 随机数0-1
|
||||
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
var num = -0.6;
|
||||
|
||||
console.log(Math.abs(num)); //取绝对值
|
||||
console.log(Math.floor(num)); //向下取整,向小取
|
||||
console.log(Math.ceil(num)); //向上取整,向大取
|
||||
console.log(Math.round(num)); //四舍五入取整(正数四舍五入,负数五舍六入)
|
||||
console.log(Math.random()); //随机数 0-1
|
||||
```
|
||||
|
||||
20180202_1601.png
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## url 编码和解码
|
||||
|
||||
URI (Uniform ResourceIdentifiers,通用资源标识符)进行编码,以便发送给浏览器。有效的URI中不能包含某些字符,例如空格。而这URI编码方法就可以对URI进行编码,它们用特殊的UTF-8编码替换所有无效的字符,从而让浏览器能够接受和理解。
|
||||
|
||||
```javascript
|
||||
encodeURIComponent(); //把字符串作为 URI 组件进行编码
|
||||
decodeURIComponent(); //把字符串作为 URI 组件进行解码
|
||||
|
||||
```
|
||||
|
||||
举例:
|
||||
|
||||
|
||||
|
||||
|
||||
```javascript
|
||||
var url = "http://www.cnblogs.com/smyhvae/";
|
||||
|
||||
var str = encodeURIComponent(url);
|
||||
console.log(str); //打印url的编码
|
||||
console.log(decodeURIComponent(str)); //对url进行编码后,再解码,还原为url
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||
20180202_1432.png
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,913 +0,0 @@
|
||||
|
||||
> 本文最初发表于[博客园](http://www.cnblogs.com/smyhvae/p/8366012.html),并在[GitHub](https://github.com/smyhvae/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。
|
||||
|
||||
> 以下是正文。
|
||||
|
||||
|
||||
## 前言
|
||||
|
||||
### JavaScript的组成
|
||||
|
||||
JavaScript基础分为三个部分:
|
||||
|
||||
- ECMAScript:JavaScript的语法标准。包括变量、表达式、运算符、函数、if语句、for语句等。
|
||||
|
||||
- **DOM**:文档对象模型,操作**网页上的元素**的API。比如让盒子移动、变色、轮播图等。
|
||||
|
||||
- **BOM**:浏览器对象模型,操作**浏览器部分功能**的API。比如让浏览器自动滚动。
|
||||
|
||||
## 事件
|
||||
|
||||
> JS是以**事件驱动为核心**的一门语言。
|
||||
|
||||
### 事件的三要素
|
||||
|
||||
**事件的三要素:事件源、事件、事件驱动程序**。
|
||||
|
||||
比如,我用手去按开关,灯亮了。这件事情里,事件源是:手。事件是:按开关。事件驱动程序是:灯的开和关。
|
||||
|
||||
再比如,网页上弹出一个广告,我点击右上角的`X`,广告就关闭了。这件事情里,事件源是:`X`。事件是:onclick。事件驱动程序是:广告关闭了。
|
||||
|
||||
于是我们可以总结出:谁引发的后续事件,谁就是事件源。
|
||||
|
||||
**总结如下:**
|
||||
|
||||
- 事件源:引发后续事件的html标签。
|
||||
|
||||
- 事件:js已经定义好了(见下图)。
|
||||
|
||||
- 事件驱动程序:对样式和html的操作。也就是DOM。
|
||||
|
||||
**代码书写步骤如下:**(重要)
|
||||
|
||||
- (1)获取事件源:document.getElementById(“box”); // 类似于Android里面的findViewById
|
||||
|
||||
- (2)绑定事件: 事件源box.事件onclick = function(){ 事件驱动程序 };
|
||||
|
||||
- (3)书写事件驱动程序:关于DOM的操作。
|
||||
|
||||
最简单的代码举例:(点击box1,然后弹框)
|
||||
|
||||
```html
|
||||
<body>
|
||||
<div id="box1"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
// 1、获取事件源
|
||||
var div = document.getElementById("box1");
|
||||
// 2、绑定事件
|
||||
div.onclick = function () {
|
||||
// 3、书写事件驱动程序
|
||||
alert("我是弹出的内容");
|
||||
}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
```
|
||||
|
||||
常见的事件如下:
|
||||
|
||||

|
||||
|
||||
下面针对这事件的三要素,进行分别介绍。
|
||||
|
||||
### 1、获取事件源的方式(DOM节点的获取)
|
||||
|
||||
获取事件源的常见方式如下:
|
||||
|
||||
```javascript
|
||||
var div1 = document.getElementById("box1"); //方式一:通过id获取单个标签
|
||||
|
||||
var arr1 = document.getElementsByTagName("div1"); //方式二:通过 标签名 获得 标签数组,所以有s
|
||||
|
||||
var arr2 = document.getElementsByClassName("hehe"); //方式三:通过 类名 获得 标签数组,所以有s
|
||||
```
|
||||
|
||||
### 2、绑定事件的方式
|
||||
|
||||
方式一:直接绑定匿名函数
|
||||
|
||||
```html
|
||||
<div id="box1" ></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var div1 = document.getElementById("box1");
|
||||
//绑定事件的第一种方式
|
||||
div1.onclick = function () {
|
||||
alert("我是弹出的内容");
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
方式二:先单独定义函数,再绑定
|
||||
|
||||
```html
|
||||
<div id="box1" ></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var div1 = document.getElementById("box1");
|
||||
//绑定事件的第二种方式
|
||||
div1.onclick = fn; //注意,这里是fn,不是fn()。fn()指的是返回值。
|
||||
//单独定义函数
|
||||
function fn() {
|
||||
alert("我是弹出的内容");
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
注意上方代码的注释。**绑定的时候,是写fn,不是写fn()**。fn代表的是整个函数,而fn()代表的是返回值。
|
||||
|
||||
方式三:行内绑定
|
||||
|
||||
```html
|
||||
<!--行内绑定-->
|
||||
<div id="box1" onclick="fn()"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
function fn() {
|
||||
alert("我是弹出的内容");
|
||||
}
|
||||
|
||||
</script>
|
||||
```
|
||||
|
||||
注意第一行代码,绑定时,是写的`"fn()"`,不是写的`"fn"`。因为绑定的这段代码不是写在js代码里的,而是被识别成了**字符串**。
|
||||
|
||||
### 3、事件驱动程序
|
||||
|
||||
我们在上面是拿alert举例,不仅如此,我们还可以操作标签的属性和样式。举例如下:
|
||||
|
||||
点击鼠标时,原本粉色的div变大了,背景变红:
|
||||
|
||||
```html
|
||||
<style>
|
||||
#box1 {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: pink;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="box1" ></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var div1 = document.getElementById("box1");
|
||||
//点击鼠标时,原本粉色的div变大了,背景变红了
|
||||
div1.onclick = function () {
|
||||
div1.style.width = "200px"; //属性值要写引号
|
||||
div1.style.height = "200px";
|
||||
div1.style.backgroundColor = "red"; //属性名是backgroundColor,不是background-Color
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
上方代码的注意事项:
|
||||
|
||||
- 在js里写属性值时,要用引号
|
||||
- 在js里写属性名时,是`backgroundColor`,不是CSS里面的`background-Color`。
|
||||
|
||||
实现效果如下:
|
||||
|
||||

|
||||
|
||||
### onload事件
|
||||
|
||||
> onload事件比较特殊,这里单独讲一下。
|
||||
|
||||
**当页面加载(文本和图片)完毕的时候,触发onload事件。**
|
||||
|
||||
举例:
|
||||
|
||||
```html
|
||||
<script type="text/javascript">
|
||||
window.onload = function () {
|
||||
console.log("smyhvae"); //等页面加载完毕时,打印字符串
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
有一点我们要知道:**js的加载是和html同步加载的**。因此,如果使用元素在定义元素之前,容易报错。这个时候,onload事件就能派上用场了,我们可以把使用元素的代码放在onload里,就能保证这段代码是最后执行。
|
||||
|
||||
建议是:整个页面上所有元素加载完毕在执行js内容。所以,window.onload可以预防使用标签在定义标签之前。
|
||||
|
||||
### 事件举例:京东顶部广告栏
|
||||
|
||||

|
||||
|
||||
比如上面这张图,当鼠标点击右上角的`X`时,关掉整个广告栏,这就要用到事件。
|
||||
|
||||
代码实现如下:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<title></title>
|
||||
<style>
|
||||
* {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.top-banner {
|
||||
background-color: pink;
|
||||
height: 80px;
|
||||
}
|
||||
.w {
|
||||
width: 1210px;
|
||||
margin: 10px auto;
|
||||
position: relative;
|
||||
}
|
||||
img {
|
||||
display: block;
|
||||
width: 1210px;
|
||||
height: 80px;
|
||||
background-color: blue;
|
||||
}
|
||||
a {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
color: #fff;
|
||||
background-color: #000;
|
||||
text-decoration: none;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
font: 700 14px/20px "simsum";
|
||||
text-align: center;
|
||||
}
|
||||
.hide {
|
||||
display: none!important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="top-banner" id="topBanner">
|
||||
<div class="w">
|
||||
<img src="" alt=""/>
|
||||
<a href="#" id="closeBanner">×</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
//需求:点击案例,隐藏盒子。
|
||||
//思路:点击a链接,让top-banner这个盒子隐藏起来(加隐藏类名)。
|
||||
|
||||
//1.获取事件源和相关元素
|
||||
var closeBanner = document.getElementById("closeBanner");
|
||||
var topBanner = document.getElementById("topBanner");
|
||||
//2.绑定事件
|
||||
closeBanner.onclick = function () {
|
||||
//3.书写事件驱动程序
|
||||
//类控制
|
||||
// topBanner.className += " hide"; //保留原类名,添加新类名
|
||||
topBanner.className = "hide";//替换旧类名(方式一)
|
||||
// topBanner.style.display = "none"; //方式二:与上一行代码的效果相同
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
```
|
||||
|
||||
注意最后一行代码,这种方式会替换旧类名,意思是,不管之前的类名叫什么,都会被修改。
|
||||
|
||||
### 事件举例:
|
||||
|
||||
要求实现效果:当鼠标悬停在img上时,更换为另外一张图片;鼠标离开时,还原为本来的图片。
|
||||
|
||||
代码实现:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<title></title>
|
||||
<script>
|
||||
//window.onload页面加载完毕以后再执行此代码
|
||||
window.onload = function () {
|
||||
//需求:鼠标放到img上,更换为另一张图片,也就是修改路径(src的值)。
|
||||
//步骤:
|
||||
//1.获取事件源
|
||||
//2.绑定事件
|
||||
//3.书写事件驱动程序
|
||||
|
||||
//1.获取事件源
|
||||
var img = document.getElementById("box");
|
||||
//2.绑定事件(悬停事件:鼠标进入到事件源中,立即触发事件)
|
||||
img.onmouseover = function () {
|
||||
//3.书写事件驱动程序(修改src)
|
||||
img.src = "image/jd2.png";
|
||||
// this.src = "image/jd2.png";
|
||||
}
|
||||
|
||||
//2.绑定事件(悬停事件:鼠标进入到事件源中,立即触发事件)
|
||||
img.onmouseout = function () {
|
||||
//3.书写事件驱动程序(修改src)
|
||||
img.src = "image/jd1.png";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<img id="box" src="image/jd1.png" style="cursor: pointer;border: 1px solid #ccc;"/>
|
||||
|
||||
</html>
|
||||
```
|
||||
|
||||
|
||||
## DOM的介绍
|
||||
|
||||
### 什么是DOM
|
||||
|
||||
DOM:Document Object Model,文档对象模型。DOM 为文档提供了结构化表示,并定义了如何通过脚本来访问文档结构。目的其实就是为了能让js操作html元素而制定的一个规范。
|
||||
|
||||
DOM就是由节点组成的。
|
||||
|
||||
### 解析过程
|
||||
|
||||
HTML加载完毕,渲染引擎会在内存中把HTML文档,生成一个DOM树,getElementById是获取内中DOM上的元素节点。然后操作的时候修改的是该元素的**属性**。
|
||||
|
||||
### DOM树(一切都是节点)
|
||||
|
||||
DOM的数据结构如下:
|
||||
|
||||

|
||||
|
||||
上图可知,**在HTML当中,一切都是节点**:(非常重要)
|
||||
|
||||
- **元素节点**:HMTL标签。
|
||||
|
||||
- **文本节点**:标签中的文字(比如标签之间的空格、换行)
|
||||
|
||||
- **属性节点**::标签的属性。
|
||||
|
||||
整个html文档就是一个文档节点。所有的节点都是Object。
|
||||
|
||||
### DOM可以做什么
|
||||
|
||||
- 找对象(元素节点)
|
||||
|
||||
- 设置元素的属性值
|
||||
|
||||
- 设置元素的样式
|
||||
|
||||
- 动态创建和删除元素
|
||||
|
||||
- 事件的触发响应:事件源、事件、事件的驱动程序
|
||||
|
||||
|
||||
## DOM节点的获取
|
||||
|
||||
DOM节点的获取方式其实就是**获取事件源的方式**,在上一段已经讲到。这里再重复一下。
|
||||
|
||||
操作元素节点,必须首先找到该节点。有三种方式可以获取DOM节点:
|
||||
|
||||
```javascript
|
||||
var div1 = document.getElementById("box1"); //方式一:通过id获取单个标签
|
||||
|
||||
var arr1 = document.getElementsByTagName("div1"); //方式二:通过 标签名 获得 标签数组,所以有s
|
||||
|
||||
var arr2 = document.getElementsByClassName("hehe"); //方式三:通过 类名 获得 标签数组,所以有s
|
||||
```
|
||||
|
||||
既然方式二、方式三获取的是标签数组,那么习惯性是**先遍历之后再使用**。
|
||||
|
||||
特殊情况:数组中的值只有1个。即便如此,这一个值也是包在数组里的。这个值的获取方式如下:
|
||||
|
||||
```javascript
|
||||
document.getElementsByTagName("div1")[0]; //取数组中的第一个元素
|
||||
|
||||
document.getElementsByClassName("hehe")[0]; //取数组中的第一个元素
|
||||
```
|
||||
|
||||
## DOM访问关系的获取
|
||||
|
||||
DOM的节点并不是孤立的,因此可以通过DOM节点之间的相对关系对它们进行访问。如下:
|
||||
|
||||

|
||||
|
||||
节点的访问关系,是以**属性**的方式存在的。
|
||||
|
||||
JS中的**父子兄**访问关系:
|
||||
|
||||

|
||||
|
||||
这里我们要重点知道**parentNode**和**children**这两个属性的用法。下面分别介绍。
|
||||
|
||||
### 获取父节点
|
||||
|
||||
调用者就是节点。一个节点只有一个父节点,调用方式就是
|
||||
|
||||
```javascript
|
||||
节点.parentNode
|
||||
```
|
||||
|
||||
|
||||
### 获取兄弟节点
|
||||
|
||||
**1、下一个节点 | 下一个元素节点**:
|
||||
|
||||
> Sibling的中文是**兄弟**。
|
||||
|
||||
(1)nextSibling:
|
||||
|
||||
- 火狐、谷歌、IE9+版本:都指的是下一个节点(包括标签、空文档和换行节点)。
|
||||
|
||||
- IE678版本:指下一个元素节点(标签)。
|
||||
|
||||
(2)nextElementSibling:
|
||||
|
||||
- 火狐、谷歌、IE9+版本:都指的是下一个元素节点(标签)。
|
||||
|
||||
**总结**:为了获取下一个**元素节点**,我们可以这样做:在IE678中用nextSibling,在火狐谷歌IE9+以后用nextElementSibling,于是,综合这两个属性,可以这样写:
|
||||
|
||||
```javascript
|
||||
下一个兄弟节点 = 节点.nextElementSibling || 节点.nextSibling
|
||||
```
|
||||
|
||||
**2、前一个节点 | 前一个元素节点**:
|
||||
|
||||
> previous的中文是:前一个。
|
||||
|
||||
(1)previousSibling:
|
||||
|
||||
- 火狐、谷歌、IE9+版本:都指的是前一个节点(包括标签、空文档和换行节点)。
|
||||
|
||||
- IE678版本:指前一个元素节点(标签)。
|
||||
|
||||
(2)previousElementSibling:
|
||||
|
||||
- 火狐、谷歌、IE9+版本:都指的是前一个元素节点(标签)。
|
||||
|
||||
**总结**:为了获取前一个**元素节点**,我们可以这样做:在IE678中用previousSibling,在火狐谷歌IE9+以后用previousElementSibling,于是,综合这两个属性,可以这样写:
|
||||
|
||||
```javascript
|
||||
前一个兄弟节点 = 节点.previousElementSibling || 节点.previousSibling
|
||||
```
|
||||
|
||||
|
||||
**3、补充:**获得任意一个兄弟节点:
|
||||
|
||||
```javascript
|
||||
节点自己.parentNode.children[index]; //随意得到兄弟节点
|
||||
```
|
||||
|
||||
### 获取单个的子节点
|
||||
|
||||
**1、第一个子节点 | 第一个子元素节点**:
|
||||
|
||||
(1)firstChild:
|
||||
|
||||
- 火狐、谷歌、IE9+版本:都指的是第一个子节点(包括标签、空文档和换行节点)。
|
||||
|
||||
- IE678版本:指第一个子元素节点(标签)。
|
||||
|
||||
(2)firstElementChild:
|
||||
|
||||
- 火狐、谷歌、IE9+版本:都指的是第一个子元素节点(标签)。
|
||||
|
||||
**总结**:为了获取第一个**子元素节点**,我们可以这样做:在IE678中用firstChild,在火狐谷歌IE9+以后用firstElementChild,于是,综合这两个属性,可以这样写:
|
||||
|
||||
```javascript
|
||||
第一个子元素节点 = 节点.firstElementChild || 节点.firstChild
|
||||
```
|
||||
|
||||
**2、最后一个子节点 | 最后一个子元素节点**:
|
||||
|
||||
(1)lastChild:
|
||||
|
||||
- 火狐、谷歌、IE9+版本:都指的是最后一个子节点(包括标签、空文档和换行节点)。
|
||||
|
||||
- IE678版本:指最后一个子元素节点(标签)。
|
||||
|
||||
(2)lastElementChild:
|
||||
|
||||
- 火狐、谷歌、IE9+版本:都指的是最后一个子元素节点(标签)。
|
||||
|
||||
**总结**:为了获取最后一个**子元素节点**,我们可以这样做:在IE678中用lastChild,在火狐谷歌IE9+以后用lastElementChild,于是,综合这两个属性,可以这样写:
|
||||
|
||||
```javascript
|
||||
最后一个子元素节点 = 节点.lastElementChild || 节点.lastChild
|
||||
```
|
||||
|
||||
### 获取所有的子节点
|
||||
|
||||
(1)**childNodes**:标准属性。返回的是指定元素的**子节点**的集合(包括元素节点、所有属性、文本节点)。是W3C的亲儿子。
|
||||
|
||||
- 火狐 谷歌等高本版会把换行也看做是子节点。
|
||||
|
||||
用法:
|
||||
|
||||
```javascript
|
||||
子节点数组 = 父节点.childNodes; //获取所有节点。
|
||||
```
|
||||
|
||||
(2)**children**:非标准属性。返回的是指定元素的**子元素节点**的集合。【重要】
|
||||
|
||||
- 它只返回HTML节点,甚至不返回文本节点。
|
||||
- 在IE6/7/8中包含注释节点(在IE678中,注释节点不要写在里面)。
|
||||
|
||||
虽然不是标准的DOM属性,但它和innerHTML方法一样,得到了几乎所有浏览器的支持。
|
||||
|
||||
用法:(**用的最多**)
|
||||
|
||||
```javascript
|
||||
子节点数组 = 父节点.children; //获取所有节点。用的最多。
|
||||
```
|
||||
|
||||
|
||||
## DOM节点的操作(重要)
|
||||
|
||||
上一段的内容:节点的**访问关系**都是**属性**。
|
||||
|
||||
本段的内容:节点的**操作**都是**函数**(方法)。
|
||||
|
||||
### 创建节点
|
||||
|
||||
格式如下:
|
||||
|
||||
```javascript
|
||||
新的标签(元素节点) = document.createElement("标签名");
|
||||
```
|
||||
|
||||
比如,如果我们想创建一个li标签,或者是创建一个不存在的adbc标签,可以这样做:
|
||||
|
||||
```html
|
||||
<script type="text/javascript">
|
||||
var a1 = document.createElement("li"); //创建一个li标签
|
||||
var a2 = document.createElement("adbc"); //创建一个不存在的标签
|
||||
|
||||
console.log(a1);
|
||||
console.log(a2);
|
||||
|
||||
console.log(typeof a1);
|
||||
console.log(typeof a2);
|
||||
</script>
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||

|
||||
|
||||
### 插入节点
|
||||
|
||||
插入节点有两种方式,它们的含义是不同的。
|
||||
|
||||
方式1:
|
||||
|
||||
```javascript
|
||||
父节点.appendChild(新的子节点);
|
||||
```
|
||||
|
||||
解释:父节点的最后插入一个新的子节点。
|
||||
|
||||
方式2:
|
||||
|
||||
```javascript
|
||||
父节点.insertBefore(新的子节点,作为参考的子节点)
|
||||
```
|
||||
|
||||
解释:
|
||||
|
||||
- 在参考节点前插入一个新的节点。
|
||||
- 如果参考节点为null,那么他将在父节点里面的最后插入一个子节点。
|
||||
|
||||

|
||||
|
||||
我们可以看到,li标签确实被插入到了box1标签的里面,和box2并列了。
|
||||
|
||||
方式2的举例:
|
||||
|
||||

|
||||
|
||||
我们可以看到,b1标签被插入到了box1标签的里面,和a1标签并列,在a1标签的前面。
|
||||
|
||||
|
||||
|
||||
|
||||
**特别强调:**
|
||||
|
||||
关于方式1的appendChild方法,这里要强调一下。比如,现在有下面这样一个div结构:
|
||||
|
||||
```html
|
||||
<div class="box11">
|
||||
<div class="box12">生命壹号</div>
|
||||
</div>
|
||||
|
||||
<div class="box21">
|
||||
<div class="box22">永不止步</div>
|
||||
|
||||
</div>
|
||||
```
|
||||
|
||||
|
||||
上方结构中,子盒子box12是在父亲box11里的,子盒子box22是在父亲box21里面的。现在,如果我调用方法`box11.appendChild(box22)`,**最后产生的结果是:box22会跑到box11中**(也就是说,box22不在box21里面了)。这是一个很神奇的事情:
|
||||
|
||||
20180129_2125.png
|
||||
|
||||
|
||||
|
||||
### 删除节点
|
||||
|
||||
格式如下:
|
||||
|
||||
```javascript
|
||||
父节点.removeChild(子节点);
|
||||
```
|
||||
|
||||
解释:**用父节点删除子节点**。必须要指定是删除哪个子节点。
|
||||
|
||||
如果我想删除自己这个节点,可以这么做:
|
||||
|
||||
```javascript
|
||||
node1.parentNode.removeChild(node1);
|
||||
```
|
||||
|
||||
### 复制节点(克隆节点)
|
||||
|
||||
格式如下:
|
||||
|
||||
```javascript
|
||||
要复制的节点.cloneNode(); //括号里不带参数和带参数false,效果是一样的。
|
||||
|
||||
要复制的节点.cloneNode(true);
|
||||
```
|
||||
|
||||
括号里带不带参数,效果是不同的。解释如下:
|
||||
|
||||
- 不带参数/带参数false:只复制节点本身,不复制子节点。
|
||||
|
||||
- 带参数true:既复制节点本身,也复制其所有的子节点。
|
||||
|
||||
## 设置节点的属性
|
||||
|
||||
我们可以获取节点的属性值、设置节点的属性值、删除节点的属性。
|
||||
|
||||
我们就统一拿下面这个标签来举例:
|
||||
|
||||
```html
|
||||
<img src="images/1.jpg" class="image-box" title="美女图片" alt="地铁一瞥" id="a1">
|
||||
```
|
||||
|
||||
下面分别介绍。
|
||||
|
||||
### 1、获取节点的属性值
|
||||
|
||||
方式1:
|
||||
|
||||
```javascript
|
||||
元素节点.属性;
|
||||
元素节点[属性];
|
||||
```
|
||||
|
||||
举例:(获取节点的属性值)
|
||||
|
||||
```html
|
||||
<body>
|
||||
<img src="images/1.jpg" class="image-box" title="美女图片" alt="地铁一瞥" id="a1">
|
||||
|
||||
<script type="text/javascript">
|
||||
var myNode = document.getElementsByTagName("img")[0];
|
||||
|
||||
console.log(myNode.src);
|
||||
console.log(myNode.className); //注意,是className,不是class
|
||||
console.log(myNode.title);
|
||||
|
||||
console.log("------------");
|
||||
|
||||
console.log(myNode["src"]);
|
||||
console.log(myNode["className"]); //注意,是className,不是class
|
||||
console.log(myNode["title"]);
|
||||
</script>
|
||||
</body>
|
||||
```
|
||||
|
||||
上方代码中的img标签,有各种属性,我们可以逐一获取,打印结果如下:
|
||||
|
||||

|
||||
|
||||
方式2:
|
||||
|
||||
```javascript
|
||||
元素节点.getAttribute("属性名称");
|
||||
```
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
console.log(myNode.getAttribute("src"));
|
||||
console.log(myNode.getAttribute("class")); //注意是class,不是className
|
||||
console.log(myNode.getAttribute("title"));
|
||||
```
|
||||
|
||||
打印结果:
|
||||
|
||||

|
||||
|
||||
方式1和方式2的区别在于:前者是直接操作标签,后者是把标签作为DOM节点。推荐方式2。
|
||||
|
||||
### 2、设置节点的属性值
|
||||
|
||||
方式1举例:(设置节点的属性值)
|
||||
|
||||
```javascript
|
||||
myNode.src = "images/2.jpg" //修改src的属性值
|
||||
myNode.className = "image2-box"; //修改class的name
|
||||
```
|
||||
|
||||
方式2:
|
||||
|
||||
```javascript
|
||||
元素节点.setAttribute(属性名, 新的属性值);
|
||||
```
|
||||
|
||||
方式2举例:(设置节点的属性值)
|
||||
|
||||
```javascript
|
||||
myNode.setAttribute("src","images/3.jpg");
|
||||
myNode.setAttribute("class","image3-box");
|
||||
myNode.setAttribute("id","你好");
|
||||
```
|
||||
|
||||
|
||||
### 3、删除节点的属性
|
||||
|
||||
格式:
|
||||
|
||||
```javascript
|
||||
元素节点.removeAttribute(属性名);
|
||||
```
|
||||
|
||||
举例:(删除节点的属性)
|
||||
|
||||
```javascript
|
||||
myNode.removeAttribute("class");
|
||||
myNode.removeAttribute("id");
|
||||
```
|
||||
|
||||
|
||||
|
||||
**总结:**
|
||||
|
||||
获取节点的属性值和设置节点的属性值,都有两种方式,但这两种方式是有区别的。
|
||||
|
||||
- 方式一的`元素节点.属性`和`元素节点[属性]`:绑定的属性值不会出现在标签上。
|
||||
|
||||
- 方式二的`get/set/removeAttribut`: 绑定的属性值会出现在标签上。
|
||||
|
||||
这其实很好理解,方式一操作的是属性而已,方式二操作的是标签本身。
|
||||
|
||||
另外,需要注意的是:**这两种方式不能交换使用**,get值和set值必须使用用一种方法。
|
||||
|
||||
举例:
|
||||
|
||||
```html
|
||||
<body>
|
||||
<div id="box" title="主体" class="asdfasdfadsfd">我爱你中国</div>
|
||||
<script>
|
||||
|
||||
var div = document.getElementById("box");
|
||||
|
||||
//采用方式一进行set
|
||||
div.aaaa = "1111";
|
||||
console.log(div.aaaa); //打印结果:1111。可以打印出来,但是不会出现在标签上
|
||||
|
||||
//采用方式二进行set
|
||||
div.setAttribute("bbbb","2222"); //bbbb作为新增的属性,会出现在标签上
|
||||
|
||||
console.log(div.getAttribute("aaaa")); //打印结果:null。因为方式一的set,无法采用方式二进行get。
|
||||
console.log(div.bbbb); //打印结果:undefined。因为方式二的set,无法采用方式一进行get。
|
||||
|
||||
</script>
|
||||
</body>
|
||||
```
|
||||
|
||||
|
||||
|
||||
## DOM对象的属性
|
||||
|
||||
DOM对象的属性和HTML的标签属性几乎是一致的。例如:src、title、className、href等。
|
||||
|
||||
### innerHTML和innerText的区别
|
||||
|
||||
- value:标签的value属性。
|
||||
|
||||
- **innerHTML**:双闭合标签里面的内容(识别标签)。
|
||||
|
||||
- **innerText**:双闭合标签里面的内容(不识别标签)。(老版本的火狐用textContent)
|
||||
|
||||
|
||||
**获取内容举例:**
|
||||
|
||||
如果我们想获取innerHTML和innerText里的内容,看看会如何:
|
||||
|
||||

|
||||
|
||||
上图显示,因为innerText识别不出标签,所以把标签也给获取到了。
|
||||
|
||||
|
||||
**修改内容举例:**
|
||||
|
||||

|
||||
|
||||
上图显示,因为innerText识别不出标签,所以把标签也给添加进去了。
|
||||
|
||||
### nodeType属性
|
||||
|
||||
这里讲一下nodeType属性。
|
||||
|
||||
- **nodeType == 1 表示的是元素节点**(标签) 。记住:元素就是标签。
|
||||
|
||||
- nodeType == 2 表示是属性节点。
|
||||
|
||||
- nodeType == 3 是文本节点。
|
||||
|
||||
### nodeType、nodeName、nodeValue
|
||||
|
||||
我们那下面这个标签来举例:
|
||||
|
||||
```html
|
||||
<div id="box" value="111">
|
||||
生命壹号
|
||||
</div>
|
||||
```
|
||||
|
||||
上面这个标签就包含了三种节点:
|
||||
|
||||
- 元素节点(标签)
|
||||
|
||||
- 属性节点
|
||||
|
||||
- 文本节点
|
||||
|
||||
获取这三个节点的方式如下:
|
||||
|
||||
```javascript
|
||||
var element = document.getElementById("box1"); //获取元素节点(标签)
|
||||
var attribute = element.getAttributeNode("id"); //获取box1的属性节点
|
||||
var txt = element.firstChild; //获取box1的文本节点
|
||||
|
||||
var value = element.getAttribute("id"); //获取id的属性值
|
||||
|
||||
console.log(element);
|
||||
console.log("--------------");
|
||||
console.log(attribute);
|
||||
console.log("--------------");
|
||||
console.log(txt);
|
||||
console.log("--------------");
|
||||
console.log(value);
|
||||
```
|
||||
|
||||
打印结果如下:
|
||||
|
||||

|
||||
|
||||
既然这三个都是节点,如果我想获取它们的nodeType、nodeName、nodeValue,代码如下:
|
||||
|
||||
```javascript
|
||||
var element = document.getElementById("box1"); //获取元素节点(标签)
|
||||
var attribute = element.getAttributeNode("id"); //获取box1的属性节点
|
||||
var txt = element.firstChild; //获取box1的文本节点
|
||||
|
||||
//获取nodeType
|
||||
console.log(element.nodeType); //1
|
||||
console.log(attribute.nodeType); //2
|
||||
console.log(txt.nodeType); //3
|
||||
|
||||
console.log("--------------");
|
||||
|
||||
//获取nodeName
|
||||
console.log(element.nodeName); //DIV
|
||||
console.log(attribute.nodeName); //id
|
||||
console.log(txt.nodeName); //#text
|
||||
|
||||
console.log("--------------");
|
||||
|
||||
//获取nodeValue
|
||||
console.log(element.nodeValue); //null
|
||||
console.log(attribute.nodeValue); //box1
|
||||
console.log(txt.nodeValue); //生命壹号
|
||||
```
|
||||
|
||||
打印结果如下:
|
||||
|
||||

|
||||
|
||||
|
||||
## 我的公众号
|
||||
|
||||
想学习<font color=#0000ff>**代码之外的软技能**</font>?不妨关注我的微信公众号:**生命团队**(id:`vitateam`)。
|
||||
|
||||
扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外:
|
||||
|
||||

|
||||
@@ -1,281 +0,0 @@
|
||||
|
||||
> 本文最初发表于[博客园](http://www.cnblogs.com/smyhvae/p/8401662.html),并在[GitHub](https://github.com/smyhvae/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。
|
||||
|
||||
> 以下是正文。
|
||||
|
||||
|
||||
## BOM的介绍
|
||||
|
||||
### JavaScript的组成
|
||||
|
||||
JavaScript基础分为三个部分:
|
||||
|
||||
- ECMAScript:JavaScript的语法标准。包括变量、表达式、运算符、函数、if语句、for语句等。
|
||||
|
||||
- **DOM**:文档对象模型,操作**网页上的元素**的API。比如让盒子移动、变色、轮播图等。
|
||||
|
||||
- **BOM**:浏览器对象模型,操作**浏览器部分功能**的API。比如让浏览器自动滚动。
|
||||
|
||||
### 什么是BOM
|
||||
|
||||
BOM:Browser Object Model,浏览器对象模型。
|
||||
|
||||
**BOM的结构图:**
|
||||
|
||||

|
||||
|
||||
从上图也可以看出:
|
||||
|
||||
- **window对象是BOM的顶层(核心)对象**,所有对象都是通过它延伸出来的,也可以称为window的子对象。
|
||||
|
||||
- DOM越是BOM的一部分。
|
||||
|
||||
**window对象:**
|
||||
|
||||
- **window对象是JavaScript中的顶级对象**。
|
||||
|
||||
- 全局变量、自定义函数也是window对象的属性和方法。
|
||||
|
||||
- window对象下的属性和方法调用时,可以省略window。
|
||||
|
||||
下面讲一下 **BOM 的常见内置方法和内置对象**。
|
||||
|
||||
## 弹出系统对话框
|
||||
|
||||
比如说,`alert(1)`是`window.alert(1)`的简写,因为它是window的子方法。
|
||||
|
||||
系统对话框有三种:
|
||||
|
||||
```javascript
|
||||
alert(); //不同浏览器中的外观是不一样的
|
||||
confirm(); //兼容不好
|
||||
prompt(); //不推荐使用
|
||||
|
||||
```
|
||||
|
||||
## 打开窗口、关闭窗口
|
||||
|
||||
1、打开窗口:
|
||||
|
||||
```
|
||||
window.open(url,target,param)
|
||||
```
|
||||
|
||||
**参数解释:**
|
||||
|
||||
- url:要打开的地址。
|
||||
|
||||
- target:新窗口的位置。可以是:`_blank` 、`_self`、 `_parent` 父框架。
|
||||
|
||||
- param:新窗口的一些设置。
|
||||
|
||||
- 返回值:新窗口的句柄。
|
||||
|
||||
**param**这个参数,可以填各种各样的参数(),比如:
|
||||
|
||||
- name:新窗口的名称,可以为空
|
||||
|
||||
- featurse:属性控制字符串,在此控制窗口的各种属性,属性之间以逗号隔开。
|
||||
|
||||
- fullscreen= { yes/no/1/0 } 是否全屏,默认no
|
||||
|
||||
- channelmode= { yes/no/1/0 } 是否显示频道栏,默认no
|
||||
|
||||
- toolbar= { yes/no/1/0 } 是否显示工具条,默认no
|
||||
|
||||
- location= { yes/no/1/0 } 是否显示地址栏,默认no。(有的浏览器不一定支持)
|
||||
|
||||
- directories = { yes/no/1/0 } 是否显示转向按钮,默认no
|
||||
|
||||
- status= { yes/no/1/0 } 是否显示窗口状态条,默认no
|
||||
|
||||
- menubar= { yes/no/1/0 } 是否显示菜单,默认no
|
||||
|
||||
- scrollbars= { yes/no/1/0 } 是否显示滚动条,默认yes
|
||||
|
||||
- resizable= { yes/no/1/0 } 是否窗口可调整大小,默认no
|
||||
|
||||
- width=number 窗口宽度(像素单位)
|
||||
|
||||
- height=number 窗口高度(像素单位)
|
||||
|
||||
- top=number 窗口离屏幕顶部距离(像素单位)
|
||||
|
||||
- left=number 窗口离屏幕左边距离(像素单位)
|
||||
|
||||
各个参数之间用逗号隔开就行,但我们最好是把它们统一放到json里。
|
||||
|
||||
2、关闭窗口:window.close()
|
||||
|
||||
(1)和(2)的代码举例:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<a href="javascript:;">点击我打开一个新的页面</a>
|
||||
<a href="javascript:;">点击我关闭本页面</a>
|
||||
<script>
|
||||
//新窗口 = window.open(地址,是否开新窗口,新窗口的各种参数);
|
||||
var a1 = document.getElementsByTagName("a")[0];
|
||||
var a2 = document.getElementsByTagName("a")[1];
|
||||
a1.onclick = function () {
|
||||
//举例1: window.open("http://www.jd.com","_blank");
|
||||
var json = {
|
||||
"name": "helloworld",
|
||||
"fullscreen": "no",
|
||||
"location": "no",
|
||||
"width": "100px",
|
||||
"height": "100px",
|
||||
"top": "100px",
|
||||
"left": "100px"
|
||||
};
|
||||
window.open("http://www.baidu.com", "_blank", json); //举例2
|
||||
}
|
||||
|
||||
//关闭本页面
|
||||
a2.onclick = function () {
|
||||
window.close();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
3、新窗口相关:
|
||||
|
||||
- 新窗口.moveTo(5,5)
|
||||
|
||||
- 新窗口.moveBy()
|
||||
|
||||
- 新窗口.resizeTo()
|
||||
|
||||
- window.resizeBy()
|
||||
|
||||
代码举例:
|
||||
|
||||
```javascript
|
||||
var newWin = window.open("demo.html", "_blank", json);
|
||||
newWin.moveTo(500, 500);
|
||||
```
|
||||
|
||||
|
||||
## location对象
|
||||
|
||||
`window.location`可以简写成location。location相当于浏览器地址栏,可以将url解析成独立的片段。
|
||||
|
||||
### location对象的属性
|
||||
|
||||
- **href**:跳转
|
||||
|
||||
- hash 返回url中#后面的内容,包含#
|
||||
|
||||
- host 主机名,包括端口
|
||||
|
||||
- hostname 主机名
|
||||
|
||||
- pathname url中的路径部分
|
||||
|
||||
- protocol 协议 一般是http、https
|
||||
|
||||
- search 查询字符串
|
||||
|
||||
**location.href属性举例**:
|
||||
|
||||
**举例1:**点击盒子时,进行跳转。
|
||||
|
||||
```html
|
||||
<body>
|
||||
<div>smyhvae</div>
|
||||
<script>
|
||||
|
||||
var div = document.getElementsByTagName("div")[0];
|
||||
|
||||
div.onclick = function () {
|
||||
location.href = "http://www.baidu.com"; //点击div时,跳转到指定链接
|
||||
// window.open("http://www.baidu.com","_blank"); //方式二
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
```
|
||||
|
||||
**举例2:5秒后自动跳转到百度**。
|
||||
|
||||
有时候,当我们访问一个不存在的网页时,会提示5秒后自动跳转到指定页面,此时就可以用到location。举例:
|
||||
|
||||
```html
|
||||
<script>
|
||||
|
||||
setTimeout(function () {
|
||||
location.href = "http://www.baidu.com";
|
||||
}, 5000);
|
||||
</script>
|
||||
```
|
||||
|
||||
|
||||
### location对象的方法
|
||||
|
||||
- location.assign():改变浏览器地址栏的地址,并记录到历史中
|
||||
|
||||
设置location.href 就会调用assign()。一般使用location.href 进行页面之间的跳转。
|
||||
|
||||
- location.replace():替换浏览器地址栏的地址,不会记录到历史中
|
||||
|
||||
- location.reload():重新加载
|
||||
|
||||
|
||||
## navigator对象
|
||||
|
||||
window.navigator 的一些属性可以获取客户端的一些信息。
|
||||
|
||||
- userAgent:系统,浏览器)
|
||||
|
||||
- platform:浏览器支持的系统,win/mac/linux
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
console.log(navigator.userAgent);
|
||||
console.log(navigator.platform);
|
||||
```
|
||||
|
||||
效果如下:
|
||||
|
||||

|
||||
|
||||
|
||||
## history对象
|
||||
|
||||
1、历史记录管理
|
||||
|
||||
2、后退:
|
||||
|
||||
- history.back()
|
||||
|
||||
- history.go(-1):0是刷新
|
||||
|
||||
3、前进:
|
||||
|
||||
- history.forward()
|
||||
|
||||
- history.go(1)
|
||||
|
||||
用的不多。因为浏览器中已经自带了这些功能的按钮:
|
||||
|
||||

|
||||
|
||||
|
||||
## 我的公众号
|
||||
|
||||
想学习<font color=#0000ff>**代码之外的软技能**</font>?不妨关注我的微信公众号:**生命团队**(id:`vitateam`)。
|
||||
|
||||
扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外:
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -1,698 +0,0 @@
|
||||
|
||||
|
||||
> 本文最初发表于[博客园](http://www.cnblogs.com/smyhvae/p/8413602.html),并在[GitHub](https://github.com/smyhvae/Web)上持续更新**前端的系列文章**。欢迎在GitHub上关注我,一起入门和进阶前端。
|
||||
|
||||
> 以下是正文。
|
||||
|
||||
|
||||
## 绑定事件的两种方式
|
||||
|
||||
我们在上一篇文章 [DOM操作详解](http://www.cnblogs.com/smyhvae/p/8366012.html) 中已经讲过事件的概念。这里讲一下注册事件的两种方式,我们以onclick事件为例。
|
||||
|
||||
### 方式一:onclick
|
||||
|
||||
举例:
|
||||
|
||||
```html
|
||||
<body>
|
||||
<button>点我</button>
|
||||
<script>
|
||||
var btn = document.getElementsByTagName("button")[0];
|
||||
|
||||
//这种事件绑定的方法容易被层叠。
|
||||
btn.onclick = function () {
|
||||
console.log("事件1");
|
||||
}
|
||||
|
||||
btn.onclick = function () {
|
||||
console.log("事件2");
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
```
|
||||
|
||||
点击按钮后,上方代码的打印结果:
|
||||
|
||||
```html
|
||||
事件2
|
||||
```
|
||||
|
||||
我们可以看到,这种绑定事件的方式,会层叠掉之前的事件。
|
||||
|
||||
### 方式二:addEventListener
|
||||
|
||||
addEventListener()里的参数:
|
||||
|
||||
- 参数1:事件名(注意,没有on)
|
||||
|
||||
- 参数2:事件名(执行函数)
|
||||
|
||||
- 参数3:事件名(捕获或者冒泡)
|
||||
|
||||
举例:
|
||||
|
||||
```html
|
||||
<body>
|
||||
<button>按钮</button>
|
||||
<script>
|
||||
var btn = document.getElementsByTagName("button")[0];
|
||||
|
||||
//addEventListener: 事件监听器。 原事件被执行的时候,后面绑定的事件照样被执行
|
||||
//第二种事件绑定的方法不会出现层叠。(更适合团队开发)
|
||||
btn.addEventListener("click", fn1);
|
||||
btn.addEventListener("click", fn2);
|
||||
|
||||
function fn1() {
|
||||
console.log("事件1");
|
||||
}
|
||||
|
||||
function fn2() {
|
||||
console.log("事件2");
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
```
|
||||
|
||||
点击按钮后,上方代码的打印结果:
|
||||
|
||||
|
||||
```html
|
||||
事件1
|
||||
事件2
|
||||
```
|
||||
|
||||
我们可以看到,这种绑定事件的方式,不会层叠掉之前的事件。
|
||||
|
||||
## 事件对象
|
||||
|
||||
在触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含着所有与事件有关的信息。比如鼠标操作时候,会添加鼠标位置的相关信息到事件对象中。
|
||||
|
||||
所有浏览器都支持event对象,但支持的方式不同。如下。
|
||||
|
||||
(1)普通浏览器支持 event。比如:
|
||||
|
||||

|
||||
|
||||
(2)ie 678 支持 window.event。
|
||||
|
||||
于是,我们可以采取一种兼容性的写法。如下:
|
||||
|
||||
```javascript
|
||||
event = event || window.event; ////兼容性写法
|
||||
```
|
||||
|
||||
代码举例:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
//点击页面的任何部分
|
||||
document.onclick = function (event) {
|
||||
event = event || window.event; ////兼容性写法
|
||||
|
||||
console.log(event);
|
||||
console.log(event.timeStamp);
|
||||
console.log(event.bubbles);
|
||||
console.log(event.button);
|
||||
console.log(event.pageX);
|
||||
console.log(event.pageY);
|
||||
console.log(event.screenX);
|
||||
console.log(event.screenY);
|
||||
console.log(event.target);
|
||||
console.log(event.type);
|
||||
console.log(event.clientX);
|
||||
console.log(event.clientY);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
|
||||
### event 属性
|
||||
|
||||
event 有很多属性,比如:
|
||||
|
||||

|
||||
|
||||
由于pageX 和 pageY的兼容性不好,我们可以这样做:
|
||||
|
||||
- 鼠标在页面的位置 = 被卷去的部分+可视区域部分。
|
||||
|
||||
## Event举例
|
||||
|
||||
### 举例1:鼠标跟随
|
||||
|
||||
代码实现:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<title></title>
|
||||
<style>
|
||||
body {
|
||||
height: 5000px;
|
||||
}
|
||||
|
||||
img {
|
||||
position: absolute;
|
||||
padding: 10px 0;
|
||||
border: 1px solid #ccc;
|
||||
cursor: pointer;
|
||||
background-color: yellowgreen;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<img src="" width="100" height="100"/>
|
||||
|
||||
<script>
|
||||
//需求:点击页面的任何地方,图片跟随鼠标移动到点击位置。
|
||||
//思路:获取鼠标在页面中的位置,然图片缓慢运动到鼠标点击的位置。
|
||||
// 兼容ie67做pageY和pageX;
|
||||
// 原理: 鼠标在页面的位置 = 被卷去的部分+可视区域部分。
|
||||
//步骤:
|
||||
//1.老三步。
|
||||
//2.获取鼠标在页面中的位置。
|
||||
//3.利用缓动原理,慢慢的运动到指定位置。(包括左右和上下)
|
||||
|
||||
//1.老三步。
|
||||
var img = document.getElementsByTagName("img")[0];
|
||||
var timer = null;
|
||||
var targetx = 0;
|
||||
var targety = 0;
|
||||
var leaderx = 0;
|
||||
var leadery = 0;
|
||||
//给整个文档绑定点击事件获取鼠标的位置。
|
||||
document.onclick = function (event) {
|
||||
//新五步
|
||||
//兼容获取事件对象
|
||||
event = event || window.event;
|
||||
//鼠标在页面的位置 = 被卷去的部分+可视区域部分。
|
||||
var pagey = event.pageY || scroll().top + event.clientY;
|
||||
var pagex = event.pageX || scroll().left + event.clientX;
|
||||
|
||||
targety = pagey - 30;
|
||||
targetx = pagex - 50;
|
||||
|
||||
//要用定时器,先清定时器
|
||||
clearInterval(timer);
|
||||
timer = setInterval(function () {
|
||||
//为盒子的位置获取值
|
||||
leaderx = img.offsetLeft;
|
||||
//获取步长
|
||||
var stepx = (targetx - leaderx) / 10;
|
||||
//二次处理步长
|
||||
stepx = stepx > 0 ? Math.ceil(stepx) : Math.floor(stepx);
|
||||
leaderx = leaderx + stepx;
|
||||
//赋值
|
||||
img.style.left = leaderx + "px";
|
||||
|
||||
|
||||
//为盒子的位置获取值
|
||||
leadery = img.offsetTop;
|
||||
//获取步长
|
||||
var stepy = (targety - leadery) / 10;
|
||||
//二次处理步长
|
||||
stepy = stepy > 0 ? Math.ceil(stepy) : Math.floor(stepy);
|
||||
leadery = leadery + stepy;
|
||||
//赋值
|
||||
img.style.top = leadery + "px";
|
||||
|
||||
//清定时器
|
||||
if (Math.abs(targety - img.offsetTop) <= Math.abs(stepy) && Math.abs(targetx - img.offsetLeft) <= Math.abs(stepx)) {
|
||||
img.style.top = targety + "px";
|
||||
img.style.left = targetx + "px";
|
||||
clearInterval(timer);
|
||||
}
|
||||
}, 30);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
实现效果:
|
||||
|
||||

|
||||
|
||||
## event应用举例:获取鼠标距离所在盒子的距离
|
||||
|
||||
关键点:
|
||||
|
||||
```
|
||||
鼠标距离所在盒子的距离 = 鼠标在整个页面的位置 - 所在盒子在整个页面的位置
|
||||
```
|
||||
|
||||
代码演示:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<title></title>
|
||||
<style>
|
||||
.box {
|
||||
width: 300px;
|
||||
height: 200px;
|
||||
padding-top: 100px;
|
||||
background-color: pink;
|
||||
margin: 100px;
|
||||
text-align: center;
|
||||
font: 18px/30px "simsun";
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="box">
|
||||
|
||||
</div>
|
||||
|
||||
<script src="animate.js"></script>
|
||||
<script>
|
||||
//需求:鼠标进入盒子之后只要移动,哪怕1像素,随时显示鼠标在盒子中的坐标。
|
||||
//技术点:新事件,onmousemove:在事件源上,哪怕鼠标移动1像素也会触动这个事件。
|
||||
//一定程度上,模拟了定时器
|
||||
//步骤:
|
||||
//1.老三步和新五步
|
||||
//2.获取鼠标在整个页面的位置
|
||||
//3.获取盒子在整个页面的位置
|
||||
//4.用鼠标的位置减去盒子的位置赋值给盒子的内容。
|
||||
|
||||
//1.老三步和新五步
|
||||
var div = document.getElementsByTagName("div")[0];
|
||||
|
||||
div.onmousemove = function (event) {
|
||||
|
||||
event = event || window.event;
|
||||
//2.获取鼠标在整个页面的位置
|
||||
var pagex = event.pageX || scroll().left + event.clientX;
|
||||
var pagey = event.pageY || scroll().top + event.clientY;
|
||||
//3.获取盒子在整个页面的位置
|
||||
// var xx =
|
||||
// var yy =
|
||||
//4.用鼠标的位置减去盒子的位置赋值给盒子的内容。
|
||||
var targetx = pagex - div.offsetLeft;
|
||||
var targety = pagey - div.offsetTop;
|
||||
this.innerHTML = "鼠标在盒子中的X坐标为:" + targetx + "px;<br>鼠标在盒子中的Y坐标为:" + targety + "px;"
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
实现效果:
|
||||
|
||||

|
||||
|
||||
**举例:商品放大镜**
|
||||
|
||||
代码实现:
|
||||
|
||||
(1)index.html:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<title></title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.box {
|
||||
width: 350px;
|
||||
height: 350px;
|
||||
margin: 100px;
|
||||
border: 1px solid #ccc;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.big {
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 360px;
|
||||
border: 1px solid #ccc;
|
||||
overflow: hidden;
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*mask的中文是:遮罩*/
|
||||
.mask {
|
||||
width: 175px;
|
||||
height: 175px;
|
||||
background: rgba(255, 255, 0, 0.4);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
cursor: move;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.small {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
img {
|
||||
vertical-align: top;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script src="tools.js"></script>
|
||||
<script>
|
||||
window.onload = function () {
|
||||
//需求:鼠标放到小盒子上,让大盒子里面的图片和我们同步等比例移动。
|
||||
//技术点:onmouseenter==onmouseover 第一个不冒泡
|
||||
//技术点:onmouseleave==onmouseout 第一个不冒泡
|
||||
//步骤:
|
||||
//1.鼠标放上去显示盒子,移开隐藏盒子。
|
||||
//2.老三步和新五步(黄盒子跟随移动)
|
||||
//3.右侧的大图片,等比例移动。
|
||||
|
||||
//0.获取相关元素
|
||||
var box = document.getElementsByClassName("box")[0];
|
||||
var small = box.firstElementChild || box.firstChild;
|
||||
var big = box.children[1];
|
||||
var mask = small.children[1];
|
||||
var bigImg = big.children[0];
|
||||
|
||||
//1.鼠标放上去显示盒子,移开隐藏盒子。(为小盒子绑定事件)
|
||||
small.onmouseenter = function () {
|
||||
//封装好方法调用:显示元素
|
||||
show(mask);
|
||||
show(big);
|
||||
}
|
||||
small.onmouseleave = function () {
|
||||
//封装好方法调用:隐藏元素
|
||||
hide(mask);
|
||||
hide(big);
|
||||
}
|
||||
|
||||
//2.老三步和新五步(黄盒子跟随移动)
|
||||
//绑定的事件是onmousemove,而事件源是small(只要在小盒子上移动1像素,黄盒子也要跟随)
|
||||
small.onmousemove = function (event) {
|
||||
//新五步
|
||||
event = event || window.event;
|
||||
|
||||
//想要移动黄盒子,必须要知道鼠标在small小图中的位置。
|
||||
var pagex = event.pageX || scroll().left + event.clientX;
|
||||
var pagey = event.pageY || scroll().top + event.clientY;
|
||||
|
||||
//x:mask的left值,y:mask的top值。
|
||||
var x = pagex - box.offsetLeft - mask.offsetWidth / 2; //除以2,可以保证鼠标mask的中间
|
||||
var y = pagey - box.offsetTop - mask.offsetHeight / 2;
|
||||
|
||||
//限制换盒子的范围
|
||||
//left取值为大于0,小盒子的宽-mask的宽。
|
||||
if (x < 0) {
|
||||
x = 0;
|
||||
}
|
||||
if (x > small.offsetWidth - mask.offsetWidth) {
|
||||
x = small.offsetWidth - mask.offsetWidth;
|
||||
}
|
||||
//top同理。
|
||||
if (y < 0) {
|
||||
y = 0;
|
||||
}
|
||||
if (y > small.offsetHeight - mask.offsetHeight) {
|
||||
y = small.offsetHeight - mask.offsetHeight;
|
||||
}
|
||||
|
||||
//移动黄盒子
|
||||
console.log(small.offsetHeight);
|
||||
mask.style.left = x + "px";
|
||||
mask.style.top = y + "px";
|
||||
|
||||
//3.右侧的大图片,等比例移动。
|
||||
//如何移动大图片?等比例移动。
|
||||
// 大图片/大盒子 = 小图片/mask盒子
|
||||
// 大图片走的距离/mask走的距离 = (大图片-大盒子)/(小图片-黄盒子)
|
||||
// var bili = (bigImg.offsetWidth-big.offsetWidth)/(small.offsetWidth-mask.offsetWidth);
|
||||
|
||||
//大图片走的距离/mask盒子都的距离 = 大图片/小图片
|
||||
var bili = bigImg.offsetWidth / small.offsetWidth;
|
||||
|
||||
var xx = bili * x; //知道比例,就可以移动大图片了
|
||||
var yy = bili * y;
|
||||
|
||||
bigImg.style.marginTop = -yy + "px";
|
||||
bigImg.style.marginLeft = -xx + "px";
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="box">
|
||||
<div class="small">
|
||||
<img src="images/001.jpg" alt=""/>
|
||||
<div class="mask"></div>
|
||||
</div>
|
||||
<div class="big">
|
||||
<img src="images/0001.jpg" alt=""/>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
(2)tools.js:
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* Created by smyhvae on 2018/02/03.
|
||||
*/
|
||||
|
||||
//显示和隐藏
|
||||
function show(ele) {
|
||||
ele.style.display = "block";
|
||||
}
|
||||
|
||||
function hide(ele) {
|
||||
ele.style.display = "none";
|
||||
}
|
||||
|
||||
function scroll() { // 开始封装自己的scrollTop
|
||||
if (window.pageYOffset != null) { // ie9+ 高版本浏览器
|
||||
// 因为 window.pageYOffset 默认的是 0 所以这里需要判断
|
||||
return {
|
||||
left: window.pageXOffset,
|
||||
top: window.pageYOffset
|
||||
}
|
||||
}
|
||||
else if (document.compatMode === "CSS1Compat") { // 标准浏览器 来判断有没有声明DTD
|
||||
return {
|
||||
left: document.documentElement.scrollLeft,
|
||||
top: document.documentElement.scrollTop
|
||||
}
|
||||
}
|
||||
return { // 未声明 DTD
|
||||
left: document.body.scrollLeft,
|
||||
top: document.body.scrollTop
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
效果演示:
|
||||
|
||||

|
||||
|
||||
## 小窗口拖拽案例
|
||||
|
||||
暂略。
|
||||
|
||||
## 事件冒泡
|
||||
|
||||
事件传播的三个阶段是:事件捕获、事件冒泡和目标。
|
||||
|
||||
- 事件捕获阶段:事件从最上一级标签开始往下查找,直到捕获到事件目标 target。(从祖先元素往子元素查找,DOM树结构)。在这个过程中,事件相应的监听函数是不会被触发的。
|
||||
|
||||
- 事件目标:当到达目标元素之后,执行目标元素该事件相应的处理函数。如果没有绑定监听函数,那就不执行。
|
||||
|
||||
- 事件冒泡阶段:事件从事件目标 target 开始,往上冒泡直到页面的最上一级标签。(从子元素到祖先元素冒泡)
|
||||
|
||||
如下图所示:
|
||||
|
||||

|
||||
|
||||
PS:这个概念类似于 Android 里的 **touch 事件传递**。
|
||||
|
||||
|
||||
### 事件冒泡的概念
|
||||
|
||||
**事件冒泡**: 当一个元素上的事件被触发的时候(比如说鼠标点击了一个按钮),同样的事件将会在那个元素的所有**祖先元素**中被触发。这一过程被称为事件冒泡;这个事件从原始元素开始一直冒泡到DOM树的最上层。
|
||||
|
||||
|
||||
通俗来讲,冒泡指的是:**子元素的事件被触发时,父盒子的同样的事件也会被触发**。取消冒泡就是取消这种机制。
|
||||
|
||||
代码演示:
|
||||
|
||||
```javascript
|
||||
//事件冒泡
|
||||
box3.onclick = function () {
|
||||
alert("child");
|
||||
}
|
||||
|
||||
box2.onclick = function () {
|
||||
alert("father");
|
||||
}
|
||||
|
||||
box1.onclick = function () {
|
||||
alert("grandfather");
|
||||
}
|
||||
|
||||
document.onclick = function () {
|
||||
alert("body");
|
||||
}
|
||||
|
||||
```
|
||||
|
||||

|
||||
|
||||
上图显示,当我点击儿子 box3的时候,它的父亲box2、box1、body都依次被触发了。即使我改变代码的顺序,也不会影响效果的顺序。
|
||||
|
||||
**冒泡顺序**:
|
||||
|
||||
一般的浏览器: (除IE6.0之外的浏览器)
|
||||
|
||||
- div -> body -> html -> document -> window
|
||||
|
||||
IE6.0:
|
||||
|
||||
- div -> body -> html -> document
|
||||
|
||||
### 事件捕获
|
||||
|
||||
addEventListener可以捕获事件:
|
||||
|
||||
```javascript
|
||||
box1.addEventListener("click", function () {
|
||||
alert("捕获 box3");
|
||||
}, true);
|
||||
```
|
||||
|
||||
上面的方法中,参数为true,代表捕获;参数为false或者不写参数,代表冒泡。
|
||||
|
||||
代码演示:
|
||||
|
||||
```javascript
|
||||
//参数为true,代表捕获;参数为false或者不写参数,代表冒泡
|
||||
box3.addEventListener("click", function () {
|
||||
alert("捕获 child");
|
||||
}, true);
|
||||
|
||||
box2.addEventListener("click", function () {
|
||||
alert("捕获 father");
|
||||
}, true);
|
||||
|
||||
box1.addEventListener("click", function () {
|
||||
alert("捕获 grandfather");
|
||||
}, true);
|
||||
|
||||
document.addEventListener("click", function () {
|
||||
alert("捕获 body");
|
||||
}, true);
|
||||
```
|
||||
|
||||
效果演示:
|
||||
|
||||

|
||||
|
||||
### 不是所有的事件都能冒泡
|
||||
|
||||
以下事件不冒泡:blur、focus、load、unload、onmouseenter、onmouseleave。意思是,事件不会往父元素那里传递。
|
||||
|
||||
我们检查一个元素是否会冒泡,可以通过事件的以下参数:
|
||||
|
||||
```
|
||||
event.bubbles
|
||||
```
|
||||
|
||||
如果返回值为true,说明该事件会冒泡;反之则相反。
|
||||
|
||||
举例:
|
||||
|
||||
```javascript
|
||||
box1.onclick = function (event) {
|
||||
alert("冒泡 child");
|
||||
|
||||
event = event || window.event;
|
||||
console.log(event.bubbles); //打印结果:true
|
||||
}
|
||||
```
|
||||
|
||||
### 阻止冒泡的方法
|
||||
|
||||
w3c的方法:(火狐、谷歌、IE11)
|
||||
|
||||
```javascipt
|
||||
event.stopPropagation();
|
||||
```
|
||||
|
||||
IE10以下则是:
|
||||
|
||||
```javascipt
|
||||
event.cancelBubble = true
|
||||
```
|
||||
|
||||
兼容代码如下:
|
||||
|
||||
```javascipt
|
||||
box3.onclick = function (event) {
|
||||
|
||||
alert("child");
|
||||
|
||||
//阻止冒泡
|
||||
event = event || window.event;
|
||||
|
||||
if (event && event.stopPropagation) {
|
||||
event.stopPropagation();
|
||||
} else {
|
||||
event.cancelBubble = true;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
上方代码中,我们对box3进行了阻止冒泡,产生的效果是:事件不会继续传递到 father、grandfather、body了。
|
||||
|
||||
## 事件委托
|
||||
|
||||
事件委托,通俗地来讲,就是把一个元素响应事件(click、keydown......)的函数委托到另一个元素。
|
||||
|
||||
比如说有一个列表 ul,列表之中有大量的列表项 li,我们需要在点击列表项li的时候响应一个事件。如果给每个列表项一一都绑定一个函数,那对于内存消耗是非常大的,效率上需要消耗很多性能。
|
||||
|
||||
因此,比较好的方法就是把这个点击事件绑定到他的父层,也就是 `ul` 上,然后在执行事件的时候再去匹配判断目标元素。
|
||||
|
||||
所以事件委托可以减少大量的内存消耗,节约效率。
|
||||
|
||||
事件委托的参考链接:[JavaScript 事件委托详解](https://zhuanlan.zhihu.com/p/26536815)
|
||||
|
||||
|
||||
## 我的公众号
|
||||
|
||||
想学习<font color=#0000ff>**代码之外的软技能**</font>?不妨关注我的微信公众号:**生命团队**(id:`vitateam`)。
|
||||
|
||||
扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外:
|
||||
|
||||

|
||||
Reference in New Issue
Block a user