1.引用类型与值类型区别
-
引用类型:复杂数据类型,object(Object、Array、Date、RegRex、function)
-
值类型:基本数据类型,五种:string number boolean undefined null。
-
1.变量只能访问栈中的空间
-
2.如果是引用类型(复杂数据类型),则将保存在堆中,而栈中存储的是这个数据的地址。
-
3.如果是值类型(基本数据类型),则数据保存在栈中(数据比较小,读取比较快捷方便)
-
4.内存主要有两部分:栈与堆
-
<script>
/* 引用类型:array,obejct 数据存储在堆中,地址存储在栈中
值类型:string number boolean undefined null 数据存储在栈中
区别:值类型:栈中存储的是数据,变量赋值时拷贝的是数据,修改拷贝后的数据不会对原数据造成影响
引用类型:栈中存储的是地址,变量赋值时拷贝的也是地址,修改拷贝后的数据会对原数据造成影响
*/
// 1.值类型:拷贝的是数据
var num1 = 10;
var num2 = num1; // 将num1的数据拷贝一份保存到num2中
num2 = 100;
console.log ( num1, num2 ); // 修改num2不会对num1造成影响
// 2.引用类型: 拷贝的是地址
var arr1 = [10,20,30,40,50];
var arr2 = arr1; // 将arr1的地址拷贝一份保存到num2中
arr2[0] = 100;
console.log ( arr1, arr2 ); // 修改arr2会对arr1造成影响
</script>
2.共享引用
-
JS中实际对象传值不是真正的引用传值(传地址),而是传递引用的副本(call by sharing):按共享传递
-
对象赋值的本质是对象引用的副本
-
保存副本的对象如果是对对象本身进行操作:那么就是引用(操作原对象)
-
保存副本的对象如果是重新赋值:那么就重新开辟存储空间
-
// 1.对象共享传递
var obj1 = { name: '我是本体' };
// 2.对象引用(共享)
var obj2 = obj1;
var obj3 = obj1;
// 3.引用的改变效果:如果操作的是对象本身(属性或者方法)那么操作的是原对象obj1,如果把保存引用的变量赋值其他任何类型数据,那么都会重开内存(不影响obj1)
obj2.name = '我是新本体'; // obj2操作的是obj1本身的对象,所以修改是共用的(不开辟新空间)
console.log(obj1); // {name: "我是新本体"}
obj3 = 1; // obj3独立开辟内存空间保存1,与obj1和obj2不再有关联
console.log(obj1); // {name: "我是新本体"}
// 共享引用:共享引用是JS中复杂数据类型的本质传递方式而已
3.基本包装类型
-
本身是基本数据类型,但是在执行代码的过程中,可以调用相关的属性和方法
-
JS中有三种基本包装类型
-
Number
-
String
-
Boolean
-
/*
// 问题:为什么num是一个基本数据类型,可以像对象一样调用方法呢?
// 基本数据类型
var num = 10;
console.log ( typeof num );
num.toString () ;
/*
本质相当于执行了以下代码(JS解释器检测到num调用来toString()方法,所以快速处理了)
(1) var num = new Number(10); // 创建对象
(2) num.toString(); // 调用对象方法
(3) num = null; // 删除对象
*/
// 对象类型
var num1 = new Number(10);
/*
由于num1本身就是对象类型,所以这里可以直接调用,无需转换
*/
num1.toString();
console.log ( num1 );
console.log ( typeof num1 ); // object
var str = '111';
str.toString();
/*
(1)var str = new String('111');
(2)str.toString();
(3)str = null;
*/
var bol = true;
bol.toString();
/*
(1) var bol = new Boolean(true);
(2) bol.toString();
(3) bol = null();
*/
/*
基本包装类型和引用类型(new Number()/String()/Boolear()的区别
1.new产生的对象是长期占用内存,直到脚本结束
2.基本包装类型属于后台瞬发,用完就销毁了对象:对象 = null
所以:String/Number/Boolean,我们在开发中都是使用基本包装类型
*/
4.数组去重
数组去重:将数组中重复的元素去掉
-
JS数组没有删除具体元素的删除(只能删掉值,删不掉元素的索引),可以使用另外一个结构来进行存储
-
新数组
-
新对象
-
-
JS数组虽然本质可以删除第一个和最后一个元素,可以利用这一特性,交换当前重复的元素到最后,然后进行删除(pop() 或者length--)
<script>
var arr = [20, 66, 88, 25, 66, 90, 88, 50]; // [20,25,66,88,90,50]
//1.排序法
// // 1.1 对数组排序
// arr.sort(function(a,b){
// return a-b;
// });
// console.log(arr);
// // 1.2 声明空数组存储去重后的数组
// var newArr = [];
// //1.3 遍历arr,检查arr[i]与arr[i+1]是否相等
// for(var i = 0;i<arr.length;i++){
// if(arr[i] != arr[i+1]){
// newArr[newArr.length] = arr[i];
// };
// };
// console.log(newArr);
// 2.假设成立法
// // 2.1 声明空数组存储去重后的数组
// var newArr = [];
// // 2.2 遍历arr,检查arr[i]在不在newArr中
// for (var i = 0; i < arr.length; i++) {
// // 假设成立法 : 某种操作结果只有两种清空。布尔类型存储两种情况。
// // 1.声明
// var single = true; // 假设不在
// // 2.遍历newArr检查 只要与arr[i]相等
// for (var j = 0;j<newArr.length;j++) {
// if (arr[i] == newArr[j]) {
// single = false;
// break; // 只要发现重复元素,后面没有必要比较
// };
// };
// // 3. 根据结果实现需求
// if (single) {
// newArr[newArr.length] = arr[i];
// };
// };
// console.log(newArr);
// 3.indexOf
// // 2.1 声明空数组存储去重后的数组
// var newArr = [];
// // 2.2 遍历arr,检查arr[i]在不在newArr中
// for (var i = 0; i < arr.length; i++) {
// if(newArr.indexOf(arr[i]) == -1){ // 不在
// newArr.push(arr[i]);
// }
// };
// console.log(newArr);
// 4.对象法
var arr = [20, 66, 88, 25, 66, 90, 88, 50];
/* 核心思路:利用对象的属性名不能重复
对象的取值赋值特点
取值 : 存在,取值。 不存在,取undefined
赋值 : 存在,修改。 不存在,动态添加
1.声明空对象 : 检查数组元素是否重复 (元素作为属性名,检查对象有没有这个属性)
2.声明空数组 :存储去重后的数组
3.遍历arr,检查arr[i]是否重复
*/
var obj = {};
var newArr = [];
for (var i = 0;i<arr.length;i++) {
// 检查对象有没有 arr[i] 这个属性?
if (obj[arr[i]] == undefined) { // 未重复
newArr.push(arr[i]);
obj[arr[i]] = 1; // 这里赋值目的是为了下一次取值,不是undefined
}
};
console.log(newArr);
// 5.重复元素自我交换删除法
/*
核心思路:判定元素在数组中查到的位置是否是自身(元素是一定能找到的)
* 如果是自身:说明当前元素还没有重复
* 如果不是自身:说明当前元素在前面已经存在过:交换最后一个元素,然后把最后一个删除
步骤:
1.遍历数组的每一个元素
2.判定当前遍历的元素在当前数组中存在的位置,判定位置是否是当当前自己的位置
2.1.是自己位置,说明前面没有重复,忽略
2.2.不是自己位置,说明前面已经存在:
2.2.1交换最后一个元素过来
2.2.2然后删除
2.2.3最后一个元素有可能已经与前面重复了,为了不跳过当前新交换的元素,重新从当前元素开始检索
*/
arr = [1,1,2,3,5,0,1];
for (var i = 0; i < arr.length; i++) {
/ /判定当前元素在数组中找出的位置
if (arr.indexOf(arr[i]) != i) {
// 说明不是自己:前面已经存在过
// 交换最后一个元素过来(因为最后一个可以删除
var temp = arr[i];
arr[i] = arr[arr.length - 1];
arr[arr.length - 1] = temp;
// 删除最后一个元素:两种方式都可以
// arr.pop();
arr.length--;
// 最后一个元素有可能已经与前面重复了,所以为了保证安全,被交换过来的元素还要重新经受考验
i--;
}
}
// 注意:以上方式会改变数组中原来元素的顺序位置
</script>
上一章:JavaScript入门第十八章(js作用域及变量预解析)
致读者:
当你学到这里说明你的JavaScript已经入门啦 咱们的JavaScript基础笔记在这里也要画上一个句号了,从明天开始就会进入到我们的webapi的学习了,你准备好了吗?