js中的作用域和作用域链

作用域
1. 全局作用域
2. 函数作用域
这里扯出来下js的函数声明和变量声明提升,直接来两段代码

if (!a in window) {
   var a = 1;
}
console.log(a) //undefined

嗯,为什么呢?因为var声明的变量会变量声明提升,所以相当于执行if判断的时候a变量已经声明过了,而此时a是一个全局变量既是window对象的一个属性,所以这里压根没有进if判断,所以这里打印出来的是undefined
再来一段坑坑的代码

(function (){
  var a = b = 10;
})()
console.log(b) // b是10
console.log(a) // a是局部变量所以在这里打印a的时候会报错

在函数中var a = b = 10,b暴露为全局变量,因为赋值是从右往左进行的,也就是说这一行先执行b=1,这时候b就是全局变量了,没有被var过。然后是var a = b;a被声明了,是局部变量。你赋值给a,b=1,是不存在的,var a=b=1,就可以等同于,b=1;var a=b;

那么下面这里的问题也很容易知道答案喽

var a;
var b;
(function () {
  console.log(a) // undefined
  console.log(b) //10
  var a = b = 10;
  console.log(a); // 10
  console.log(b); // 10
})();
console.log(a) // undefined
console.log(b) // 10

作用域链是怎么回事呢

1. 执行环境和作用域 (函数第一次调用的时候会创建作用域链和执行环境,并把作用域链赋值给一个内部属性[scope]),然后使用this、arguments和其他命名参数来初始化函数的活动对象。但在作用域链中,外部函数的活动对象始终处于第二位,外部函数的外部函数始终处于第三位...直至作用域链的终点全局执行环境。
2. 活动对象
3. 变量对象(每个执行环境都会有一个变量对象)

先来个函数吧!!!

var a = 10, b = 20;
function sum (a, b) {
  return a + b;
}
var result = sum(a, b)

// 在sum函数被调用的时候,会创建它的作用域和执行环境,然后,使用arguments和其他命名参数初始化其活动参数。在作用域链中,它的外部函数处于第二位,外部函数的外部函数处于第三位......,直到作用域链的终点全局执行环境

一般,在函数执行完毕后,局部活动对象就会销毁,内存中仅仅保存全局作用域(全局执行环境的变量对象)。

 闭包中的作用域链又是怎么回事呢???

在另一个函数内部定义的函数会将包含函数的活动对象添加到它的作用域链中。外部函数执行完后,虽然作用域链会销毁,但是由于内部函数仍然在引用这个活动对象,外部函数的活动对象不会销毁,一直保存到内存中,直到内部函数被销毁后,外部函数的活动对象才会被销毁。

闭包会携带包含他的函数的作用域链,所以比其他函数占用更多的内存。过度使用闭包会导致内存使用过多。

时间: 2024-08-06 11:58:22

js中的作用域和作用域链的相关文章

js中的原型与原型链详解

js中的原型与原型链详解 记住下面三句话就可以理解原型: 所有的函数数据类型都天生自带一个属性Prototype(原型)这个属性的值是一个对象,浏览器会默认给他开辟一个堆内存 在浏览器给prototype开辟的堆内存当中有一个天生自带的属性是constructor,这个属性存储的值是当前函数本身 每一个对象都有一个__proto__的属性,这个属性指向当前实例所属类的prototype(如果不能确定他是谁的实例,都是Object的实例) 原型链:如果引用构造函数的实例想要查找某个属性p的话: 首

理解js中的自由变量以及作用域的进阶

