变量作用域问题,函数传参问题,null 问题

2018-03-21  本文已影响0人  你隔壁的陌生人

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元素的事件绑定方法,该栈内存不会被销毁

上一篇 下一篇

猜你喜欢

热点阅读