GithubHelp home page GithubHelp logo

Comments (51)

giscafer avatar giscafer commented on May 3, 2024 163

几个例子:

var b = 10;
(function b() {
   // 内部作用域,会先去查找是有已有变量b的声明,有就直接赋值20,确实有了呀。发现了具名函数 function b(){},拿此b做赋值;
   // IIFE的函数无法进行赋值(内部机制,类似const定义的常量),所以无效。
  // (这里说的“内部机制”,想搞清楚,需要去查阅一些资料,弄明白IIFE在JS引擎的工作方式,堆栈存储IIFE的方式等)
    b = 20;
    console.log(b); // [Function b]
    console.log(window.b); // 10,不是20
})();

所以严格模式下能看到错误:Uncaught TypeError: Assignment to constant variable

var b = 10;
(function b() {
  'use strict'
  b = 20;
  console.log(b)
})() // "Uncaught TypeError: Assignment to constant variable."

其他情况例子:

window

var b = 10;
(function b() {
    window.b = 20; 
    console.log(b); // [Function b]
    console.log(window.b); // 20是必然的
})();

var:

var b = 10;
(function b() {
    var b = 20; // IIFE内部变量
    console.log(b); // 20
   console.log(window.b); // 10 
})();

from daily-interview-question.

GeekQiaQia avatar GeekQiaQia commented on May 3, 2024 126

1打印结果内容如下:
ƒ b() {
b = 20;
console.log(b)
}
2原因:
作用域:执行上下文中包含作用于链:
在理解作用域链之前,先介绍一下作用域,作用域可以理解为执行上下文中申明的变量和作用的范围;包括块级作用域/函数作用域;
特性:声明提前:一个声明在函数体内都是可见的,函数声明优先于变量声明;
在非匿名自执行函数中,函数变量为只读状态无法修改;

from daily-interview-question.

blockmood avatar blockmood commented on May 3, 2024 89

我的理解是,先不看函数自执行,直接fn b()
首先函数声明比变量要高,其次b = 20 没有var 获取其他,说明是window最外层定义的变量。
js作用域中,先找最近的 那就是b fn ,直接打印了,如果 b = 20 有var 那就是打印20

from daily-interview-question.

LasyIsLazy avatar LasyIsLazy commented on May 3, 2024 38

所以重点是:非匿名自执行函数,函数名只读。

from daily-interview-question.

jefferyE avatar jefferyE commented on May 3, 2024 13

@jessie-zly
这个上面有回答
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/A_re-introduction_to_JavaScript#Functions
里面说明一个潜在问题——既然匿名函数没有名字,那该怎么递归调用它呢?在这一点上,JavaScript 允许你命名这个函数表达式。你可以命名立即调用的函数表达式(IIFES——Immediately Invoked Function Expressions)
例如:

var charsInBody = (function counter(elm) {
  if (elm.nodeType == 3) { // 文本节点
       return elm.nodeValue.length;
   }
   var count = 0;
   for (var i = 0, child; child = elm.childNodes[i]; i++) {
       count += counter(child);
   }
   return count;
})(document.body);

如上所提供的函数表达式的名称的作用域仅仅是该函数自身。这允许引擎去做更多的优化,并且这种实现更可读、友好。该名称也显示在调试器和一些堆栈跟踪中,节省了调试时的时间。

from daily-interview-question.

dingLeiOnly avatar dingLeiOnly commented on May 3, 2024 8

var b = 10; (function b() { b = 20; console.log(b); })();
具名自执行函数的变量为只读属性,不可修改

from daily-interview-question.

windcanvas avatar windcanvas commented on May 3, 2024 8

《在JavaScript的立即执行的具名函数A内修改A的值时到底发生了什么?》

这篇文章的解释还比较清晰。

from daily-interview-question.

chenzesam avatar chenzesam commented on May 3, 2024 7

非匿名自执行函数,函数名只读

from daily-interview-question.

YYYCondi avatar YYYCondi commented on May 3, 2024 6

