一、变量
变量是用于存储信息/数据的"容器"。
在程序运行的过程中可以随时改变变量中存储的数据。
1. 声明变量
在 JavaScript 中创建变量通常称为"声明"变量,使用var
关键字来声明变量。
-
格式: var 变量名称;
-
var 是一个 JS关键字,用来声明变量( variable 变量的意思 )。使用该关键字声明变量后,计算机会自动为变量分配内存空间,不需要程序员管
-
age 是程序员定义的变量名,我们要通过变量名来访问内存中分配的空间
var age; // 声明一个名称为age的变量
2. 赋值
变量声明之后,该变量是空的(它没有值),如需向变量赋值,需使用等号=
=
用来把右边的值赋给左边的变量空间中
age = 20; // 把20赋值给age这个变量
3. 变量的初始化
声明一个变量并赋值, 我们称之为变量的初始化。
var age = 20; // 声明变量同时赋值为20
4. 变量语法扩展
1)同时声明多个变量
同时声明多个变量时,只需要写一个 var, 多个变量名之间使用英文逗号隔开。
var name = '张三', age = 20, address= '西安';
2)更新变量
一个变量被重新复赋值后,它原有的值就会被覆盖,变量值将以最后一次赋的值为准。
var age = 18;
age = 81; // age最后的结果是81,因为18被覆盖掉了
3)声明变量特殊情况
情况 | 说明 | 结果 |
---|---|---|
var age ; console.log (age); | 只声明 不赋值 | undefined |
console.log(age) | 不声明 不赋值 直接使用 | 报错 |
age = 10; console.log (age); | 不声明 只赋值 | 10 |
5. 变量命名规范
- 由字母、数字、下划线 _ 、美元符号 $ 组成
- 不能以数字开头,$ 和 _ 可以作为开头,但不推荐使用
- 严格区分大小写
- 不能使用关键字、保留字。例如:var、for、while
- 变量名要有意义
- 全字母小写,如果有多个单词组成,可以用 $ 或 _ 连接
二、数据类型
1. 数据类型简介
-
为什么需要数据类型?
在计算机中,不同的数据所需占用的存储空间是不同的,为了便于把数据分成所需内存大小不同的数据,充分利用存储空间,于是定义了不同的数据类型。
简单来说,数据类型就是数据的类别型号。比如姓名“张三”,年龄18,这些数据的类型是不一样的。
-
变量的数据类型
变量是用来存储值的所在处,它们有名字和数据类型。
变量的数据类型决定了如何将代表这些值的位存储到计算机的内存中。
JavaScript 是一种弱类型或者说动态语言。
这意味着不用提前声明变量的类型,在程序运行过程中,类型会被自动确定:
// 下面的num我们不确定是属于哪种数据类型的,只有赋值后根据值才能判断
var num;
var age = 10; // 这是一个数字型
var name = '张三'; // 这是一个字符串
在代码运行时,变量的数据类型是由 JS引擎根据等号=
右边变量值的数据类型来判断的,运行完毕之后, 变量就确定了数据类型。
JavaScript 拥有动态类型,同时也意味着相同的变量可用作不同的类型:
var x = 6; // x 为数字
var x = "Bill"; // x 为字符串
-
数据类型分2大类:
值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、空(Null)、未定义(Undefined)、Symbol。
Symbol 是 ES6 引入的一种新的原始数据类型,表示独一无二的值。
引用数据类型:对象(Object)、数组(Array)、函数(Function)。
2. 字符串(String)
字符串是存储字符的变量。
字符串可以是 引号 中的任意文本,引号可以使用 ‘单引号’ 或 “双引号” ,只要不匹配包围字符串的引号即可。
(因为 HTML 标签里面的属性使用的是双引号,JS 这里更推荐使用单引号。)
1)字符串引号嵌套
JS 可以用单引号嵌套双引号 ,或者用双引号嵌套单引号 (外双内单,外单内双)
var str1 = '我爱你,"祖国"'; // 外单内双
var str2 = "我爱你,'祖国'"; // 外双内单
2)字符串转义符
类似HTML里面的特殊字符,字符串中也有特殊字符,我们称之为转义符。
转义符都是 \
开头的,常用的转义符及其说明如下:
转义符 | 解释说明 |
---|---|
\n | 换行符,n 是 newline 的意思 |
\\ | 斜杠 \ |
\' | ’ 单引号 |
\" | ” 双引号 |
\t | tab 缩进 |
\b | 空格 ,b 是 blank 的意思 |
3)字符串长度
字符串是由若干字符组成的,这些字符的数量就是字符串的长度。
通过字符串的 length 属性可以获取整个字符串的长度。
var str = "我爱我的祖国";
alert(str.length); // 显示6
4)字符串拼接
-
多个字符串之间可以使用
+
进行拼接,其拼接方式为 字符串 + 任何类型 = 拼接之后的新字符串 -
拼接前会把与字符串相加的任何类型转成字符串,再拼接成一个新的字符串
//1. 字符串拼接 alert('hello' + ' ' + 'world'); // hello world //2. 数值 + 字符串 alert('100' + 100); // 100100 //3. 数值相加 alert(100 + 100); // 200
-
+ 号总结口诀:数值相加 ,字符相连
5)字符串拼接加强
console.log('张三' + 18 + '岁'); // 张三18岁 只要有字符就会相连
var age = 18;
console.log('张三age岁'); // 张三age岁 age会变成字符串
console.log('张三' + age + '岁'); // 张三18岁
- 经常会将字符串和变量来拼接,变量可以很方便地修改里面的值
变量是不能添加引号的
,因为加引号的变量会变成字符串- 如果变量两侧都有字符串拼接,口诀“引引加加 ”,删掉数字,变量写到加加的中间
3. 数字(Number)
JavaScript 数字类型既可以保存整数,也可以保存小数(浮点数)。
var x1 = 8.88; // 小数
var x2 = 88; // 整数
极大或极小的数字可以通过科学(指数)计数法来书写
var y=123e5; // 12300000
var z=123e-5; // 0.00123
1)数字型进制
最常见的进制有二进制、八进制、十进制、十六进制。
在JS中,八进制前面加0,十六进制前面加 0x
// 1.八进制数字序列范围:0~7
var num1 = 010; // 8
// 2.十六进制数字序列范围:0~9以及A~F
var num2 = 0xA; // 10
2)数字型范围
JavaScript中数值的最大和最小值
// 最大值 这个值为:1.7976931348623157e+308
console.log(Number.MAX_VALUE);
// 最小值 这个值为:5e-324
console.log(Number.MIN_VALUE);
3)数字型三个特殊值
- Infinity ,代表无穷大,大于任何数值
- -Infinity ,代表无穷小,小于任何数值
- NaN ,Not a number,代表一个非数值
4)isNaN() 非数字
用来判断一个变量是否为非数字的类型,返回 true 或者 false
var book = '语文';
console.log(isNaN(book)); // true '语文'是一个非数字 是字符串
var math = 99;
var what = isNaN(math);
console.log(what); // false 99不是一个非数字 是数字
4. 布尔(Boolean)
布尔(逻辑)只能有两个值:true 或 false。
布尔常用在条件判断中。
var x = true;
var y = false;
布尔型 和 数字型 相加的时候, true 的值为 1 ,false 的值为 0。
console.log(true + 1); // 2
console.log(false + 1); // 1
5. 空(Null)
null是一个只有一个值的特殊类型。表示一个空对象引用。
声明一个变量,给 null 值,表示里面存的值为空,“什么都没有”。
可以通过将变量的值设置为 null 来清空变量。
var test = null;
alert(test); // null
var vari = null;
console.log('你好' + vari); // 你好null
console.log(11 + vari); // 11
console.log(true + vari); // 1
6. 未定义(Undefined)
Undefined 表示变量不含有值。
一个声明后没有被赋值的变量 会有一个默认值 undefined。
var variable;
console.log(variable); // undefined
console.log('你好' + variable); // 你好undefined
console.log(11 + variable); // NaN
console.log(true + variable); // NaN
7. 对象(Object)
JavaScript 对象是拥有属性和方法的数据集合。
所有的事物都是对象,例如字符串、数值、数组、函数等。
对象由花括号{ }表示,花括号{ }内部可以出现2种元素:
- 属性 2. 方法
var student = {
name: '张三',
age: 23,
address: '西安',
getInfo: function () {
alert('我是student对象的一个方法');
}
};
1)对象属性
属性:事物的特征,在对象中用属性来表示(常用名词)
键值对在 JavaScript 对象通常称为 对象属性。
- 写法为—— 属性名称: 属性值;
键与值以冒号:
分割,属性与属性之间 或 属性与方法之间使用逗号 ,
分割。
a 得到对象中的属性值
2种访问方式:
- 对象名称.属性名称
- 对象名称[“属性名称”]
alert(student.name); // 张三
alert(student['address']); // 西安
b 修改对象中的属性值
- 对象名称.属性名称 = 新值
student.name = '李四';
alert(student.name); // 李四
2)对象方法
方法:事物的行为,在对象中用方法来表示(常用动词)
对象的方法定义了一个函数,并作为对象的属性存储。
对象方法通过添加 ( ) 调用, ( )作为一个函数。
- 写法为——方法名称: function( ){ }
方法与方法之间 或 方法与属性之间使用逗号 ,
分割。
a 调用对象中的方法
- 对象名称.方法名称( )
student.getInfo(); // 弹出:我是student对象的一个方法
8. 数组(Array)
- 数组可以把一组相关的数据存储在单个变量下,并提供方便的访问( 获取)方式。
- 数组是指一组数据的集合,其中的每个数据被称作元素,在数组中可以存放任意类型的元素。
1)创建数组
JS 中创建数组有两种方式:
a 利用 new 创建数组
// 1. 先创建 后赋值
// 先创建一个新的空数组 注意Array() ,A要大写
var arr1 = new Array();
// 再向数组中赋值 —— 数组名称[下标]=数据值;
// []---数组的标志
// 下标---数据值在数组中的位置,从0开始
arr1[0] = "张三";
arr1[1] = 23;
arr1[2] = "西安";
// 2. 创建+赋值
// var 数组名称 = new Array("数据值1",数据值2,数据值3);
var arr2 = new Array("张三", 23, "西安");
b 利用数组字面量创建数组
//1. 使用数组字面量方式创建空的数组
var arr3 = [];
//2. 使用数组字面量方式创建带初始值的数组(创建+赋值)
var arr4 = ["张三", 23, "西安"];
- 数组的字面量是方括号 [ ]
- 声明数组并赋值称为数组的初始化
2)获取数组中的数据值
索引 (下标) :用来访问数组元素的序号(数组下标从 0 开始)。
数组可以通过索引来访问、设置、修改对应的数组元素。
- 获取数组中的元素的写法——数组名 [ 索引下标 ];
alert(arr4[0]); // 获取arr数组中的第1个元素 张三
alert(arr4[0] + ',' + arr4[1] + ',' + arr4[2]); // 张三,23,西安
// 数组的length属性---得到数组中的元素的个数
alert(arr4.length); // 3 arr4中一共有3个元素
// 如果访问时数组没有和索引值对应的元素,则得到的值是undefined
alert(arr4[3]); // undefined
9. 函数(Function)
在 JS 里面,可能会定义非常多的相同代码或者功能相似的代码,这些代码可能需要大量重复使用。
函数:就是封装了一段可被重复调用执行的代码块,通过此代码块可以实现大量代码的重复使用。
// 声明函数
function 函数名() {
//函数体代码
return // 返回值
}
// 调用函数
函数名(); // 通过调用函数名来执行函数体代码
1)声明函数
- function 是声明函数的关键字,必须小写
- 由于函数一般是为了实现某个功能才定义的, 所以通常我们将函数名命名为动词,比如 getSum
- {}——函数体包含的是具体功能实现的代码
2)调用函数
-
在需要使用函数的地方直接写函数名称([参数列表]);
-
调用的时候千万不要忘记添加小括号()
-
口诀:函数不调用,自己不执行
注意:声明函数本身并不会执行代码,只有调用函数时才会执行函数体代码。
3)函数的封装
函数的封装是把一个或者多个功能通过函数的方式封装起来,对外只提供一个简单的函数接口。
// 案例:计算1-100的总和
// 1. 声明函数
function getSum(){
var sumNum = 0; // 准备一个变量,保存数字和
for (var i = 1; i <= 100; i++) {
sumNum += i; // 把每个数值 都累加 到变量中
}
alert(sumNum);
}
// 2. 调用函数
getSum();
4)函数的参数
参数的作用 : 在函数内部某些值不能固定,我们可以通过参数在调用函数时传递不同的值进去,即—接收函数之外的数据进入本函数中进行运算。
- 形参:形式上的参数,函数定义的时候传递的参数,当时并不知道是什么
- 实参:实际上的参数,函数调用的时候传递的参数(传入小括号内的真实数据),实参是传递给形参的
- 形参和实参必须以一致的顺序出现。第一个形参就是第一个被传递的实参的给定的值,以此类推。
// 带参数的函数声明
function 函数名(形参1, 形参2 , 形参3...) { // 可以定义任意多的参数,用逗号分隔
// 函数体
}
// 带参数的函数调用
函数名(实参1, 实参2, 实参3...);
- 函数可以带参数也可以不带参数
- 声明函数的时候,函数名括号里面的是形参,形参的默认值为 undefined
- 调用函数的时候,函数名括号里面的是实参
- 多个参数中间用逗号分隔
5)函数的返回值
return 语句
返回值:函数的执行结果,函数执行完成后可以通过return语句将指定数据返回 。
在使用 return 语句时,函数会停止执行,并返回指定的值。
// 声明函数
function 函数名(){
// 函数体
return 需要返回的值;
}
// 调用函数
函数名(); // 此时调用函数就可以得到函数体内return后面的值
break ,continue ,return 的区别
- break :结束当前的循环体
- continue :跳出本次循环,继续执行下次循环
- return :不仅可以退出循环,还能够返回 return 语句中的值,同时还可以结束当前的函数体内的代码
6)案例
// 1. 没有参数,没有返回值的函数
// 声明
function test1() {
alert('没有参数,没有返回值的函数');
}
// 调用
test1();
// 2. 有一个参数,没有返回值的函数
// 声明
function test2(num1) {
alert('有一个参数,没有返回值的函数,参数是:' + num1);
}
// 调用时要传参
test2('张三');
// 3. 有多个参数,没有返回值的函数
// 声明
function test3(num1, num2, num3) {
alert('有多个参数,没有返回值的函数,参数是:' + num1 + ',' + num2 + ',' + num3);
}
// 调用时要传参:相同数量对应顺序
test3('张三', 23, '西安');
// 4. 没有参数,有返回值的函数
// 声明
function test4() {
alert('没有参数,有返回值的函数');
return '返回值1';
}
// 调用时要声明一个变量来保存接收的函数返回值结果
var result = test4();
alert('test4的运行结果是:' + result);
// 5. 有参数,有返回值的函数
// 声明
function test5(num1, num2) {
alert('有参数,有返回值的函数,参数是:' + num1 + ',' + num2);
return '返回值2';
}
// 调用时:要传参,并且要声明一个变量来保存接收的函数返回值结果
var result = test5('李四', 25); // 因为局部变量只作用于函数内,所以不同的函数可以使用相同名称的变量。
alert('test5的运行结果是:' + result);
- 总结: 要什么,给什么; 给什么,收什么。
10. typeof 操作符
typeof 可用来检测变量的数据类型
类型 | 举例 | 结果 |
---|---|---|
字符串string | typeof “张三” | string |
数字number | typeof 50 | number |
布尔boolean | typeof false | boolean |
空null | typeof null | object |
未定义undefined | var nu; typeof nu | undefined |
对象object | typeof {name:‘张三’, age:20} | object |
数组array | typeof [1,2,3,4] | object |
函数function | var fun = function test(){alert(‘函数’)} ; typeof fun | function |
三、变量与函数的关系
1. 作用域
通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。
JavaScript(es6前)中的作用域有两种:
- 全局作用域
- 局部作用域(函数作用域)
1)全局作用域
作用于所有代码执行的环境 (整个script标签内部) 或独立的js文件。
2)局部作用域(函数作用域)
作用于函数内的代码环境,就是局部作用域。
因为跟函数有关系,所以也称为函数作用域。
2. 变量的作用域
在JavaScript中,根据作用域的不同,变量可以分为两种:
- 全局变量
- 局部变量
1)全局变量
在全局作用域下声明的变量叫做全局变量(在函数外部定义的变量)。
- 网页中所有脚本和函数均可使用全局变量
- 如果变量在函数内没有声明(没有使用 var 关键字),该变量为全局变量(不建议使用)
2)局部变量
在局部作用域下声明的变量叫做局部变量(在函数内部定义的变量)。
- 局部变量只能在该函数内部使用
- 局部变量在函数开始执行时创建,函数执行完后局部变量会自动销毁。
- 因为局部变量只作用于函数内,所以不同的函数可以使用相同名称的变量。
- 函数参数只在函数内起作用,是局部变量。
3)全局变量和局部变量的区别
- 全局变量: 网页中所有脚本和函数均可使用,只有在浏览器关闭时才会被销毁,因此比较占内存
- 局部变量: 只在函数内部使用,当其所在的代码块被执行时,会被初始化,当代码块运行结束后,就会被销毁,因此更节省内存空间
var num = 50;
function test1() {
var name = '张三';
alert('函数访问全局变量num是:' + num); // 50
alert('函数访问本函数内部变量name是:' + name); // 张三
}
test1();
alert('全局作用域下访问全局变量num是:' + num); // 50
alert('全局作用域下访问函数内局部变量name是:' + name); // (空的 什么都不显示)
3. 预解析
1)概念
JavaScript 代码是由浏览器中的 JavaScript 解析器来执行的。
JavaScript 解析器在运行 JavaScript 代码的时候分为两步:
- 预解析:在当前作用域下,,JS 代码执行之前,浏览器会默认把带有 var 和 function 声明的变量在内存中进行提前声明或者定义,预解析也叫做变量/函数提升。
- 代码执行: 从上到下执行JS语句。
注意:预解析会把变量和函数的声明在代码执行之前执行完成。
2)变量预解析
变量的声明会被提升到当前作用域的最上面,变量的赋值不会提升。
console.log(num); // 结果是多少?
var num = 10; // ?
结果:undefined
注意:变量提升只提升声明,不提升赋值
// 相当于:
var num;
console.log(num);
num = 10;
3)函数预解析
函数的声明会被提升到当前作用域的最上面,但是不会调用函数。
fn();
function fn() {
console.log('打印');
}
结果:控制台打印字符串 — ”打印“
注意:函数声明代表函数整体,所以函数提升后,函数名代表整个函数,但是函数并没有被调用!
4)函数表达式声明函数问题
函数表达式创建函数,会执行变量提升
fn();
var fn = function() {
console.log('想不到吧');
}
结果:报错提示 ”fn is not a function"
解释:该段代码执行之前,会做变量声明提升,fn在提升之后的值是undefined;而fn调用是在fn被赋值为函数体之前,此时fn的值是undefined,所以无法正确调用
// 相当于:
var fn;
fn();
fn = function() {
console.log('想不到吧');
}
四、运算符
运算符(operator)也被称为操作符,是用于实现赋值、比较和执行算数运算等功能的符号。
JavaScript中常用的运算符有:
- 算数运算符
- 递增和递减运算符
- 赋值运算符
- 比较运算符
- 逻辑运算符
- 条件运算符
1. 算数运算符
用于执行两个变量或值的算术运算。
运算符 | 描述 |
---|---|
+ | 加法 |
- | 减法 |
* | 乘法 |
/ | 除法 |
% | 取模(余数) |
-
+
2种用法:- 用于字符串拼接
- 用于运算加值
// 1. 用于字符串拼接 var num1 = 123; var str1 = "你好"; alert(num1 + str1); // 123你好 // 2. 用于运算加值 var num2 = 30; var num3 = 50; alert(num2 + num3); // 80
-
浮点数的精度问题
浮点数值的最高精度是 17 位小数,但在进行算术计算时其精确度远远不如整数。
所以:不要直接判断两个浮点数是否相等 !
var result = 0.1 + 0.2; // 结果不是 0.3,而是:0.30000000000000004 console.log(0.07 * 100); // 结果不是 7, 而是:7.000000000000001
2. 递增和递减运算符
如果需要反复给数字变量添加或减去1,可以使用递增(++)和递减( – )运算符来完成。
在 JavaScript 中,递增(++)和递减( – )既可以放在变量前面,也可以放在变量后面。
放在变量前面时,我们可以称为前置递增(递减)运算符,
放在变量后面时,我们可以称为后置递增(递减)运算符。
注意:递增和递减运算符必须和变量配合使用。
1)递增运算符 ++
前置递增运算符
var num1 = 100;
// 前置递增运算符 ++num 先加1后用
alert(++num1); //101
alert(num1); //101
后置递增运算符
var num1 = 100;
// 后置递增运算符 num++ 先用后加1
alert(num1++); //100
alert(num1); //101
2)递减运算符 –
前置递减运算符
var num1 = 100;
// 前置递减运算符 --num 先减1后用
alert(--num1); //99
alert(num1); //99
后置递减运算符
var num1 = 100;
// 后置递减运算符 num-- 先用后减1
alert(num1--); //100
alert(num1); //99
3. 赋值运算符
赋值运算符用于给 JavaScript 变量赋值。
运算符 | 说明 |
---|---|
= | 直接赋值 |
+= 、 -= | 加、减一个数后 再赋值 |
*= 、 /= 、 %= | 乘、除、取余后 再赋值 |
var age = 10;
age += 5; // 相当于 age = age + 5;
age -= 5; // 相当于 age = age - 5;
age *= 10; // 相当于 age = age * 10;
age /= 10; // 相当于 age = age / 10;
age %= 10; // 相当于 age = age / 10 后取余数;
4. 比较运算符
比较运算符是两个数据进行比较时所使用的运算符,比较运算后,会返回一个布尔值(true / false)作为比较运算的结果。
运算符 | 描述 | 比较 | 返回值 |
---|---|---|---|
> | 大于 | 5>8 | false |
< | 小于 | 5<8 | true |
>= | 大于或等于 | 5>=8 | false |
<= | 小于或等于 | 5<=8 | true |
== | 等于(注意此时有隐式转换) | 5==8 | false |
!= | 不等于 | 5!=8 | true |
=== | 绝对等于(值和类型均相等) | 5===“5” | false |
!== | 不绝对等于(值和类型有一个不相等,或两个都不相等) | 5!==“5” | true |
5. 逻辑运算符
逻辑运算符是用来进行布尔值运算的运算符,其返回值也是布尔值。
后面开发中经常用于多个条件的判断。
运算符 | 描述 | 例子 | 结果 |
---|---|---|---|
&& | 逻辑与 and | (6 < 10 && 3 > 1) | true |
|| | 逻辑或 or | (6 == 5 || 3 == 5) | false |
! | 逻辑非 not | !(6==3) | true |
1)逻辑与&&
两边都是 true才返回 true,只要有一边为 false ,就返回 false
2)逻辑或 ||
两边都是false才返回 false,只要有一边为 true ,就返回 true
3)逻辑非 !
逻辑非(!)也叫作取反符,用来取一个布尔值相反的值。
var res = !true;
console.log(res); // false
4)逻辑短路
逻辑短路是对于逻辑运算而言的,是指:
仅计算逻辑表达式中的一部分便能确定结果,而不对整个表达式进行计算的现象。
-
对于
逻辑或&&
运算符,当第一个操作数为 false 时,将不会判断第二个操作数,因为此时无论第二个操作数为何,最后的运算结果一定是 false; -
对于
逻辑与||
运算符,当第一个操作数为 true 时,将不会判断第二个操作数,因为此时无论第二个操作数为何,最后的运算结果一定是 true。
用到js里就变成拿值(对象)了:
-
只要 && 前面是 false,无论 && 后面是true还是 false,结果都将返 && 前面的值;
-
只要 && 前面是 true,无论 && 后面是true还是false,结果都将返 && 后面的值;
-
只要 || 前面为 true,无论 || 后面是true还是 false,结果都返回 || 前面的值。
-
只要 || 前面为 false,无论 || 后面是true还是 false,结果都返回 || 后面的值。
5)运算符优先级
- 先算小括号()里面的
- 递增++ 递减-- 逻辑非!
- 算数运算符(先乘/除/取余,后加/减)
- 关系运算符 > >= < <=
- 相等运算符 == != === ! ==
- 逻辑运算符 先逻辑或 && 后逻辑与 ||
- 赋值运算符 =
注意:
- 一元运算符里面的逻辑非优先级很高
- 逻辑与比逻辑或优先级高
6. 条件运算符(三元表达式)
条件表达式 ? 表达式1 : 表达式2;
- 如果条件表达式结果为 true ,则返回表达式1的值
- 如果条件表达式结果为 false,则返回表达式2的值