var 和 function造成混乱原因有:
globalThis、允许重复声明等function 的影响var 声明的变量var 变量提升:
undefinedglobalThis:到了 var 语句才会挂载,相当于 globalThis.a = a
// 'use strict'
// 严格模式无影响
console.log(globalThis.a)
console.log(a)
{
console.log(globalThis.a)
console.log(a)
var a = 1
console.log(globalThis.a)
console.log(a)
}
console.log(globalThis.a)
console.log(a)
// ------------- 相当于 -------------
var a // !!! var 变量声明提升
console.log(globalThis.a) // undefined
console.log(a) // undefined
{ // !!! 无视块级作用域
console.log(globalThis.a) // undefined
console.log(a) // undefined
a = 1 // !!! 赋值不提升
globalThis.a = a // !!! 浏览器在全局作用域下会挂载到 globalThis;Node.js 不会
console.log(globalThis.a) // 浏览器: 1; Node.js: undefined
console.log(a) // 1
}
console.log(globalThis.a) // 浏览器: 1; Node.js: undefined
console.log(a) // 1
// 'use strict'
// 严格模式无影响
;(function () {
console.log(globalThis.a)
console.log(a)
{
console.log(globalThis.a)
console.log(a)
var a = 1
console.log(globalThis.a)
console.log(a)
}
console.log(globalThis.a)
console.log(a)
})()
console.log(globalThis.a)
console.log(a)
// ------------- 相当于 -------------
;(function () {
var a // !!! var 变量声明提升
console.log(globalThis.a) // undefined
console.log(a) // undefined
{ // !!! 无视块级作用域
console.log(globalThis.a) // undefined
console.log(a) // undefined
a = 1 // !!! 赋值不提升
// !!! 浏览器和 Node.js 在函数作用域下都不会挂载到 globalThis
console.log(globalThis.a) // undefined
console.log(a) // 1
}
console.log(globalThis.a) // undefined
console.log(a) // 1
})()
console.log(globalThis.a) // undefined
console.log(a) // ReferenceError: a is not defined
undefinedglobalThis:到了 function 语句才会挂载,相当于 globalThis.a = a
// 'use strict'
console.log(globalThis.a)
console.log(a)
{
console.log(globalThis.a)
console.log(a)
function a() {}
// do something
function a() { 1 }
console.log(globalThis.a)
console.log(a)
}
console.log(globalThis.a)
console.log(a)
// ------------- 相当于 -------------
var a // !!! 非严格模式:函数声明提升到全局作用域或函数作用域
console.log(globalThis.a) // undefined
console.log(a) // undefined
{
块内a = function a() {} // !!! 非严格模式:函数赋值提升到最近的块级作用域
块内a = function a() { 1 } // !!! 重复声明
console.log(globalThis.a) // undefined
console.log(a) // [Function: a{1}]
全局a = 块内a
globalThis.a = a // !!! 非严格模式:浏览器在全局作用域下挂载到 globalThis; Node.js 不会
// do something
全局a = 块内a
globalThis.a = a // !!! 遇到 function 或 var 就会判断是否需要挂载:是否全局作用域、是否严格模式、浏览器环境
console.log(globalThis.a) // 浏览器: [Function: a{1}], Node.js: undefined
console.log(a) // [Function: a{1}]
}
console.log(globalThis.a) // 浏览器: [Function: a{1}], Node.js: undefined
console.log(a) // [Function: a{1}]
'use strict'
console.log(globalThis.a)
console.log(a)
{
console.log(globalThis.a)
console.log(a)
function a() {}
console.log(globalThis.a)
console.log(a)
}
console.log(globalThis.a)
console.log(a)
// ------------- 相当于 -------------
'use strict'
console.log(globalThis.a) // undefined
console.log(a) // ReferenceError: a is not defined
{
function a() {} // !!! 严格模式:函数声明和赋值都提升到最近的块级作用域
console.log(globalThis.a) // undefined
console.log(a) // [Function: a]
// !!! 严格模式:浏览器和 Node.js 在全局作用域下都不挂载到 globalThis
console.log(globalThis.a) // undefined
console.log(a) // [Function: a]
}
console.log(globalThis.a) // undefined
// !!! 严格模式:函数有块级作用域
console.log(a) // ReferenceError: a is not defined
globalThis.a = 1,即:在函数作用域下也会挂载到 globalThisvar a = 1,而是 globalThis.a = 1'use strict'
// !!! 严格模式不修正,访问未声明变量直接报错
a = 1 // ReferenceError: a is not defined
// 'use strict'
console.log(globalThis.a) // undefined
console.log(a) // ReferenceError: a is not defined
{
console.log(globalThis.a) // undefined
console.log(a) // ReferenceError: a is not defined
a = 1 // !!! 修正为 globalThis.a = 1
console.log(globalThis.a) // 1
// !!! 相当于省略了 globalThis.
console.log(a) // 1
}
console.log(globalThis.a) // 1
// !!! 相当于省略了 globalThis.
console.log(a) // 1
// 'use strict'
console.log(globalThis.a)
console.log(a)
{
console.log(globalThis.a)
console.log(a)
a = 1
console.log(globalThis.a)
console.log(a)
function a() {}
console.log(globalThis.a)
console.log(a)
}
console.log(globalThis.a)
console.log(a)
// ------------- 相当于 -------------
var a // !!! 函数声明提升
console.log(globalThis.a) // undefined
console.log(a) // undefined
{
块内a = function a() {} // !!! 函数赋值提升
console.log(globalThis.a) // undefined
console.log(a) // [Function: a]
块内a = 1 // !!! 这里的 a 已经声明过了,而不是未声明而直接赋值
console.log(globalThis.a) // undefined
console.log(a) // 1
全局a = 块内a
globalThis.a = a // !!! 判断是否需要挂载
console.log(globalThis.a) // 浏览器: 1, Node.js: undefined
console.log(a) // 1
}
console.log(globalThis.a) // 浏览器: 1, Node.js: undefined
console.log(a) // 1
// 'use strict'
console.log(globalThis.a)
console.log(a)
{
console.log(globalThis.a)
console.log(a)
function a() {}
console.log(globalThis.a)
console.log(a)
a = 1
console.log(globalThis.a)
console.log(a)
}
console.log(globalThis.a)
console.log(a)
// ------------- 相当于 -------------
var a // !!! 函数声明提升
console.log(globalThis.a) // undefined
console.log(a) // undefined
{
块内a = function a() {} // !!! 函数赋值提升
console.log(globalThis.a) // undefined
console.log(a) // [Function: a]
全局a = 块内a
globalThis.a = a // !!! 判断是否需要挂载
console.log(globalThis.a) // 浏览器: [Function: a], Node.js: undefined
console.log(a) // [Function: a]
块内a = 1 // !!! 这里的 a 已经声明过了,而不是未声明而直接赋值
console.log(globalThis.a) // 浏览器: [Function: a], Node.js: undefined
console.log(a) // 1
}
console.log(globalThis.a) // 浏览器: [Function: a], Node.js: undefined
console.log(a) // [Function: a]
// 'use strict'
console.log(globalThis.a)
console.log(a)
{
console.log(globalThis.a)
console.log(a)
function a() {}
console.log(globalThis.a)
console.log(a)
a = 1
function a() { 1 }
console.log(globalThis.a)
console.log(a)
console.log(globalThis.a)
console.log(a)
}
console.log(globalThis.a)
console.log(a)
// ------------- 相当于 -------------
var a // !!! 函数声明提升
console.log(globalThis.a) // undefined
console.log(a) // undefined
{
块内a = function a() {}
块内a = function a() { 1 } // !!! 函数赋值提升
console.log(globalThis.a) // undefined
console.log(a) // [Function: a{1}]
全局a = 块内a
globalThis.a = a // !!! 判断是否需要挂载
console.log(globalThis.a) // 浏览器: [Function: a{1}], Node.js: undefined
console.log(a) // [Function: a{1}]
块内a = 1 // !!! 这里的 a 已经声明过了,而不是未声明而直接赋值
全局a = 块内a
globalThis.a = a // !!! 判断是否需要挂载
console.log(globalThis.a) // 浏览器: 1, Node.js: undefined
console.log(a) // 1
console.log(globalThis.a) // 浏览器: 1, Node.js: undefined
console.log(a) // 1
}
console.log(globalThis.a) // 浏览器: 1, Node.js: undefined
console.log(a) // 1
let、const、classReferenceError: Cannot access 'a' before initializationglobalThislet、class:可以const:
TypeError: Assignment to constant variable.SyntaxError: Missing initializer in const declaration
使用 let、const、class 关键字声明变量时,这些变量会被提升到它们所在的作用域的顶部,这就是变量提升 (Hoisting)
但是,与 var 不同,声明的变量在声明之前是不可访问的。如果试图在声明之前访问这些变量,JavaScript 会抛出一个错误。这个从块的开始到变量声明位置之间的区域,就被称为“暂时性死区”(Temporal Dead Zone,TDZ)
与 function 函数的区别:
this 指向定义环境上下文argumentsGenerator 函数|GeneratorFunction]]箭头函数是“纯”函数,function 是函数 + 构造器
let,声明常量使用 const,不要使用 varclassfunction 仍可以使用,因为箭头函数只能先声明后使用,而 function 有函数提升且严格模式支持块级作用域