// 验证1
var b = 10; // 报错
function b () {
b =20;
console.log(b);
}
b();
// 验证2
var b =10;
(function b(b){
b = 20;
console.log(b); // 20,说明如果函数作用域挂载了名为b的变量,那么就会赋值改变
})()
// 验证3
var b =10;
(function b(){
var b = 20;
console.log(b); // 20
})()
// 验证4
var b =10;
(function a(b){
b = 20;
console.log(b); // 20
})()
// 验证5
function b () {
alert(0)
}
(function b(){
b()
console.log(b); // 无限循环,而不是alert(0)
})()
从上面的验证其实就可以看到,在自执行函数b的执行环境中是没有变量b,但是有函数b的,因为没有进行实参传入和var,let声明,所以b=20会顺着作用域链往外找,就找到了b=10,那个地方,对应b=20,改变的也是全局环境的b变量.所以,当你在函数b中打印b,这时是不分变量和函数的,因为b的执行环境中挂载的有函数b,函数b就会被打印出来.你可以参考我最后一个验证,不是b=20,而是直接调用b,就会形成死循环,递归调用.所以这是一个执行环境的问题

from daily-interview-question.

AnaniZhu avatar AnaniZhu commented on May 3, 2024 5

@ravencrown

两种情况:

var b = 20

var b 则在函数 b 内申明了一个局部变量,当执行 b = 20 时,顺着作用域链向上找,于是在函数内找到了局部变量 b(也就是 var b 的), 将其修改为 20。console.log(b)同理,顺着作用域链向上找,找到了局部变量 b,且其值为 20.

b = 20

执行 b = 20 时,顺着作用域链向上找,找到函数 b, 尝试给 b 赋值为 20,由于函数 b 是函数表达式,而函数表达式的函数名是常量,无法二次赋值(在正常模式下静默失效,在严格模式下报错),赋值失败,所以输出的还是该函数

from daily-interview-question.

jjeejj avatar jjeejj commented on May 3, 2024 1
var b = 10;
(function b() {
  b = 20;
  console.log(b)
})()

针对这题,在知乎上看到别人的回答说:

  1. 函数表达式与函数声明不同,函数名只在该函数内部有效,并且此绑定是常量绑定。
  2. 对于一个常量进行赋值,在 strict 模式下会报错,非 strict 模式下静默失败。
  3. IIFE中的函数是函数表达式,而不是函数声明。

实际上,有点类似于以下代码,但不完全相同,因为使用const不管在什么模式下,都会TypeError类型的错误

const foo = function () {
  foo = 10;
  console.log(foo)
}
(foo)() // Uncaught TypeError: Assignment to constant variable.

我的理解是,b函数是一个相当于用const定义的常量,内部无法进行重新赋值,如果在严格模式下,会报错"Uncaught TypeError: Assignment to constant variable."
例如下面的:

var b = 10;
(function b() {
  'use strict'
  b = 20;
  console.log(b)
})() // "Uncaught TypeError: Assignment to constant variable."

不知道我这回答有没有问题

这个回答主要表达的是:函数表达式的函数名只在该函数内部有效,且绑定是常量类似 const,不能修改

解答了一部分疑问,但是这个是ES 的规范吗?

from daily-interview-question.

qiannianchong25 avatar qiannianchong25 commented on May 3, 2024 1
(function b(){
  b = 20;
  console.log(b); 
})

上式function用括号括起来了,说明这是一个函数表达式,而不是一个函数声明。括号可以改变运算符的优先级,在这里它是一个分组符。可参考文章:https://www.cnblogs.com/TomXu/archive/2011/12/29/2290308.html
具名函数表达式中的函数名在函数内部是可以访问的,但函数外面是无法访问到的,这点和函数声明有很大的不同。没有括号的话,全局变量是可以访问到b的。至于函数里面的b是全局变量自然不必细说。因此,console.log里面的b肯定现在函数内部找,然后再在全局找,所有b就是funcition b{}。
因此,代码等价于:

