前端-JS (1)

106 阅读3分钟

js底层原理

js原理,js内存中只存在一种——关联数组。不涉及堆栈

举例:var a = 10; a应存放在栈内存中,但是window.a 是可以访问a的,window是对象,应该存放在堆内存中。这不就自相矛盾了。

所以一切内存关系,都是关联数组。证明:window.a / window[a] 都可访问 10;

 

作用域&作用域链

js中,作用域和作用域链都是对象结构。更准确来说是关联数组

作用域(scope)

浅显定义

作用域就是变量的可用范围

 

为什么要有作用域

目的是防止不同范围的变量之间互相影响

 

JS中包含2类作用域

作用域有两类:全局作用域和函数作用域

 

全局作用域

不属于任何函数的外部范围称为全局作用域。

其实是一个名为 window 的对象,所有的全局变量和全局函数都是window对象的成员

定义在全局的变量叫全局变量

全局变量的特点:

优点:可反复使用

缺点:全局污染——开发时,如果是变量,禁止使用

 

函数作用域

一个函数内的范围称为函数作用域

其实是JS引擎在调用函数时才临时创建的一个作用域对象。其中保存函数的局部变量。函数调用完,函数作用域对象就会释放

所以js中函数作用域对象,还有个别名——(活动的对象(Actived Object)),简称,AO。所以,局部变量不可重用

保存在函数的变量叫局部变量,除在函数内声明的变量,形参也属于局部变量

局部变量的特点:

优点:不造成污染

缺点:无法重复使用

不是所有的{}都能生成函数作用域,也不是所有的{}内的数据都是局部变量,只有函数function内的变量才是局部变量, 也只有函数{}会形成作用域. 例如


console.log(a);

if (false) {

var a = 10;

}

console.log(a);

局部变量:只有两种, 只要看不到var,也不是形参,就不是这个函数的局部变量。

  1. 函数内 var 出来的
  1. 函数的形参变量。

 

 

作用域链(scopes)

js规定,一个函数,既要用到自己作用域内的变量,又想用到外层乃至window的作用域变量,就通过像路线图一样的作用域链关联起来。

定义函数时,就已经规划好自己由内向外的查找变量的路线,称为作用域链

一个函数可用的所有作用域串联起来,就形成函数的作用域链,而当执行某条语句时,js引擎就会自动按照由内向外延函数作用域链进行查找要用的变量。

查找不到时

会报错 “ x is not defined”

 

当给未声明的变量赋值时

不报错,而是自动在全局创建变量 x

 

闭包

浅显定义

即重用变量又保护变量不被污染的一种编程方法。

 

如何使用(三步)

  1. 用外层函数包裹 要保护的变量和使用变量的内层函数
  1. 在外部函数内返回内部函数对象
  1. 调用外层函数,用变量接住内层函数对象

// 第一步

function mother(){

var total=1000;

function pay (money) { // 第二步

total -= money;

console.log(花了${money}还剩${total}元) }

}

}

var pay=mother(); // 第三步

 

闭包是如何形成的

外层函数调用后,外层函数被返回的内层函数的作用域链引用着,无法释放,形成闭包对象

 

闭包缺点

由于闭包藏得很深,几乎找不到,所以,极容易内存泄漏

解决:将保存内层函数的对象的变量赋值为null