一、JavaScript 简介
JavaScript 诞生于 1995年,是一种专为与网页交互而设计的脚本语言。由三种不同部分组成:
- ECMAScript,提供核心语言功能;
- 文档对象模型(DOM),提供访问和操作网页内容的方法和接口;
- 浏览器对象模型(BOM),提供和浏览器交互的方法和接口
1.1 ECMScript
ECMScript 是这本语言的基础,规定了这门语言的下列组成部分:
1.2 文档对象模型(DOM)
文档对象模型(DOM, Document Object Model) 是针对XML但经过扩展用于HTML的应用程序编程接口。提供了以下方法和接口的定义:
- DOM 视图;
- DOM 事件;
- DOM 样式;
- DOM 遍历和方法;
- SVG;
- MathML;
- SMIL;
1.3 浏览器对象模型(BOM)
浏览器对象模型(BOM, Browser Object Model) 用来访问和操作浏览器窗口,有以下的扩展:
- 弹出新浏览器窗口的功能;
- 移动、缩放和关闭浏览器窗口的功能;
- 提供浏览器详细信息的 navigator 对象;
- 提供浏览器所加载页面的详细信息的 location 对象;
- 提供用户显示器分辨率详细信息的 screen 对象;
- 对 cookies 的支持;
- 像 XMLHttpRequest 和 IE 的 ActiveXObject 这样自定义对象;
二、在 HTML 中使用 JavaScript
2.1 内嵌脚本
在 HTML 内部直接写入 <script> 片断,这种写法要注意JavaScript 是单线程的,如果在初始化页面的时候,你的代码中存在大量同步运行的代码,导致 JS 线程一直处于繁忙状态,这时候用户在页面上进行交互时将不会得到任何反应,就像是卡死了一样。想了解具体原因,参考文章浏览器渲染原理
2.2 引入外部脚本
<script src="example.js" src="defer"></script>
- defer属性让脚本在文档完全呈现之后再执行
- async属性表示当前文本不用等待其他文本,异步执行。
三、基本概念
3.1 变量
ESCAScript 的变量是 松散类型 的,就是说可以用来保存任何类型的数据。也就是说一个变量就是一个占位符。
定义变量可以使用 var 操作符,定义多个变量,每个变量之间用 逗号 分开,如果 省略 var 操作符可以定义 全局变量,未经初始化的变量,会保存一个特殊的值—— undefined
function show() {
var _message = '局部变量',
_name = 'lily';
g_message = '全局变量';
}
show();
console.log(g_message); // 全局变量
console.log(_message); // _message is not defined
在 ESCScript 中变量会被自动 提升
console.log(enhance); // 变量提升
var enhance = "变量提升";
3.2 数据类型
ECMAScript 有6种数据类型,其中5种基本的数据类型: Undefined、Null、Boolean、Number和String,还有1种复杂的数据类型: Object。一般使用 typeof 检查5种基本的数据类型,使用 instanceof 检查是哪种复杂的数据类型。
-
typeof
常见的就不说了,说几个可能容易混或者错的。
| 值 |
使用typeof操作符返回 |
| 值未初始化 |
'undefined' |
| 值对象、null |
'Object' |
| 值是函数 |
'function' |
// 未初始化的变量
var uninital;
console.log('未初始化的变量:---' +typeof uninital); // undefined
// 未定义的变量
console.log('未定义的变量:---' + typeof liy); // undefined
// 值为null
var obj = null;
console.log('值是null的时候:---' + typeof obj); // object
// 值未函数
function add (a, b) {
return a + b;
}
console.log('值是funciton:---' + typeof add); // function
-
Boolean 类型
Boolean 类型是 ECMAScript 中使用最多的一种类型,只有两个字面量值: true、false;区分大小写,也就是说 True 不是布尔值。
流程控制语句(例如 if 语句)自动执行 转型函数 Boolean()。
var message = "hello world";
if (message) {
console.log('转换为 true'); // 执行这句
} else {
console.log('转换为 false');
}
下表给出了几种数据类型及其对应的转换规则
| 数据类型 |
转换为true 值 |
转换为false值 |
| Boolean |
true |
false |
| String |
任何非空字符串 |
''(空字符串) |
| Number |
任何非0数字(包括无穷大) |
0、NaN |
| Object |
任何对象 |
null |
| Undefined |
不适用 |
undefined |
-
Number 类型
- 浮点数值计算会产生舍入误差
- isFinite(值) 用于判断一个数值是不是位于最小值和最大值之间
var result = Number.MAX_VALUE + Number.MAX_VALUE;
console.log('数值是否是有穷的:' + isFinite(result)); // false
- isNan(值) 用于判断一个数值是不是非数值。isNaN 也适用于对象。在基于对象调用 isNaN() 函数时,会首先调用对象的 valueof() 方,然后确定返回值是否可以转换为数值。如果不能,则基于这个返回值再调用 toString() 方法,再测试返回值。
console.log(isNaN(10)); // false
console.log(isNaN('10')); // false
console.log(NaN == NaN); // false
- 将数值转换为数值:Number(值), parseInt(值,几进制),parseFloat(值,几进制)
console.log(Number('hello')); // NaN
console.log(Number('')); // 0
-
String 类型
-
Object 类型
访问对象的属性有两种方式
person['name']
person.name
3.3 操作符
-
布尔操作符
逻辑非和逻辑或都是 短路 操作符
-
关系操作符
console.log('Brink'.toLowerCase() < 'alpha'.toLowerCase()); // false
console.log(NaN < 3); // false
3.4 语句
-
for 语句
在 ECMAScript 中没有块级作用域的概念,因此循环内部定义的变量也可以在外部访问到。
for (var i = 0;i < 10 ; i++) {}
console.log(i); //10
其实以上的代码就相当于
var j;
for (j = 0; j < 10; j ++) {}
console.log(j);
-
for-in 语句
for-in 语句用来遍历对象的属性,但此时的对象不能是null或者undefined。
-
switch 语句
switch 语句在比较值的时候使用的是全等
看一个我觉得很新颖的语句
var num = 18;
switch (true) {
case num < 0:
alert('less than 0');
break;
case num > 0 && num < 10:$
alert('between 0 and 10');
breka;
default:
alert('more than 10');
}
-
函数
可以向 ECMAScript 函数传递任意数量的参数,并且可以通过arguments对象来访问这些参数。即便你定义的函数只接收两个参数,在调用这个函数也未必一定传递两个参数,可以传递一个、三个甚至不传递参数。如果没传递值的命名参数将自动被赋予undefined值。
function add() {
if (arguments.length == 1) {
alert(arguments[0] + 10);
} else {
alert(arguments[0] + arguments[1]);
}
}
add(10); // 20
四、变量、作用域和内存问题
4.1 变量
ECMAScript 变量包含两种不同类型的值:基本类型和引用类型值。
-
基本类型的值
-
引用类型
4.2 执行环境和作用域
- 执行环境
执行环境定义了变量或函数有权访问的其他数据,决定了他们的行为;
执行环境可以分为**全局执行环境** 和 **每个函数自己的执行环境**;
- 作用域链
代码在执行环境中执行,会创建对象的一个 **作用域链**,这个作用域链可以保证对执行环境有权访问的所有变量和函数的有序访问。
4.3 内存管理
优化内存占用的最佳方式,就是为代码只保存必要的数据。一旦数据不再用了,最好通过将其值设置为 null 来释放引用。
function cretePerson(name) {
var localPerson = new Object();
localPerson.name = name;
return localPerson;
}
var g_person = cretePerson('lily');
g_person = null;
五、引用类型
在 ECMAScript中,引用类型是一种数据结构,常用的有:Object、Date、RegExp、Function、基本包装类型、单体内置对象。
5.1 Array 类型
-
插入
- 在末尾插入数据:
arr[length] = 'add data from bottom';
- 在末尾插入数据:
arr.push('add data from bottom');
- 在头部插入数据:
arr.unshift('add data from head');
- 在任意位置插入数据,返回删除数据组成的数组:
splice(2,0,'red','green');,三个参数,第一个是位置,第二个是要删除的数据个数,第三个数据为插入的数据;
-
删除
- 在末尾删除数据:
arr[length] = arr.length - 1;
- 在末尾删除数据,返回删除的数据:
arr.pop();
- 在头部删除数据,返回删除的数据:
arr.shift();
- 任意位置删除,返回删除数据的数组:
arr.splice(0,1);,两个参数,第一个参数是位置,第二个参数是要删除的个数;
-
替换
- 替换任意位置数据,返回被替换的数据组成数组:
arr.splice(2,1,'red')
-
检测数组
检测是否是数组
if(Array.isArray(value)){}
-
转换为字符串的方法
- join
- toString
- tolocalString
- valueOf
-
排序方法
-
合并
var color1 = ['color1', 'color2'];
var color2 = color1.concat('yellow'); // color1,color2,yellow
-
位置方法
- indexof('要查找内容',起始位置),不包含返回 -1
- lastIndexof
-
迭代
- every(): 对数组的每一项运行给定函数,每一项都 true 的时候,返回 true;
- some(): 对数组中的每一项运行给定函数,有任意一项返回 true 时候,才会返回 true;
- filter(): 对数组中的每一项都运行给定函数,返回该函数返回 true 项组成的数组
- forEach(): 对数组中的每一项运行给定的函数,无返回值
- map(): 对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。
10.归并数组
- reduce
- reduceRight
5.1 Function 类型
函数分为函数声明和函数表达式,函数表达式可以随时访问,因为函数声明提升。
- 函数内部属性
window.color = 'red';
var obj = {color: 'obj bule'};
function showColor () {
console.log(this.color);
}
showColor(); // red
obj.sayColor = showColor;
obj.sayColor(); // obj bule
- 非继承的函数方法
每个函数都包含两个方法:call() 和 apply()。这两个方法的用途都是在特定的作用域中调用函数,实际上就是设置函数体内this的值。
-
apply(运行函数的作用域, 参数数组)
window.color = 'window color red';
var obj = {color: 'obj color blue'};
function showColor(data) {
console.log(this.color); //window color red
console.log(`传入数据${data}`);
}
showColor();
showColor.apply(obj, ['我用了apply']);
// obj color blue 传入数据我用了apply
-
call(运行函数的作用域,其余参数)
window.color = 'window color red';
var obj = {color: 'obj color blue'};
function showColor(data) {
console.log(this.color); //window color red
console.log(`传入数据${data}`);
}
showColor.call(obj, '我用了call');
//obj color blue
//传入数据我用了call
5.1 String 类型
1. length
2. charAt(位置)
3. charCodeAt(位置):返回字符编码
4. substring(start, [end])
5. substr(start, [end])
6. slice(start, [end])
7. indexof(要查找内容,位置)
8. trim: 去除空格
9. toUpperCase
10. toLocaleUpperCase
11. toLowerCase
12. toLocalLowerCase
13. split(切割符),返回数组
一、JavaScript 简介
JavaScript 诞生于 1995年,是一种专为与网页交互而设计的脚本语言。由三种不同部分组成:
1.1 ECMScript
ECMScript 是这本语言的基础,规定了这门语言的下列组成部分:
1.2 文档对象模型(DOM)
文档对象模型(DOM, Document Object Model) 是针对XML但经过扩展用于HTML的应用程序编程接口。提供了以下方法和接口的定义:
1.3 浏览器对象模型(BOM)
浏览器对象模型(BOM, Browser Object Model) 用来访问和操作浏览器窗口,有以下的扩展:
二、在 HTML 中使用 JavaScript
2.1 内嵌脚本
在 HTML 内部直接写入
<script>片断,这种写法要注意JavaScript 是单线程的,如果在初始化页面的时候,你的代码中存在大量同步运行的代码,导致 JS 线程一直处于繁忙状态,这时候用户在页面上进行交互时将不会得到任何反应,就像是卡死了一样。想了解具体原因,参考文章浏览器渲染原理2.2 引入外部脚本
三、基本概念
3.1 变量
ESCAScript 的变量是 松散类型 的,就是说可以用来保存任何类型的数据。也就是说一个变量就是一个占位符。
定义变量可以使用 var 操作符,定义多个变量,每个变量之间用 逗号 分开,如果 省略 var 操作符可以定义 全局变量,未经初始化的变量,会保存一个特殊的值—— undefined
在 ESCScript 中变量会被自动 提升
3.2 数据类型
ECMAScript 有6种数据类型,其中5种基本的数据类型: Undefined、Null、Boolean、Number和String,还有1种复杂的数据类型: Object。一般使用 typeof 检查5种基本的数据类型,使用 instanceof 检查是哪种复杂的数据类型。
typeof
常见的就不说了,说几个可能容易混或者错的。
Boolean 类型
Boolean 类型是 ECMAScript 中使用最多的一种类型,只有两个字面量值: true、false;区分大小写,也就是说 True 不是布尔值。
流程控制语句(例如 if 语句)自动执行 转型函数 Boolean()。
下表给出了几种数据类型及其对应的转换规则
Number 类型
String 类型
转换为字符串有两种方式 toString([几进制]) 和 String(名)
Object 类型
访问对象的属性有两种方式
3.3 操作符
布尔操作符
逻辑非和逻辑或都是 短路 操作符
逻辑与
如果第一个操作数是对象,则返回 第二个 操作数;
如果第二个操作符是对象,则只有第一个操作数的求值结果是 true 的情况下才会返回该 对象;
逻辑与
如果第一个操作数是对象,则返回 第一个 操作数;
如果两个操作数都是对象,则返回 第一个 操作数;
关系操作符
如果两个操作数都是字符串,则比较两个字符串对应的 字符编码,所以字符串比较的时候一般都转换为大写(或者小写);
任何操作数与 NaN 进行比较,结果都是 false;
3.4 语句
for 语句
在 ECMAScript 中没有块级作用域的概念,因此循环内部定义的变量也可以在外部访问到。
其实以上的代码就相当于
for-in 语句
for-in 语句用来遍历对象的属性,但此时的对象不能是null或者undefined。
switch 语句
switch 语句在比较值的时候使用的是全等
看一个我觉得很新颖的语句
函数
可以向 ECMAScript 函数传递任意数量的参数,并且可以通过arguments对象来访问这些参数。即便你定义的函数只接收两个参数,在调用这个函数也未必一定传递两个参数,可以传递一个、三个甚至不传递参数。如果没传递值的命名参数将自动被赋予undefined值。
四、变量、作用域和内存问题
4.1 变量
ECMAScript 变量包含两种不同类型的值:基本类型和引用类型值。
基本类型的值
基本类型的值在内存中占据固定大小的空间,因此保存在 栈 内存中
如果从一个变量向另一个变量复制基本类型的值,会在变量对象上创建一个新值,然后把值复制到新变量的位置上。
传递参数的时候是按 值 传递的,和复制变量一样。
引用类型
引用类型的值是对象,保存在 堆 内存中;
从一个变量向另一个变量复制引用类型的值时,同样也将存储在变量对象中的值复制一份到新分配的空间中。不同的是,这个值的副本实际上时一个指针。
但是当为对象添加属性的时候,操作的是实际对象。
传递参数的时候是按 值 传递的,和引用类型复制一样。
4.2 执行环境和作用域
4.3 内存管理
优化内存占用的最佳方式,就是为代码只保存必要的数据。一旦数据不再用了,最好通过将其值设置为 null 来释放引用。
五、引用类型
在 ECMAScript中,引用类型是一种数据结构,常用的有:Object、Date、RegExp、Function、基本包装类型、单体内置对象。
5.1 Array 类型
插入
arr[length] = 'add data from bottom';arr.push('add data from bottom');arr.unshift('add data from head');splice(2,0,'red','green');,三个参数,第一个是位置,第二个是要删除的数据个数,第三个数据为插入的数据;删除
arr[length] = arr.length - 1;arr.pop();arr.shift();arr.splice(0,1);,两个参数,第一个参数是位置,第二个参数是要删除的个数;替换
arr.splice(2,1,'red')检测数组
检测是否是数组
转换为字符串的方法
排序方法
合并
位置方法
迭代
10.归并数组
- reduce
- reduceRight
5.1 Function 类型
函数分为函数声明和函数表达式,函数表达式可以随时访问,因为函数声明提升。
arguments 对象
arguments 对象主要用途是保存函数参数,包含一个特殊属性callee属性,是个指针,指向拥有这个arguments对象的函数;
this 对象
this 引用的是函数执行环境对象
每个函数都包含两个方法:call() 和 apply()。这两个方法的用途都是在特定的作用域中调用函数,实际上就是设置函数体内this的值。
apply(运行函数的作用域, 参数数组)
call(运行函数的作用域,其余参数)
5.1 String 类型