1、null的使用
在网上找了这么一段话:
NULL,可以近似理解为变量未赋值(定义了变量,但是未使用,变量不指向具体存储空间,因此,理论上不消耗存储空间),同时,它理论上不可以输出,因为变量本身没有内容。
空“”,你可以近似理解为空串(定义了变量,并且赋值为空,这个空是具有含义的,需要消耗存储空间),可以输出来,展示表现为空。
一个变量等于null表示这个变量还不存在,一个变量不等于null,即使内容为空,这个变量也是存在的。null用来判断这个变量对象是否存在,并不是内容是否为空
var hello = document.getElementById("player").innerHTML;
if (isNaN(num) || num < 6 || num > 18) {
alert("请输入6-18的数字"); //验证数字
} else if (hello === null) { //使用 null 判断是否有内容是错误的,alert函数不会被执行。因为空内容不等于hello是无的状态。
alert("请设置玩家数量");
} else {
location.href = 'turnover.html';//跳转
}
所以当我判断一个标签内容是否为空时不能使用null,使用 null 判断是否有内容是错误的,alert函数不会被执行。因为空内容不等于hello是无的状态。好比一个创建了一个名字,但是没有没有代表任何东西,是无的状态,就是null,不占内存。空是创造了内存,但是没有内容。
判断内容是否为空可以使用布尔值,空 "" .
var hello = document.getElementById("player").innerHTML;
if (isNaN(num) || num < 6 || num > 18) {
alert("请输入6-18的数字"); //验证数字
} else if (hello == false) { //使用 布尔值 判断 是否有内容
alert("请设置玩家数量");
} else {
location.href = 'turnover.html';//跳转
}
// var hello = document.getElementById("player").innerHTML;
// if (isNaN(num) || num < 6 || num > 18) {
// alert("请输入6-18的数字"); //验证数字
// } else if(hello === "" ){ // 使用空引号 “ ” 判断 是否有内容
// alert("请设置玩家数量");
// }else {
// location.href = 'turnover.html';//跳转
// }
2、还是函数变量作用域的问题
var mytime; //放在函数里不起作用?(变量初始化,将定时器清除了.
// 每次执行函数都会从新定义这个变量,这个变量没有初始化,
// clearInterval(mytime);就没有意义。放在函数外面,当执行一次函数后,
// 这个变量就初始化为mytime = setInterval(start, 1000); 。从而保存了一个值。后面函数执行就可以调用)
function myFunction() {
clearInterval(mytime); //清除定时
mytime = setInterval(start, 1000); //连续执行定时
// setInterval('start()', 1000);
// setInterval(function(){ start() }, 1000);
}
var mytime; 这个变量放在函数内部时mytime会出现错误,报错为“分配的价值从未被用过。”定时器无效。
// 这个变量就初始化为mytime = setInterval(start, 1000); 。从而保存了一个值。后面函数执行就可以调用)
function myFunction() {
var mytime;
clearInterval(mytime); //清除定时
mytime = setInterval(start, 1000); //连续执行定时
// setInterval('start()', 1000);
// setInterval(function(){ start() }, 1000);
}
经过师兄帮忙讲解,总算是了解了:每次执行函数都会从新定义var mytime这个变量,而刚开始时var mytime这个变量没有初始化, clearInterval(mytime);就没有意义,定时器无效。当var mytime放在函数外面,执行一次函数后,这个变量就初始化为mytime = setInterval(start, 1000); 。从而保存了一个值。后面函数执行就可以继续调用了。
3、函数参数的传递:
高程讲函数参数是按值传递的。基本类型变量的传递很好理解。函数内基本类型变量发生改变,不会影响函数外部的变量的值。
高程的例子:
function addTen(num) {
num += 10;
return num;
}
var count = 20;
var result = addTen(count);
alert(count); // 20, 没有变化
alert(result); // 30
这个基本类型的传递参数还是比较好理解的。将count 的值传递给函数的参数num,也就是将count 的值20复制给了函数参数num。从此count 与num两不相干,所以当num改变时count 不变。这与变量的复制一样。
但是给函数传递对象时就比较难理解了。看例子
function setname(obj){
obj.name = "hello";
obj = new Object();
obj.name = "你好";
// return obj.name;
}
var person = new Object();
setname(person);
console.log(person.name); //hello
console.log(setname(person)); //undefined
当将对象person传递给函数的参数obj后,实际上是将person对象的指针复制给了obj,person与obj指向同一个对象(在堆内存)。所以当obj改变时,相应的person对象也会有反应,存入name : "hello"。
为什么最后不是打印“你好”出来?
当在函数内部从新定义一个新的对象,并将这个对象的指针复制给obj,此时obj的指针就从指向person 改成了指向这个新定义的对象obj.name = "你好";是给这个新的对象存值,不是person了。所以console.log(person.name); 还是hello(在开始时person传入函数,复制指针给obj,obj指向person,创建了name : "hello"。此时person就保存了hello)。
console.log(setname(person)); //undefined 函数打印出undefined 是因为函数没有return出东西,函数在执行完毕后就被销毁了。但是当 return obj.name; 时,console.log(setname(person)); 就可以打印出 “你好”。
第二个例子:
var a = {value: 111};
var b = {value: 222};
function changeStuff(obj){
obj.value = 333;
obj = b;
obj.value = 444;
return obj.value;
}
console.log(changeStuff(a)); // 444
console.log(a.value); // 333
console.log(b.value); //444
首先 a 对象传入函数,将a 对象保存在栈 中的指针复制给形参obj,这时候 obj.value = 333; a 对象value值改变为 333;接下来 将 b 对象保存在栈中的指针复制给 obj ,这时候obj 从开始 保存 a 对象的指针 被替换为指向 b 对象的指针。当 obj.value = 444; 时,实际改变的是 b 对象的value值。所以最后打印出来 a 为333; b 为444 ;函数为 444。
从知乎上看到一篇文章这样写:
基本类型是传值调用
引用类型传共享调用
传值调用本质上传递的是变量的值的拷贝。
传共享调用本质上是传递对象的指针的拷贝,其指针也是变量的值。所以传共享调用也可以说是传值调用。
所以《JavaScript 高级程序设计》说 JavaScript 参数传递都是按值传参也是有道理的。
链接:https://zhuanlan.zhihu.com/p/25314908
4、关于变量在 栈 和堆内存的情况,
1、基本类型变量 值保存在栈内存中,占有固定大小的空间,可以通过按值来直接访问。
2、对象数组等引用类型保存在堆内存中,并在栈内存中创建一个指针,指向堆内存对象。这些引用类型的值大小不固定,通过保存在栈中的指针访问,也就是按引用访问。
5、关于变量寿命,网上查找的资料:
基本类型在当前执行环境结束时销毁,而引用类型不会随执行环境结束而销毁,只有当所有引用它
的变量不存在时这个对象才被垃圾回收机制回收。
1、堆内存释放或销毁:把所有知道该引用地址的变量赋值null,即没人知道该引用地址,浏览器就会在空闲的时候销毁它,也叫垃圾回收
2、全局作用域的栈内存:页面关闭的时候,才会销毁
3、私有作用域的栈内存(只有函数执行的时候才有私有作用域):
a.一般情况:函数执行会形成一个新的私有作用域,当私有作用域的代码执行完之后,栈内存会自动销毁和释放
b.特殊情况:1、函数执行返回一个引用类型的值,且在别的作用域被接收了,该栈内存不会被销毁
2、私有作用域中,给DOM元素的事件绑定方法,该栈内存不会被销毁