Giter VIP home page Giter VIP logo

Comments (166)

rccoder avatar rccoder commented on May 2, 2024 149

核心就是: 函数的作用域在函数定义的时候就决定了

真正理解这句话的时候闭包什么的也就理解了。

Like most modern programming languages, JavaScript uses lexical scoping. This means that functions are executed using the variable scope that was in effect when they were defined, not the variable scope that is in effect when they are invoked. In order to implement lexical scoping, the internal state of a JavaScript function object must in- clude not only the code of the function but also a reference to the current scope chain. (Before reading the rest of this section, you may want to review the material on variable scope and the scope chain in §3.10 and §3.10.3.) This combination of a function object and a scope (a set of variable bindings) in which the function’s variables are resolved is called a closure in the computer science literature. (This is an old term that refers to the fact that the function’s variables have bindings in the scope chain and that therefore the function is “closed over” its variables.)

Technically, all JavaScript functions are closures: they are objects, and they have a scope chain associated with them. Most functions are invoked using the same scope chain that was in effect when the function was defined, and it doesn’t really matter that there is a closure involved. Closures become interesting when they are invoked under a different scope chain than the one that was in effect when they were defined. This happens most commonly when a nested function object is returned from the function within which it was defined. There are a number of powerful programming techniques that involve this kind of nested function closures, and their use has become relatively common in JavaScript programming. Closures may seem confusing when you first en- counter them, but it is important that you understand them well enough to use them comfortably.

JavaScript, The Definite Guide

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 2, 2024 106

@rccoder 我搬运了下你的博客中这段的翻译,希望不要介意~

翻译成中文的话也许是这样:

和大多数的现代化编程语言一样,JavaScript是采用词法作用域的,这就意味着函数的执行依赖于函数定义的时候所产生(而不是函数调用的时候产生的)的变量作用域。为了去实现这种词法作用域,JavaScript函数对象的内部状态不仅包含函数逻辑的代码,除此之外还包含当前作用域链的引用。函数对象可以通过这个作用域链相互关联起来,如此,函数体内部的变量都可以保存在函数的作用域内,这在计算机的文献中被称之为闭包。

从技术的角度去将,所有的JavaScript函数都是闭包:他们都是对象,他们都有一个关联到他们的作用域链。绝大多数函数在调用的时候使用的作用域链和他们在定义的时候的作用域链是相同的,但是这并不影响闭包。当调用函数的时候闭包所指向的作用域链和定义函数时的作用域链不是同一个作用域链的时候,闭包become interesting。这种interesting的事情往往发生在这样的情况下: 当一个函数嵌套了另外的一个函数,外部的函数将内部嵌套的这个函数作为对象返回。一大批强大的编程技术都利用了这类嵌套的函数闭包,当然,javascript也是这样。可能你第一次碰见闭包觉得比较难以理解,但是去明白闭包然后去非常自如的使用它是非常重要的。

通俗点说,在程序语言范畴内的闭包是指函数把其的变量作用域也包含在这个函数的作用域内,形成一个所谓的“闭包”,这样的话外部的函数就无法去访问内部变量。所以按照第二段所说的,严格意义上所有的函数都是闭包。

需要注意的是:我们常常所说的闭包指的是让外部函数访问到内部的变量,也就是说,按照一般的做法,是使内部函数返回一个函数,然后操作其中的变量。这样做的话一是可以读取函数内部的变量,二是可以让这些变量的值始终保存在内存中。

链接地址: rccoder 博客链接

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 2, 2024 90

@yangshun352607664 结果是 10 ,因为变量 a 并不能读取到对象 o 的属性 a ,如果 console.log(o.a),就会打印 11,函数 fn 的作用域链为 [AO, Global.VO],而 Global.VO 中包括了变量 a 和变量 o。

from blog.

yangshun352607664 avatar yangshun352607664 commented on May 2, 2024 82

作者的案列太过简单,应该写那种嵌套比较深的的

from blog.

suoz avatar suoz commented on May 2, 2024 60

在全局作用域中“定义”一个函数到时候,只会创建包含全局作用域的作用域链。
只有“执行”该函数的时候,才会复制创建时的作用域,并将当前函数的局部作用域放在作用域链的顶端。

from blog.

JSupot avatar JSupot commented on May 2, 2024 58

之前一直不太理解什么是词法作用域,受教了

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 2, 2024 34

