首页 > 其他分享 >作用域和闭包

作用域和闭包

时间:2023-11-06 20:55:22浏览次数:33  
标签:闭包 function console log 作用域 var foo

一、作用域

var可以重复声明,重复声明时实际是跳过声明处理,继续执行赋值操作。

宽松模式下,a=2如果找不到a的声明,会在全局声明一个a;严格模式下严格模式禁止自动或隐式地创建全局变量。

function foo(a) {
    console.log(a + b);
    b = a;
}
foo(2); // ReferenceError: b is not defined,直接使用b时作用域内找不到b,所以报引用错误

function foo(a) {
    console.log(a + b);
    let b = a;
}
foo(2); // ReferenceError: Cannot access 'b' before initialization, let声明不会变量提升

function foo(a) {
    console.log(a + b);
    var b = a;
}
foo(2); // NaN, var声明存在变量提升,用b时未赋值但已声明,不会报错,返回undefined

function foo(a) {
    var b = a;
}
foo(2);
console.log(b); // ReferenceError: b is not defined, var在foo函数内部定义的变量,只在foo内部能访问

function foo(a) {
    b = a;
}
foo(2);
console.log(b); // 2,b是定义在全局的,外部能够访问到

function foo(a) {
    b = a;
}
var b = 3;
foo(2);
console.log(b); // 2,foo内部修改了外部的b

function foo() {
    function bar(a) {
      i = 3;
      console.log(a + i);
    }
    for (var i=0; i<10; i++) {};
    bar(2); // 5,这里的i是foo内部for循环定义的i
}
foo();
console.log(i); // ReferenceError: i is not defined,外部访问不到内部的i

function foo() {
    function bar(a) {
      i = 3;
      console.log(a + i);
    }
	bar(2);
}
foo(); // 5
console.log(i); //3,i在全局定义

(function foo(){
    var a = 3;
    console.log(a);
})();
foo; //ReferenceError: foo is not defined,上面为函数表达式,外部访问不到foo

a=1;
var b=2;
let c=3;
console.log(window.a,window.b,window.c);; // 1,2,undefined,let声明的变量不会挂到window上

function process(data) {
    // 在这里做点有趣的事情
}
// 在这个块中定义的内容完事可以销毁!因为someReallyBigData只在块作用域内有效
{
    let someReallyBigData = { .. };
    process(someReallyBigData);
}
var btn = document.getElementById("my button");
btn.addEventListener("click", function click(evt){
    console.log("button clicked"); // click形成了一个覆盖整个作用域的闭包
}, /*capturingPhase=*/false );

foo();
function foo() {
    console.log(a); // undefined
    var a = 2;
}
console.log(a); // undefined,a在foo函数作用域内

foo(); // TypeError,能找到foo,因为变量提升,但是是undefined,直接调用报类型错误
bar(); // ReferenceError,表达式后面的具名函数不能被提升
var foo = function bar() {
  // ...
};

foo(); // 1
var foo; // 函数声明优先级高于变量,重复声明被忽略
function foo() {
  console.log(1);
}
foo = function() {
  console.log(2);
};

foo(); // 3 可重复赋值声明,后面会覆盖前面
function foo() {
    console.log(1);
}
var foo = function() {
    console.log(2);
};
function foo() {
    console.log(3);
}

二、闭包

无论通过何种手段将内部函数传递到所在的词法作用域以外,它都会持有对原始定义作用域的引用,无论在何处执行这个函数都会使用闭包。

function foo() {
    var a = 2;
    function bar() {
      console.log(a);
    }
    return bar;
}
var baz = foo(); // 因为foo内部的bar被传出,bar引用了变量a,引擎不知道什么时候会用到a,因此不会销毁foo的内部作用域
baz(); // 2 bar()依然持有对foo内部作用域的引用,而这个引用就叫作闭包。

for (var i=1; i<=5; i++) {
    setTimeout(function timer() {
      console.log(i);
    }, i*1000 );
} // 以每秒一次的频率输出五次6,放入event loop时i*1000已经被转换为时间,但最后打印的i用的是全局定义的

for (var i=1; i<=5; i++) {
    (function() {
      setTimeout(function timer() {
          console.log(i);
      }, i*1000 );
    })();
} // 效果同上,空IIFE里面找不到i,同样是去外部找

