第 33 题:下面的代码打印什么内容,为什么?

发布于 2022-07-16 11:41:05 字数 730 浏览 245 评论 43

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."

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(43

随梦而飞# 2022-05-04 13:57:12

@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 变量指的是函数表达式的函数名。试想一下:如果你在函数里面拿不到该函数的函数名,那你怎么进行递归?

绝情姑娘 2022-05-04 13:57:12

// 验证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,就会形成死循环,递归调用.所以这是一个执行环境的问题

梦里人 2022-05-04 13:57:12

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

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

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

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

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

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

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

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

苹果你个爱泡泡 2022-05-04 13:57:12

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

我不会写诗 2022-05-04 13:57:12

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

高速公鹿^ε^ 2022-05-04 13:57:12

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

何以心动→ 2022-05-04 13:57:12

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

冰魂雪魄 2022-05-04 13:57:12

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

瑾夏年华 2022-05-04 13:57:12
(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()
遥远的她 2022-05-04 13:57:12
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是函数自身的一个引用,对于全局变量来说,它是不可见的。
墨洒年华 2022-05-04 13:57:12

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

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

梦巷^ 2022-05-04 13:57:12

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

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

清风疏影 2022-05-04 13:57:12

@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 是函数表达式,而函数表达式的函数名是常量,无法二次赋值(在正常模式下静默失效,在严格模式下报错),赋值失败,所以输出的还是该函数

时间海 2022-05-04 13:57:12

@daiyunchao 严格模式下会报错

<逆流佳人身旁> 2022-05-04 13:57:12

把()中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

忆依然 2022-05-04 13:57:12
var b = 10;
(function b(){
    b = 20;
    console.log(b); 
})();
御弟哥哥 2022-05-04 13:57:12

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

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

今天小雨转甜 2022-05-04 13:57:12

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

var b = 10;
var c = function b () {
	b = 20;
	console.log(b);
}
c();
山色无中 2022-05-04 13:57:12

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

风月客 2022-05-04 13:57:12
  1. 非匿名自执行函数,函数名只读(类似常量)
  2. 非严格模式下给常量命名静默失败
  3. 严格模式下给常量命名报错 TypeError
纵山崖 2022-05-04 13:57:12

樱花坊 2022-05-04 13:57:12

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 
})();
无声静候 2022-05-04 13:57:12

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

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

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

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

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

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

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

(function b() {
  b = 20;  // 无效
  console.log(b);
})()
一个人的旅程 2022-05-04 13:57:12

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

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

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

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

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

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

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

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

你真棒棒。。。麽麽噠

调妓 2022-05-04 13:57:12

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

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

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

寻鱼水之欢 2022-05-04 13:57:12

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

    /* 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 才会优先指向《命名函数》本身,《命名函数》本身必须处于一种“流离失所”的状态

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

心是晴朗的。 2022-05-04 13:57:12

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

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

隱形的亼 2022-05-04 13:57:12

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

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

香橙ぽ 2022-05-04 13:57:12

首先运行结果是打印 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了。

碍人泪离人颜 2022-05-04 13:57:11

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

(function(counter){
	if (counter) {
		return;
	}
	return arguments.callee(1);
})()
陌生。 2022-05-04 13:57:06

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

智商已欠费 2022-05-04 13:57:05
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 的规范吗?

苏佲洛 2022-05-04 13:56:56

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

平生欢 2022-05-04 13:56:47

几个例子:

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 
})();
随风而去 2022-05-04 13:56:43

@jefferyE

@jessie-zly
这个上面有回答
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/A_re-introduction_to_JavaScript
里面说明一个潜在问题——既然匿名函数没有名字,那该怎么递归调用它呢?在这一点上,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是函数表达式,而不是函数声明,但发现是个具名函数了...

鸠魁 2022-05-04 13:56:28

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

猫九 2022-05-04 13:50:21

@jessie-zly
这个上面有回答
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/A_re-introduction_to_JavaScript
里面说明一个潜在问题——既然匿名函数没有名字,那该怎么递归调用它呢?在这一点上,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);

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

黄昏下泛黄的笔记 2022-05-04 13:44:30
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吗?

这样的小城市 2022-05-04 13:41:56
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 的规范吗?

允世 2022-05-04 12:11:56

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

怼怹恏 2022-05-03 19:09:09

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

~没有更多了~

关于作者

0 文章
0 评论
23 人气
更多

推荐作者

烙印

文章 0 评论 0

singlesman

文章 0 评论 0

独孤求败

文章 0 评论 0

晨钟暮鼓

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文