Js基本语法
在哪里引入Js代码?
1)首先JavaScript代码可以直接嵌在网页的任何地方,不过通常我们都把JavaScript代码放到<head>
中,我们看到网页的源码的时候被<script>...</script>
包含的代码就是JavaScript代码,它会直接被浏览器执行。
2)单独的写一个 .js文件,然后在HTML中通过<script src="..."></script>
引入这个文件。这样的话是方便多个网页应用到了同一份Js文件。
数据类型,运算符以及变量的申明
1)Js的数据类型主要有Number,布尔值,字符串。JavaScript不区分整数和浮点数,统一用Number表示。
1 | 123; // 整数123 |
Number可以直接做四则运算,规则和数学一致。
注意一个点:字符串也可以使用加号,但是字符串将被级联但是注意字符串和数字相加会返回一个字符串,例如:
1 | var x = "8" + 3 + 5; |
布尔值的话只能有false,true两种。
字符串的话就跟Java,c++的都差不多,不过JavaScript中以单引号’或双引号”括起来的任意文本都是字符串。
2)运算符:&&
运算,||
运算,!
运算,比较运算符。基本上都差不多,但是要注意的是相等运算符==
。JavaScript在设计时,有两种比较运算符:
第一种是==
比较,它会自动转换数据类型再比较,很多时候,会得到非常诡异的结果;
第二种是===
比较,它不会自动转换数据类型,如果数据类型不一致,返回false
,如果一致,再比较。
通常的话我们是坚持使用===
。
另外是NaN
这个特殊的Number,它和其他所有的值都不相等,包括本身。唯一能判断NaN
的方法是通过isNaN()
函数。
3)变量的申明方式
变量名的要求:变量名是大小写英文、数字、$
和_
的组合,且不能用数字开头。变量名也不能是JavaScript的关键字,如if
、while
等。
1 | var age = 15; |
同一个变量可以反复赋值,而且可以是不同类型的变量,但是要注意只能用var
申明一次,注意在JavaScript中通过赋值可以修改变量的数据类型,JavaScript是一个动态的语言。像Java这种静态的语言就不能这样的进行赋值。
注意:不用var
申明的变量会被视为全局变量,为了避免这一缺陷,所有的JavaScript代码都应该使用strict模式。我们在后面编写的JavaScript代码将全部采用strict模式。
字符串
在前面我们看到字符串就是用''
或""
括起来的字符。跟c++一样有转义字符,具体的熟悉一下就行。
通过+
来连接字符串。
通过s.length
来获取字符的长度
通过下标索引获取字符串某个指定位置的字符,索引号从0开始,需要注意的是,字符串是不可变的,如果对字符串的某个索引赋值,不会有任何错误,但是,也没有任何效果,如下:
1 | var s = 'Test'; |
toUpperCase()
把一个字符串全部变为大写
toLowerCase()
把一个字符串全部变为小写:
indexOf()
会搜索指定字符串出现的位置(字符串第一个出现该字符的位置)
substring()
返回指定索引区间的子串
split()
把字符串转换为数组
1 | var txt = "a,b,c,d,e"; // 字符串 |
数组和对象
通过arr.length
获取数组长度,直接给Array
的length
赋一个新的值会导致Array
大小的变化如:
1 | var arr = [1, 2, 3]; |
和字符串不同,数组可以通过下表索引修改对应的元素值。但是要是索引超过范围的话同样会导致数组大小的变化。
通过indexOf()
来搜索一个指定的元素的位置(同字符串第一个出现该字符的位置)
slice()
截取Array
的部分元素,然后返回一个新的Array
push()
向Array
的末尾添加若干元素,pop()
则把Array
的最后一个元素删除掉
往Array
的头部添加若干元素,使用unshift()
方法,shift()
方法则把Array
的第一个元素删掉
sort()
可以对当前Array
进行排序,它会直接修改当前Array
的元素位置
reverse()
把整个Array
反转
splice()
方法可以从指定的索引开始删除若干元素,然后再从该位置添加若干元素
concat()
方法把当前的Array
和另一个Array
连接起来,并返回一个新的Array
,并不是修改当前的数组。
join()
方法能把当前Array
的每个元素都用指定的字符串连接起来,然后返回连接后的字符串。
练习:在新生欢迎会上,你已经拿到了新同学的名单,请排序后显示:欢迎XXX,XXX,XXX和XXX同学!
:
1 | ; |
JavaScript用一个{...}
表示一个对象,键值对以xxx: xxx
形式申明,用,
隔开。注意,最后一个键值对不需要在末尾加,
可以通过delete删除属性,赋值增加属性如:
1 | var xiaoming = { |
利用in
操作符检测是否拥有一个属性,但是注意所有对象最终都会在原型链上指向object
,所以我们定义的对象都有object
对象的属性,所以要判断一个属性是否是我们定义的对象拥有的,而不是继承得到的,可以用hasOwnProperty()
方法
容器和一些控制语句
条件判断if...else
,这些都差不多,就是逻辑的判断。
练习:小明身高1.75,体重80.5kg。请根据BMI公式(体重除以身高的平方)帮小明计算他的BMI指数,并根据BMI指数:
- 低于18.5:过轻
- 18.5-25:正常
- 25-28:过重
- 28-32:肥胖
- 高于32:严重肥胖
用if...else...
判断并显示结果:
1 | ; |
循环也是一样利用for
或者while
或者do...while
练习:
利用for
循环计算1 * 2 * 3 * ... * 10
的结果:
1 | ; |
请利用循环遍历数组中的每个名字,并显示Hello, xxx!
:
1 | ; |
Map和Set容器
Map
是一组键值对的结构,利用key
和value
。常用的函数有set
,delete
,get
。用法都差不多。
set
一组key的集合且不重复,常用的函数有delete
,add
。
iterable
类型,Array
、Map
和Set
都属于iterable
类型。具有iterable
类型的集合可以通过新的for ... of
循环来遍历。因为遍历Array
可以采用下标循环,遍历Map
和Set
就无法使用下标。如:
1 | var a = ['A', 'B', 'C']; |
或者通过forEach()
方法循环,forEach()
有三个参数
1 | var s = new Set(['A', 'B', 'C']); |
如果对某些参数不感兴趣,由于JavaScript的函数调用不要求参数必须一致,可以忽略。
Js 函数
函数
函数定义如下:
1 | function abs(x) { |
JavaScript在调用参数的时候允许任意个参数调用,不管传多还是传少都不会报错。因此JavaScript提供了一个关键字arguments
,它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数。arguments
类似Array
但它不是一个Array
,利用它可以判断传入参数的个数。
之后JavaScript又引入了rest参数,rest参数只能写在最后,前面用...
标识,从运行结果可知,传入的参数先绑定a
、b
,多余的参数以数组形式交给变量rest
,所以,不再需要arguments
我们就获取了全部参数。如
1 | function foo(a, b, ...rest) { |
练习:
请用rest参数编写一个sum()
函数,接收任意个参数并返回它们的和:
1 | ; |
定义一个计算圆面积的函数area_of_circle()
,它有两个参数:
r: 表示圆的半径;
pi: 表示π的值,如果不传,则默认3.14
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22;
function area_of_circle(r, pi) {
var area;
if (arguments.length == 2) {
area = pi * r * r;
} else if (arguments.length < 2){
pi = 3.14;
area = pi * r * r;
}
else{
console.log("arguments number must be 1 or 2.");
return ;
}
return r * r * (pi || 3.14);
}
// 测试:
if (area_of_circle(2) === 12.56 && area_of_circle(2, 3.1416) === 12.5664) {
console.log('测试通过');
} else {
console.log('测试失败');
}
函数变量作用域以及解析赋值
在JavaScript中,用var
申明的变量实际上是有作用域的。一个变量在函数体内部申明,则该变量的作用域为整个函数体,在函数体外不可引用该变量,但是由于JavaScript的函数可以嵌套,此时,内部函数可以访问外部函数定义的变量。但是如果内部函数和外部函数的变量名重名的情况下在查找变量时从自身函数定义开始,从“内”向“外”查找。如果内部函数定义了与外部函数重名的变量,则内部函数的变量将“屏蔽”外部函数的变量。看样例:
1 | function foo() { |
而且JavaScript的函数定义有个特点,它会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部,也就是所有的变量都会在函数初步就定义了。
同时JavaScript默认有一个全局对象window
,不在任何函数内定义的变量就具有全局作用域,全局作用域的变量实际上被绑定到window
的一个属性。我们在之前说过函数定义有两种方式,以变量方式var foo = function () {}
定义的函数实际上也是一个全局变量,因此,顶层函数的定义也被视为一个全局变量,并绑定到window
对象,其实我们每次直接调用的alert()
函数其实也是window
的一个变量。
所以JavaScript中任何变量(函数也视为变量),如果没有在当前函数作用域中找到,就会继续往上查找,最后如果在全局作用域中也没有找到,则报ReferenceError
错误。
因此在这个基础上,个人感觉引用了c++的using namespace std
命名空间的概念,在JavaScript中有一个名字空间,因为全局变量会绑定到window
上,不同的JavaScript文件如果使用了相同的全局变量,或者定义了相同名字的顶层函数,就会造成命名冲突,解决的方式就是把自己的所有变量和函数绑定到一个全局变量里面会减少全局变量冲突的几率。
1 | // 唯一的全局变量MYAPP: |
解构赋值:在ES6后引入了这个解构赋值,直接对于多个变量同时赋值如:
1 | var [x, y, z] = ['hello', 'JavaScript', 'ES6']; |
同理解构赋值也能对对象进行同样的操作如:
1 | var person = { |
方法和高阶函数
在一个对象中绑定函数,那么就成为这个对象的方法,如
1 | var xiaoming = { |
在函数内部this
是一个特殊变量,它始终指向当前对象,也就是xiaoming
这个变量。所以,this.birth
可以拿到xiaoming
的birth
属性,但是我们要注意this
这个指向,最好是在引用函数之前就把这个this
给记录下来如that
,然后在方法内定义其他的函数,用that
去代替this
;或者呢用aplpy
函数去修复,apply
它接收两个参数,第一个参数就是需要绑定的this
变量,第二个参数是Array
,表示函数本身的参数。同样有个call
函数。
一个很重要的点高阶函数:
什么叫高阶函数?高阶函数指最少满足下列条件之一的函数:函数可以作为参数传递,函数可以作为返回值输出。(理解的不够,再细致的理解再补)
map
/reduce
函数:它们都是Array
中定义的,我们调用Array
的map()
方法,传入我们自己的函数,就得到了一个新的Array
作为结果,比方说我要得到一个数组中每个数的平方:
1 | ; |
reduce
函数的话是把一个函数作用在这个Array
的[x1, x2, x3...]
上,这个函数必须接收两个参数,reduce()
把结果继续和序列的下一个元素做累积计算,实际能做的事情是对一个数组进行重复的处理,比方说求和,求积,如:
1 | ’use strict'; |
把[1, 3, 5, 7, 9]
变换成整数13579,reduce()
也能派上用场:
1 | var arr = [1, 3, 5, 7, 9]; |
练习:
不要使用JavaScript内置的parseInt()
函数,利用map和reduce操作实现一个string2int()
函数:
1 | ; |
请把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。输入:['adam', 'LISA', 'barT']
,输出:['Adam', 'Lisa', 'Bart']
。
1 | ; |
小明希望利用map()
把字符串变成整数,他写的代码很简洁:
1 | ; |
这个主要是parseInt的一些误区,后序会写篇来介绍这个,先暂时性看这个理解一下https://blog.csdn.net/wjl84945979/article/details/56478927
filter
函数filter()
把传入的函数依次作用于每个元素,然后根据返回值是true
还是false
决定保留还是丢弃该元素。类似一个筛选的功能,例如:在一个Array
中,删掉偶数,只保留奇数
1 | var arr = [1, 2, 4, 5, 6, 9, 10, 15]; |
看上面的调用filter()
接收的回调函数,其实可以有多个参数。通常我们仅使用第一个参数,表示Array
的某个元素。回调函数还可以接收另外两个参数,表示元素的位置和数组本身。
练习:
请尝试用filter()
筛选出素数:
1 | ; |