@mengxin-FE 词法作用域决定了变量查找的顺序,这个顺序是从函数内部开始,然后到函数定义的外层,函数内部已经有值,所以就会打印 2

from blog.

mengxin-FE avatar mengxin-FE commented on May 2, 2024 14

即时通讯的效率其实不如邮件,题主也不不是为了回答你的问题而存在呀,他还有他自己的事情。

from blog.

double-chen avatar double-chen commented on May 2, 2024 7

我有一点想不通,在读作者 执行上下文的文章,感觉执行上下文是在函数调用时准备的,作用域规定了如何查找变量。可是查找的变量是通过执行上下文中的变量对象和作用域链查找的,这是动态作用域的原理啊,为什么JS又是静态作用域了。

from blog.

qiqingfu avatar qiqingfu commented on May 2, 2024 4

@yh284914425

var a = 10;
var o = {
     a:11,
     b:{
         fn:function(){
              console.log(a);
         }
     }
}
o.b.fn();

你这个例子全局看下来只有两个作用域。一个是全局作用域(Global), 一个是 o.b.fn引用的这个函数作用域。
变量对象(VO): 变量对象是与执行上下文相关的数据作用域。它是与上下文关联的特殊对象,用于存储被定义在上下文中的变量函数声明
而 Global的变量对象(VO)只有两个。
a: 10
b: object

在一个函数的上下文中有变量对象(VO)还有活动对象(AO)和[[Scope]]作用域链。

活动对象(AO):
在一个函数上下文中, 变量对象(VO)被表示为活动对象(activation object) AO, 活动对象(AO)相比变量对象(VO),还可以包含特殊对象arguments。

所以o.b.fn对应的函数中的活动对象是空的。因为既没有参数arguments,也没有变量声明,更没有函数声明。 那么在o.b.fn中打印 console.log(a)。这个函数自身没有,就会去它的父作用域(Global | 全局作用域)中查找。你再看一下它父作用域中的变量对象中只保存两个属性。a: 10 b:object。 所以打印10

个人见解,如有错误麻烦勘正。

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 2, 2024 3

@nightn “变量对象就是 JavaScript 对作用域这个概念的实现”,可以这样认为呀~~ let 和 const 的作用域跟 var 类似呀,只是没有变量提升,又多了些“检查”而已。

我没有建立任何交流群哈,写得文章现在只在 Github、掘金、Segmentfault 上发,有问题大家可以在 Github 上留言。

之所以不建立交流群,确实如 @mengxin-FE 所说,真的很忙哈,并没有足够的精力来打理一个交流群,这段时间因为很多事情,所以大家的留言也回复的非常迟,我很抱歉,接下来的一段时间会好很多。

日常除了工作之外,还要研究新的课题,跟大家讨论一些问题,在加上生活上的各种琐事,以及不间断的懒散,能用来做其他事情的时间已经很少了,还请谅解哈~

from blog.

wd2010 avatar wd2010 commented on May 2, 2024 3

@Nanchenk 我也产生了同样的疑惑

var m=1
function foo(){
  console.log(m);//2
}
try{
  var m=2
  foo()
}catch(e){
  console.log(e)
}

在try/catch中若是静态编辑的话,那按理foo输出来的m应该是1,但这里是2 。

@mqyqingfeng 冴羽大大,麻烦指导下

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 2, 2024 2

@rccoder 感谢补充!非常赞同,词法作用域其实是非常重要的基础,所以才会作为第二篇去讲解。

from blog.

mengxin-FE avatar mengxin-FE commented on May 2, 2024 2
var value = 1;
function bar(){
    var value =2;
    console.log(value)
}
bar() //2

为什么这回又返回2了呢? 我还是没理解

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 2, 2024 2

@nicelj

function out( function (){console.log(1)} ){}

首先这种写法会导致语法错误,正常应该这样写:

var value = 1;
var f = function() { console.log(value) }
function out(f) {
        var value = 2;
        f();
}
out(f)

f 函数的作用域就是 [f.AO, global.VO]

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 2, 2024 2

@thisisandy 这段代码确实是返回 "local scope",因为是根据函数创建的位置,然后向外查找变量,自然是 'local scope'


说错了…… 应该是 undefined,因为有函数提升和变量提升,相当于

function f() {return scope};
var scope;
f();
scope = "local scope";

from blog.

