JavaScript
一、初识js
JavaScript输入输出语句
方法 | 说明 | 归属 |
---|---|---|
alert(msg) | 浏览器弹出警示框 | 浏览器 |
console.log(msg) | 浏览器控制台打印输出信息 | 浏览器 |
prompt(info) | 浏览器弹出输入框,用户可以输入 | 浏览器 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 这是一个输入框
prompt('请输入您的年龄:');
// alert 弹出警示框 输出的 展示给用户的
alert('计算的结果是');
// console 控制台输出 显示给程序员测试用的
console.log('我是程序员能看到的');
</script>
</head>
<body>
</body>
</html>
变量
变量本质:是程序在内存中申请的一块用来储存数据的空间
变量的使用:声明 赋值
声明变量
var age;//声明一个名为age的var变量
赋值
age = 10;//给名为age的变量赋值
变量语法扩展
1、更新变量 ,一个变量被重新赋值后,它原有的值就会被覆盖,变量值将以最后一次赋的值为准
2、同时声明多个变量
数据类型
变量的数据类型
JavaScript是一种弱类型或者说动态语言。意味着不用提前声明变量的类型,在程序的运行过程中,类型会自动被确定。
JavaScript拥有动态类型,同时也意味着相同变量可用作不同的类型
数据类型的分类
简单数据类型
简单数据类型 | 说明 | 默认值 |
---|---|---|
Number | 数字型,包含整型值和浮点型值 | 0 |
Boolean | 布尔值类型,如true false | false |
String | 字符串类型 | “” |
Undefined | var a;声明了a但是没有给a赋值 | undefined |
Null | var a = null | null |
Number型
1、八进制 0~7 我们程序里面的数字前面加0 表示八进制
2、十六进制 0~9 a~f #ffffff 数字的前面加0x表示十六进制
数字型范围:
alert(NUmber.Max_VALUE);//1.7976931348623157e+308
alert(Number.Max_VALUE);5e-324
数字的三个特殊值
Infinity,代表无穷大,大于任何值
-Infinity,代表无穷小,小于任何值
NaN,Not a number,代表一个非数值
isNan()这个方法用来判断非数字 并且返回一个值 如果是数字返回的是false 如果不是数字返回的是true
String型
1、字符串引号嵌套
JS可以用单引号嵌套双引号,或者用双引号嵌套单引号(外双内单,外单内双)
2、字符串转义符
转义符 | 解释说明 |
---|---|
\n | 换行符 |
\\ | 斜杠\ |
\’ | ‘单引号 |
\" | "双引号 |
\t | tab 缩进 |
\b | 空格 |
3、字符串长度
字符串是由若干字符组成的,这些字符的数量就是字符串的长度。通过字符串的length属性可以获取整个字符串的长度。
4、字符串的拼接
多个字符串之间使用+进行拼接,其拼接方式为字符串+任何类型=拼接之后的新字符串
布尔型 Boolean
布尔类型对应false(0)和true(1)两个值,默认值为false
Undefined 和Null
一个声明后没有被赋值的变量会有一个默认值undefined(如果进行相连或者相加时,注意结果)
undefined和字符串相加直接拼接,和数字相加结果为NaN
null
空值 + 数字返回数字
获取数据类型
typeof可用来获取检测变量的数据类型
字面量
字面量是在源代码中一个固定的表示法,通俗来说,就是字面量表示如何表达这个值
数字字面量:8,9,10
字符串字面量:‘黑马程序员’,“大前端”
布尔字面量;true,false
数据类型的转换
使用表单、prompt获取过来的数据默认就是字符串类型,此时就不能直接简单的进行加法运算,而需要转换变量的数据类型。通俗来说,就是把一种数据类型的变量转换成另外一种数据类型。
转换为字符串
方式 | 说明 | 案例 |
---|---|---|
toString() | 转换字符串 | var num = 1; alert(num.toString()); |
String()强制转换 | 转换成字符串 | var num = 1; alert(String(num)); |
加号拼接字符串 | 和字符串拼接的结果都是字符串 | var num = 1; alert(num + “我是字符串”) |
转换为数字型(重点)
方式 | 说明 | 案例 |
---|---|---|
parseInt(string)函数 | 将string类型转换成整数数值型 | parseInt(‘78’) |
parseFloat(string)函数 | 将string类型转换成浮点型数值 | parseFloat(‘78.21’) |
Number()强制转换函数 | 将string类型转换为数值型 | Number(‘12’) |
js隐式转换(- * /) | 利用算术运算饮食转换为数值型 | ‘12’ - 0 |
转换为布尔型
方式 | 说明 | 案例 |
---|---|---|
Boolean()函数 | 其他类型值转换为布尔值 | Boolean(‘true’); |
代表空、否定的值会被转换为false,如:’ ', 0, NaN, null, undefined
其余值都会被转换为true
复杂数据类型
运算符
运算符也称操作符,是用于实现赋值、比较和执行算数运算等功能的符号。
算术运算符
+ | - | * | / | % |
---|
浮点数的精度问题
浮点数的最高精度是17位小数,但在进行算术运算时其精确度远远不如整数,因此不要直接判断两个浮点数是否相等
前置自增运算符
a++
先自增,后返回值
后置递增运算符
先表达式返回原值 后面变量再自加1
注意
1、前置自增和后置自增如果单独使用,效果是一样的
小结
1、前置递增和后置递增运算符可以简化代码的编写,让变量的值+1 比以前的写法更简单
2、单独使用时运行结果相同
3、与其他代码连用时,执行结果会不同
4、后置:先原值运算,后自加(先人后己)
5、前置:先自加,后运算(先己后人)
6、开发时,大多使用后置递增/减,并且代码独占一行
比较运算符
概念:比较运算符(关系运算符)是两个数据进行比较时所使用的运算符,比较运算后,会返回一个布尔值(true/false)作为比较运算的结果。
运算符名称 | 说明 | 案例 | 结果 |
---|---|---|---|
< | |||
> | |||
>= | |||
<= | |||
== | 判等号(会转型含有隐式转换) | ||
!= | |||
=== !== | 全等 要求值和数据类型都一直 |
逻辑运算符
概念:逻辑运算符是用来进行布尔值运算的运算符,其返回值也是布尔型。开发中经常用于多个条件的判断
逻辑与运算符
运算符:&&
逻辑或运算符
运算符:||
逻辑非运算符
运算符:!
短路运算(逻辑中断)
短路运算的原理:当有多个表达式(值)时,左边的表达式值可以确定结果时,就不再继续运算右边的表达式的值
1、逻辑与
语法:表达式1 && 表达式2
如果第一个表达式为真则返回表达式2,如果第一个表达为假则返回表达式1
2、逻辑或
如果表达式1结果为真,则返回表达式1; 如果表达式1结果为假,则返回表达式2
赋值运算符
= | +=,-= | *=,/=,%= |
---|
运算符优先级
优先级 | 运算符 | 顺序 |
---|---|---|
1 | 小括号 | () |
2 | 一元运算符 | ++ – ! |
3 | 算数运算符 | 先*/%后± |
4 | 关系运算符 | > >= < <= |
5 | 相等运算符 | == != === !== |
6 | 逻辑运算符 | 先&&后|| |
7 | 赋值运算符 | = |
8 | 逗号运算符 | , |
流程控制分支结构
流程控制
概念:控制代码按照什么顺序运行
顺序流程控制
按照代码的先后顺序依次执行
分支流程控制
if语句
if (条件表达式){
//执行语句
}
if-else语句
if (条件表达式){
//执行语句1
}
else{
//执行语句2
}
if -else if语句
if(条件表达式){
//执行语句1
}
else if (条件表达式){
//执行语句2
}
else {
//执行语句3
}
三元表达式
概念:有三元运算符组成的式子称为三元表达式
语法结构:
条件表达式 ? 表达式1 : 表达式2
如果条件表达式结果为真,则返回表达式1的值,如果条件表达式结果为假,则返回表达式2的值
分支流程switch语句
语法结构
switch(表达式){
case value1:
执行语句1; break;
case value2:
执行语句2; break;
default:
执行最后的语句;
}
执行思路 利用表达式的值和case的值相匹配,如果匹配上就执行该case里面的语句 如果没有匹配上,就执行default里面的语句
注意事项
1、开发时 表达式经常写成变量
2、num里的值和case里面的值相匹配时必须是全等 必须是值和数据类型一致才可以 num === 1
3、break;如果当前的case里面没有break,则不会退出,继续执行下一个case
循环结构
在程序中,一组被重复执行的语句被称之为循环体,能否继续重复执行,取决于循环的中止条件。由循环体及循环的中止条件组成的语句称为循环语句
for循环
for (初始化变量;条件表达式;操作表达式){
//循环体
}
断点调试
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pWwvfPsQ-1650767209290)(JavaScript.assets/QQ图片20220405155413.png)]
while循环
while(条件表达式)
{
//循环语句
}
do-while循环
先执行一次循环体再判断条件 至少执行一次循环体
do{
//循环语句
}while(条件表达式)
continue
用于立即跳出本次循环继续下一次循环(本次循环体中continue之后的循环语句少执行一次)
break
break关键字用于立即跳出整个循环 (循环结束)
数组
利用new创建数组
var 数组名 = new Array();
var arr = new Array();//创建一个新的空数组
利用数组字面量创建数组
//1、使用数组字面量方式创建空的数组
var 数组名 = [];
//2、使用数组字面量方式创建带初始化值的数组
var 数组名 = ['小白','小黑','大黄','瑞奇'];
数组中可以存放任意类型的数据。
数组中新增元素
通过修改length长度新增数组元素
1、可以通过修改length长度来实现数组扩容的目的
2、length属性是可读写的
var arr = [1,2,3,4];
arr.length = 5;//将数组长度修改为了5
通过修改索引号增加数组元素
var arr = [1,2];
arr[3] = 3;
注意:
不能直接给数组名赋值,否则里面的数组元素将会全部丢失
函数
函数就是封装了一段可以被重复执行调用的代码块 目的:就是让大量代码重复使用
声明函数
function 函数名(){
//函数体
}
1、function 声明函数的关键字 全部小写
2、函数是做某件事情,函数名一般是动词
3、函数不调用,自己不执行
调用函数
函数名();
调用函数的时候必须有小括号
注意:函数本身不执行自己的代码,只有调用函数了才会执行自己的代码
函数的参数
利用函数的参数实现函数重复不同的代码
形参实参
function 函数名(形参1,形参2...){//在声明函数的小括号里是形参(形式上的参数)
}
函数名(实参1,实参2...);//在函数调用的小括号里面是实参(实际的参数)
注意:1、函数的参数可以有也可以没有,数量不限
2、形参和实参的个数要匹配
函数形参和实参个数不匹配问题
参数个数 | 说明 |
---|---|
实参个数等于形参个数 | 输出正确结果 |
实参个数多于形参个数 | 只取到形参的个数 |
实参个数小于形参个数 | 多的形参定义为undefined,结果为NaN |
函数的返回值格式
function 函数名(){
return 需要返回的结果;
}
1、函数只是实现某种功能,最终的结果需要返回给函数的调用者 函数名() 通过return实现的
2、只要函数遇到return 就把后面的结果返回给函数的调用者 函数名() = return后面的结果
return终止函数
1、return后面的代码不会被实现
2、return只能返回一个值,多个值以最后一个值为准
3、return可以返回一个数组
function getResult(num1, num2){
return [num1+num2,num1-num2,num1*num2,num1/num2];
}
var re = getResult(1,2);
console.log(re);
注意:函数如果有return则返回return后面的值,没有return则返回undefined。
arguments的使用
当我们不确定有多少个参数传递的时候,可以用arguments来获取。在JavaScript中,arguments实际上它是当前函数的一个内置对象。所有函数都内置了一个arguments对象,arguments对象中储存了传递的所有实参。
arguments的使用
function fn(){
console.log(arguments);
}
fn(1,2,3);
arguments展示形式是一个伪数组,因此可以进行遍历。伪数组具有以下特点:
1、具有length属性
2、按索引方式储存数据
3、不具有真正数组的push,pop等方法
函数的声明方式2
函数表达式(匿名函数)
var 变量名 = function(){
};
var fun = function(){
console.log('我是函数表达式');
}
fun();
//1 fun是变量名不是函数名
1、fun是变量名不是函数名
2、函数表达式声明方式跟声明变量差不多,只不过变量里面存的是值 而 函数表达式里面存的是函数
3、函数表达式也可以进行参数传递
作用域
概念:代码名字(变量)在某个范围内起作用和效果 目的是为了提高程序的可靠性更重要的是减少命名冲突
全局作用域
整个script标签或者是一个单独的js文件
局部作用域
在函数内部就是局部作用域 这个代码的名字旨在函数内部起效果和作用
变量作用域
全局变量
在全局作用域下的变量,在全局下都可以使用
局部变量
在局部作用域下的变量 (在函数内部的变量
注意:如果在函数内部没有声明直接赋值的变量也属于全局变量
从执行效率来看全局变量和局部变量
1、全局变量只有浏览器关闭的时候才会销毁,比较占内存资源
2、局部变量当程序执行完毕就会销毁,比较节约内存资源
作用域链
1、只要是代码,就至少有一个作用域
2、写在函数内部的局部作用域
3、如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
4、根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链(采用就近原则)
预解析
1、我们js引擎运行js分为两步: 预解析 代码执行
2、预解析 js引擎会把js 里面所有的var 还有function 提升到当前作用域的最前面
3、代码执行 按照代码书写的顺序从上往下执行
变量预解析
1、变量提升 就是把所有的变量声明提升到当前作用域的最前面 不提升赋值操作
函数预解析
2、函数提升 就是把所有的函数声明提升到当前作用域最前面 不调用函数
对象
在js中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串、数值、数组、函数等
对象由属性和方法组成
属性
事物的特征,在对象中用属性来表示(常用名词)
方法
事物的行为,在对象中用方法来表示(常用动词)
创建对象的方法
利用字面量创建对象
对象字面量:就是{}里面包含了表达这个事物的属性和方法
var obj = {
uname: '张三丰',
age: 18,
sex: '男',
sayHi: function(){
console.log('hi~');
}
}
①、里面的属性或者方法我们采取键值对的形式 键 属性名:值 属性值
②、多个属性或者方法之间用逗号隔开
③、方法冒号后面跟的是一个匿名函数
2、使用对象
①、调用对象的属性 采用对象名.属性名
console.log(obj.uname);
②、调用属性还有一种方法 对象名[‘属性名’]
console.log(obj['age']);
③、调用对象的方法 sayHi 对象名.方法名
obj.sayHi();
利用new Object创建对象
var obj = new Object();//创建了一个空的对象
obj.name = '张三丰';
obj.age = 18;
obj.sex = '男';
obj.sayHi = function(){
console.log('hi~');
}
1、利用等号 = 赋值的方法 添加对象的属性和方法
2、每个属性和方法之间用分号结束
console.log(obj.name);
console.log(obj[‘age’]);
利用构造函数创建对象
函数里面封装的不是普通代码而是对象
语法格式
function 构造函数名(){
this.属性 = 值;
this.方法 = function(){}
}
new 构造函数名();
//***********************************
function Star(uname, age, sex)
{
this.name = uname;
this.age = age;
this.sex = sex;
this.sing = function(sang){
console.log(sang);
}
}
var ldh = new Star('刘德华',18,'男');//调用函数返回的是一个对象
ldh.sing('冰雨');
注意:1、构造函数名字首字母要大写
2、构造函数不需要return 就可以返回结果
3、调用构造函数需要使用new
4、只要使用new Star()调用函数就创建一个对象 ldh{}
5、属性和方法前面必须添加this
遍历对象
for…in语句用于对数组或者对象的属性进行循环操作。
语法格式
for (变量 in 对象){
}
//****************
var obj = {
name:'liuyihan',
age:18,
sex:'女'
}
for(var k in obj){
console.log(k);//k变量 输出得到的是属性名
console.log(obj[k]);//obj[k]得到的是属性值
}
注意:1、使用for in里面的变量 喜欢写k或者key
小结
1、对象可以让代码结构更清晰
2、对象复杂数据类型object
3、本质:对象就是一组无序的相关属性和方法的集合
4、构造函数泛指某一大类,比如苹果、不管是红色苹果还是绿色苹果,都统称为苹果
5、对象实例特指一个事物
6、for in语句可以用于对象属性的遍历
js内置对象
内置对象指js语言自带的一些对象供开发者使用,并且提供了一些常用的或者是最基本而必要的功能(属性和方法)
Math对象
Math对象不是一个构造器,不需要new来调用,而是直接使用里面的属性和方法即可
random随机数
得到两个数之间的随机整数 并且包含这两个整数
function getRandom(min,max){
return Math.floor(Math.random() * (max - min + 1)) + min;
}
//随机点名
var arr = ['张三','张三丰','张三疯子','李四','李思思'];
console.log(arr[getRandom(0,arr.length-1)]);
Date对象
Date()日期对象是一个构造函数必须使用new来调用创建我们的日期对象
var date = new Date();
console.log(date);
1、如果没有参数,返回当前系统的当前时间
2、参数常用的写法 数字型 2019,10,01 或者是字符串型 ‘2019-10-1 8:8:8’
//要求封装一个函数返回当前的时分秒 格式 08:08:08
function getTimer(){
var time = new Date();
var h = time.getHours();
h = h < 10 ? '0'+h:h;
var m = time.getMinutes();
m = m < 10 ? '0'+m:m;
var s = time.getSeconds();
s = s < 10 ? '0'+s:s;
return h + ':' + m + ':' + s;
}
获取Date的毫秒数(时间戳)
//1、通过Date总的毫秒数(时间戳)不是当前时间的毫秒数 而是距离1970年1月1号过了多少毫秒数
//1、通过 valueOf() getTime()
var date = new Date();
console.log(date.valueOf());
console.log(date.getTime());
//2、简单的写法(最常用的写法)
var date1 = +new Date();//+new Date()返回的就是总毫秒数
console.log(date1);
//3、H5 新增的获得总的毫秒数
console.log(Date.now());
倒计时案例
核心算法:输入的时间减去现在的时间就是剩余的时间
做法:1、用时间戳来做。用户输入的时间总的毫秒数减去现在时间的总的毫秒数,得到的就是剩余时间的毫秒数
2、把剩余时间的总的毫秒数转换为天、时、分、秒(时间戳转换为时分秒)
转换公式:
d = parseInt(总秒数/60/60/24);
h = parseInt(总秒数/60/60%24);
d = parseInt(总秒数/60%60);
function countDown(time){
var nowTime = +new Date();//返回的是当前时间总的毫秒数
var inputTime = +new Date(time);//用户输入时间总的毫秒数
var times = (inputTime - nowTime) / 1000;//time是剩余时间总的秒数
var d = parseInt(times/60/60/24);
d = d < 10 ? '0'+d:d;
var h = parseInt(times/60/60%24);
h = h < 10 ? '0'+h:h;
var m = parseInt(times/60%60);
m = m < 10 ? '0'+m:m;
var s = parseInt(times%60);
s = s < 10 ? '0'+s:s;
return d + '天' + h + '时' + m + '分' + s + '秒';
}
console.log(countDown('2022-5-1 18:00:00'));
数组对象
检测是否为数组
1、intanceof 运算符 它可以用来检测是否为数组
var arr = [];
var obj = {};
console.log(arr instanceof Array);
console.log(obj instanceof Array);
//翻转数组
function reverse(arr){
if (arr instanceof Array){
var newArr = [];
for (var i = arr.length - 1; i >= 0; i--){
newArr[newArr.length] = arr[i];
}
return newArr;
}else{
return 'error 这个输入不是数组格式'
}
}
2、Array.isArray(参数);
console.log(Array.isArray(arr));
添加删除数组元素的方法
方法名 | 说明 | 返回值 |
---|---|---|
push(参数1…) | 末尾添加一个或多个元素,注意修改原数组 | 并返回新的长度 |
pop() | 删除数组最后一个元素,把数组长度-1 无参数、修改原数组数 | 返回它删除的元素的值 |
unshift(参数1…) | 向数组的开头添加一个或更多元素,注意修改原数组 | 并返回新的长度 |
shift() | 删除数组的第一个元素,数组的长度-1 无参数、修改原数组 | 并返回第一个元素的值 |
数组排序
方法名 | 说明 | 是否修改原数组 |
---|---|---|
reverse() | 颠倒数组中元素的顺序,无参数 | 该方法会改变原来的数组 返回新数组 |
sort() | 对数组的元素进行排序 | 该方法会改变原来的数组返回新数组 |
var arr1 = [13, 4, 77, 1, 7];
arr1.sort(function(a, b){
return a - b;//升序排列
});
arr1.sort(function(a, b){
return b - a;//降序排列
});
数组索引方法
方法名 | 说明 | 返回值 |
---|---|---|
indexOf() | 数组中查找给定元素的第一个索引 | 如果存在返回索引号,如果不存在,则返回-1 |
lastIndexOf() | 在数组中的最后一个的索引 | 如果存在返回索引号,如果不存在,则返回-1 |
数组转换为字符串
方法名 | 说明 | 返回值 |
---|---|---|
toString() | 把数组转换成字符串,逗号分隔每一项 | 返回一个字符串 |
join(‘分隔符’) | 方法用于把数组中的所有元素转换成一个字符串 | 返回一个字符串 |
其他常用方法
方法名 | 说明 | 返回值 |
---|---|---|
concat() | 连接两个或多个数组 不影响原数组 | 返回一个新的数组 |
slice() | 数组截取slice(begin,end) | 返回呗截取项目的新数组 |
splice() | 数组删除splice(第几个开始,要删除个数) | 返回被删除项目的新数组 注意,这个会影响原数组 |
字符串对象
基本包装类型
基本包装类型就是把简单数据类型包装为复杂数据类型。
字符串的不可变性
指的是里面的值不可变,虽然看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间
根据字符返回位置
字符串的所有方法,都不会修改字符串本身(字符串是不可变的),操作完成会返回一个新的字符串
方法名 | 说明 |
---|---|
indexOf(‘要查找的字符’,开始的位置) | 返回指定内容在原字符串中的位置,如果找不到就返回-1,开始的位置是index索引号 |
lastIndexOf() | 从后往前找,只找第一个匹配的 |
根据位置返回字符
方法名 | 说明 | 使用 |
---|---|---|
charAt(index) | 返回指定位置的字符(index字符串的索引号) | str.charAt(0) |
charCodeAt(index) | 获取指定位置处字符的ASCII码(index索引号) | str.charCodeAt(0) |
str[index] | 获取指定位置处字符 | HTML5,IE8+支持和charAt()等效 |
字符串操作方法
方法名 | 说明 |
---|---|
concat(str1,str2,str3…) | concat()方法用于连接两个或多个字符串。拼接字符串,等效于+,+更常用 |
substr(start, length) | 从start位置开始(索引号),length取的个数 |
slice(start,end) | 从start位置开始,截取到end位置,end取不到 |
substring(start,end) | 从start位置开始,截取到end位置,end取不到,基本和slice相同但是不接受负值 |
方法名 | 说明 |
---|---|
replace(‘被替换字符’,‘替换为的字符’) | 只会替换第一个字符,形成一个新d字符串 |
split(‘分隔符’) | 将字符转换为数组 分隔符取决于字符串里面的分隔符 |
数据类型
简单数据类型与复杂数据类型
简单数据类型储存在栈里复杂数据类型储存到堆里
简单类型传参:形参值改变不会影响实参值
复杂类型传参:函数的形参看做是一个变量,当复杂类型变量传给形参时,其实是把变量在栈空间里保存的堆地址复制给了形参,形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象。因此新参值改变会影响实参的值
和charAt()等效 |
字符串操作方法
方法名 | 说明 |
---|---|
concat(str1,str2,str3…) | concat()方法用于连接两个或多个字符串。拼接字符串,等效于+,+更常用 |
substr(start, length) | 从start位置开始(索引号),length取的个数 |
slice(start,end) | 从start位置开始,截取到end位置,end取不到 |
substring(start,end) | 从start位置开始,截取到end位置,end取不到,基本和slice相同但是不接受负值 |
方法名 | 说明 |
---|---|
replace(‘被替换字符’,‘替换为的字符’) | 只会替换第一个字符,形成一个新d字符串 |
split(‘分隔符’) | 将字符转换为数组 分隔符取决于字符串里面的分隔符 |
数据类型
简单数据类型与复杂数据类型
简单数据类型储存在栈里复杂数据类型储存到堆里
简单类型传参:形参值改变不会影响实参值
复杂类型传参:函数的形参看做是一个变量,当复杂类型变量传给形参时,其实是把变量在栈空间里保存的堆地址复制给了形参,形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象。因此新参值改变会影响实参的值