问题重现:一段让人困惑的代码
起因是我最近在回顾JavaScript基础,恰巧早一段时间看到了函数这一章节,今天打算整理一下笔记,因为B站up主讲的太过于浅显,我就翻看了一下《犀牛书-JavaScript权威指南》
,看到函数声明那一节的时候,我看到了箭头函数有一个特性:箭头函数,他们从定义自己的环境继承上下文,而不是像以其他方式定义的函数那样定义自己的调用上下文。 又加上昨天天和兄弟们在群里讨论了this指向的问题,就突发奇想写下了下面的代码:
js
'use strict'
const name = 'bkk';
const f = () => { console.log(this.name) };
function f1() { console.log(this.name); };
f();
f1();
我预想的是第一个输出:'bkk'
,第二个直接报错,但实际结果是第一个输出:''
,第二个直接报错了
为什么我不是想着两个都输出'bkk'
?
因为,在严格模式 下,全局作用域的 this
是 undefined
,但浏览器环境会特殊处理:
箭头函数内部的 this
被替换为全局对象 window
(这是历史遗留行为)
- 当箭头函数在 全局作用域 定义时,它的外层
this
本该是严格模式下的undefined
,但浏览器却强制让它指向了window
。 - ECMAScript 规范 没有明确禁止这种行为:规范规定箭头函数继承外层
this
,但未严格定义全局作用域this
的继承逻辑 [ECMA-262 §14.2.16]。
为什么不如我所料呢?
-
let/const 与 var 的本质区别 :
const name = 'bkk'
存在于模块作用域(或脚本作用域),但:- 不会成为
window
的属性 - 不会覆盖
window.name
- 不会成为
-
window.name
的默认值 :浏览器中
window.name
是一个内置属性,默认值为空字符串 `''
总结:
现象 | 原因 |
---|---|
f() 输出空字符串 |
箭头函数 this →window + window.name 默认存在且为 '' |
f1() 报错 |
严格模式下普通函数 this →undefined ,访问属性报错 |
const name 不生效 |
let/const 声明的全局变量不与 window 绑定 |
**注意:
**在node环境下,全局对象为global,global.name = undefined
如何正确输出?
js
'use strict'
const name = 'bkk';
const f = () => { console.log(name) };
function f1() { console.log(name); };
f();
f1();