js 中数据类型中包含:
基本数据类型:String、Boolean、Number、undefined、null、Symbol
引用数据类型(复杂数据类型):Object
如代码:var n1 = 10; var n2 = n1
求 如果n1 里面的值发生变化时,n2 是否有影响
过程如图所示:
1 . 访问n1时 在栈内存开辟一个空间,定义为10,到时访问变量n1时,就会直接调取空间的值。
2 . 访问n2时,也是需要在内存中开辟一个空间,存储值为10,相当于复制了一份n1,如果n1改变值时,n2不会影响。
// 复杂类型 : Object 所有对象都是复杂类型 (所有的对象都是基于Object)
定义一个自定义构造函数,
function Person(name, age, sayHi) {
this.name = name;
this.age = age;
this.sayHi = function () {
console.log(this.name + 'hello');
}
}
var p1 = new Person('zs', 18);
var p2 = p1;
console.log(p2);
// 求 如果p1 里面的值发生变化时,p2 是否有影响
复杂类型:只有在新建一个对象时,才会在内存存储对象。此时在内存中新建了一个p1的对象,里 面包含所有属性,方法。
访问变量p1时,会先在栈上访问内存地址,再访问内存地址指向的对象属性,
如果访问p2时,因p2等于p1,所以两个内存地址一样的,所以在堆上不会新建对象,
直接访问p1的对象属性,如p1对象属性发生变化时,p2也会随之发生变化。
function fn(a, b) {
a = a+1;
b = b+1;
console.log(a);
console.log(b);
}
var x = 10;
var y = 20;
fn(x, y);
console.log(x);
console.log(y);
// 求: 在函数内部对 a 和 b 的值进行修改,那么函数外部是否会影响 x 和 y 的值。、
简单类型作为函数:首先,function fn (a,b)到函数内部没有调用,所以内存不会运行,
当函数调用时,内存才会运行,所以先运行x y的运算。当:x=10, y=20时,会在内存栈开辟一个空间,存
储x和y的值。再把函数的实参传给形参,a和b,当函数内存a和b发生变化时:a+1 (10+1),
b+1 (20+1),那么在内存另外开辟一个空间,分别存a和b 的值,然后再打印a 和b改变后的值,
然后函数fn(x,y)执行完毕。函数执行完毕后,再打印x 和y 的值。所以x和y值不会受函数内部变化而影响。
function Person(name, age) {
this.name = name;
this.age = age;
this.sayHi = function () {
console.log(this.name + '--hello')
}
}
var p = new Person('zs', 18);
function fn(person) {
person.name = 'ls';
// 假如person = new person ,重新赋值
person = new Person('ww' ,20);
console.log(person.name);
// 此时求 person的name?
/* 2. 因为 person 重新创建了一个对象,所以在堆上会重新建立一个名为person的对象,里面属性包含 ww 和20
再在栈上开辟一个空间,存储person的内存地址,此时,p的内存地址和person的内存地址不同 ,指向了不同的对象,
所以上面求的person.name的结果为:ww 。p 的结果为ls */
}
fn(p);
console.log(p.name);
// 求:最后打印的p.name 的值为?
- 运算过程:在堆里内存里创建一个p的对象,里面包含name, age,再在栈中开辟一个空间,
存储变量p的内存地址。访问变量p时,首先访问栈上的地址,再通过廾上的地址可以访问堆内存的对象里面的所有属性。
往下:声明了一个函数,name= ls.再调用函数,p为实参,把实参赋值给形参(function fn (person))
部分没有new关键字,所以不会在堆上开辟新的对象, p为实参,把实参赋值给形参,把p的值赋值给person,
所以person的内存地址就是P的地址。指向同一个对象,如果函数内部改变name的属性,
因为p和person指向的是同一个对象,所以p.name 也会随之改变。
数组也是复杂类型。
冒泡排序(从小排到大),数组作为函数参数的特点
function sort (arry) {
// 外层循环,控制趟数
for (var i = 0; i < arry.length-1; i++ ) {
// 假设排序好了
var isSort = true;
// 内层循环,控制两两比较的次数
for (var j = 0; j < arry.length -1 -i; j++) {
if (arry [j] > arry [j+1]) {
isSort = false;
// 如果没排序好,两个交换位置
//如果前一个数 大于 后一个数,将前一个的值存在temp中,后一个的值赋值给前一个位置,
// 然后将temp中的前一个赋值给后一个
var tmp = arry[j];
arry[j] = arry [j+1];
arry [j+1] = tmp;
}
// 判断是否排序好
if (isSort) {
break;
}
}
return arry;
}
// 定义一组数组
var arry = [3, 40, 5, 3, 90, 47];
function fn (arr) {
arr[0] = -5;
}
fn(arry);
sort(arry);
console.loe(arry);
// 求,如果改变arr函数的第一个下标,最后arry的值是否会受影响?
运算过程:在堆里内存里创建一个arry的对象,里面包含下标0-3的值的属性,,再在栈中开辟一个空间,
存储变量arry的内存地址。访问变量arry时,首先访问栈上的地址,再通过廾上的地址可以访问堆内存的对象里面的所有属性。
往下:声明了一个函数,调用函数,让arry的实参传给fn 的形参。相当于复制了一份arry变量,栈上的内存地址一样,
两个指向的是同一个对象,让函数的第一个下标值等于 -1,因为两个指向了同一个对象,所以arry的属性结果也会受影响。