var b = 10;
fun=function b(){
  b = 20;
  console.log(b); 
};
fun()

from daily-interview-question.

lovelmh13 avatar lovelmh13 commented on May 3, 2024 1

可以写成这个,配合作用域和变量提升,就可以知道为什么打印的是函数b了

var b = 10;
var c = function b () {
	b = 20;
	console.log(b);
}
c();

from daily-interview-question.

15025639392 avatar 15025639392 commented on May 3, 2024 1

1.函数表达式中的函数名只在函数体内部可用,指代函数表达式本身,其他地方都不可用
2.函数表达式中的函数名是只读的,所以b=20;会赋值失败

from daily-interview-question.

zuoyi615 avatar zuoyi615 commented on May 3, 2024 1
  1. 非匿名自执行函数,函数名只读(类似常量)
  2. 非严格模式下给常量命名静默失败
  3. 严格模式下给常量命名报错 TypeError

from daily-interview-question.

xgqfrms avatar xgqfrms commented on May 3, 2024 1

good answer

考察知识点

  1. closure
  2. IIFE
  3. hoisting
  4. scope
  5. function declaration / function expression
  6. named function / anonymous function

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions

几个例子:

var b = 10;
(function b() {
   // 内部作用域,会先去查找是有已有变量b的声明,有就直接赋值20,确实有了呀。
   // 发现了具名函数 function b(){},拿此b做赋值;
   // IIFE的函数无法进行赋值(内部机制,类似const定义的常量),所以无效。
   //(这里说的“内部机制”,想搞清楚,需要去查阅一些资料,
   // 弄明白IIFE在JS引擎的工作方式,堆栈存储IIFE的方式等)
    b = 20;
    console.log(b); // [Function b]
    console.log(window.b); // 10,不是20
})();

所以严格模式下能看到错误:Uncaught TypeError: Assignment to constant variable

var b = 10;
(function b() {
  'use strict'
  b = 20;
  console.log(b)
})() // "Uncaught TypeError: Assignment to constant variable."

其他情况例子:

window

var b = 10;
(function b() {
    window.b = 20; 
    console.log(b); // [Function b]
    console.log(window.b); // 20是必然的
})();

var:

var b = 10;
(function b() {
    var b = 20; // IIFE内部变量
    console.log(b); // 20
   console.log(window.b); // 10 
})();

from daily-interview-question.

 avatar commented on May 3, 2024
var b = 10;
(function b() {
  b = 20;
  console.log(b)
})()

针对这题,在知乎上看到别人的回答说:

  1. 函数表达式与函数声明不同,函数名只在该函数内部有效,并且此绑定是常量绑定。
  2. 对于一个常量进行赋值,在 strict 模式下会报错,非 strict 模式下静默失败。
  3. IIFE中的函数是函数表达式,而不是函数声明。

实际上,有点类似于以下代码,但不完全相同,因为使用const不管在什么模式下,都会TypeError类型的错误

const foo = function () {
  foo = 10;
  console.log(foo)
}
(foo)() // Uncaught TypeError: Assignment to constant variable.

我的理解是,b函数是一个相当于用const定义的常量,内部无法进行重新赋值,如果在严格模式下,会报错"Uncaught TypeError: Assignment to constant variable."
例如下面的:

var b = 10;
(function b() {
  'use strict'
  b = 20;
  console.log(b)
})() // "Uncaught TypeError: Assignment to constant variable."

不知道我这回答有没有问题

关键function b() { b = 20; console.log(b) }这是一个具名函数,
(function b() { b = 20; console.log(b) })()那这还是IIFE吗?

from daily-interview-question.

jefferyE avatar jefferyE commented on May 3, 2024

@jjeejj
这个目前暂时还没有去确认下是不是ES5规范,只是看到了一篇博客上是这么说的
image

from daily-interview-question.

 avatar commented on May 3, 2024

@jefferyE

