JS简介
- HTML 定义了网页的内容
- CSS 描述了网页的布局
- JavaScript 网页的行为
基础知识
用途
一般把JavaScript代码放到一个单独的.js文件,然后在HTML中引入这个文件:
<html>
<head>
<script src="/static/js/abc.js"></script>
</head>
<body>
...
</body>
</html>
可以在同一个页面中引入多个.js文件,还可以在页面中多次编写,浏览器按照顺序依次执行。
语句
JavaScript的语法和Java语言类似,每个语句以;结束,语句块用{…}。如赋值,条件语块:
var a = 1;
if (a>2){
b=2;
c=1;//注意花括号{...}内的语句具有缩进,通常是4个空格。缩进不是JavaScript语法要求必须的,但缩进有助于我们理解代码的层次.
}
数据类型
Number
不区分浮点数数和整数。同时还包括NaN(无法计算)和Infinity(无限大)
字符串
“”和‘’中的内容。如“abc”。
由于多行字符串用\n写起来比较费事,所以最新的ES6标准新增了一种多行字符串的表示方法,用反引号 ``表示
和python中的字符串一样,这里也可以用+来进行字符串的拼接。不过我们还是会避免这样:
var name = '小明';
var age = 20;
var message = `你好, ${name}, 你今年${age}岁了!`;
alert(message);
字符串是不可变的,如果对字符串的某个索引赋值,不会有任何错误,但是,也没有任何效果:
JavaScript为字符串提供了一些常用方法,注意,调用这些方法本身不会改变原有字符串的内容,而是返回一个新字符串
toUpperCase toLowerCase indexOf substring(切片)
布尔值
true false
比较运算符
注意两个等于:第一种是==
比较,它会自动转换数据类型再比较,很多时候,会得到非常诡异的结果;第二种是===
比较,它不会自动转换数据类型,如果数据类型不一致,返回false,如果一致,再比较。
NaN不等于任何,只能用isNan判断
注意浮点数的比较
null
null
表示一个“空”的值,它和0
以及空字符串''
不同,0是一个数值,''
表示长度为0的字符串,而null
表示“空”。
数组
数组是一组按顺序排列的集合,集合的每个值称为元素。JavaScript的数组可以包括任意数据类型。数组的长度在定义后都能改变
var arr = [1, 2, 3.14, 'Hello', null, true];
arr[0]; // 返回索引为0的元素,即1
arr[5]; // 返回索引为5的元素,即true
arr[6]; // 索引超出了范围,返回undefined
请注意,直接给Array的length赋一个新的值会导致Array大小的变化。
请注意,如果通过索引赋值时,索引超过了范围,同样会引起Array大小的变化:
var arr = [1, 2, 3];
arr[5] = 'x';
arr; // arr变为[1, 2, 3, undefined, undefined, 'x']
push()向Array的末尾添加若干元素,pop()则把Array的最后一个元素删除掉。
如果要往Array的头部添加若干元素,使用unshift()方法,shift()方法则把Array的第一个元素删掉。
sort()可以对当前Array进行排序,它会直接修改当前Array的元素位置,直接调用时,按照默认顺序排序。
slice()就是对应String的substring()版本,它截取Array的部分元素,然后返回一个新的Array:
var arr = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
arr.slice(0, 3); // 从索引0开始,到索引3结束,但不包括索引3: ['A', 'B', 'C']
arr.slice(3); // 从索引3开始到结束: ['D', 'E', 'F', 'G']
splice()方法是修改Array的“万能方法”,它可以从指定的索引开始删除若干元素,然后再从该位置添加若干元素:
var arr = ['Microsoft', 'Apple', 'Yahoo', 'AOL', 'Excite', 'Oracle'];
// 从索引2开始删除3个元素,然后再添加两个元素:
arr.splice(2, 3, 'Google', 'Facebook'); // 返回删除的元素 ['Yahoo', 'AOL', 'Excite']
arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']
// 只删除,不添加:
arr.splice(2, 2); // ['Google', 'Facebook']
arr; // ['Microsoft', 'Apple', 'Oracle']
// 只添加,不删除:
arr.splice(2, 0, 'Google', 'Facebook'); // 返回[],因为没有删除任何元素
arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']
concat()方法把当前的Array和另一个Array连接起来,并返回一个新的Array
join()方法是一个非常实用的方法,它把当前Array的每个元素都用指定的字符串连接起来,然后返回连接后的字符串
对象
var person = {
name: 'Bob',
age: 20,
tags: ['js', 'web', 'mobile'],
city: 'Beijing',
hasCar: true,
zipcode: null
};
JavaScript对象的键都是字符串类型,值可以是任意数据类型。
要获取一个对象的属性,我们用对象变量.属性名的方式。
访问属性是通过.操作符完成的,但这要求属性名必须是一个有效的变量名。如果属性名包含特殊字符,就必须用’'括起来,且必须用[‘xxx’]来访问。
JavaScript规定,访问不存在的属性不报错,而是返回undefined。
由于JavaScript的对象是动态类型,你可以自由地给一个对象添加或删除属性:有点类似python。
strict模式
JavaScript在设计之初,为了方便初学者学习,并不强制要求用var
申明变量。这个设计错误带来了严重的后果:如果一个变量没有通过var
申明就被使用,那么该变量就自动被申明为全局变量:
在同一个页面的不同的JavaScript文件中,如果都不用var
申明,恰好都使用了变量i,将造成变量i互相影响,产生难以调试的错误结果。使用var
申明的变量则不是全局变量,它的范围被限制在该变量被申明的函数体内,同名变量在不同的函数体内互不冲突。为了修补JavaScript这一严重设计缺陷,ECMA在后续规范中推出了strict模式,在strict模式下运行的JavaScript代码,强制通过var申明变量,未使用var申明变量就使用的,将导致运行错误。
启用strict模式的方法是在JavaScript代码的第一行写上:
"using strict"
有的JavaScript代码都应该使用strict模式。我们在后面编写的JavaScript代码将全部采用strict模式。
判断
JavaScript使用if () { … } else { … }来进行条件判断
循环
for:
var x = 0;
var i;
for (i=1; i<=10000; i++) {
x = x + i;
}
for … in:
for循环的一个变体是for … in循环,它可以把一个对象的所有属性依次循环出来:
var o = {
name: 'Jack',
age: 20,
city: 'Beijing'
};
for (var key in o) {
if (o.hasOwnProperty(key)) {
console.log(key); // 'name', 'age', 'city'
}
}
请注意,for … in对Array的循环得到的是String而不是Number。
while (){}
map和set
JavaScript的默认对象表示方式{}可以视为其他语言中的Map或Dictionary的数据结构,即一组键值对。但是JavaScript的对象有个小问题,就是键必须是字符串。但实际上Number或者其他数据类型作为键也是非常合理的。
MAP就是可以解决这个问题。
var m = new Map(); // 空Map
m.set('Adam', 67); // 添加新的key-value
m.set('Bob', 59);
m.has('Adam'); // 是否存在key 'Adam': true
m.get('Adam'); // 67
m.delete('Adam'); // 删除key 'Adam'
m.get('Adam'); // undefined
由于一个key只能对应一个value,所以,多次对一个key放入value,后面的值会把前面的值冲掉
Set和Map类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在Set中,没有重复的key。要创建一个Set,需要提供一个Array作为输入,或者直接创建一个空Set:
s = new Set([1,2,3])//s = new Set()
s.add(4);
s; // Set {1, 2, 3, 4}
s.add(4);
s; // 仍然是 Set {1, 2, 3, 4}
s.delete(3);
s; // Set {1, 2}
iterable
遍历Array可以采用下标循环,遍历Map和Set就无法使用下标。为了统一集合类型,ES6标准引入了新的iterable类型,Array、Map和Set都属于iterable类型。具有iterable类型的集合可以通过新的for … of循环来遍历。
var a = ['A', 'B', 'C'];
var s = new Set(['A', 'B', 'C']);
var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
for (var x of a) { // 遍历Array
console.log(x);
}
for (var x of s) { // 遍历Set
console.log(x);
}
for (var x of m) { // 遍历Map
console.log(x[0] + '=' + x[1]);
}
var a = ['A', 'B', 'C'];
a.name = 'Hello';
for (var x in a) {
console.log(x); // '0', '1', '2', 'name'
}
f
for … of循环和for … in循环有何区别?for … in循环由于历史遗留问题,它遍历的实际上是对象的属性名称。一个Array数组实际上也是一个对象,它的每个元素的索引被视为一个属性(字符)。当我们手动给Array对象添加了额外的属性后,for … in循环将带来意想不到的意外效果,or … in循环将把name包括在内,但Array的length属性却不包括在内。for … of循环则完全修复了这些问题,它只循环集合本身的元素:
var a = ['A', 'B', 'C'];
a.name = 'Hello';
for (var x of a) {
console.log(x); // 'A', 'B', 'C'
}