for (var i=1; i<=5; i++) {
    (function() {
      var j = i;
      setTimeout(function timer() {
          console.log(j);
      }, j*1000 );
    })();
} // 每隔一秒依次输出递增的i

for (var i=1; i<=5; i++) {
    (function(j) {
      setTimeout(function timer() {
          console.log(j);
      }, j*1000 );
    })(i);
} // 结果同上,正常执行

for (var i=1; i<=5; i++) {
    let j = i; // 是的,闭包的块作用域!
    setTimeout( function timer() {
      console.log(j);
    }, j*1000 );
} // 每次循环创建一个单独的块,存放循环体的内容,因此在块内部j是唯一的

for (let i=1; i<=5; i++) {
    setTimeout(function timer() {
      console.log(i);
    }, i*1000 );
} // 效果同上,正常执行

标签:闭包,function,console,log,作用域,var,foo
From: https://www.cnblogs.com/lhjc/p/17813700.html

相关文章

  • Jemeter元件执行顺序及作用域
          ......
  • 前端歌谣-第贰拾陆课-闭包
    前言我是歌谣最好的种树是十年前其次是现在今天继续给大家带来的是闭包的讲解环境配置npminit-yyarnaddvite-D修改page.json配置端口{"name":"demo1","version":"1.0.0","description":"","main":"index.js",&......
  • C++_02_命名空间和作用域运算符 - 重写版
    命名空间在C++中命名空间(namespace)的作用:命名空间,就是为了解决同一个源代码中相同命名的变量或者函数之间相互冲突的问题,就是要避免这种冲突,让程序代码中可以多次使用同一个标识符而存在的。对于一名开发者而言,代码量过于庞大,或多或少会忘记之间之前用过的变量名或函......
  • JavaScript函数变量的生命周期,自执行函数、闭包、反转数组案例及冒泡排序案例
    一、变量的生命周期JavaScript变量的生命期从它们被声明的时间开始。局部变量会在函数运行以后被删除。全局变量会在页面关闭后被删除。二、自执行函数执行函数通常都是定义之后立即执行,以后都不再会调用,所以声明时可以省略函数名,因此自执行函数又叫匿名函数。通用的自执行......
  • JavaScript 函数、函数构造、函数调用、参数、函数返回值、变量的作用域、预解析
    一、函数及函数的构造函数是一个可重用的代码块,用来完成某个特定功能。每当需要反复执行一段代码时,可以利用函数来避免重复书写相同代码。函数包含着的代码只能在函数被调用时才会执行,就可以避免页面载入时执行该脚本简单来说就是一个封装,封装的是一个特定的功能,重复使用函......
  • 【闭包应用】JS:防抖、节流
    1、防抖:当进行连续操作时,只执行最后一次的操作。//防抖的概念是当进行连续操作时,只执行最后一次的操作。functiondebounce(fn,delayTime){lettimeout=null;returnfunction(){if(timeout){clearTimeout(timeout);......
  • 理解Golang的闭包
    闭包是指一个函数值(functionvalue),它可以引用其函数体之外的变量闭包代码示例funcmakeSuffix()func(strstring)string{ varsuffix=".jpg" returnfunc(strstring)string{ ifstrings.HasSuffix(str,suffix){ returnstr }else{ //引用函数体之外......
  • python基础 :作用域
    一前言环境:python3.10.11win10二关于作用域先来一个简单的例子,如下执行结果如上,在eating_other函数内为变量重新赋值,指向了一个新的对象,在该函数内输出的是新值,在该函数外输出的依旧是旧值,因为给变量重新赋值所产生的影响仅仅局限在在赋值所在的函数内,对赋值所在......
  • 自底向上的语法分析,闭包、GOTO函数
    自底向上的语法分析一、一个串ω归约(reduction)为文法开始符号的过程关键问题:1.何时进行规约,2.用哪个产生式规约句柄右边的串ω一定只包含终结符号。如果文法是无二义性的,那么文法的每个右句型都有且只有一个句柄二、LR(0)自动机Automaton项1.定义:产生式加上位于体中......
  • Python 作用域:局部作用域、全局作用域和使用 global 关键字
    变量只在创建它的区域内可用。这被称为作用域。局部作用域在函数内部创建的变量属于该函数的局部作用域,并且只能在该函数内部使用。示例:在函数内部创建的变量在该函数内部可用:defmyfunc():x=300print(x)myfunc()函数内部的函数如上面的示例所解释的那样,变量x在......