JS的作用域、内存、垃圾清理

1.函数

通过函数可以封装多条语句,可以在任何地方,任何时候调用执行。

function sum(num1,num2){
return num1+num2;
alert("hello world");//永远不会执行
}

定义函数的方法:函数声明 函数表达式。

function hello(){
}
var a=function (){//......};//匿名函数,name属性为空

1.ECMAScript不介意传进来多少参数,也不在乎参数是什么类型,都保存在arguments数组里。
2.参数都是值,不可能通过引用传递参数。
3.没有重载,如果定义了两个同名函数,后者覆盖前者。

function howmanyargs(){
alert(arguments.length);
}
howmanyargs(12,34);//2

4.能够把函数作为返回值返回
递归

function factorial(num){
if(num<=1)
   return 1;
else{
return num*arguments.callee(num-1);//指向正在执行的函数的指针(严格模式下使用该指针会报错)
}}

2.JS储存

基本类型(简单,不能给基本类型的值添加属性)被保存在栈里(因为在内存中占据固定大小)
引用类型(可能由多个值构成的对象)保存在堆里

3.垃圾回收机制

js垃圾自动回收,主要的方法是标记清除,还有一种不常用的是引用计数
标记清除:把要删除的变量加上标记,垃圾收集器完成内存清除的工作。

4.复制变量与传递参数

复制基本类型变量,会创建一个新值,向参数传递基本类型的值,传值
复制引用类型,复制的指针指向对象,向参数传递引用类型的值,传地址

function add(num){
num=num+10;
return num;
}
var count=20;
var result=add(count);
alert(count);//20
alert(result);//30

function set(obj){
obj.name="lailai";
obj=new Object();
obj.name="zhangsan";
}
var person=new Object();
set(person);
alert(person.name);//lailai

即使在函数内部修改了参数的值,原始的引用仍然不变。当在函数内部重写obj,这个变量引用的就是一个局部对象,局部对象会在函数执行完毕被销毁。

5.作用域(执行环境)

作用域就是执行环境,有全局作用域和局部作用域。某个作用域中所有代码执行完毕后,该执行环境环境被销毁,变量和函数定义一起被销毁。每个函数都有自己的作用域。当函数被定义时,会创建作用域链(可以理解成为一个对象列表)。作用域的使用,提高了程序的逻辑的局部性,增强程序的可靠性,以及避免命名冲突;为代码的模块化开发提供便利;

全局作用域是最外围的执行环境。(window).即对任何内部函数来说,都是可以访问的:
局部作用域一般只在固定的代码片段内可访问到,而对于函数外部是无法访问的,最常见的例如函数内部

作用域链:根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问。
作用域链的作用:保证对执行环境有权访问的变量和函数的有序访问。作用域链的前端始终是当前执行的代码所在环境的变量对象。(函数中第一个是arguments对象,最后是全局执行环境的变量对象)
在这里插入图片描述
**标识符解析·:**沿着作用域链一级一级搜索标识符的过程。
tips:
1.内部环境可以访问外部,但外部的不能访问内部的变量和函数。

var a=10; 
function aaa(){ 
 alert(a);
};            
function bbb(){
var a=20;
aaa();
}
bbb(); //结果为10,因为aaa()函数不能访问到bbb()里面的局部变量,所以访问到的是a=10,这个全局变量。

2.延长作用域链:(1) try-catch语句的catch块(创建一个新的变量对象)(2)with语句(将指定的对象添加到作用域前端)
3.不用var 定义变量时,会默认为是全局变量(不规范,不推荐)

function aaa(){
      var a=b=10; 
}
 aaa();
 alert(a);//结果为,无法访问    b=10;var a=b;    a是局部变量
 alert(b);//结果为10;b是全局变量

4.没有块级作用域。javascript的作用域是相对函数而言的,可以称为函数作用域

for(i=0;i<10;i++){
//dosomething
}
alert(i);////////////////////////////10

5.在搜索的过程中,局部搜到了,就不去全局搜了。

var a=[1,2,3];
var b=a;
b.push(4); 
alert(a);//结果为[1,2,3,4] 当b改变的时候a也发生了改变  


当b重新被赋值的时候 a不会改变.示例:
var a=[1,2,3];
var b=a;
b=[1,2,3,4]
alert(a)//结果为[1,2,3]

6.只要函数内定义了一个局部变量,函数在解析的时候都会将这个变量提前声明.

 var scope = "global";
function fn(){
 console.log(scope);//result:undefined
 var scope = "local";
 console.log(scope);//result:local;
      }
fn();

防止作用域污染

1.闭包
2.定义全局变量命名空间,只创建一个全局变量,并定义该变量为当前应用容器,把其他全局变量追加在该命名空间下

猜你喜欢

转载自blog.csdn.net/weixin_43836308/article/details/88353993