前言
1.JavaScript背景
Web
前端有三层:
-
HTML
:从语义的角度,描述页面结构 -
CSS
:从审美的角度,描述样式(美化页面) -
JavaScript
:从交互的角度,描述行为(提升用户体验)
JavaScript
是世界上用的最多的脚本语言。
2.浏览器工作原理
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
3.JavaScript 的使用范围,慢慢超越了浏览器,正在向通用的系统语言发展。
- (1)浏览器的平台化
- (2)Node
- (3)数据库操作
- (4)移动平台开发
- (5)内嵌脚本语言
- (6)跨平台的桌面应用程序
4.强大的性能
-(1)灵活的语法,表达力强。
JavaScript 既支持类似 C 语言清晰的过程式编程,也支持灵活的函数式编程,可以用来写并发处理(concurrent)。这些语法特性已经被证明非常强大,可以用于许多场合,尤其适用异步编程。
JavaScript 的所有值都是对象,这为程序员提供了灵活性和便利性。因为你可以很方便地、按照需要随时创造数据结构,不用进行麻烦的预定义。
JavaScript 的标准还在快速进化中,并不断合理化,添加更适用的语法特性。
-(2)支持编译运行。
JavaScript 语言本身,虽然是一种解释型语言,但是在现代浏览器中,JavaScript 都是编译后运行。程序会被高度优化,运行效率接近二进制程序。而且,JavaScript 引擎正在快速发展,性能将越来越好。
此外,还有一种 WebAssembly 格式,它是 JavaScript 引擎的中间码格式,全部都是二进制代码。由于跳过了编译步骤,可以达到接近原生二进制代码的运行速度。各种语言(主要是 C 和 C++)通过编译成 WebAssembly,就可以在浏览器里面运行。
-(3)事件驱动和非阻塞式设计。
JavaScript 程序可以采用事件驱动(event-driven)和非阻塞式(non-blocking)设计,在服务器端适合高并发环境,普通的硬件就可以承受很大的访问量。
1.JavaScript基础
JavaScript的组成
JavaScript基础分为三个部分:
ECMAScript
:JavaScript的语法标准。包括变量、表达式、运算符、函数、if语句、for语句等。DOM
:文档对象模型,操作网页上的元素的API。比如让盒子移动、变色、轮播图等。BOM
:浏览器对象模型,操作浏览器部分功能的API。比如让浏览器自动滚动。
PS:JS机械重复性的劳动几乎为0,基本都是创造性的劳动。而不像HTML、CSS中margin、padding都是机械重复劳动。
JavaScript的特点
(1)简单易用:可以使用任何文本编辑工具编写,只需要浏览器就可以执行程序。
(2)解释型语言:事先不需要被编译为机器码再执行,逐行执行、无需进行严格的变量声明。
由于少了编译这一步骤,所以解释型语言开发起来尤为轻松,但是解释型语言运行较慢也是它的劣势。不过解释型语言中使用了JIT技术,使得运行速度得以改善。
(3)基于对象:内置大量现成对象,编写少量程序可以完成目标
编程语言的分类
解释型语言:边解析边执行,不需要事先编译。例如:JavaScript、php。
编译型语言:事先把所有的代码翻译成计算机能够执行的指令,然后整体执行。例如:c、c++。
1.字面量:数字和字符串【常量】;变量:值可以改变
“字面量”即常量,是固定值,不可改变。看见什么,它就是什么。变量:变量可以用来保存字面量,而且变量的值可以任意改变。
alert(886); //886是数字,所以不需要加引号。
// 变量定义
var a = 100;
变量名有命名规范:只能由英语字母、数字、下划线、美元符号$构成,且不能以数字开头,并且不能是JavaScript保留字。并且变量是大小写敏感的
变量的命名规则:
- 1.建议用驼峰命名规则:getElementById/matherAndFather/aaaOrBbbAndCcc
- 2.变量命名必须以字母或是下标符号”_”或者”$”为开头。
- 3.变量名长度不能超过255个字符。
- 4.变量名中不允许使用空格,首个字不能为数字。
- 5.不用使用脚本语言中保留的关键字及保留字作为变量名。
- 6.变量名区分大小写(javascript是区分大小写的语言)。
- 7.汉语可以作为变量名。但是不建议使用,因为 low。
1.JavaScript
是一种动态类型语言,也就是说,变量的类型没有限制,变量可以随时更改类型。
2.JavaScript
引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这就叫做变量提升(hoisting)。
3.源码中被 JavaScript
引擎忽略的部分就叫做注释,它的作用是对代码进行解释。JavaScript
提供两种注释的写法:一种是单行注释,用//起头;另一种是多行注释,放在/和/之间。
4.JavaScript
使用大括号,将多个相关的语句组合在一起,称为“区块”(block
)。对于var命令来说,JavaScript
的区块不构成单独的作用域(scope
)。
{
var a = 1;
}
a // 1
2.数据类型
在JS中一共有六种数据类型:
- 基本数据类型(值类型):
String
字符串、Number
数值、Boolean
布尔值、Null
空值、Undefined
未定义。 - 引用数据类型(引用类型):
Object
对象。
强制类型转换:将一个数据类型强制转换为其他的数据类型。类型转换主要指,将其他的数据类型,转换为:String、Number、Boolean。
vat a = 123; // Number 类型
console.log(a + ''); // 转换成 String 类型
console.log(a + 'haha'); // 转换成 String 类型
- 数值(number):整数和小数(比如1和3.14)
- 字符串(string):文本(比如Hello World)。
// 字符串
'Did she say \'Hello\'?'
// "Did she say 'Hello'?"
"Did she say \"Hello\"?"
// "Did she say "Hello"?"
// 默认只有一行 分多行报错,分成多行,可以在每一行的尾部使用反斜杠。
'a
b
c'
// SyntaxError: Unexpected token ILLEGAL
var longString = 'Long \
long \
long \
string';
// 连接运算符(+)可以连接多个单行字符串,将长字符串拆成多行书写,输出的时候也是单行。
var longString = 'Long '
+ 'long '
+ 'long '
+ 'string';
反斜杠(\)在字符串内有特殊含义,用来表示一些特殊字符,所以又称为转义符。
需要用反斜杠转义的特殊字符,主要有下面这些。
\0 :null(\u0000)
\b :后退键(\u0008)
\f :换页符(\u000C)
\n :换行符(\u000A)
\r :回车键(\u000D)
\t :制表符(\u0009)
\v :垂直制表符(\u000B)
\' :单引号(\u0027)
\" :双引号(\u0022)
\\ :反斜杠(\u005C)
// 字符串可以被视为字符数组,因此可以使用数组的方括号运算符,用来返回某个位置的字符(位置编号从0开始)。
var s = 'hello';
s[0] // "h"
s[1] // "e"
s[4] // "o"
// 直接对字符串使用方括号运算符
'hello'[1] // "e"
- 布尔值(boolean):表示真伪的两个特殊值,即true(真)和false(假)
- undefined:表示“未定义”或不存在,即由于目前没有定义,所以此处暂时没有任何值
- null:表示空值,即此处的值为空。
- 对象(object):各种值组成的集合。
- ES6 又新增了第七种 Symbol 类型的值
对象是最复杂的数据类型,又可以分成三个子类型。
- 狭义的对象(object)
- 数组(array)
- 函数(function)
狭义的对象和数组是两种不同的数据组合方式,除非特别声明,本教程的“对象”都特指狭义的对象。函数其实是处理数据的方法,JavaScript 把它当成一种数据类型,可以赋值给变量,这为编程带来了很大的灵活性,也为 JavaScript 的“函数式编程”奠定了基础。
3.运算符
运算符有很多分类,比如:
算数运算符: [
+ - * / 取余% ()
]自增运算符:【自增 ++,自减--】
逻辑运算符
&& 与(且):两个都为真,结果才为真。
|| 或:只要有一个是真,结果就是真。
! 非:对一个布尔值进行取反。赋值运算符:可以将符号右侧的值赋值给符号左侧的变量。
+=。a += 5 等价于 a = a + 5
-=。a -= 5 等价于 a = a - 5
*=。a *= 5 等价于 a = a * 5
/=。a /= 5 等价于 a = a / 5
%=。a %= 5 等价于 a = a % 5
- 关系运算符:比较两个值之间的大小关系
> 大于号
< 小于号
>= 大于或等于
<= 小于或等于
== 等于
=== 全等于
!= 不等于
!== 不全等于
JavaScript 还有一个三元运算符(即该运算符需要三个运算子)?:,也可以用于逻辑判断。* 三元运算符(条件运算符):三元运算符也叫条件运算符。
(条件) ? 表达式1 : 表达式2
上面代码中,如果“条件”为true,则返回“表达式1”的值,否则返回“表达式2”的值。
var even = (n % 2 === 0) ? true : false;
4.流程控制语句:(if-else, 循环语句)
JavaScript 提供if
结构和switch
结构,完成条件判断,即只有满足预设的条件,才会执行相应的语句。
流程控制语句分类
- 顺序结构
- 选择结构:if语句、switch语句
- 循环结构:while语句、for语句
if (条件表达式1) {
// 条件1为真时,做的事情
} else if (条件表达式2) {
// 条件1不满足,条件2满足时,做的事情
} else if (条件表达式3) {
// 条件1、2不满足,条件3满足时,做的事情
} else {
// 条件1、2、3都不满足时,做的事情
}
//switch 条件分支语句
switch(表达式) {
case 值1:
语句体1;
break;
case 值2:
语句体2;
break;
...
...
default:
语句体 n+1;
break;
}
// for循环举例
for (var i = 1; i < 13; i = i + 4) {
console.log(i);
}
// while循环语法:
while(条件表达式){
语句...
}
do{
语句...
}while(条件表达式)
while循环和 do...while循环的区别
这两个语句的功能类似,不同的是:
- while是先判断后执行,而do...while是先执行后判断。
也就是说,do...while可以保证循环体至少执行一次,而while不能。
break 中断结束
- break可以用来退出switch语句或整个循环语句(循环语句包括for、while。不包括if。if里不能用 break 和 continue,否则会报错)。
- break会立即终止离它最近的那个循环语句。
- 可以为循环语句创建一个label,来标识当前的循环(格式:label:循环语句)。使用break语句时,可以在break后跟着一个label,这样break将会结束指定的循环,而不是最近的。
continue
- continue可以用来跳过当次循环。
- 同样,continue默认只会离他最近的循环起作用。
标签(
label
)
JavaScript
语言允许,语句的前面有标签(label
),相当于定位符,用于跳转到程序的任意位置,标签的格式如下。
label:
语句
标签可以是任意的标识符,但不能是保留字,语句部分可以是任意语句。
标签通常与break
语句和continue
语句配合使用,跳出特定的循环。
top:
for (var i = 0; i < 3; i++){
for (var j = 0; j < 3; j++){
if (i === 1 && j === 1) break top;
console.log('i=' + i + ', j=' + j);
}
}
// i=0, j=0
// i=0, j=1
// i=0, j=2
// i=1, j=0
5.对象
面向对象简介
对象的作用是:封装信息。比如Student类里可以封装学生的姓名、年龄、成绩等。
对象具有特征(属性)和行为(方法)。
- 面向对象:可以创建自定义的类型,很好的支持继承和多态。
- 面向对象的特征:封装、继承、多态。
对象(object)是 JavaScript 语言的核心概念,也是最重要的数据类型。
什么是对象?简单说,对象就是一组“键值对”(key-value)的集合,是一种无序的复合数据集合。
var obj = {
foo: 'Hello',
bar: 'World'
};
上面代码中,大括号就定义了一个对象,它被赋值给变量obj,所以变量obj就指向一个对象。该对象内部包含两个键值对(又称为两个“成员”),第一个键值对是foo: 'Hello',其中foo是“键名”(成员的名称),字符串Hello是“键值”(成员的值)。键名与键值之间用冒号分隔。第二个键值对是bar: 'World',bar是键名,World是键值。两个键值对之间用逗号分隔。
- 只要不是那五种基本数据类型,就全都是对象。
- 如果使用基本数据类型的数据,我们所创建的变量都是独立,不能成为一个整体。
- 对象属于一种复合的数据类型,在对象中可以保存多个不同数据类型的属性。
-
对象是保存到堆内存中的,每创建一个新的对象,就会在堆内存中开辟出一个新的空间。变量保存的是对象的内存地址(对象的引用)。
换而言之,对象的值是保存在堆内存中的,而对象的引用(即变量)是保存在栈内存中的。 - 如果两个变量保存的是同一个对象引用,当一个通过一个变量修改属性时,另一个也会受到影响。
对象的引用
如果不同的变量名指向同一个对象,那么它们都是这个对象的引用,也就是说指向同一个内存地址。修改其中一个变量,会影响到其他所有变量。
var o1 = {};
var o2 = o1;
o1.a = 1;
o2.a // 1
o2.b = 2;
o1.b // 2
上面代码中,o1和o2指向同一个对象,因此为其中任何一个变量添加属性,另一个变量都可以读写该属性。
JavaScript 语言将函数看作一种值,与其它值(数值、字符串、布尔值等等)地位相同。凡是可以使用值的地方,就能使用函数。比如,可以把函数赋值给变量和对象的属性,也可以当作参数传入其他函数,或者作为函数的结果返回。函数只是一个可以执行的值,此外并无特殊之处。
由于函数与其他数据类型地位平等,所以在 JavaScript 语言中又称函数为第一等公民。
作用域(scope)指的是变量存在的范围。在 ES5 的规范中,JavaScript 只有两种作用域:一种是全局作用域,变量在整个程序中一直存在,所有地方都可以读取;另一种是函数作用域,变量只在函数内部存在。ES6 又新增了块级作用域
JS 数组
6.JS错误处理机制
Error 实例对象:
avaScript 解析或运行时,一旦发生错误,引擎就会抛出一个错误对象。JavaScript 原生提供Error构造函数,所有抛出的错误都是这个构造函数的实例。
var err = new Error('出错了');
err.message // "出错了"
message:错误提示信息
name:错误名称(非标准属性)
stack:错误的堆栈(非标准属性)
错误类型
-
SyntaxError
对象【语法错误】 -
ReferenceError
对象【引用一个不存在的变量时发生的错误】 -
RangeError
对象【超出有效范围时发生的错误。主要有几种情况,一是数组长度为负数,二是Number对象的方法参数超出范围,以及函数堆栈超过最大值。数组越界】 -
TypeError
对象【变量或参数不是预期类型时发生的错误】 -
URIError
对象【URI 相关函数的参数不正确时抛出的错误,主要涉及encodeURI()、decodeURI()、encodeURIComponent()、decodeURIComponent()、escape()、unescape()
这六个函数】 -
EvalError
对象【eval
函数没有被正确执行时,会抛出EvalError
错误。该错误类型已经不再使用了,只是为了保证与以前代码兼容,才继续保留。】
处理错误&异常
- 1.
throw
语句:手动中断程序执行,抛出一个错误。 - 2.
try...catch
结构:一旦发生错误,程序就中止执行了。JavaScript
提供了try...catch
结构,允许对错误进行处理,选择是否往下执行。 - 3.
finally
代码块:try...catch
结构允许在最后添加一个finally
代码块,表示不管是否出现错误,都必需在最后运行的语句。
7.console 对象与控制台
console对象是 JavaScript 的原生对象,它有点像 Unix 系统的标准输出stdout和标准错误stderr,可以输出各种信息到控制台,并且还提供了很多有用的辅助方法。
console的常见用途有两个。
- 调试程序,显示网页代码运行时的错误信息。
- 提供了一个命令行接口,用来与网页代码互动。
console对象的浏览器实现,包含在浏览器自带的开发工具之中。以 Chrome 浏览器的“开发者工具”(Developer Tools)为例,可以使用下面三种方法的打开它。
- 1.按 F12 或者Control + Shift + i(PC)/ Command + Option + i(Mac)。
- 2.浏览器菜单选择“工具/开发者工具”。
- 3.在一个页面元素上,打开右键菜单,选择其中的“Inspect Element”。
1.console.log(),console.info(),console.debug()
2.console.warn(),console.error()
3.console.table()
4.console.count()用于计数,输出它被调用了多少次。
5.console.time(),console.timeEnd()这两个方法用于计时,可以算出一个
操作所花费的准确时间。