clChenLiang avatar clChenLiang commented on May 2, 2024 2

这个跟 context、this 蛮容易弄混的。this 跟 context 都是指运行时的上下文,是跟运行时有关的参数。所以,一般在 定义 的时候使用 that = this 来保留上下文

from blog.

AnsonZnl avatar AnsonZnl commented on May 2, 2024 1
var value = 1;
function bar(){
    var value =2;
    console.log(value)
}
bar() //2

为什么这回又返回2了呢? 我还是没理解

哈哈 ,兄弟,我怀疑你这是看文章看的走火入魔了...

from blog.

Saitmob avatar Saitmob commented on May 2, 2024 1

image
函数声明提升,所function foovar value = 1之前导致undefined的吧,怎么会是1呢

from blog.

Sphinm avatar Sphinm commented on May 2, 2024 1

from blog.

MissCuriosity avatar MissCuriosity commented on May 2, 2024

JS的上下文真的是个很神奇的东西,我看的是汤姆大叔的深入理解JS,这本书里面解释的也挺详细的,让我感觉看了之后稍微懂了,但是后面又会忘。
在看你文末两段代码的时候我其实觉得挺奇怪的,因为return f,我认为会返回function f() {};后面再看了一眼,原来checkscope()();也是无奈。

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 2, 2024

@MissCuriosity 我也看过汤姆大叔的深入理解 JavaScript 系列,深受启发和影响。return f 确实会返回 function f(){},只是因为 checkscope()(),返回的 f 函数又被执行了~

from blog.

wqxc avatar wqxc commented on May 2, 2024

谢谢😜

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 2, 2024

@yangshun352607664 哈哈,快来举一个例子~~~

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 2, 2024

@suoz 你剧透了哈~ 😂

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 2, 2024

@double-chen 动态作用域和静态作用域,决定的是作用域链的顺序

from blog.

yh284914425 avatar yh284914425 commented on May 2, 2024
var a = 10;
var o = {
     a:11,
     b:{
         fn:function(){
              console.log(a);
         }
     }
}
o.b.fn();

函数包裹函数那种作用域理解了,这样的又有点懵了

from blog.

watsonnnnn avatar watsonnnnn commented on May 2, 2024

如果是这样的,function out(function(){console.log(xxx)})这种形式,那括号里的函数作用域是怎么样的?

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 2, 2024

@nicelj 你说的是

function out () {
	function inner() {
	}
}

这种形式吗?

如果是这种,可以接着往下看~

from blog.

watsonnnnn avatar watsonnnnn commented on May 2, 2024

@mqyqingfeng 不是啊

function out( function (){console.log(xxx)} ){

}

是这样的,一个匿名函数直接当参数传进去

from blog.

JarenZheng avatar JarenZheng commented on May 2, 2024

动态作用域 怎么演示。

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 2, 2024

@JarenZheng 使用 bash
default

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 2, 2024

@nicelj 跟上面的例子是一样的,都是 [f.AO, global.VO]

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 2, 2024

@nicelj 关于作用域:

default

此外,作用域是动态的,这跟动态作用域不是一个概念哈~

from blog.

Yoomin233 avatar Yoomin233 commented on May 2, 2024

this应该就是典型的动态作用域吧.

from blog.

thisisandy avatar thisisandy commented on May 2, 2024

f(); function f() { return scope; } var scope = "local scope";
有个问题希望您能帮助我解答一下,这里f()返回了‘local scope’,但是按照作用域链那篇文章,在调用f时,这里的globalContext.VO中的scope应该是undefined的状态啊,怎么会返回‘local scope’呢?

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 2, 2024

@thisisandy 这段代码返回的确实是 undefined,并不是 'local scope',不知道你是怎么写的,不如试试不用 return, 改成 console.log

