1. 认识JavaScript
1.1 主流浏览器
IE(高版本)/Edge、Chrome、Firefox、Safari、Opera
浏览器由外壳与内核组成,内核分为渲染引擎和JS引擎
渲染引擎将html和css代码渲染成图形界面,js引擎解析js代码
V8引擎是目前解析js代码速度最快的js引擎,下表是主流浏览器的内核
| 浏览器 | 渲染引擎 | JS引擎 |
|---|---|---|
| IE | Trident | JScript -> Chakra |
| Firefox | Gecko | Monkey系列 |
| Chrome | Webkit -> Blink | V8 |
| Safari | Webkit | SquirrelFish系列 |
| Opera | Presto -> Blink | Carakan |
1.2 JS的发展
在1995 年 Netscape,一位名为 Brendan Eich 的工程师创造了 JavaScript,随后在 1996 年初,JavaScript 首先被应用于 Netscape 2 浏览器上。最初的 JavaScript 名为 LiveScript(活力脚本),后来因为 Sun Microsystem 的 Java 语言的兴起和广泛使用,Netscape 出于宣传和推广的考虑,将它的名字从最初的 LiveScript 更改为 JavaScript——尽管两者之间并没有什么共同点。这便是之后混淆产生的根源。
几个月后,Microsoft 随着 IE 3 推出了一个与之基本兼容的语言 JScript(注意微软的人生哲学,当它发现别人的东西很好的时候,就必须拧巴的推出自己的,然后自己的又被市场排斥,又开始兼容别人的)。又几个月后,Netscape 将 JavaScript 提交至 Ecma International(一个欧洲标准化组织),ECMAScript 标准第一版便在 1997 年诞生了,随后在 1999 年以 ECMAScript 第三版的形式进行了更新,从那之后这个标准没有发生过大的改动。由于委员会在语言特性的讨论上发生分歧,ECMAScript 第四版尚未推出便被废除,但随后于 2009 年 12 月发布的 ECMAScript 第五版引入了第四版草案加入的许多特性。第六版标准已经于2015年六月发布 。
2003年: 页面上漂浮的广告、弹窗广告;所以当时的浏览器就推出一个功能,禁用广告,实际上本质就是禁用JavaScript。
2004年:谷歌在JavaScript中添加了ajax,从此JavaScript被人重视,很多人开始学习JS语言。
2007年:三层分离,iPhone发布,人们开始重视用户体验。大家发现了,JavaScript是web页面中制作交互效果唯一的语言,所以把JS的重视程度,提到了相当高的一个地位。
2008年:Chrome浏览器发布,V8引擎加快了JS的解析,之前的浏览器解析JS的时候卡顿卡顿的,动画效果是蹦蹦的。在Chrome里,它的引擎叫做V8,运行JS很流畅。
2009年:jQuery变得流行,解决了浏览器兼容问题,制作页面效果变得简单,越来越多的初学者愿意学习JavaScript。
2011年:Node.js得到广泛应用,实际上就是把JavaScript运行在了服务器上,单线程非阻塞,能够让企业用最小的成本实现后台网站,比如之前4万的服务器都卡,现在用了node之后,4000的机器都很流畅。
2015年:ECMA Script 6发布,叫做ECMA Script 2015。重量级的改变,把语言的特性颠覆性的一个增强。
1.3 JS的特点及组成
特点:弱类型,解释型,单线程, 基于原型 ,脚本语言
传统语言:OOL 基于类和对象=>实例
Javascript:基于原型,对象,原型可以指定
脚本语言:依赖环境(宿主环境)运行,浏览器可以使用DOM/BOM,还有node.js(服务端)
弱类型(动态类型):声明变量不需要规定类型,且可以相互装换
解释型:没有编译的过程,不生成其它可执行文件,完成语法分析后逐行解析执行[保留]
组成(客户端):ECMAScript,Dom,Bom
ECMAScript:规定语法使用的规则 (等同于html里的<>和css里的{}) ,是JS的本质
es是js的标准,js是es的实现
Dom: DocumentObjectModel 文档对象模型,页面元素和方法的整合工具箱,用户可以直接使用
Bom: BrowserObjectModel 浏览器对象模型,浏览器提供的工具箱,用户可以直接使用
1.4 JS的实现
JS在html页面中有三种书写位置:行内、内嵌、外部
行内JS
可以将单行或少量的JS代码写在HTML标签的事件属性中(以on开头的属性),不推荐
<input type="button" value="点击" onclick="alert('这是写在标签属性中的JS代码!')">
引号的使用:在html中推荐使用双引号,在JS中推荐使用单引号
缺点:可读性差,引号多层嵌套时,容易混淆
内嵌JS
可以将多行JS代码写到标签中, 标签内的内容会被当做JS代码执行
JS代码中不能出现字符串,有需求时可以通过转义字符解决</script>
<script> alert('这是写在script标签中的JS代码!')</script>
外部JS
JS代码可以放在外部的.js文件中,通过src属性引入
优点:有利于HTML页面代码的结构化,可维护性强、可缓存、适应未来
script标签若引入了外部文件,就不能再在标签中编写代码
//test.jsalert('这是写在外部.js文件中的JS代码!')在html文件中引用:<script src="test.js"></script>
加载外部JS代码的三种方式
正常模式:
当执行到此标签时,会立刻下载脚本,下载完毕后立即执行脚本,下载和执行的过程中,HTML暂停解析
async模式:
当有async属性时,会立刻下载脚本,并在下载完毕后立即执行脚本。下载脚本的时候,HTML不停止解析,当执行脚本的时候,HTML才暂停解析。脚本的执行顺序并不单与书写顺序相关。
defer模式:
当有defer属性时,会立刻下载脚本,并在HTML解析完成后执行脚本,下载脚本时, HTML不停止解析
1.5 输入输出
输入:在JS中使用prompt(info)在浏览器弹出一个输入框,供用户输入
<script> prompt('请输入您的姓名:')</script>
输出:alert【浏览器】,document.write("hello world!")【向body输出】,console.log('hello world!')【控制台】
<script> alert('hello world!')</script><script> document.write('hello world!')</script><script> console.log('hello world!'')</script>
1.6 语句和注释
JS代码是从上往下执行的(阻断式执行)
每行结尾的分号可有可无
对大小写敏感
字符串使用单引号和双引号均可
在文本字符创中使用反斜杠进行换行操作: document.write("Hello\World!");
单行注释://(默认快捷键:Ctrl+/)
多行注释:/**/(默认快捷键:ALt+Shitf+A)
一般在行末使用注释
2. 变量和数据类型
定义: 变量是用于存放数据的容器,通俗的讲,变量就是一个装东西的盒子。
本质: 变量是程序在内存中申请的一块用来存放数据的空间
2.1 变量使用
声明变量
var age; // 声明一个 名称为age 的变量 var 是一个 JS关键字,用来声明变量(variable),使用该关键字声明变量后,计算机会自动为变量分配内存空间age 是用户定义的变量名,我们要通过变量名来访问内存中分配的空间
[ES6]:在ES6中还可以使用let关键词定义变量,语法与var相同
| 使用var定义变量 | 使用let定义变量 | 举例 | |
|---|---|---|---|
| 变量提升现象 | 存在 | 不存在 | |
| 在同一作用域内多次定义同一个变量 | 允许 | 不允许 | |
| 暂时性死区问题 | 不存在 | 存在 | 例1 |
| 全局变量是否为顶层对象(window)的属性 | 是 | 否 | 例2 |
| 作用域 | 按照ES5语法确定 | 按照ES6语法确定 |
例1console.log(a); // undefinedvar a = 10;console.log(b); // Uncaught ReferenceError: Cannot access 'b' before initializationlet b = 20;例2var a = 10;let b = 20;console.log(window.a); // 10console.log(window.b); //undefined[ES6]给变量赋值除了使用赋值运算符=外,在es6中只要变量与数值具有相同的结构就可以进行赋值,通常称为解构赋值例如:let [a, b] = [10, 20]; // 相当于let a = 10, b = 20;let [q, w, e] = [1, [2, 3]]; // 相当于 let q = 1, w = [2, 3], e;let [q, [w, e]] = [1, [2, 3]]; // 相当于 let q = 1, w = 2 , e = 3;let [a, b, c] = ['1', 'ss']; // 相当于 let a = '1', b = 'ss', c; (不成功的解构)let [a, b] = [10, 20, 30] // 相当于 let a = 10, b = 20; (不完全解构)let [, a, b] = [10, 20, 30] // 相当于 let a = 20, b = 30; (不完全解构)let [a, b = 10] = [5]; // 相当于let a = 5, b = 10; (传undefined也使用默认值)let [x = f()] = [1]; // 相当于let x = 1; 函数f不执行let [x = f()] = []; // 相当于let x = f();let {x: c, y: d} = {x: 50, y: 80}; // 相当于let c = 50, d = 80;// 上面一条也可写为 let {c, d} = {c: 50, d: 80};// 完整写出来为 let {c: c, d: d} = {c: 50, d: 80};
变量赋值
age = 10;= 用来把右边的值赋给左边的变量空间中,此处代表赋值的意思变量值是用户保存到变量空间里的值
变量的初始化
声明一个变量并赋值, 称之为变量的初始化
语法拓展
更新变量 :一个变量被重新复赋值后,它原有的值就会被覆盖,变量值将以最后一次赋的值为准
var age = 18;age = 81; // 最后的结果就是81,因为18被覆盖掉了
同时声明多个变量时,只需要写一个 var, 多个变量名之间使用英文逗号隔开
var age = 20, name = 'pikaka', sex = '男';
在严格模式下必须定义后才能赋值
2.2 变量命名规范
只允许使用 数字(0-9)/字母(A-Z,a-z)/下划线(_)/美元符号($)
语义化命名
小驼峰命名(构造函数的函数名用大驼峰命名)
不覆盖系统自带API
严格区分大小写:var app; 和 var App; 是两个变量
不能以数字开头
不能是关键字和保留字:var for while
2.3 控制台输出
window.console.log(...x)普通输出,如有多个参数则依次输出
window.console.info(x)输出信息
window.console.log与console.info只是语义上的差别,效果上差别不大,在有的浏览器中有info的标记,但在Google Chrome中完全一样
window.console.warn(x)输出警告信息,不阻碍代码继续执行
window.console.error(x)输出错误信息,不阻碍代码继续执行
throw 'xxx';throw new Error('xxx');
window.console.dir:如果输出的是对象,则可以显示对象的所有属性与方法,如果不是对象,则除只能接收一个参数外与log无明显差异
2.4 数据类型简介
JS是以一种弱类型语言,在定义变量时不需要指定类型,一个变量可以存储任何类型的值
分为简单数据类型(基本数据类型)和复杂数据类型
简单数据类型(值类型): 在存储时变量中存储的是值本身
string: 字符串类型,需要用引号括起来
【ES6】新增模板字符串,反引号``括起来的字符串, 使用此符号时,内部可以换行,而且可以使用`${变量或表达式}来直接得到对应的值,避免多次拼接
number
boolean
undefined
null
复杂数据类型(引用类型): 在存储时变量中存储的仅仅是地址,通过new关键字创建的对象
Object
Array
Function
【ES6】新增: Symbol , BigInt
2.5 数据类型的检测
暂时用typeof操作符来检测数据类型
-
number类型返回number -
string类型返回string -
boolean类型返回boolean -
undefined类型返回undefined -
null类型返回object -
object类型(function除外)返回object -
function返回function
2.6 数据类型之间的转换
转换为数字
若x为纯由数字组成的字符串(可以有正负号或小数点,忽略最前面和最后面空格),则返回对应的数字
-
若x为含有非数字字符的字符串,则返回结果为NaN
-
若x为空字符串,则返回0
-
若x为true,则返回1
-
若x为false,则返回0
-
若x为null,则返回0
-
若x为undefined或对象,则先转换为字符串,再将得到的字符串按照上述规则转换为数字,返回得到的数字
parseInt(string, radix)方法:将以数字开头的字符串转换为整数数字(第一个非数字字符后面的内容不再解析,正负号算作数字),返回获得的结果,第二个参数为进制的基数,表示第一个参数是以多少进制表示的
parseFloat(x)方法:将以数字开头的字符串转换为数字(第一个非数字且非第一个.字符后面的内容不再解析,正负号算作数字),返回获得的结果
【ES6】在ES6中window.parseInt和window.parseFloat可以用window.Number.parseInt和window.Number.parseFloat代替
转换为字符串
将x转换为字符串的结果如下:
-
若x为数字,则转换为对应的纯数字的字符串
-
若x为
true或false或null或undefined或NaN则对应转换为'true'或'false'或'null'或'undefined'或'NaN' -
若x为对象类型(函数和数组除外),则转换为
'[object Object]' -
若x为数组,则转换为经扩展运算符(...)运算后的值
-
若x为函数,则转换为整个函数体