目录
初识 JavaScript
JavaScript 是什么
JavaScript (简称 JS)
- 是世界上最流行的编程语言之一
- 是一个脚本语言, 通过解释器运行
- 主要在客户端(浏览器)上运行, 现在也可以基于 node.js 在服务器端运行
JavaScript 最初只是为了完成简单的表单验证(验证数据合法性), 结果后来不小心就火了.
当前 JavaScript 已经成为了一个通用的编程语言
JavaScript 的能做的事情:
- 网页开发(更复杂的特效和用户交互)
- 网页游戏开发
- 服务器开发(node.js)
- 桌面程序开发(Electron, VSCode 就是这么来的)
- 手机 app 开发
发展历史
JavaScript 之父 布兰登 * 艾奇 (Brendan Eich)
1995 年, 用 10 天时间完成 JS 的设计 (由于设计时间太短,语言的一些细节考虑得不够严谨,导致 后来很长一段时间,Javascript 写出来的程序混乱不堪)
最初在网景公司, 命名为 LiveScript,
一般认为,当时 Netscape 之所以将 LiveScript 命名为 JavaScript,是因为 Java 是当时最流行的 编程语言,带有 "Java" 的名字有助于这门新生语言的传播。
其实 Java 和 JavaScript 之间的语法风格相去甚远。
JavaScript 和 HTML 和 CSS 之间的关系
编辑
- HTML: 网页的结构(骨)
- CSS: 网页的表现(皮)
- JavaScript: 网页的行为(魂)
JavaScript 运行过程
- 编写的代码是保存在文件中的, 也就是存储在硬盘(外存上).
- 双击 .html 文件浏览器(应用程序)就会读取文件, 把文件内容加载到内存中(数据流向: 硬盘 => 内存)
- 浏览器会解析用户编写的代码, 把代码翻译成二进制的, 能让计算机识别的指令(解释器的工作)
- 得到的二进制指令会被 CPU 加载并执行(数据流向: 内存 => CPU)
编辑
浏览器分成渲染引擎 + JS 引擎.
- 渲染引擎: 解析 html + CSS, 俗称 "内核"
- JS 引擎: 也就是 JS 解释器. 典型的就是 Chrome 中内置的 V8
JavaScript 的组成
- ECMAScript(简称 ES): JavaScript 语法
- DOM: 页面文档对象模型, 对页面中的元素进行操作
- BOM: 浏览器对象模型, 对浏览器窗口进行操作
光有 JS 语法, 只能写一些基础的逻辑流程.
但是要想完成更复杂的任务, 完成和浏览器以及页面的交互, 那么久需要 DOM API 和 BOM API.
重要概念: ECMAScript
这是一套 "标准", 无论是啥样的 JS 引擎都要遵守这个标准来实现.
前置知识
<script> alert("你好!"); </script>
- JavaScript 代码可以嵌入到 HTML 的 script 标签中.
JavaScript 的书写形式
1. 行内式
直接嵌入到 html 元素内部
<input type="button" value="点我一下" onclick="alert('haha')">
注意
- JS 中字符串常量可以使用单引号表示, 也可以 使用双引号表示.
- HTML 中推荐使用双引号, JS 中推荐使用单引号.
2. 内嵌式
写到 script 标签中
<script> alert("haha"); </script>
3. 外部式
写到单独的 .js 文件中
<script src="hello.js"></script>
alert("hehe");
这种情况下 script 标签中间不能写代码. 必须空着(写了代码也不会执行).
注释
单行注释 // [建议使用]
多行注释 /* */
- 使用 ctrl + / 切换注释.
- 多行注释不能嵌套.
输入输出
输入: prompt
弹出一个输入框
// 弹出一个输入框 prompt("请输入您的姓名:");
输出: alert
弹出一个警示对话框, 输出结果
// 弹出一个输出框 alert("hello");
- + 表示字符串拼接, 也就是把两个字符串首尾相接变成一个字符串.
- \n 表示换行
选择框:confirm
弹出一个选择对话框,确认或取消
// 弹出选择框 confirm("确认删除吗?");
输出: console.log
在控制台打印一个日志(供程序员看)
// 向控制台输出日志 console.log("这是一条日志");
- 在 VSCode 中直接输入 "log" 再按 tab 键, 就可以快速输入 console.log
需要打开浏览器的开发者工具(F12) => Console 标签页 才能看到结果.
重要概念: 日志
日志是程序员调试程序的重要手段
重要概念: .
console 是一个 js 中的 "对象"
. 表示取对象中的某个属性或者方法. 可以直观理解成 "的"
console.log 就可以理解成: 使用 "控制台" 对象 "的" log 方法.
语法概览
JavaScript 虽然一些设计理念和 Java 相去甚远, 但是在基础语法层面上还是有一些相似之处的. 有了Java 的基础很容易理解 JavaScript 的一些基本语法.
变量的使用
基本用法
创建变量(变量定义/变量声明/变量初始化)
var name = 'zhangsan'; var age = 20;
- var 是 JS 中的关键字, 表示这是一个变量.
- = 在 JS 中表示 "赋值", 相当于把数据放到内存的盒子中. = 两侧建议有一个空格
- 每个语句最后带有一个 ; 结尾. JS 中可以省略 ; 但是建议还是加上.
- 注意, 此处的 ; 为英文分号. JS 中所有的标点都是英文标点.
- 初始化的值如果是字符串, 那么就要使用单引号或者双引号引起来.
- 初始化的值如果是数字, 那么直接赋值即可.
使用变量
console.log(age); // 读取变量内容 age = 30; // 修改变量内容
理解 动态类型
1) JS 的变量类型是程序运行过程中才确定的(运行到 = 语句才会确定类型)
var a = 10; // 数字 var b = "hehe"; // 字符串
2) 随着程序运行, 变量的类型可能会发生改变.
var a = 10; // 数字 a = "hehe"; // 字符串
基本数据类型
JS 中内置的几种类型
- number: 数字. 不区分整数和小数.
- boolean: true 真, false 假.
- string: 字符串类型.
- undefined: 只有唯一的值 undefined. 表示未定义的值.
- null: 只有唯一的值 null. 表示空值.
number 数字类型
JS 中不区分整数和浮点数, 统一都使用 "数字类型" 来表示。
数字进制表示
var a = 07; // 八进制整数, 以 0 开头 var b = 0xa; // 十六进制整数, 以 0x 开头 var c = 0b10; // 二进制整数, 以 0b 开头
注意:
- 一个八进制数字对应三个二进制数字
- 一个十六进制数字对应四个二进制数字. (两个十六进制数字就是一个字节)
特殊的数字值
- Infinity: 无穷大, 大于任何数字. 表示数字已经超过了 JS 能表示的范围.
- -Infinity: 负无穷大, 小于任何数字. 表示数字已经超过了 JS 能表示的范围.
- NaN: 表示当前的结果不是一个数字.
var max = Number.MAX_VALUE; // 得到 Infinity console.log(max * 2); // 得到 -Infinity console.log(-max * 2); // 得到 NaN console.log('hehe' - 10);
注意:
- 负无穷大 和 无穷小 不是一回事. 无穷小指无限趋近与 0, 值为 1 / Infinity
- 'hehe' + 10 得到的不是 NaN, 而是 'hehe10', 会把数字隐式转成字符串, 再进行字符串拼接.
- 可以使用 isNaN 函数判定是不是一个非数字.
string 字符串类型
基本规则
字符串字面值需要使用引号引起来, 单引号双引号均可。
如果字符串中本来已经包含引号需要使用转义字符。
转义字符
有些字符不方便直接输入, 于是要通过一些特殊方式来表示.
- \n
- \\
- \'
- \"
- \t
求长度
使用 String 的 length 属性即可
字符串拼接
- 使用 + 进行拼接
- 数字和字符串也可以进行拼接
boolean 布尔类型
表示 "真" 和 "假"
- Boolean 参与运算时当做 1 和 0 来看待.
undefined 未定义数据类型
如果一个变量没有被初始化过, 结果就是undefined, 是 undefined 类型
var a; console.log(a)
undefined 和字符串进行相加, 结果进行字符串拼接
console.log(a + "10"); // undefined10
undefined 和数字进行相加, 结果为NaN
console.log(a + 10);
null 空值类型
null 表示当前的变量是一个 "空值".
var b = null; console.log(b + 10); // 10 console.log(b + "10"); // null10
注意:
- null 和 undefined 都表示取值非法的情况, 但是侧重点不同.
- null 表示当前的值为空. (相当于有一个空的盒子)
- undefined 表示当前的变量未定义. (相当于连盒子都没有)
运算符
JavaScript 中的运算符和 Java 用法基本相同
算术运算符
- +
- -
- *
- /
- %
赋值运算符 & 复合赋值运算符
- =
- +=
- -=
- *=
- /=
- %=
自增自减运算符
- ++: 自增1
- --: 自减1
比较运算符
- <
- >
- <=
- >=
- == 比较相等(会进行隐式类型转换)
- !=
- === 比较相等(不会进行隐式类型转换)
- !==
逻辑运算符
用于计算多个 boolean 表达式的值.
- && 与: 一假则假
- || 或: 一真则真
- ! 非
位运算
- & 按位与
- | 按位或
- ~ 按位取反
- ^ 按位异或
移位运算
- << 左移
- >> 有符号右移(算术右移)
- >>> 无符号右移(逻辑右移)
条件语句
if 语句
基本语法格式
条件表达式为 true, 则执行 if 的 { } 中的代码
// 形式1 if (条件) { 语句 } // 形式2 if (条件) { 语句1 } else { 语句2 } // 形式3 if (条件1) { 语句1 } else if (条件2) { 语句2 } else if .... { 语句... } else { 语句N }
三元表达式
是 if else 的简化写法.
条件 ? 表达式1 : 表达式2
条件为真, 返回表达式1 的值. 条件为假, 返回表达式2 的值
switch
更适合多分支的场景
switch (表达式) { case 值1: 语句1; break; case 值2: 语句2: break; default: 语句N; }
循环语句
重复执行某些语句
while 循环
while (条件) { 循环体; }
执行过程:
- 先执行条件语句
- 条件为 true, 执行循环体代码.
- 条件为 false, 直接结束循环
continue
结束这次循环
break
结束整个循环
for 循环
for (表达式1; 表达式2; 表达式3) { 循环体 }
- 表达式1: 用于初始化循环变量.
- 表达式2: 循环条件
- 表达式3: 更新循环变量
执行过程:
- 先执行表达式1, 初始化循环变量
- 再执行表达式2, 判定循环条件
- 如果条件为 false, 结束循环
- 如果条件为 true, 则执行循环体代码.
- 执行表达式3 更新循环变量
数组
创建数组
使用 new 关键字创建
// Array 的 A 要大写 var arr = new Array();
使用字面量方式创建 [常用]
var arr = []; var arr2 = [1, 2, 'haha', false]; // 数组中保存的内容称为 "元素"
- JS 的数组不要求元素是相同类型
获取数组元素
- 使用下标的方式访问数组元素(从 0 开始)
- 如果下标超出范围读取元素, 则结果为 undefined
新增数组元素
1. 通过修改 length 新增
相当于在末尾新增元素. 新增的元素默认值为 undefined
2. 通过下标新增
如果下标超出范围赋值元素, 则会给指定位置插入新元素
3. 使用 push 进行追加元素
var arr = [9, 5, 2, 7, 3, 6, 8]; var newArr = []; for (var i = 0; i < arr.length; i++) { newArr.push(arr[i]); }
删除数组中的元素
使用 splice 方法删除元素
var arr = [9, 5, 2, 7]; // 第一个参数表示从下表为 2 的位置开始删除. 第二个参数表示要删除的元素个数是 1 个 arr.splice(2, 1); console.log(arr); // 结果 [9, 5, 7]
函数
语法格式
// 创建函数/函数声明/函数定义 function 函数名(形参列表) { 函数体 return 返回值; } // 函数调用 函数名(实参列表) // 不考虑返回值 返回值 = 函数名(实参列表) // 考虑返回值
- 函数定义并不会执行函数体内容, 必须要调用才会执行. 调用几次就会执行几次.
- 调用函数的时候进入函数内部执行, 函数结束时回到调用位置继续执行. 可以借助调试器来观察.
- 函数的定义和调用的先后顺序没有要求. (这一点和变量不同, 变量必须先定义再使用)
关于参数个数
实参和形参之间的个数可以不匹配. 但是实际开发一般要求形参和实参个数要匹配
- 1) 如果实参个数比形参个数多, 则多出的参数不参与函数运算
- 2) 如果实参个数比形参个数少, 则此时多出来的形参值为 undefined
函数表达式
另外一种函数的定义方式
var add = function() { var sum = 0; for (var i = 0; i < arguments.length; i++) { sum += arguments[i]; } return sum; } console.log(add(10, 20)); // 30 console.log(add(1, 2, 3, 4)); // 10 console.log(typeof add); // function
形如 function() { } 这样的写法定义了一个匿名函数, 然后将这个匿名函数用一个变量来表示.
作用域
某个标识符名字在代码中的有效范围.
在 ES6 标准之前, 作用域主要分成两个
- 全局作用域: 在整个 script 标签中, 或者单独的 js 文件中生效.
- 局部作用域/函数作用域: 在函数内部生效.
作用域链
背景:
- 函数可以定义在函数内部
- 内层函数可以访问外层函数的局部变量.
对象
基本概念
对象是指一个具体的事物
在 JS 中, 字符串, 数值, 数组, 函数都是对象.
每个对象中包含若干的属性和方法.
- 属性: 事物的特征.
- 方法: 事物的行为.
JavaScript 的对象 和 Java 的对象概念上基本一致. 只是具体的语法表项形式差别较大.
1. 使用 字面量 创建对象 [常用]
使用 { } 创建对象
- 使用 { } 创建对象
- 属性和方法使用键值对的形式来组织.
- 键值对之间使用 , 分割. 最后一个属性后面的 , 可有可无
- 键和值之间使用 : 分割.
- 方法的值是一个匿名函数
2. 使用 new Object 创建对象
var student = new Object(); // 和创建数组类似 student.name = "蔡徐坤"; student.height = 175; student['weight'] = 170; student.sayHello = function () { console.log("hello"); }
3. 使用 构造函数 创建对象
前面的创建对象方式只能创建一个对象. 而使用构造函数可以很方便 的创建 多个对象
function 构造函数名(形参) { this.属性 = 值; this.方法 = function... } var obj = new 构造函数名(实参);
注意:
- 在构造函数内部使用 this 关键字来表示当前正在构建的对象.
- 构造函数的函数名首字母一般是大写的.
- 构造函数的函数名可以是名词.
- 构造函数不需要 return
- 创建对象的时候必须使用 new 关键字.