@jessie-zly
这个上面有回答
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/A_re-introduction_to_JavaScript#Functions
里面说明一个潜在问题——既然匿名函数没有名字,那该怎么递归调用它呢?在这一点上,JavaScript 允许你命名这个函数表达式。你可以命名立即调用的函数表达式(IIFES——Immediately Invoked Function Expressions)
例如:

var charsInBody = (function counter(elm) {
  if (elm.nodeType == 3) { // 文本节点
       return elm.nodeValue.length;
   }
   var count = 0;
   for (var i = 0, child; child = elm.childNodes[i]; i++) {
       count += counter(child);
   }
   return count;
})(document.body);

如上所提供的函数表达式的名称的作用域仅仅是该函数自身。这允许引擎去做更多的优化,并且这种实现更可读、友好。该名称也显示在调试器和一些堆栈跟踪中,节省了调试时的时间。

如果是这样的话,那很好奇预编译后的代码了...
ps: 我第一眼也认为是IIFE是函数表达式,而不是函数声明,但发现是个具名函数了...

from daily-interview-question.

 avatar commented on May 3, 2024
var b = 10;
(function b() {
  b = 20;
  console.log(b)
})()

针对这题,在知乎上看到别人的回答说:

函数表达式与函数声明不同,函数名只在该函数内部有效,并且此绑定是常量绑定。
对于一个常量进行赋值,在 strict 模式下会报错,非 strict 模式下静默失败。
IIFE中的函数是函数表达式,而不是函数声明。
实际上,有点类似于以下代码,但不完全相同,因为使用const不管在什么模式下,都会TypeError类型的错误

const foo = function () {
  foo = 10;
  console.log(foo)
}

(foo)() // Uncaught TypeError: Assignment to constant variable.
我的理解是,b函数是一个相当于用const定义的常量,内部无法进行重新赋值,如果在严格模式下,会报错"Uncaught TypeError: Assignment to constant variable."
例如下面的:

var b = 10;
(function b() {
  'use strict'
  b = 20;
  console.log(b)

})() // "Uncaught TypeError: Assignment to constant variable."
不知道我这回答有没有问题

这个回答主要表达的是:函数表达式的函数名只在该函数内部有效,且绑定是常量类似 const,不能修改

解答了一部分疑问,但是这个是ES 的规范吗?

from daily-interview-question.

 avatar commented on May 3, 2024

@jefferyE 匿名函数是可以递归调用的,只不过在严格模式下会报错

(function(counter){
	if (counter) {
		return;
	}
	return arguments.callee(1);
})()

from daily-interview-question.

 avatar commented on May 3, 2024

@wasonal

在题目中的 IIFE 里面 b = 20 其实访问的是 window 下的 b 变量

按照你这种说法,外面 b 变量的值会变成 20,但是最后验证发现:外面 b 变量的值仍然是 10。所以从侧面验证,你上面的这句话是错误的。

	var b = 10;

	var _b = function b() {
		b = 20;
		console.log(b);
	}();

根据作用域链的知识,当出现同名的变量的时候,会优先访问更 "近" 的变量

这句话是正确的,具体解释可以去看这篇文章

所以 IIFE 中其实没有 b 变量

这句话是错误,b 变量指的是函数表达式的函数名。试想一下:如果你在函数里面拿不到该函数的函数名,那你怎么进行递归?

from daily-interview-question.

formattedzzz avatar formattedzzz commented on May 3, 2024

原题
var b = 10; (function b() { b = 20; console.log(b); })()//输出函数b

针对这道题我提一下我的想法,有不正确的地方还希望各位大佬指出

IIFE会创建一个块级作用域,

根据作用域链的知识,当出现同名的变量的时候,会优先访问更"近"的变量

在题目中的IIFE里面b=20其实访问的是window下的b变量,

所以IIFE中其实没有b变量,

那么最近的b变量就是这个函数。

我觉得这个最棒的也最好理解的回答 如果执行体内加了var声明 那就是声明的值

from daily-interview-question.

ablikim915 avatar ablikim915 commented on May 3, 2024

