文章目录
原始类型与引用类型
前提
JavaScript有六种数据类型:
- 数值型
- 字符串型
- 布尔型
- Null
- Undefined
- 对象
原始类型(或叫值类型)
数值、字符串、布尔、Null、Undefined
引用类型对象
原始类型赋值给变量,遍历存储的是这个值本身,而你用类型赋值给变量,变量存储的是一个引用,这个引用会指向内存中的这个对象。
一 赋值的区别
代码示例:
//1 赋值区别
//原始类型赋值,引用类型赋的引用。
//原始类型
let str1 = "hello";
let str2 = str1;
str1 = "JS";
console.log(str1); //输出JS
console.log(str2); //输出hello
//引用类型
let obj1 = {name:"小米"};
let obj2 = obj1;
obj1.name = "小芳";
console.log(obj1.name); //输出 小芳
console.log(obj2.name); //输出小芳
二 比较的区别
原始类型比较的是值
let str1 = "hello";
let str2 = str1;
console.log(str1===str2);//输出true
引用类型比较的是引用是否指向同一个对象(类似C语言指针,指针指向看地址,不看对应的存储内容是否相等)
let obj1 = {name: "小米"};
let obj2 = {name: "小米"};
console.log(obj1===obj2); //输出false
三 传参的区别
//传参的区别
//原始类型
function fun(x){
x = 100;
console.log(`x的值是${x}`); //输出 x的值是100
}
let number = 10;
fun(number);
console.log(`number的值是${number}`); //输出 number的值是10
//引用类型
let obj = {name:"小米"};
function trans(o){
o.name = "小芳";
console.log(`o的名字是${o.name}`); //o的名字是小芳
//内部o.name对外部obj.name进行了操作,且操作进行了保留,因为传入的是引用
}
trans(obj);
console.log(`obj的名字是${obj.name}`); //obj的名字是小芳
原始类型和引用类型的类型检测
1 原始类型检测:typeof(值)
let num = 100;
let obj = {name:"小米"};
console.log(typeof(obj));
2 引用类型检测: 值 instanceof 类型
let arr = Array(1,2,4); //object
console.log(arr instanceof Array); //true
let date = new Date();
console.log(date instanceof Date); //true date是Date类型
// Array RegExp Date ... extends Object 除了原始类型,其他基本都继承Object 所以都是Object类型
console.log(null instanceof Object); //false 是错误的,再次佐证null是原始类型
练习(数组存储学生列表)
要求:
1 数组StudentList
2 点击按钮,将表单中的姓名 和年龄 赋值给Student对象,并push到StudentList中
第一次代码结果不符合
代码结果(最后一次的覆盖前几次的输入结果)
<!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>学生数组表单添加</title>
</head>
<body>
<input type="text" class="name" placeholder="姓名">
<input type="text" class="age" placeholder="年龄">
<button>添加</button>
<script>
//获取元素
let inputName = document.querySelector(".name");
let inputAge = document.querySelector(".age");
let btn = document.querySelector("button");
let studentList = []; // 空数组
let student = {}; //空对象 真的可以开始不赋值任何属性,在代码中进行赋值,长见识了,还是我太浅薄了,继续努力
btn.onclick = function() {
student.name = inputName.value;
student.age = inputAge.value;
// console.log(student);
studentList.push(student);
//数组是引用类型,
console.log(studentList); //数组的每个个体可以是对象
}
</script>
</body>
</html>
问题及原因
问题:最后输出的数组中的对象都会被最后一个输入的对象覆盖
原因:因为student{}是对象类型,是object类型,引用类型,指向是一致的,导致重新赋值全部的值跟着变化
解决方法1
每次重新输入的时候,把student{}重新初始化
btn.onclick = function() {
student.name = inputName.value;
student.age = inputAge.value;
// console.log(student);
studentList.push(student);
student={}; // 解决方法1 重新赋值为空,保证清楚上一次的,因为数组是object类型 (自己想的 hhh)
//数组是引用类型,
console.log(studentList); //数组的每个个体可以是对象
}
解决方法2
创建class类,用类初始化对象,则每次初始化是不一样的
<script>
//获取元素
let inputName = document.querySelector(".name");
let inputAge = document.querySelector(".age");
let btn = document.querySelector("button");
let studentList = []; // 空数组
// let student = {}; //空对象 真的可以开始不赋值任何属性,在代码中进行赋值,长见识了,还是我太浅薄了,继续努力
class Student{
constructor(name,age){
this.naem = name;
this.age = age;
}
}
btn.onclick = function() {
// student.name = inputName.value;
// student.age = inputAge.value;
// console.log(student);
let student = new Student(inputName.value,inputAge.value);
//每次都new了一个新的对象,则保证不会对前面的进行覆盖
studentList.push(student);
student={}; // 解决方法1 重新赋值为空,保证清楚上一次的,因为数组是object类型
//数组是引用类型,
console.log(studentList); //数组的每个个体可以是对象
}
</script>
两种方式都解决了问题