函数
function,是被设计为执行特定任务的代码块
说明:
函数可以把具有相同或相似逻辑的代码“包裹”起来,通过函数调用执行这些被“包裹”的代码逻辑,这么做的优势是有利于精简代码方便复用。
函数的声明语法
函数使用
函数名命名规范
和变量命名基本一致
尽量小驼峰式命名法
前缀应该为动词
命名建议:常用动词约定
如之前的乘法表
<script>
// 函数封装 代码复用
// function 函数 sheet99 函数名
function sheet99(){
for (let index = 1; index <= 9; index++) {
for (let index1 = 1; index1 <= index; index1++){
let num = index1 * index
document.write(`<span> ${index1} x ${index} = ${num}</span>`)
}
document.write(`<br/>`)
}
}
// 函数一次声明可以多次条用 每一次函数调用函数体 里面的代码会重新执行一次
// sheet99()
// sheet99()
// sheet99()
// sheet99()
// 可以用for循环 循环调用
for (let index = 1; index <= 3; index++){
// 要多少个乘法表 就循环几次
sheet99()
}
</script>
函数传参
-
为什么要有参数的函数
思考:这样的函数只能求 10 + 20, 这个函数功能局限非常大
解决办法:把要计算的数字传到函数内
结论:
若函数完成功能需要调用者传入数据,那么就需要用有参数的函数 这样可以极大提高函数的灵活性
2、有参数的函数声明和调用
演示
<script>
// 声明函数 输入形参
function getSum(num1, num2){
document.write(num1 + num2)
}
// 输入实际参数
getSum(15, 100)
getSum(200, 100)
</script>
3 形参和实参
形参:声明函数时写在函数名右边小括号里的叫形参(形式上的参数)
实参:调用函数时写在函数名右边小括号里的叫实参(实际上的参数)
形参可以理解为是在这个函数内声明的变量(比如 num1 = 10)实参可以理解为是给这个变量赋值 开发中尽量保持形参和实参个数一致
我们曾经使用过的 alert('打印'), parseInt('11'), Number('11') 本质上都是函数调用的传参
函数封装求和
<script>
// 数组求和
// 设置一个形式上的参数 a 一个数据 别名
function calcSum(a){
let sum = 0
// 与循环里形成对应 相当于a 此时是个空数组
for (let i = 0; i < a.length; i++) {
sum += a[i]
}
console.log(sum);
}
let arr1 = [85, 90, 100, 85, 60]
let arr2 = [90, 100, 100, 70, 80]
// 调用参数 输入实际参数 arr1是实际参数 让形式上的a成为实际参数arr1 把里面的数组调用进去使用
calcSum(arr1)
calcSum(arr2)
</script>
函数返回值
函数是被设计为执行特定任务的代码块 把处理结果返回给调用者
有返回值函数的概念:
当调用某个函数,这个函数会返回一个结果出来
这就是有返回值的函数
用 return 返回数据
细节:
在函数体中使用 return 关键字能将内部的执行结果交给函数外部使用
函数内部只能运行到 1 次 return,并且 return 后面代码不会再被执行,所以 return 后面的数据不要换行写
return会立即结束当前函数
函数可以没有 return,这种情况函数默认返回值为 undefined
演示案例
<script>
// 函数最大值
function getMax(n1, n2){
if(n1 > n2){
// return 代表函数的返回值 n1 就是 函数在执行完毕的时候 会返回的数据
return n1
}else {
return n2
}
}
// 通过 console.log 帮我打印结果
console.log(getMax(1, 3));
// 通过 document.write 帮我打印
document.write(getMax(6, 9))
// 通过 alert 帮我打印
alert(getMax(8, 12))
</script>
函数返回值练习
<script>
// 声明一个函数 计算数组的最大值 并且返回
let arr1 = [1, 3, 4, 33, 22]
function getMax(arr){
let max = arr[0]
for (let index = 0; index < arr.length; index++) {
if (arr[index] > max) {
max = arr[index]
}
}
return max
}
console.log(getMax(arr1)); //max 该组的最大值
// 声明一个函数 计算数组的最小值 并且返回
function getMin(arr){
let min = arr[0]
for (let index = 0; index < arr.length; index++) {
if (arr[0] < min) {
min = arr[index]
}
}
return min //返回值要在循环外面填写
}
let min = getMin(arr1)
console.log(min);
</script>
作用域
作用域概述
通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。
演示
<script>
// script 标签内的运行环境就是全局作用域
let num = 100 //全局作用域
function getMax(){
// 这个区域内就不属于全局作用域
// 局部作用域 或者 也叫做 函数作用域
let num2 = 200
}
for (let index = 0; index < array.length; index++) {
// 块级作用域
}
while (true) {
// 块级作用域
}
</script>
变量的作用域
在JavaScript中,根据作用域的不同,变量可以分为
变量作用域特殊情况:
- 如果函数内部或者块级作用域内部,变量没有声明,直接赋值,也当全局变量看,但是强烈不推荐
- 函数内部的形参可以看做是局部变量,所以形参相当于函数内部定义的局部变量,只有在函数内部可以使用。
演示案例 - 全局讲解
<script>
// 直接卸载全局作用域下的变量 = 全局变量
let num = 100 // 全局变量 在任何地方都可以访问
function getMax(){
console.log('函数 访问全局变量', num);
}
getMax()
for (let index = 0; index < array.length; index++) {
console.log('for循环内 块级作用域 访问全局变量', num);
}
if(true){
console.log('if语句 也可以访问全局变量', num);
}
</script>
演示案例 - 局部变量
<script>
/* 如果是在函数内部定义的变量 就做局部变量
局部变量 不能在它的大括号之外使用 否则就会报错
*/
let num = 100
let msg = 10000 //全局变量
// 局部变量 函数内部 声明的变量
function getMax(){
// 声明一个数字
let num = 200 // 局部变量
console.log(num); // 200 就近原则 寻找变量的时候 优先找自己的作用域
}
getMax()
// 局部变量 不能在 超出它的大括号来使用
// 例如:
// console.log(num); //会报错
</script>
LET 变量
let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问
<script>
// 定义一个变量 没使用 let 关键字 那么它就是一个全局变量
//
// userName = '索隆'
// console.log(userName);
function func1() {
// userName = '索隆'// 全局变量 没使用let关键字
let userName = '索隆'//局部变量
}
func1()
console.log(userName)// 报错
</script>
变量的作用域
变量作用域特殊情况:
- 如果函数内部或者块级作用域内部,变量没有声明,直接赋值,也当全局变量看,但是强烈不推荐
- 函数内部的形参可以看做是局部变量,所以形参相当于函数内部定义的局部变量,只有在函数内部可以使用。
变量访问原则-作用域链
只要是代码,就至少有一个作用域
写在函数内部的局部作用域
如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链
演示
<script>
// 判断当前的变量 输出是什么
// 就近原则 判断是要根据函数的定义 来判断 而不是函数的调用
let num = 100 //结果为100
function func1(){
let num = 200
// 函数的调用
func2()
}
// 函数的定义-声明
function func2(){
console.log(num);
}
func1()
</script>
匿名函数
函数可以分为:
将匿名函数赋值给一个变量,并且通过变量名称进行调用 我们将这个称为函数表达式
演示
使用场景
目前没有, 先认识 后期 web API 会使用:
<script>
// 函数按照有没有名字 分成两种
// 有名字 具名函数
// 没有名字 匿名函数
// 具名函数 函数名称 func1
function func1 () {
}
// 匿名函数 = function(){} 匿名函数 了解即可
// let func2 = function(){} 叫做 函数表达式
// 表达式 可以表示结果的一段代码 函数表达式
let func2 = function() {
console.log('123');
}
// 调用
func2()
</script>
立即执行函数
场景介绍: 避免全局变量之间的污染
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
</style>
</head>
<body>
<script>
// 自执行函数 = 匿名函数一起出现 通用的功能是 防止变量污染
// 函数在定义的同事 直接就执行
// 适合做一次性的任务 不希望这个函数可以得到复用
// 函数包装多段代码 让程序比较简洁
// 1、页面打开时候
// 1、设置 页面的标题 = 月薪过万
// 2、设置 页面的背景颜色 = 黄色
// 自执行函数
// function (){
// // 设置 页面的标题 = 月薪过万
// document.title = '月薪过万'
// // 设置 页面的背景颜色 = 黄色
// document.body.style.backgroundColor = 'yellow'
// }
//let msg = 123;
// 自执行函数
(function () {
let msg = 123;
// 设置 页面的标题 = 月薪过万
document.title = '月薪过万';
// 设置 页面的背景颜色 = 黄色
document.body.style.backgroundColor = 'yellow';
})();
console.log(msg);
</script>
转换时间案例
需求: 用户输入秒数,可以自动转换为时分秒
分析:
①: 用户输入总秒数
②:计算时分秒(封装函数) 里面包含数字补0
③:打印输出
计算公式:计算时分秒
小时: h = parseInt(总秒数 / 60 / 60 % 24)
分钟: m = parseInt(总秒数 / 60 % 60 )
秒数: s = parseInt(总秒数 % 60)
<script>
// let num = +prompt('请输入你的秒数')
// h = parseInt(num / 60 / 60 % 24)
// m = parseInt(num / 60 % 60)
// s = parseInt(num % 60)
// console.log(h)
// console.log(m)
// console.log(s)
// console.log(`${h}:${m}:${s}`)
function getTime (a, b, c){
let seconds = +prompt('请输入你的秒数')
// 设置空数组 要加0 不然补0失效
let arr = [0]
h = parseInt(seconds / 60 / 60 % 24)
m = parseInt(seconds / 60 % 60)
s = parseInt(seconds % 60)
// 数字补0
for (let index = 0; index < arr.length; index++) {
if (h < 10){
h = '0' + h;
}
if (m < 10){
m = '0' + m;
}
if (s < 10){
s = '0' + s;
}
}
// 打印输出
console.log(`${h}:${m}:${s}`);
// 页面输出
// document.write(`${h}:${m}:${s}`)
}
// 调用 传入实际参数
getTime(['h', 'm', 's'])
</script>
计时器2
<script>
let h = 0;
let m = 0;
let time = +prompt('请输入秒数');
function getTime(seconds){
while (seconds >= 3600){
seconds -= 3600
h++
}
while (seconds >= 60) {
seconds -= 60
m++
}
document.write(h + ':' + m + ':' + seconds);
}
getTime(time);
</script>
计时器3
<script>
function getTime(time){
let hour = parseInt(time / 60 / 60); //计算小时单位
let minute = parseInt(time / 60) % 60; // 分钟数取余
let second = time % 60; // 计算秒数取余
// 数字补0
hour = hour < 10 ? '0' + hour : hour;
minute = minute < 10 ?"0" + minute : minute;
second = second < 10 ? "0" + second : second;
// 返回时分秒
return [hour, minute, second];
}
let times = getTime(1000); console.log(times);
// 写在网页上
document.write(`${times[0]}:${times[1]}:${times[2]}`);
</script>
对象
对象(object):JavaScript里的一种数据类型
可以理解为是一种无序的数据集合
用来描述某个事物,例如描述一个人
人有姓名、年龄、性别等信息、还有吃饭睡觉打代码等功能
如果用多个变量保存则比较散,用对象比较统一
比如描述 班主任 信息:
静态特征 (姓名, 年龄, 身高, 性别, 爱好) => 可以使用数字, 字符串, 数组, 布尔类型等表示 动态行为 (点名, 唱, 跳, rap) => 使用函数表示
对象使用
对象声明语法
对象有属性和方法组成
属性:信息或叫特征(名词)。 比如 手机尺寸、颜色、重量等…
方法:功能或叫行为(动词)。 比如 手机打电话、发短信、玩游戏…
属性
数据描述性的信息称为属性,如人的姓名、身高、年龄、性别等,一般是名词性的。
属性都是成 对出现的,包括属性名和值,它们之间使用英文 : 分隔
多个属性之间使用英文 , 分隔
属性就是依附在对象上的变量(外面是变量,对象内是属性)
属性名可以使用 "" 或 '',一般情况下省略,除非名称遇到特殊符号如空格、中横线等
演示
<script>
let goods = {
uname : '小米10青春版',
num : '100012816024',
weight : '0.55kg',
address : '中国大陆'
}
console.log(goods);
</script>
对象的增删改查
对象本质是无序的数据集合, 操作数据无非就是 增 删 改 查 语法:
属性访问 (查)
声明对象,并添加了若干属性后,可以使用 . 或 [] 获得对象中属性对应的值,我称之为属性访问。 简单理解就是获得对象里面的属性值。
对象访问属性有两种方式
点形式 对象.属性
[ ] 形式 对象[‘属性’]
两种方式区别
点后面的属性名一定不要加引号
[ ] 里面的属性名加引号,除非它是一个变量
后期不同使用场景会用到不同的写法
对象的改 : 对象名.属性 = 新的属性值
对象的增 : 对象名.新属性 = 新的属性值
对象的删 :delete 对象名.属性;
演示 对象的增删改查
<script>
let goods = {
uname : '小米10青春版',
num : '100012816024',
weight : '0.55kg',
address : '中国大陆'
}
// 打印输出
console.log(goods);
// 单独查询 对象名.属性名 或者 console.log(goods['address']) 中括号里加引号
console.log(goods.address);
console.log(goods['uname']);
// 对象里的属性值修改
goods.uname = '华为 p50'
// console.log(goods);
// 对象名.新属性值 = 新值 增加新的属性值进去
goods.hobby = '王者荣耀'
console.log(goods);
// 新增一个方法 匿名函数 固定写法
let person = {}
person.sayHi = function () {
document.write('新增方法')
}
person.sayHi() //调用方法
// 删除 语法:delete 对象名.属性; 开发中少用 了解即可
delete goods.weight;
console.log(goods);
</script>
对象中的方法
数据行为性的信息称为方法,如跑步、唱歌等,一般是动词性的,其本质是函数。
- 方法是由方法名和函数两部分构成,它们之间使用 : 分隔
- 多个属性之间使用英文 , 分隔
- 方法是依附在对象中的函数
- 方法名可以使用 "" 或 '',一般情况下省略,除非名称遇到特殊符号如空格、中横线等
对象中的方法访问
声明对象,并添加了若干方法后,可以使用 . 调用对象中函数,我称之为方法调用。
注意: 千万别忘了给方法名后面加小括号
演示1
<script>
let obj = {
uname: '张国荣',
// 方法
song: function(){
console.log('沉默是金');
}
}
// 方法调用 对象名.方法名
obj.song()
let obj1 = {
uname: '张国荣',
// 方法 设置形参
song: function(x, y){
// console.log('沉默是金');
console.log(x + y);
}
}
// 方法调用 对象名.方法名
// 加入实参
obj1.song(1, 2)
</script>
演示2
<script>
let person = {
uname : 'andy',
sayHi : function (msg) {
document.write(msg)
return '来自于爸爸的问候'
},
}
// 方法 其实就是一个函数
// 函数 接受参数
// 函数 有返回值
// 函数的使用 函数()
person.sayHi('爸爸爱你们 <br/>')
person.sayHi('爸爸砍死你们 <br/>')
let result = person.sayHi('我来看你们了')
console.log(result);
</script>
遍历对象
对象没有像数组一样的 length 属性,所以无法确定长度
对象里面是无序的键值对, 没有规律. 不像数组里面有规律的下标
一般不用这种方式遍历数组、主要是用来遍历对象
一定记住: k 是获得对象的属性名, 对象名 [ k ] 是获得 属性值
遍历对象小结
遍历对象用那个语句? :for in
遍历对象中, for k in obj, 获得对象属性是那个,获得值是那个?
获得对象属性是 k
获得对象值是 obj[k]
<script>
// 遍历对象
let goods = {
uname : '小米10青春版',
num : '100012816024',
weight : '0.55kg',
address : '中国大陆'
}
// for in 不推荐用来遍历数组
// k 或 key 表示获取属性名 属性名以字符串形式获取 'uname' 'num'
for (let k in goods) {
// 输出的是对象里的属性名
// console.log(k)
// 输出对象里的属性名 'uname' 'num' 表示字符串 无法输出属性值
// (goods.k) = (goods.'uname')
// console.log(goods.k) // 输出结果 undefined
//正确方法 (goods[k]) = (goods['uname'])
console.log(goods[k]);//输出属性值
}
</script>
演示
<script>
// 创建一个对象
let person = {
username : '海贼王',
color : 'yellow',
age : 20,
height : 180
}
for (let k in person) {
console.log(person.k); //找对象中 属性名 k
console.log(person['k']); //找对象中 属性名 k
// k 表示变量 k = 'username'
console.log(person[k]);
console.log(person['username']); // k 表示变量 k = 'username'
console.log(`属性名:${k} 属性值:${person[k]}`);
}
</script>
遍历数组对象案例
<script>
let students = [
{ name: '小明', age: 18, gender: '男', hometown: '河北省' },
{ name: '小红', age: 19, gender: '女', hometown: '河南省' },
{ name: '小刚', age: 17, gender: '男', hometown: '山西省' },
{ name: '小丽', age: 18, gender: '女', hometown: '山东省' }
]
for (let i = 0; i < students.length; i++) {
// console.log(i) 下标 索引号
console.log(students[i]); //每个对象的信息
console.log(students[i].name) //显示每次循环的名字
console.log(students[i].hometown) //显示每次循环的地址信息
// 传统for 可以在加点 (students[i].hometown)
}
</script>
遍历数组对象表格版案例
<style>
table{
margin: 100px auto;
width: 400px;
height: 400px;
border-collapse: collapse;
}
thead{
background-color: #ccc;
}
</style>
</head>
<body>
<script>
let students = [
{ name: '小明', age: 18, gender: '男', hometown: '河北省' },
{ name: '小红', age: 19, gender: '女', hometown: '河南省' },
{ name: '小刚', age: 17, gender: '男', hometown: '山西省' },
{ name: '小丽', age: 18, gender: '女', hometown: '山东省' }
]
/* 先写好基本布局
重点去拼接 html
先拼头 部分
再去遍历部分
对数组和对象的数据获取
拼接结尾部分
*/
// tabltHTML 设置开头table 结尾再拼接
//thead是列表标题部分 不用重复 因此把thead跟table写在开头一起
// 再把身体的开头tbody也写在开头 中间做遍历
let tabltHTML = `
<table border="1"> <thead>
<tr>
<th>序号</th>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>家乡</th>
</tr>
</thead> <tbody>`;
// 遍历生成 外部循环 students 的数组 数组里有几个就循环几次
for (let index = 0; index < students.length; index++) {
// 外循环 添加表格里序号的循环
tabltHTML += `<tr> <td>${index+1}</td>`
// 对 对象做forin遍历 students[index] = students[name] 索引号0-3
for (let k in students[index]) {
// person[k] person = students[index]
let person = students[index] // 数组中的每一个对象
// tabltHTML += `<td> students[index][k] </td>`
tabltHTML += `<td> ${person[k]} </td>`
}
// 结尾
tabltHTML += `</tr>`
}
// 首尾相接
tabltHTML += `</tbody> </table>`
// 输出结果
document.write(tabltHTML)
</script>
内置对象
内置对象是什么 :JavaScript内部提供的对象,包含各种属性和方法给开发者调用
我们之前用过的内置对象 :document.write() , console.log()
内置对象Math
Math对象是JavaScript提供的一个“数学高手”对象
提供了一系列做数学运算的方法
方法有:
random:生成0-1之间的随机数(包含0不包括1)
ceil:向上取整
floor:向下取整
round :就近取整 (0.5 往大取整)四舍五入
max:找最大数
min:找最小数
pow:幂运算
abs:绝对值
内置对象演示
<script>
console.log(Math.PI); // 圆周率 π
console.log(Math.random()); // random() 代表生成随机数字 随机抽奖 随机点名 生成0-1之间的随机数(包含0不包括1)
// 向上取整 返回的是整数 向上就是尽量往上变大到整数
console.log(Math.ceil(1.1)); // 2 1 <-- 1.1 --> 2
console.log(Math.ceil(1.5)); // 2 1 <-- 1.5 --> 2
console.log(Math.ceil(1.9)); // 2 1 <-- 1.9 --> 2
// 向下取整 返回的是整数 向下就是尽量往下变到整数
console.log(Math.floor(1.1)); // 1 1 <-- 1.1 --> 2
console.log(Math.floor(1.5)); // 1 1 <-- 1.5 --> 2
console.log(Math.floor(1.9)); // 1 1 <-- 1.9 --> 2
console.log('-----------------------------')
// round 就近取整 (0.5 往大取整) 返回的是整数
console.log(Math.round(1.1)); // 1 1 <-- 1.1 --> 2 就近 1.1 离1最近
console.log(Math.round(1.5)); // 2 1 <-- 1.5 --> 2 1.5中间 2>1 取2
console.log(Math.round(1.9)); // 2 1 <-- 1.9 --> 2 就近 1.9 离2最近
console.log('-----------------------------')
console.log(Math.round(-1.1)); // -1 -1 <-- -1.1 --> -2 就近原则 -1 最近
console.log(Math.round(-1.5)); // -1 -1 <-- -1.5 --> -2 就近原则 负数往大取 -1 > -2
console.log(Math.round(-1.6)); // -2 -1 <-- -1.6 --> -2 就近原则 近 -2
console.log(Math.round(-1.9)); // -2 -1 <-- -1.9 --> -2 就近原则 -2 最近
console.log('-----------------------------')
// 最大值和最小值
console.log(Math.max(1, 3, 6, 10, 22, 45, 2))
console.log(Math.min(1, 3, 6, 10, 22, 45, 2))
// 幂运算 对某个数字 平方或者立方
// 2平方 = 2 * 2
// 2立方 = 2 * 2 * 2
console.log(Math.pow(2, 3)); // 2立方 3个2相乘
console.log(Math.pow(2, 2)); // 2平方
console.log(Math.pow(3, 3)); // 3的立方
// 绝对值 -1 = 1 -2 = 2
console.log(Math.abs(-2));
console.log(Math.abs(-3));
</script>
生成随机数
如何生成0-10的随机数呢?
Math.floor(Math.random() * (10 + 1))
如何生成5-10的随机数?
Math.floor(Math.random() * (5 + 1)) + 5
<script>
// 生成0-10 的随机数
// 向下 则代表无法取到11这个数字 random本来有小数点 因为floor变成整数
// floor 向下取整 random :取0-1之间 相当 0.12253...乘以11 再向下取整数 生成0-10数字
Math.floor(Math.random() * (10 + 1))
console.log(Math.floor(Math.random() * (10 + 1)));
// 生成0-10 的随机数 第二种方式
Math.round(Math.random() * 10)
console.log(Math.round(Math.random() * 10));
// 生成5-10 的随机数
// 在floor里面先计算结果 再加5 向下取整 floor里 最小为0 最大为5 后面再加5
// 因此随机数在5-10
Math.floor(Math.random() * (5 + 1)) + 5
console.log(Math.floor(Math.random() * (5 + 1)) + 5);
</script>
如何生成N-M之间的随机数
Math.floor(Math.random() * (M - N + 1)) + N
<script>
let arr = ['赵云', '关羽', '黄忠', '马超', '张飞', '吕布', '典韦', '刘备']
// document.write(`${arr[Math.round(Math.random() * (arr.length-1))]}`)
// 获取随机数
function getRandom(min,max){
return Math.floor(Math.random() * (max - min + 1) + min)
}
let index = getRandom(0, arr.length - 1)
console.log(arr[index]);
// 删除数组中的某个元素
arr.splice(index, 1)
console.log(arr);
</script>
易错案例
<script>
let username = '123'
let person = {
username : '海贼王',
color : 'yellow'
}
// 访问它
console.log(person.username); //固定用户 .username 找对象里的 海贼王
console.log(person['username']);//有加引号 代表字符串 找里面 也是海贼王
console.log(person[username]); //中括号里 代码没有加字符串 表示一个变量 username = 'color'
console.log(person['color']); // 变成中括号里是加引号的color 最后是 yellow
// console.log(person[color]); //color 是一个变量 没有这个变量会报错
console.log(person.sgj); // undefined
</script>
拓展-术语解释
知道一些术语,让自己更专业
拓展- 基本数据类型和引用数据类型
简单类型又叫做基本数据类型或者值类型,复杂类型又叫做引用类型。
值类型:简单数据类型/基本数据类型,在存储时变量中存储的是值本身,因此叫做值类型 string ,number,boolean,undefined,null
引用类型:复杂数据类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用数据类型 通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等
堆栈空间分配区别:
1、栈(操作系统):由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;
简单数据类型存放到栈里面
2、堆(操作系统):存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。
引用数据类型存放到堆里面
<script>
/*栈
1、 适合存放具体大小的数据, 这一些数据一般变化不会太大 */
let num = 100
let show = true;
let msg = '你好'
// 堆
// 1、 适合存放可能会经常改变大小的数据 这一些数据变化比较大
let person = {}
person.uname = '悟空' // 增加数据属性
delete person.uname // 删除了数据属性
let arr = []
// for 100次 arr.push(index) 数组被修改的比较多了
// arr.splice(3, 1) //修改元素
// 只要我们开始声明一个变量 内存中就开始开辟了空间
let a = 100 // 有a在 开辟空间 来存放变量 (写代码 故意写多个let 。。。相当于浪费内存性能下降)
// 栈 和 堆 两个都是存放数据的地方
</script>