我简单点再说下自己的看法:
因为具名函数的函数名标识符(这在例子中的b)只能在函数体内可以访问,并且是不可修改的。所以对b重新赋值也是无效的,所以输出的结果是一个函数。
详细解析请访问:https://segmentfault.com/q/1010000002810093/a-1020000002810564

from daily-interview-question.

sisi529 avatar sisi529 commented on May 3, 2024

当JS 解释器遇到非匿名立即执行函数时,会创建一个辅助的特定对象,然后将函数名称当作这个对象的属性,因此函数内部才可以访问到b,但是这个值又是只读的,所以对他的赋值并不生效,所以打印的结果还是这个函数,并且外部的值也没有发生更改
这里说的很清楚了,各位大佬可以看看~~(咦,这个链接不能直接在这里打开,要复制到浏览器中才能打开?)
https://yuchengkai.cn/docs/frontend/#%E6%89%A7%E8%A1%8C%E4%B8%8A%E4%B8%8B%E6%96%87

from daily-interview-question.

gdrpAPeng avatar gdrpAPeng commented on May 3, 2024

var b = 10;
(function b(){
b = 20;
console.log(this.b);
})();
// 打印:10
var b = 10;
(function b(){
var b = 20;
console.log(b);
})();
// 打印:20

from daily-interview-question.

tyktianxia avatar tyktianxia commented on May 3, 2024

问:这个函数还是不是立即执行函数,立即执行函数不得是一个匿名函数吗

from daily-interview-question.

qiannianchong25 avatar qiannianchong25 commented on May 3, 2024
var b = 10;
(function b() {
  b = 20;
  console.log(b)
})()

针对这题,在知乎上看到别人的回答说:

  1. 函数表达式与函数声明不同,函数名只在该函数内部有效,并且此绑定是常量绑定。
  2. 对于一个常量进行赋值,在 strict 模式下会报错,非 strict 模式下静默失败。
  3. IIFE中的函数是函数表达式,而不是函数声明。

实际上,有点类似于以下代码,但不完全相同,因为使用const不管在什么模式下,都会TypeError类型的错误

const foo = function () {
  foo = 10;
  console.log(foo)
}
(foo)() // Uncaught TypeError: Assignment to constant variable.

我的理解是,b函数是一个相当于用const定义的常量,内部无法进行重新赋值,如果在严格模式下,会报错"Uncaught TypeError: Assignment to constant variable."
例如下面的:

var b = 10;
(function b() {
  'use strict'
  b = 20;
  console.log(b)
})() // "Uncaught TypeError: Assignment to constant variable."

不知道我这回答有没有问题

常量的话没必要,这只是严格模式下为了规范代码,防止b被修改罢了。但是在非严格模式下,就是说可以修改的,不必当成常量。因为要考虑到具名函数声明的情况下,函数的名称在其所在的执行环境下,都是可以访问的,也是可修改的。