如果你不知道什么是作用域,建议你先看什么是作用域链,什么是原型链.这篇文章,因为这些内容都是有关联性的. 什么是自由变量? 如我在全局中定义了一个变量a,然后我在函数中使用了这个a,这个a就可以称之为自由变量,可以这样理解,凡是跨了自己的作用域的变量都叫自由变量. var a = "追梦子"; function b(){ console.log(a); //追梦子 } b(); 上面的这段代码中的变量a就是一个自由变量,因为在函数b执行到console.log(a)的时候,发现在函数中

js中的对象、原型链机制、构造函数

一.在js中创建对象的方式 //一.字面量或直接量创建对象 var obj1 = { name:"zs", age:12 }; //二.通过new来创建对象 var obj2 = new Object(); obj2.name = "zs"; obj2.age = 16; //三.通过工厂函数来创建 function creatObj() { return {}; } //四.通过new 构造函数来创建 function Obj() { } //测试 var obj

关于js中变量声明和作用域的理解

1. var是声明一个变量:虽然声明了这个变量,但在存入值之前,它的初始值是 undefined:2.全局变量:拥有全局作用域,在js代码中的任何地方都是有定义的:3.局部变量:在函数内声明的变量只在函数内有定义,作用域是局部的,只在函数内有定义:4.全局作用域编写代码时可以不写var,但声明局部变量时必须使用var语句;5.在函数体内,局部变量的优先级高于同名的全局变量.如果局部变量和全局变量同名,那么全局变量会被局部变量所遮盖:但全局变量的值不会改变:6.作用域链查找规则:自上而下(一个或多

JS中函数的词法作用域

在javascript中,每一个函数都拥有自己的词法作用域.简单理解就是,每个函数在被定义(注意不是调用!)时,都会创建一个属于自己的环境(作用域). 比如, function foo(){ var a = 1; foo2(); } function foo2(){ console.log(a); }fon(); 运行结果: ReferenceError: fon is not defined. 因为,函数foo2在被定义时,它可以访问的环境只有全局作用域和它自己的函数作用域,并不能访问到函数f

JS中的块级作用域,var、let、const三者的区别

1. 块作用域{ } <script type="text/javascript"> { var a = 1; console.log(a); // 1 } console.log(a); // 1 // 可见,通过var定义的变量可以跨块作用域访问到. (function A() { var b = 2; console.log(b); // 2 })(); // console.log(b); // 报错, // 可见,通过var定义的变量不能跨函数作用域访问到 if(

[转] 浅谈JS中的变量及作用域

Situation One <script> var i; function sayHello() { var x=100; alert(x); x++; } sayHello();   // 输出100 alert(x);  // 报错,因为x是局部变量,访问不到 </script> Situation Two <script> function sayHello() { var x=100; if (x==100) { var y=x+1; alert(y);  /

快速理解JS中的继承与原型链

语言是用来表达的工具.当我们需要代指某个东西的时候,通常称其为一个对象.在编程语言中,对象并不像真实世界中那样随处可见,随口可以指代.通常我们只有少数的原生对象,剩下的,需要我们自己去创建.在Java语言中,创建一只会“咯咯咯”叫的鸡时,我们是这么做的: public class Chicken{ public void makeSound(){ System.out.println("咯咯咯"); } } Chicken littleChicken = new Chicken();

js的作用域与作用域链

JavaScript的作用域和作用域链.在初学JavaScript时,觉得它就和其他语言没啥区别,尤其是作用域这块,想当然的以为"全局变量就是在整个程序的任何地方都可以访问,也就是写在函数外的变量,局部变量也就是写在函数内部或循环体内部,出了循环体和函数就不可访问",但是在JavaScript中并不是这么简单,需要去深入的学习. 一. 什么是作用域任何程序语言都有作用域的概念,简单的说,作用域就是变量与函数的可访问范围.比如C/C++等,都是块级作用域,也就是说在每一个代码块内声明的变

js中三种作用域详解(全局,函数,块级)

1.全局变量:声明在函数外部的变量(所有没有var直接赋值的变量都属于全局变量) 2.局部变量:声明在函数内部的变量(所有没有var直接赋值的变量都属于全局变量) JS中变量申明分显式申明和隐式申明. vari=100;//显式申明 i=100;//隐式申明 在函数中使用var关键字进行显式申明的变量是做为局部变量,而没有用var关键字,使用直接赋值方式声明的是全局变量. 当我们使用访问一个没有声明的变量时,JS会报错.而当我们给一个没有声明的变量赋值时,JS不会报错,相反它会认为我们是要隐式申