f(); 
function f() { console.log(scope ; } 
var scope = "local scope";

from blog.

thisisandy avatar thisisandy commented on May 2, 2024

@mqyqingfeng 唔,顺序错了 f(); var scope = "local scope"; function f() { return scope; } 应该是这样

from blog.

ryouaki avatar ryouaki commented on May 2, 2024

因为 JavaScript 采用的是词法作用域,[函数的作用域]在函数定义的时候就决定了。

而与词法作用域相对的是动态作用域,[函数的作用域]是在函数调用的时候才决定的。

后面应该是动态作用域吧?

from blog.

Tvinsh avatar Tvinsh commented on May 2, 2024

你不知道的js,对这个也有挺详细�的介绍,博主写得很好,感谢🙏

from blog.

jimczj avatar jimczj commented on May 2, 2024

jimczj/jimczj.github.io#21 这是最近总结的,可以看下呗

from blog.

hu-shuaishuai avatar hu-shuaishuai commented on May 2, 2024

楼主你好。看了这篇文章,我对词法作用域的理解是函数时在创建的时候就已经把他的作用域给确定了,是这个意思吗?

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 2, 2024

@xiaohu-xiaohu 是的,就是这个意思~

from blog.

Ghohankawk avatar Ghohankawk commented on May 2, 2024

涨知识了,之前原来是一种,误会,对这个地方,明白了,函数场景的时候,已经确定了作用域,这句话,感谢,继续往下读

from blog.

FengYangLiu avatar FengYangLiu commented on May 2, 2024

收益匪浅

from blog.

imaxing avatar imaxing commented on May 2, 2024

将复制的作用域放在顶部这一块不是很明白能否解惑?

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 2, 2024

@imaxing 没有明白想问的问题哈……能再详细的描述一下吗?

from blog.

nightn avatar nightn commented on May 2, 2024

《JavaScript权威指南》对作用域的描述是:

一个变量的作用域(scope)是程序源代码中定义这个变量的区域。

是不是可以认为变量对象就是 JavaScript 对作用域这个概念的实现。而且,作用域链其实就是变量对象链,这进一步证实了这种观点。

当我们说通过 catch 语句或者 with 语句来延长作用域链的时候,其实就是在作用域链的最前端添加一个新的变量对象,执行完代码块时再移除这个变量对象。我觉得用 catch 或 with 的时候应该只是暂时延长作用域链,并不会创建一个新的执行上下文。(因为按照博主所说,执行上下文总共只有 3 种:全局执行上下文、函数执行上下文、eval。那我很好奇 ES6 中的 let/const 的作用域是如何实现的,也像 with 一样吗)。

望博主解疑,非常感谢!!

PS:对了,博主你有建立什么交流群吗,我觉得你的文章非常有价值,大家在阅读的过程中也会思考很多问题,如果只是在 issue 下提问,博主也很难每个一一作答。建议博主创建一个交流群,这样大家可以在上面提问,知道的同学都可以回答。

from blog.

wenbingyan avatar wenbingyan commented on May 2, 2024

关于作者最后的一个问题,
return f(); 与return f()()的区别是前一个,return f()此时的作用域在函数作用域的顶端,而return f()()的作用域是在全局作用域的顶端,是这个意思吗?
@mqyqingfeng @suoz

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 2, 2024

@wenbingyan 这个理解可能有些问题,建议接着看后面的文章~

from blog.

DFLovingWM avatar DFLovingWM commented on May 2, 2024

原来词法作用域就等同于静态作用域!文章不错!

from blog.

liSong5713 avatar liSong5713 commented on May 2, 2024

`
var x = 21;

var talk = function () {

    console.log(x);

    var x = 20;

};

talk ();

`
这个怎么用词法作用域解释下呢

from blog.

Sphinm avatar Sphinm commented on May 2, 2024

from blog.

liSong5713 avatar liSong5713 commented on May 2, 2024

from blog.

jasonzhangdong avatar jasonzhangdong commented on May 2, 2024

@mqyqingfeng

// 题1
var a = 1;
function f(b) {
b = 2;
}
f(a);
// a == 1
// 题2
var a = [1, 3];
function f(b) {
b.push(2);
}
f(a)
// a == [1,3,2]
// 题3
var a = {k: 12};
function f(b) {
a.c = 100;
}
f(a)
// a == {k:12,c:100}

为什么会有这样的结果?????

from blog.

lzuliuyun avatar lzuliuyun commented on May 2, 2024

@jasonzhangdong 问题关键在于基本类型和引用类型如何传参。

题1,a是基本类型,传参是直接复制a的值,因此a的值不变。
题2、题3,数组和对象是引用类型,传的是引用地址,可以理解为a,b操控的是同一块堆内存地址。

from blog.

xiaofan9 avatar xiaofan9 commented on May 2, 2024

@lzuliuyun 很好奇的是词法分析(词法作用域)这个阶段是发生在js编译阶段,还是执行阶段

from blog.

lzuliuyun avatar lzuliuyun commented on May 2, 2024

@xiaofan9 词法分析是在编译阶段决定的,也就是说,在执行之前就已经确定了作用域的范围。你可以阅读下作者的“JavaScript深入之变量对象”:#5

from blog.

xie991283109 avatar xie991283109 commented on May 2, 2024

大佬,你后面举的javascript权威指南的两个例子,看着就是闭包呀,最终打出‘local scope‘从闭包也可以解释的通,能否把闭包和词法作用域打通说一下呢,感觉还是有点迷啊,谢谢

from blog.

weiyuu avatar weiyuu commented on May 2, 2024

from blog.

slogeor avatar slogeor commented on May 2, 2024

@yuu95 看权威指南就行?

from blog.

jiayousuda avatar jiayousuda commented on May 2, 2024

你好,,我想问下,,实际项目中一般尽量写成局部变量还是全局变量,,

from blog.

xiaofan9 avatar xiaofan9 commented on May 2, 2024

@jiayousuda 建议局部

from blog.

findpikachu avatar findpikachu commented on May 2, 2024

你说错了,JavaScript即是词法作用域又是动态作用域,动态作用域指的是匿名函数的this和argument

from blog.

1011cat avatar 1011cat commented on May 2, 2024

你好,其实在最早之前学习js时就有这样的疑问,JavaScript里的作用域是对象吗?感觉不是,但是有这样一句话"JavaScript里万物皆对象".最近读<你不知道的JavaScript>其中有这样一句话"在 JavaScript 内部,作用 域确实和对象类似,可见的标识符都是它的属性。但是作用域“对象”无法通过 JavaScript 代码访问,它存在于 JavaScript 引擎内部。"所以更加迷惑了,请问,你是怎么理解的?谢谢!

from blog.

Nanchenk avatar Nanchenk commented on May 2, 2024

JS也存在动态作用域吧,with,try/catch的catch子句好像就是动态的吧,包含eval的代码也不能由定义时确定。

from blog.

xiaofan9 avatar xiaofan9 commented on May 2, 2024

@wd2010 你这个结果完全没问题啊,在foo调用前,重新声明了m,并赋值为2,foo调用的时候拿到的确实是2

from blog.

wd2010 avatar wd2010 commented on May 2, 2024

@xiaofan9 我被try/catch给迷惑了,es5中他不会产生块级作用域

from blog.

Nanchenk avatar Nanchenk commented on May 2, 2024

@xiaofan9 我被try/catch给迷惑了,es5中他不会产生块级作用域

catch中的作用域就是块级的,你的例子不对没体现出来

from blog.

wd2010 avatar wd2010 commented on May 2, 2024

@Nanchenk es5中catch作用域不是块级的,比如

(function(){
  e="default";
  try{
    throw "test";
  }catch(e){
    var e,x=123;
    console.log(e); //test
    console.log(delete e); //false
    e=456;
    console.log(e); //456
  };
  console.log(x); //123
  console.log(e); //default
  console.log(window.e); //undefined
})();

from blog.

xiaofan9 avatar xiaofan9 commented on May 2, 2024

@Nanchenk es5 没块级作用域的概念

from blog.

webXLing avatar webXLing commented on May 2, 2024

`
var x = 21;

var talk = function () {

    console.log(x);

    var x = 20;

};

talk ();

`
这个怎么用词法作用域解释下呢

`
var x = 21;

var talk = function () {

    console.log(x);

    var x = 20;

};

talk ();

`
这个怎么用词法作用域解释下呢

这个是因为var 是具有变量提升的, 会在函数顶部 先声明变量 然后在去赋值 ,console 的位置在声明之后 赋值之前所以打印出来时undefined

from blog.

Jemair avatar Jemair commented on May 2, 2024

es5 的 try 是没有块级作用域的 所以在 try 里面的 var 修改了外部的 m 的值
同样的情况下在 es6 下,由于产生了块级作用域,输出就符合预期了

const m=1
function foo(){
  console.log(m);//1
}
try{
  const m=2
  foo()
}catch(e){
  console.log(e)
}

from blog.

xiaoxiongzi avatar xiaoxiongzi commented on May 2, 2024

关于静态作用域与动态作用域,《你不知道的JavaScript》上册讲的很详细

from blog.

imaxing avatar imaxing commented on May 2, 2024

from blog.

xiaofan9 avatar xiaofan9 commented on May 2, 2024

@SageWu 你只执行function f() {return scope}; var scope; f(); 这段代码你就会发现 打印出来的确实是undefined
image

from blog.

SageWu avatar SageWu commented on May 2, 2024

@xiaofan9 谢谢,最终发现,竟然是我用的那工具缓存了之前的赋值。

from blog.

imaxing avatar imaxing commented on May 2, 2024

from blog.

zhoubhin avatar zhoubhin commented on May 2, 2024

看了好几遍,基本上是看懂了……

from blog.

zhoubhin avatar zhoubhin commented on May 2, 2024

image
函数声明提升,所function foovar value = 1之前导致undefined的吧,怎么会是1呢

为何我输出的结果是:
1
undefined

from blog.

comeon-heqiang avatar comeon-heqiang commented on May 2, 2024

看了好几遍,基本上是看懂了……

基本懂了,那么很快就忘了

from blog.

zhoubhin avatar zhoubhin commented on May 2, 2024

看了好几遍,基本上是看懂了……

基本懂了,那么很快就忘了

所以还得彻底搞懂才行啊~🤦‍♂️

from blog.

winfredwyw avatar winfredwyw commented on May 2, 2024

个人觉得 javascript 只有词法作用域,执行上下文 this 不能称之为动态作用域

from blog.

zhoubhin avatar zhoubhin commented on May 2, 2024

此处的 undefined 是由于函数没有 return 返回值导致的...

在 2019年3月6日,下午1:19,Salvador Zhou @.***> 写道: https://user-images.githubusercontent.com/22002351/53856044-3df82000-400b-11e9-9767-0869a71d98e2.png 函数声明提升,所function foo在 var value = 1之前导致undefined的吧,怎么会是1呢 为何我输出的结果是: 1 undefined — You are receiving this because you commented. Reply to this email directly, view it on GitHub <#3 (comment)>, or mute the thread https://github.com/notifications/unsubscribe-auth/APuGepXekQN7kuhhf3nfcAONnqCRC-aIks5vT0_ZgaJpZM4NFWFZ.

最后为何输出undefined这个我知道的,我在这边其实是为了告诉楼上那位朋友 @Saitmob ,那段代码最终输出结果为1,而非他认为的undefined。

from blog.

Saitmob avatar Saitmob commented on May 2, 2024

此处的 undefined 是由于函数没有 return 返回值导致的...

在 2019年3月6日,下午1:19,Salvador Zhou @.***> 写道: https://user-images.githubusercontent.com/22002351/53856044-3df82000-400b-11e9-9767-0869a71d98e2.png 函数声明提升,所function foo在 var value = 1之前导致undefined的吧,怎么会是1呢 为何我输出的结果是: 1 undefined — You are receiving this because you commented. Reply to this email directly, view it on GitHub <#3 (comment)>, or mute the thread https://github.com/notifications/unsubscribe-auth/APuGepXekQN7kuhhf3nfcAONnqCRC-aIks5vT0_ZgaJpZM4NFWFZ.

最后为何输出undefined这个我知道的,我在这边其实是为了告诉楼上那位朋友 @Saitmob ,那段代码最终输出结果为1,而非他认为的undefined。

emmm,因为只有一个输出,所以。。明明之前一直都知道那个undefined并不是console.log出来的。。话说怎么会只有一个undefined啊?

from blog.

zhoubhin avatar zhoubhin commented on May 2, 2024

此处的 undefined 是由于函数没有 return 返回值导致的...

在 2019年3月6日,下午1:19,Salvador Zhou @.***> 写道: https://user-images.githubusercontent.com/22002351/53856044-3df82000-400b-11e9-9767-0869a71d98e2.png 函数声明提升,所function foo在 var value = 1之前导致undefined的吧,怎么会是1呢 为何我输出的结果是: 1 undefined — You are receiving this because you commented. Reply to this email directly, view it on GitHub <#3 (comment)>, or mute the thread https://github.com/notifications/unsubscribe-auth/APuGepXekQN7kuhhf3nfcAONnqCRC-aIks5vT0_ZgaJpZM4NFWFZ.

最后为何输出undefined这个我知道的,我在这边其实是为了告诉楼上那位朋友 @Saitmob ,那段代码最终输出结果为1,而非他认为的undefined。

emmm,因为只有一个输出,所以。。明明之前一直都知道那个undefined并不是console.log出来的。。话说怎么会只有一个undefined啊?

我也觉得奇怪,不是应该正确地输出最终结果 1 嘛,咋会只有一个undefeated……

from blog.

Tmac-1 avatar Tmac-1 commented on May 2, 2024

function foo() {
console.log(value);
}

function bar() {
var value = 2;
foo();
}
var value = 1;
bar();
为什么这个也会打印1啊。

from blog.

pinguo-luozhijian avatar pinguo-luozhijian commented on May 2, 2024

function foo() {
console.log(value);
}

function bar() {
var value = 2;
foo();
}
var value = 1;
bar();
为什么这个也会打印1啊。

这个代码相当于:
var value;

function foo() {
console.log(value);
}

function bar() {
var value = 2;
foo();
}
value = 1;
bar();
1是foo中打印出来的
foo是在调用bar中调用的
而bar是在value = 1之后调用的
所以打印出来是1
函数的作用域在创建的时候已经确定了
foo的作用域跟 bar同级 foo中 没有value 所以 沿着作用域链网上找 就找到 顶层的 value = 1

from blog.

yenava avatar yenava commented on May 2, 2024

var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
checkscope()();

最后这个例子 返回的f是什么呀?
checkscope后面为什么是接两个()?

from blog.

zhoubhin avatar zhoubhin commented on May 2, 2024

var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
checkscope()();

最后这个例子 返回的f是什么呀?
checkscope后面为什么是接两个()?

执行checkscope最终输出checkscope(){ var scope = "local scope"; function f(){ return scope; } return f; }
执行checkscope();最终输出f(){ return scope; }
执行checkscope()();最终输出"local scope"
因为每一个的最终执行结果都是对应的(大雾)

from blog.

Tmac-1 avatar Tmac-1 commented on May 2, 2024

function foo() {
console.log(value);
}
function bar() {
value = 2;
foo();
}
var value = 1;
bar();
这个就会打印2了,这个的执行顺序是什么样的啊?

from blog.

ddzy avatar ddzy commented on May 2, 2024

function foo() {
console.log(value);
}
function bar() {
value = 2;
foo();
}
var value = 1;
bar();
这个就会打印2了,这个的执行顺序是什么样的啊?

  • 初始的全局value = 1
  • 调用bar, 全局value赋值为2
  • 调用foo, 输出2

from blog.

fengandzhy avatar fengandzhy commented on May 2, 2024

如果是这样的,function out(function(){console.log(xxx)})这种形式,那括号里的函数作用域是怎么样的?
这种写法是错误的。声明函数只能是function out(a){},

from blog.

rongda avatar rongda commented on May 2, 2024

JavaScript 采用的是词法作用域,函数的作用域在函数定义的时候就决定了,函数的作用域是基于函数创建的位置

from blog.

chinawzc avatar chinawzc commented on May 2, 2024

"根据书写的位置” 先记住这句话 🤣

from blog.

wyj1993 avatar wyj1993 commented on May 2, 2024

@double-chen 动态作用域和静态作用域,决定的是作用域链的顺序

能具体说一下吗,这两个分着看还行,但是合起来就不理解了。

from blog.

cell617 avatar cell617 commented on May 2, 2024

@double-chen 动态作用域和静态作用域,决定的是作用域链的顺序

作用域链存储在什么地方

from blog.

7neves avatar 7neves commented on May 2, 2024

function foo() {
console.log(value);
}

function bar() {
var value = 2;
foo();
}
var value = 1;
bar();
为什么这个也会打印1啊。

因为词法作用域,在书写foo()函数的时候,全局变量var value = 1;已经存在了,foo()持有对value的引用,所以不论在哪里执行foo()函数都会输出全局变量中的value的值;第二次写的代码中bar()函数中未用var声明,所以定义了全局变量value = 2;修改了全局变量value的值,所以输出的结果为2;

from blog.

Wolfeather avatar Wolfeather commented on May 2, 2024

闭包能理解,前面的静态作用域的例子不大能理解。。。为啥foo()中没找到value之后,就去最外层找了?不应该去bar()中找吗?求助大神们

from blog.

xiaodun avatar xiaodun commented on May 2, 2024

作者的案列太过简单,应该写那种嵌套比较深的的

是用来出面试题嘛

from blog.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.