function test(){
  'use strict';
  function b(){
    console.log(23)
  }
  b=null;
  console.log(b)
}
test()
```js
函数如果是声明的话,那么在其声明所在的执行环境内,其函数名可做为一个执行环境的一个变量;如果是表达式的话,在其所声明的执行环境内,是不可访问的,只是单纯的作为一个函数名称,它的引用可通过name属性来获取它;在函数内部,除非被重新声明,它是指向自身的引用值。这个题中,是因为括号的存在,导致它变成了一个函数表达式,而不是一个函数声明。参见帖子:https://www.cnblogs.com/TomXu/archive/2011/12/29/2290308.html
所以console.log(b)中的b是函数自身的一个引用,对于全局变量来说,它是不可见的。

from daily-interview-question.

daiyunchao avatar daiyunchao commented on May 3, 2024

1打印结果内容如下:
ƒ b() {
b = 20;
console.log(b)
}
2原因:
作用域:执行上下文中包含作用于链:
在理解作用域链之前,先介绍一下作用域,作用域可以理解为执行上下文中申明的变量和作用的范围;包括块级作用域/函数作用域;
特性:声明提前:一个声明在函数体内都是可见的,函数声明优先于变量声明;
在非匿名自执行函数中,函数变量为只读状态无法修改;

只读状态为什么没报错呢?

from daily-interview-question.

ravencrown avatar ravencrown commented on May 3, 2024

var b = 10;
(function b() {
var b = 20;
console.log(b)
})()

为什么用了 var b = 20,输出变成20呢。不用var输出b()

from daily-interview-question.

AnaniZhu avatar AnaniZhu commented on May 3, 2024

@daiyunchao 严格模式下会报错

from daily-interview-question.

woshidamaomao avatar woshidamaomao commented on May 3, 2024

把()中IIFE函数执行过程这样理解试一下:

var b = function () {
  b = 20;
  console.log(b);
};

Object.defineProperty(window, "b", {
  writable: false,
  configurable: false
});

b();

An anonymous function that is called immediately is most often called an immediately invoked function expression (IIFE). It resembles a function declaration, but because it is enclosed in parentheses it is interpreted as a function expression.

这段话引用自:《javascript高级程序设计第4版》大概意思是立即执行函数,写法上看着像是个“函数声明” 实际上是按“函数表达式”解析的。

回过头来,我们看IIFE为什么要这样设计?

var b = 10;
(function b() {
  b = 20;
  console.log(b)
})()

这里的局部变量b(函数体b)我们外部能调用吗?
不能,该变量只能在函数体内部被访问,它代表命名空间函数本身。

我们没有理由去声明一个与命名空间函数名冲突的变量名,也没有理由更改这个变量,很显然这与命名空间的**冲突,我们应该保持该变量的纯净。

因此,这种“命名空间函数名”被作为常量的设计是合理的,建议使用新的变量名存储自己的变量。

至于具体是如何实现的,懂C的同学可以去扒一下v8的源码,臣妾真的是做不到了。

Note:其中不明白的术语,请自行Google

from daily-interview-question.

yygmind avatar yygmind commented on May 3, 2024
var b = 10;
(function b(){
    b = 20;
    console.log(b); 
})();

from daily-interview-question.

TheHtmler avatar TheHtmler commented on May 3, 2024

1打印结果内容如下:
ƒ b() {
b = 20;
console.log(b)
}
2原因:
作用域:执行上下文中包含作用于链:
在理解作用域链之前,先介绍一下作用域,作用域可以理解为执行上下文中申明的变量和作用的范围;包括块级作用域/函数作用域;
特性:声明提前:一个声明在函数体内都是可见的,函数声明优先于变量声明;
在非匿名自执行函数中,函数变量为只读状态无法修改;

我有个疑问,函数声明的确优于变量声明,但是却不优于变量赋值,所以我的疑问是跟优先级没有关系,不知对不对

from daily-interview-question.

lianglixiong avatar lianglixiong commented on May 3, 2024

image

from daily-interview-question.

Wluyao avatar Wluyao commented on May 3, 2024

1.IIFE中的函数是一个函数表达式,不是函数声明。

区分函数声明和表达式最简单的方法是看function关键字出现在声明中的位置(不仅仅是一行代码,而是整个声明中的位置)。如果function是声明中的第一个词,那么就是一个函数声明,否则就是一个函数表达式。比如这里的第一个词是"(",不是function,所有这里的函数是一个函数表达式。

2.函数声明中的的函数名被绑定在它声明所在的作用域中。函数表达式中的函数名被绑定在函数自身的函数体中。

在IIFE中的函数名不会污染外部作用域。

(function b() {
  console.log(b);
})()

这里函数名"b"只在函数内部有效,它是函数内部的局部变量。

3.在函数表达式的内部只能通过函数名访问该函数,但是不能通过函数名对该函数重新赋值

(function b() {
  b = 20;  // 无效
  console.log(b);
})()

from daily-interview-question.

fariellany avatar fariellany commented on May 3, 2024

1.IIFE中的函数是一个函数表达式,不是函数声明。

区分函数声明和表达式最简单的方法是看function关键字出现在声明中的位置(不仅仅是一行代码,而是整个声明中的位置)。如果function是声明中的第一个词,那么就是一个函数声明,否则就是一个函数表达式。比如这里的第一个词是"(",不是function,所有这里的函数是一个函数表达式。

2.函数声明中的的函数名被绑定在它声明所在的作用域中。函数表达式中的函数名被绑定在函数自身的函数体中。

在IIFE中的函数名不会污染外部作用域。

(function b() {
  console.log(b);
})()

这里函数名"b"只在函数内部有效,它是函数内部的局部变量。

3.在函数表达式的内部只能通过函数名访问该函数,但是不能通过函数名对该函数重新赋值

(function b() {
  b = 20;  // 无效
  console.log(b);
})()

你真棒棒。。。麽麽噠

from daily-interview-question.

soraly avatar soraly commented on May 3, 2024

下面的代码打印什么内容,为什么

var b = 10;
(function b(){
    b = 20;
    console.log(b); 
})();

输出函数体,原因:
IFFE中的函数是一个函数表达式,不是函数声明,类似于 const a = function(){} 常量绑定,
加入对一个常量进行赋值,非strict模式默认无效,strict模式报错,
所以a=20不会覆盖原有的函数名b,而是会在全局,也就是window下添加一个名为b的属性,值为20,
输出 function(){ xxx }

from daily-interview-question.

justsoup avatar justsoup commented on May 3, 2024

var fn1=function fn2(){ fn1=222; fn2=333; console.log(fn1); console.log(fn2); } fn1();
=>222
=>fn2()

var fn1=(function fn2(){ fn1=222; fn2=333; console.log(fn1); console.log(fn2); })()
=>222
=>fn2()

结果是一样的,跟立即执行没啥关系
因为这个fn2是定义在fn2.prototype.constructor对象中,属性名为name
console.log(fn2.prototype.constructor.name); => fn2
个人理解
fn2=333走的是作用域链
console.log(fn2)走的原型链

from daily-interview-question.

aeroxy avatar aeroxy commented on May 3, 2024

我可能搞错了,但是我觉得以下这个代码片段

    /* part 1 */
    function a() { 
        a = 1;
        console.log("a1:", a); 
    };
    /* part 2 */
    function a() { 
        a = 2;
        console.log("a1:", a); 
    };
    a();
    console.log("a2:", a);

证明了它和 Function.name 的 Writable 属性 是没有关系的

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/name

Function.name 只是一个 Function 的命名和它是否可以被赋值无关

同时,另外一种说法,也就是《命名函数》如 function a() {...} 内《和命名函数同名的变量》会优先指向命名函数本身

这种说法应该也是错误的,为什么呢,因为以上的代码打印的是 a1: 2, a2: 2 也就是说,不仅《命名函数》/* part 2 */ function a() {...} 内的 a 可以被修改,打印为2,实际上 window.a 也被修改了,最终打印为2

也就是说实际上只有单纯有《命名函数》,是不构成函数内《和命名函数同名的变量》会优先指向命名函数本身这个现象,而以上片段实际上应该相当于

    /* part 1 */
    var a = function () { 
        a = 1;
        console.log("a1:", a); 
    };
    /* part 2 */
    var a = function () { 
        a = 2;
        console.log("a1:", a); 
    };
    a();
    console.log("a2:", a);

那么我们发现只有在《自启动命名函数》或《被赋值的命名函数》,也就是:

    void function a() { ... }

    var a = function a() { ... }

时,函数的内部作用域中的 《和命名函数同名的变量》 a 才会优先指向《命名函数》本身

实际上无论哪种写法,都是需要该命名函数《不被挂载在window对象上》,换而言之,需要使得《和命名函数同名的变量》 a 才会优先指向《命名函数》本身,《命名函数》本身必须处于一种“流离失所”的状态

from daily-interview-question.

MrLeihe avatar MrLeihe commented on May 3, 2024

自执行函数会被编译成函数表达式,函数表达式的函数名所在的作用域为函数本身,且函数名是只读的,不可被重新赋值。

from daily-interview-question.

lei334453 avatar lei334453 commented on May 3, 2024

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

执行是这样执行的 在window环境下查找 函数执行 环境决定的预估跟左右查询变量有关系 但说不上问题出在哪里了

from daily-interview-question.

LeeRayno avatar LeeRayno commented on May 3, 2024

var b = 10; (function b() { b = 20; console.log(b); })();
具名自执行函数的变量为只读属性,不可修改

我记得你不知道的js里面有说这个,但是找不到在哪里了。

from daily-interview-question.

chxlvwh avatar chxlvwh commented on May 3, 2024

首先运行结果是打印 b 函数;
我觉得这个问题想要考察的是:一个是 IIFE 有独立的词法作用域,第二是b=20是将 b 定义为全局变量。
词法检查的结果为:

window: {
    b: 20,
    IIFE: {
        b: function b() {}
    }
}

在执行 IIFE 的时候,第一行 b = 20,会将b挂到window上,并不会在这个IIFE 的词法作用域内,所以最终打印的是 b 函数。
另外,如果把函数b 中的 b = 20 改成 var b = 20 那么结果就会打印20了。

from daily-interview-question.

 avatar commented on May 3, 2024

from daily-interview-question.

Yangfan2016 avatar Yangfan2016 commented on May 3, 2024

非匿名函数,函数名只在函数内有效,且不可赋值

from daily-interview-question.

 avatar commented on May 3, 2024

from daily-interview-question.

88wixi avatar 88wixi commented on May 3, 2024

var b = 10;
(function a() {
b = 20;
console.log(b)
})()
将立即执行函数的函数名该为不为b,要不然b=20,是将函数名b拿来赋值而
IIFE的函数无法进行赋值(内部机制,类似const定义的常量),所以无效。

from daily-interview-question.

JDongKhan avatar JDongKhan commented on May 3, 2024

js经过发展,搞出来很多概念,而这些概念有些又很绕人,在其他语言上压根不会存在,所以到底是简单了还是复杂了?

我的理解是b既然赋值了整数10,就不能再赋给其他类型。

from daily-interview-question.

adele-ty avatar adele-ty commented on May 3, 2024

这段代码会打印出函数本身,不会输出任何其他值。

在这段代码中,存在一个函数表达式 (function b() { ... }),并将其赋值给变量 b。这个函数表达式具有函数名 b,但函数名只在自执行函数内部有效,不会影响变量 b 的值。

在函数体内部,试图将函数名 b 赋值为 20。然而,由于函数名 b 在函数内部被视为只读的标识符,赋值操作将被忽略。这意味着函数名 b 的值仍然是指向该函数本身的引用。

from daily-interview-question.

hongyingxin avatar hongyingxin commented on May 3, 2024

这个代码片段是一个有趣的 JavaScript 例子,展示了函数表达式、变量作用域以及变量和函数名的优先级如何互相影响。让我们一步步解析这段代码:

var b = 10; 在全局作用域下声明了一个变量 b 并赋值为 10。

(function b() { ... })() 定义了一个匿名自执行函数(IIFE,立即调用的函数表达式),其函数名也被命名为 b。这里的函数名 b 只在函数体内部可见,它是函数的一个局部变量。

在这个自执行函数中,b = 20; 试图给 b 赋新值。然而,由于 b 在这个上下文中是一个命名函数(即函数本身),它是不可变的。你不能改变一个函数名称指向的函数体。因此,这个赋值操作实际上没有效果。

console.log(b); 打印出的是函数本身,而不是数字 20,这是因为在这个作用域内 b 引用的是这个名为 b 的函数,而不是全局作用域下的变量 b。

因此,这段代码的执行结果会是打印出函数 b 的代码体,而不是数字 20 或 10。这个例子很好地展示了 JavaScript 中作用域、变量提升和函数声明的复杂性。
ChatGpt4给的答案

from daily-interview-question.

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.