JavaScript
基础部分
html/css属于标记语言
JavaScript是运行在客户端的脚本语言
浏览器由渲染引擎和JS引擎组成
浏览器本身并不会执行JS代码,而是通过内置JavaScript引擎(解释器)来执行JS代码,JS引擎执行代码时逐行解释每一句源码(转换成机器语言),然后由计算机去执行。
Js的组成包括 ECMAScript(JavaScript语法)、DOM(页面文档对象模型)、BOM(浏览器对象模型)
Js有三种书写位置,行内、内嵌、外部
字面量:字面量就是见词知意
JS输入语句
**注:在prompt中输入的数据为string类型**
prompt('请输入你的年龄')
JS弹出语句
alert('这是一个弹出框')
JS输出语句(控制台)
console.log('这是程序员看到的打印内容')
1.变量
1.变量初始化
变量简述:变量是程序在内存中申请的一块用来存放数据的空间
变量是一个容器,需要有一个名字,通过名字可以访问到容器里的数据。
1.声明变量
var age;
2.赋值 将值存入内存,名字为age
age=10;
3.打印
console.log(age)
4.变量的初始化
//单个变量
var name="anti";
console.log(name);
//声明多个变量
var name="anti",
age=18
5.语法扩展
//未赋值
var age;
//undefined 未定义的
console.log(age); //undefined
//未声明
console.log(sex); //not defined
//未声明 直接赋值使用 JS 可以不声明直接使用,不推荐
qq=100;
console.log(qq); //100
6.小案例 (交换内容)
var temp;
var num1=5;
var num2=10;
temp=num1;
num1=num2;
num2=temp;
2.数据类型
数据类型简述:不同的数据所需占用的存储空间是不同的,为了便于把数据分成所需内存大小不同的数据,充分利用存储空间,于是定义了不同的数据类型。
JavaScript中的数据类型只有程序在运行过程中,根据等号(=)右边的值来确定的。同时,Js是动态语言,变量的数据类型时可以变化的。
var x=10; //number型
x='red'; //string型
1.简单数据类型(基本数据类型)
1.数字型
在JS中八进制前面加0,十六进制前面加0x
//数字型 最大值 和 最小值
alert(Number.MAX_VALUE);
alert(Number.MAX_VALUE * 2); //Infinity 无穷大
alert(Number.MIN_VALUE);
//非数字 NaN
console.log('red'-100); //NaN (not a number)
//isNaN()方法 是数字返回false 不是数字返回ture
console.log(isNaN(100)); //false
//在这里记录下面这两个 带有双引号的"100",在isNaN中返回false,即表明是数字,但是在typeof中却显示为字符型。
//根据查询 说明isNaN只判定是否为数字,而不管其类型
console.log(isNaN("100")); //false
console.log(typeof("100")); //string
console.log(isNaN("100za")); //true
console.log(isNaN("string")); //true
2.字符串型
1.转义字符以及单双引号
在JS中可以用单引号或者双引号来确定字符串型,两个一起使用时,要保证外双内单,内单外双。
在引号里面所有东西都被解释为字符串,如果要使用HTML里面的标签,例如
换行,那么需要使用转义字符。
console.log("我是一个\n换行符")
//我是一个
//换行符
2.字符串长度 (length) 以及字符串拼接
//拼接口诀:数值相加,字符相连
var str='my name is Ruby'
console.log(str.length); //15 包含空格
console.log('沙漠'+123+'骆驼'); //沙漠123骆驼
console.log('沙漠'+12); //沙漠12
console.log(12+12); //24
console.log('12'+12); //1212
//变量拼接口诀:引引加加
var age=18;
console.log('我今年'+age+'岁了'); //我今年18岁了
3.布尔型
//在与数值型运算时 true=1 false=0
var f=true;
console.log(1+f); //2
4.Undefined型
//任何类型和字符串相加 结果都为字符型
var variable=undefined;
console.log(variable+'字符型'); //undefined字符型
console.log(typeof(variable+'字符型')); //string
console.log(typeof(variable+1)); //NaN
5.Null型
var space=null;
console.log(space+'字符型'); //null字符型
console.log(space+'1'); //null1
console.log(space+1); //1
//注:通过这个例子,可以区分null和undefined的区别。
注:一个声明后没有被赋值的变量会有一个默认值undefined(如果进行相连或相加时,注意结果);
一个声明变量给null值,里面存的值为空(学习对象时,将继续研究null)
6.数据类型转换
1.转换成字符型
2.转换成数字型**(重点)**
注:在prompt()中输入的数据为string类型
3.转换成布尔型
注:代表空、否定的值会被转换成false,如’ ‘、0、NaN、null、undefined;其余的都为true
2.运算符
运算符分为以下内容
-
算术运算符
//加减乘除 取余(取模) //这种情况是因为 浮点数 转换成二进制导致数据很小很小,产生误差 console.log(0.1+0.2); //0.30000000000000004
-
递增和递减运算符
//区分先加后用跟先用后加的区别就好 var a++; var ++b; //前置自增和后置自增单独使用时,效果一样的。 //后置自增,先返回原值,后自加1 var a=10; console.log(a++ + 10); //20 console.log(a); //11
-
比较运算符
- 逻辑运算符
短路运算
当有多个表达式(值)时,左边的表达式可以确定结果时,就不再继续用运算右边的表达式的值
//注:在逻辑运算符中,采用的是布尔值 true 和 false 进行运算
//123 && 456
//当有多个表达式(值)时,左边的表达式可以确定结果时,就不再继续用运算右边的表达式的值
-
逻辑与短路运算
//如果表达式1结果为真 则返回表达式2 console.log(123 && 456); //456 //如果表达式1结果为假 则返回表达式1 console.log(0 && 123); //0
-
逻辑或短路运算
//如果表达式1结果为真 则返回表达式1 console.log(123 || 456); //123 //如果表达式1结果为假 则返回表达式2 console.log(0 || 456 ||456+123); //456
-
小案例
var a=0; console.log(123 || ++a); //123 在这里只运算到或符号前面,因为表达式1 为真,所以后面的自增没发生过。 console.log(a); //0
- 赋值运算符
-
运算符优先级
3.分支/循环语句
-
流程控制
顺序结构、分支结构、循环结构
-
分支结构
//if //if ... else if...else
-
小案例(判断是否为闰年)
//算法:能被 4 整除 且 不能整除 100 的为闰年(如2004年就是闰年,1901年不是闰年)或者 能够被400整除的就是闰年。 var year = prompt("请输入一个年份") if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) { console.log("是闰年"); } else { console.log("是平年"); }
-
三元表达式(三目运算符)
var num=10; var result = num > 5 ? '是的' : '不是的'; console.log(result); //是的
-
小案例(数字补0)
var num = prompt('请输入一个数字'); var num1 = num < 10 ? '0' + num : num; alert(num1)
-
switch 语句
switch(表达式){ case value1: 执行语句1; break; case value2: 执行语句2; break; ... default: 执行最后的语句; } //注:如果没表达式和value的值 一样 ,那就执行default //关于break 如果匹配到符合条件的, 如果该条件没有break语句,会接着往下执行其他选项,直至break语句出现
-
循环结构
-
for循环
for(初始化变量;条件表达式;操作表达式){ //循环体 } //1.打印五个*号 for (var i = 1; i <= 5; i++) { str = str + '*'; } console.log(str);
-
双重for循环
//两行五列的* for(var j=1;j<3;j++){ for (var i = 1; i <= 5; i++) { str = str + '*'; } str=str+'\n' } console.log(str); //倒三角形 var str = ''; for(var j=1;j<=10;j++){ for (var i = j; i <= 10; i++) { str = str + '*'; } str=str+'\n' } console.log(str); //********** ********* ******** ******* ****** ***** **** *** ** *
-
while循环
//条件为真才开始循环 while(条件表达式){ //循环体 }
-
do while 循环
//无论条件是否为真 都会至少执行一次 do { //循环体 } while(条件表达式)
-
continue break
continue关键字用于立即跳出本次循环,继续下一次循环(本次循环在continue后的代码将会少执行一次)
break跳出整个循环
-
4.数组
1.创建数组
//利用new创建数组
var arr = new Array();
//利用数组字面量创建数组
var 数组名=[];
var 数组名=['a','b','c']
2.获取数组元素
//根据索引号
var arr=['a','b','c']
console.log(arr[1]); //b
3.数组长度
数组名.length
1.小案例(数组中间插符号)
var arr=['1','2','3','4']
var str=''
for(i=0;i<arr.length;i++){
str+=arr[i]+'$$'
}
console.log(str);
4.数组新增元素
-
通过修改length长度
var arr=['1','2','3','4'] var arr.length=5;
-
新增数组元素
var arr=['1','2','3','4'] arr[4]=5; //不要直接给数组名重新赋值,否则里面的全部数据会被覆盖
2.小案例(数组翻转)
var arr=['1','2','3','4']
var newArr=[];
for(var i=arr.length-1;i>=0;i--){
newArr[newArr.length]=arr[i]
}
console.log(newArr);
3.小案例(数组排序之冒泡排序)
//冒泡排序 从大到小或者从小到大
var arr = [4, 4, 2, 3, 1, 5]
for (var i = 0; i <= arr.length - 1; i++) {
for (var j = 0; j <= arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
var temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp
}
}
}
console.log(arr);
5.函数
简述:函数就是封装了一段可以被重复调用的代码块
1.函数使用
-
声明函数
function 函数名(){ //函数体 }
function sayHi(){ console.log('Hi') }
-
调用函数
sayHi(); //Hi
-
参数
function 函数名(形参1,形参2...){ //函数体 } 函数名(实参1,实参2...) function say(a,b){ console.log(a); console.log(a+b); } say('Hi','你好') //Hi //Hi你好
-
函数返回值return
return 后面的语句是不会被执行的
function getResult(num1,num2){ return num1+num2; alert('这是不会被执行的弹窗'); } console.log(getResult(1,2));
return 有多个值时,返回最后一个
function getResult(num1,num2){ return num1,num2; } console.log(getResult(1,2)); //2
-
arguments的使用
arguments是当前函数的一个内置对象,arguments对象中存储了传递的所有实参。
function fn(){ console.log(arguments); //里面存储了所有实参 arguments属于伪数组 } fn(1,2,3)
伪数组: 并不是真正意义上的数组
- 具有数组的length属性
- 按照索引的方式进行存储
- 它没有真正数组的一些方法 pop(), puh()等等…
-
小案例(函数封装翻转数组)
function reverse(arr) { var newArr = []; for (var i = arr.length-1; i >= 0; i--) { newArr[newArr.length] = arr[i] } return newArr; } var arr1 = reverse([1, 2, 3, 4, 5]) console.log(arr1);
-
小案例(函数封装冒泡排序)
function sort(arr) { for (var i = 0; i < arr.length - 1; i++) { for (var j = 0; j < arr.length - i - 1; j++) { if (arr[j] > arr[j + 1]) { var temp = arr[j]; arr[j] = arr[j + 1] arr[j + 1] = temp } } } return arr } var z=sort([1,3,2,4,5,6,11,22,3,2]) console.log(z);
-
小案例(函数封装是否闰年)
function isRunYear(year){ //如果是闰年我们返回 true 否则 返回false var flag=false; if(year % 4 ==0 && year % 100 != 0 || year %400 == 0){ flag=true; } return flag; }
2.函数声明
-
利用函数关键字自定义函数(命名函数)
function fn(){ //函数体 } fn()
-
函数表达式(匿名函数)
var fun = function(){ //函数体 } fun(); //在这里 fun 是变量名 不是函数名。
6.作用域
简述:JavaScript作用域,就是代码名字(变量)在某个范围内起作用和效果,目的是为了提高程序的可靠性,更重要的是减少命名冲突
1.作用域(全局、局部)
在es6(之后会单独记录块级作用域)之前…作用域分为下面两项:
-
全局作用域
整个script标签,或者是一个单独的js文件
-
局部作用域
只在函数内部起效果的就是局部作用域。
var num=10; //全局作用域 console.log(num); //10 function fn(){ //局部作用域 var num=20; console.log(num); } fn(); //20
-
全局变量
在全局作用域下的变量
注:如果在函数内部 没有声明直接赋值的变量也属于全局变量
-
局部变量
在局部作用域下的变量
注:函数的形参也可以看作是局部变量
-
执行效率
- 全局变量只有在浏览器关闭的时候才销毁,比较占内存空间
- 局部变量在函数执行完成则销毁,比较节省内存空间
2.作用域链
简述:嵌套的函数,输出哪个值,从目标处开始往外查找
3.预解析
-
预解析
预解析 js引擎 会把js 里面所有的 var 还有 function 提升到当前作用域的最前面
-
代码执行
按照代码书写的顺序从上往下执行
-
预解析分为 变量预解析(变量提升) 和 函数预解析(函数提升)
注:1.变量提升 就是把所有的变量声明提升到当前的作用域最前面 不提升赋值操作
2.函数提升 就是把所有的函数声明提升到当前作用域的最前面 不调用函数
变量预解析
console.log(num); //undefined var num=10; //变量提升 var num; console.log(num); num=10; //上面这两个是相等的。
函数预解析
fun(); var fun = function(){ console.log(22); } //相当于执行以下代码 var fun(); fun(); var fun = function(){ console.log(22); }
小案例(预解析)
f1(); console.log(c); console.log(b); console.log(a); function f1(){ var a = b = c = 9; console.log(a); console.log(b); console.log(c); } //预解析后 function f1(){ //在这里这个var是这样的 // var a=9;b=9;c=9 所以bc是没有var的 当全局变量看 //这个和 var a,b,c=9 这种 集体声明 有差别的 var a = b = c = 9; //提升后的顺序 var a; a=b=c=9; console.log(a); //9 console.log(b); //9 console.log(c); //9 } f1(); console.log(c); //9 console.log(b); //9 console.log(a); //a is not defined
7.对象
简述:对象是一组无序的相关属性和方法的集合
注:JavaScript中的对象分为3种:自定义对象、内置对象、浏览器对象
1.创建对象的三种方式
1.利用字面量创建对象{}
- 里面的属性或者方法我们采用键值对的形式
- 多个属性或者方法采用逗号隔开
- 方法冒号后面跟的是一个匿名函数
var obj={
uname='张子',
age:18;
sex:'男',
sayHi:function(){
console.log('hi~')
}
};
使用对象
//1.调用对象的属性 我们采取 对象名.属性名
console.log(obj.uname); //张子
//2.调用属性还有一种方法 对象名['属性名']
console.log(obj.['age']); //18
//3.调用对象的方法 sayHi() 对象名.方法名 记得添加小括号
obj.sayHi();
2.利用new Object 创建对象
- 先创建一个空对象,然后通过 等号 = 赋值的方法, 进行属性和方法的追加
var obj = new Object();
obj.uname='张子';
obj.age=18;
obj.sayHi=function(){
console.log('hi~');
}
3.利用构造函数创建对象
- 利用构造函数,是因为前两种方法一次只能创建一个对象
- 封装函数后,可以多次调用
- 称为构造函数,是因为这个函数里面装的不是普通代码,而是 对象
- 构造函数的首字母大写
- 构造函数不需要return 就可以返回结果
- 调用构造函数 必须使用 new 关键字
- 属性和方法都需要添加this this代表谁调用 指向谁
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,'男');
var zzf = new Star('张子枫',18,'女');
console.log(typeof(ldh)); //Object
console.log(ldh.name); //刘德华
console.log(ldh['sex']); //男
ldh.sing('冰雨')
注:new关键字
4.遍历对象 for…in…
for (变量 in 对象){
}
var obj={
name:'123',
age:18
}
for (var k in obj){
console.log(k); //k 变量 输出得到的是属性名
console.log(obj[k]);//obj[k] 得到的是 属性值
}
8.JavaScript的内置对象
注:JavaScript中的对象分为3种:自定义对象、内置对象、浏览器对象
前两种属于ECMAScript;第三种,浏览器对象是JS独有的。后面学习API会单独记录。
内置对象的使用,可以到MDN上面查询。
1.Math对象
注:Math对象不是一个构造函数,所以不需要new 可以直接使用
console.log(Math.PI);
cosnole.log(Math.max(1,99,3));
1.小案例(利用对象封装自己的数学对象) 里面有PI 最大值和最小值
var myMath={
PI:3.141592653,
max:function(){
var max=arguments[0];
for (var i = 1; i < arguments.length; i++){
if(arguments[i]>max){
max=arguments[i];
}
}
return max;
},
min:function(){
var min=arguments[0];
for (var i = 1; i < arguments.length; i++){
if(arguments[i]<min){
min=arguments[i];
}
}
return min;
}
}
console.log(myMath.PI);
console.log(myMath.max(1,23,4,1));
console.log(myMath.min(1,23,4,1));
Math常用方法:
MDN查询方法后如何使用:
1.Math对象随机数方法 random() 返回一个随机的小数 0=< x <1
2.这个方法里不跟参数
3.代码验证如下
console.log(Math.random());
4.我们想要得到两个数之间的随机整数 并且 包含这 2 个整数
//MDN 上的方法 Math.floor(Math.random()*(max-min+1))+min;
function getRandom(max,min){
return Math.floor(Math.random()*(max-min+1))+min;
}
console.log(getRandom(1,10))
5.随机点名
var arr= ['张三','张er','张si','张wu','张liu']
console.log(arr[getRandom(0,arr.length-1)])
2.日期对象
**注:Math对象是一个构造函数,所以需要new **
1.如果没有跟参数,返回系统的当前时间
var date=new Date();
console.log(date)
2.参数常用的写法
-
数字型 2019,10,01
var date1= new Date(2019,10,1); console.log(date1)
-
字符串型 ‘2019-10-8’
var date1= new Date('2019-10-8');
console.log(date1)
3.日期格式化
注:月份和星期
-
输出年月日
-
封装日期时分秒
var date=new Date(); function getTime(){ 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; }
-
倒计时效果
function countDown(time){ var nowTime= +new Date(); //返回当前时间总的毫秒数 距离1970年1月1日 var inputTime = +new Date(time); //返回的使用户输入时间总的毫秒数 var times=(inputTime-nowTime)/1000; //times 是剩余时间总的秒数 var d=parseInt(times/60/60/24);//天 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('2021-10-11 20:00:00')); var year=prompt('请按照xxxx-xx-xx xx:xx:xx格式输入一个时间'); alert(countDown(year))
3.数组对象
1.instanceof 检测是否为数组
var arr=[];
console.log(arr instanceof Array); //true
2.isArray H5新增检测方法
var arr = [];
console.log(Array.isArray(arr)); //true
3.添加删除数组方法
-
push() 在数组的末尾 添加一个或多个 返回新数组长度
-
unshift() 在数组的前面 添加一个或多个 返回新数组长度
-
pop() 删除数组最后一个元素 返回删除的元素的值
-
shift() 删除数组的第一个元素 返回删除的元素的值
//把数组的中符合要求的重新放到一个新的数组 var arr=[1500,1200,2000,2100,1800]; var newArr=[]; for(var i = 0; i<arr.length;i++){ if(arr[i]<2000){ newArr.push(arr[i]); } } console.log(newArr);
-
数组翻转reverse
reverse() var arr=['1','2','3']; arr.reverse();
-
数组排序(冒泡排序)sort
sort() var arr=['1','2','3']; arr.sort(function(a,b){ // 升序 return a-b; // 降序 return b-a; }); console.log(arr)
-
数组索引方法 indexOf lastIndexOf
//两个方法只分从前或从后开始 如果元素不重复 坐标是一样的。 var arr=['1','2','3']; console.log(arr.indexOf('2')); //只会找到第一个 如果没有该元素 会返回 负一
1.小案例(封装一个去重的函数)
function unique(){ var newArr=[]; for(var i=0;i<arr.length;i++){ if(newArr.indexOf(arr[i])===-1){ newArr.push(arr[i]); } } return newArr; } var arr=['1','2','3','3','4','1','5']; console.log(unique(arr))
-
数组转换成字符串 toSting() join()
//toSting() 把数组转换成字符串,逗号分隔每一项 返回一个字符串 //join('分隔符') 把数组转换成字符串,自定义符号分隔每一项 返回一个字符串 var arr=['1','2','3','3','4','1','5']; console.log(arr.join('-'))
-
部分方法
9.字符串对象
1.基本包装类型
简述就是把简单数据类型包装成复杂数据类型,这样的基本数据类型就有了属性和方法。
var str='andy'
console.log(str.length); //4
//实际如下
var temp=new String('andy');
str=temp;
//销毁
temp=null;
2.字符串的不可变
简述:一个变量的值变了,但是只是指针指向了一块新开辟的内存空间
var str='小明';
console.log(str); //小明
str='小红';
console.log(str); //小红
//注:但这不是覆盖原有数据 ,而是指针指向一块新开辟的内存空间
3.根据字符返回位置
跟数组的基本一样
//indexOf('值','从x开始查找的索引')
//lastIndexOf()
4.根据位置返回字符
//charAt(index)
//charCodeAt(index)
//str[index]
5.字符串操作方法(重点)
除了下面这四个,还有
- 还有替换字符 replace()
- split(‘分隔符’)字符串转换成数组
- toUpperCase() 转换成大写
- toLowerCase() 转换成小写
//replace('被替换','替换成') 只会替换第一个 如果要替换全部 可以搭配indexOf()
//split()把字符串转换成数组 和前面学的数组 join()相反
10.总结(简单类型/复杂类型)
简述:简单类型又叫做基本数据类型或者值类型;复杂类型又叫做引用类型。
1.值类型
基本数据类型(string,number,boolean,undefined,null),在存储时变量中存储的是只本身,因此也叫做值类型。
//null 返回的是一个空的对象 object
var timer=null;
console.log(typeof timer); //object 这其实更像历史遗留问题
//如果有个变量我们以后打算存储为对象,暂时还不确定要存啥 这时候就可以给null
2.引用类型
复杂数据类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用数据类型。
通过 new 关键字创建的对象(系统对象,自定义对象),如Object,Array,Date等。
3.栈
栈:由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;简单数据类型存放到栈里面。
4.堆
堆:存储复杂数据类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。复杂数据类型存放到堆里面。
5.小总结
注:简单来说,内存在这分两样,一个是栈,另一个是堆,就是基本数据类型在栈存放的是真实数据,而复杂数据类型在栈里面放的是一个指向堆的地址,在这个地址在堆里面存放的才是复杂数据类型真实数据。
原有数据 ,而是指针指向一块新开辟的内存空间
#### 3.根据字符返回位置
```js
跟数组的基本一样
//indexOf('值','从x开始查找的索引')
//lastIndexOf()
4.根据位置返回字符
[外链图片转存中…(img-s9ppVzZS-1635168541270)]
//charAt(index)
//charCodeAt(index)
//str[index]
5.字符串操作方法(重点)
除了下面这四个,还有
- 还有替换字符 replace()
- split(‘分隔符’)字符串转换成数组
- toUpperCase() 转换成大写
- toLowerCase() 转换成小写
//replace('被替换','替换成') 只会替换第一个 如果要替换全部 可以搭配indexOf()
//split()把字符串转换成数组 和前面学的数组 join()相反
[外链图片转存中…(img-qlutkNKB-1635168541276)]
10.总结(简单类型/复杂类型)
简述:简单类型又叫做基本数据类型或者值类型;复杂类型又叫做引用类型。
1.值类型
基本数据类型(string,number,boolean,undefined,null),在存储时变量中存储的是只本身,因此也叫做值类型。
//null 返回的是一个空的对象 object
var timer=null;
console.log(typeof timer); //object 这其实更像历史遗留问题
//如果有个变量我们以后打算存储为对象,暂时还不确定要存啥 这时候就可以给null
2.引用类型
复杂数据类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用数据类型。
通过 new 关键字创建的对象(系统对象,自定义对象),如Object,Array,Date等。
3.栈
栈:由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;简单数据类型存放到栈里面。
4.堆
堆:存储复杂数据类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。复杂数据类型存放到堆里面。
[外链图片转存中…(img-wlWHZh5o-1635168541281)]
5.小总结
注:简单来说,内存在这分两样,一个是栈,另一个是堆,就是基本数据类型在栈存放的是真实数据,而复杂数据类型在栈里面放的是一个指向堆的地址,在这个地址在堆里面存放的才是复杂数据类型真实数据。
注:本文仅作为自己学习的经验日志…如若侵权,联系即删。