【JS 之我不知道系列】ES6 声明变量的方式开始

js 我不知道的东西太特么多了,基础不扎实,因此这系列是在日常学习中看到的知识点然后自己作不同的尝试去扩展与填充自己知识空白部分

从 ES6 声明变量的方式开始


声明变量这个东西必须用,但真的了解多少?

未声明变量

当我直接输出一个未声明的变量 myname 是会报一个未捕获的错误 Uncaught ReferenceError: myname is not defined

var log = '能够执行到这里?';
console.log(myname); // Uncaught ReferenceError: myname is not defined
console.log(log); // 上行代码报错后此行及之后的代码不会继续执行
未捕获的错误

捕获异常

为了不影响后续代码执行,我们需要用 try catch 来捕获错误,

// var 的变量提升
var log = '能够执行到这里?'

try {
    console.log(myname);
    alert('不会执行') // 上行代码捕获到异常后此行代码也不会执行
} catch (e) {
    console.log(e); // 日志输出
    console.warn(e); // 警告黄色输出
    console.error(e); // 错误红色输出
    console.table(e); // 表格的方式输出,包含了错误在文件中第几行第几列
}
console.log(log); // 能够执行到这里? 由于捕获了异常所以可以执行这行代码

这里正好用控制台的 4 个 api 来输出错误信息

控制台的 4 个 api 来输出错误信息

这里你会看到 try catch 后的两点变化

  • 代码能继续执行
  • 未捕获的错误 Uncaught ReferenceError 已经变成 ReferenceError

这里有个小插曲,为什么变量要用 myname 而不是 name,因为 name 是 window 的一个内置属性,值为空字符串,所以在未声明 name 的前访问是不会报错,但未声明 myName 则胡报错

console.log(name); // ''
console.log(myName); // Uncaught ReferenceError: myName is not defined

代码地址 git repo
commit 5c9642bfdfdc73be20543b8c39bddd58ce308bec


var 声明变量

  • 变量提升
  • 可重复声明并赋值
// var 声明变量
console.log(log); // var 声明的变量会变量提升,因此这里不会报错而是输出默认值 undefined
var log = '存在'
console.log(log); // 存在
var log = "已成功改变"; // 可重复声明 var,不会报错
console.log(log); // 已成功改变
var log; // 不赋值不改变值
console.log(log); // 已成功改变

let 声明变量

  • 变量不会提升
  • 不可重复声明并赋值
// var 声明变量
console.log(log); // var 声明的变量会变量提升,因此这里不会报错而是输出默认值 undefined
var log = '存在'
console.log(log); // 存在
var log = "已成功改变"; // 可重复声明 var,不会报错
console.log(log); // 已成功改变
var log; // 不赋值不改变值
console.log(log); // 已成功改变

// let 声明变量
console.log(log1); // 不能在用 let 声明变量前访问 Uncaught ReferenceError: Cannot access 'log1' before initialization,let 声明的变量不存在提升
let log1 = 'let 声明的变量'; 

let log = '修改 var 变量的值'; // 不可重复声明 var 或 let 声明过的变量 Uncaught SyntaxError: Identifier 'log' has already been declared, SyntaxError 会导致整个程序不运行

// 无论是 var 还是 let 声明过的变量,都不能重复声明
let log1 = '重新赋值'; // Uncaught SyntaxError: Identifier 'log1' has already been declared
let log = '重新赋值'; // Uncaught SyntaxError: Identifier 'log' has already been declared

进入语法分析时:

  • 如果语法错误SyntaxError,则整个程序不会运行;
  • 如果引用错误ReferenceError,只会导致错误后面的代码无法执行;

代码地址 git repo
commit f75661ecbff1687aa05df88ed06961a22d309d21


作用域

  • js 里面只有全局作用域函数作用域,没有局部作用域
  • js 运行会有一个预解析过程,解析后会有一个语法树,再进入执行阶段
if (false) {
    var log = "能否输出?"
}
console.log(log); // undefined 这里会有一个预解析(解析后会有一个语法树,再进入执行阶段)的过程,var 声明的变量会在执行前将变量提升到作用域上

if (false) {
    let log1 = "能否输出?" // let 声明的变量只存在离他最近的大括号内
}
console.log(log1); // Uncaught ReferenceError: log1 is not defined,即使是 true log1 这行还是会报错
  • for 循坏
    • var 声明的变量没有局部作用域,因此控制台可以输出最后计算的值
    • let 声明的变量在 for 循环中使用是存在局部作用域(离他最近的大括号内),因此这里不会覆盖 var 声明的 i,也不会出现重复声明 i
// var 声明的变量没有局部作用域,因此控制台可以输出最后计算的值
for (var i = 0; i < 3; i++) {}
console.log(i); // 3

// let 声明的变量在 for 循环中使用是存在局部作用域(离他最近的大括号内),因此这里不会覆盖 var 声明的 i,也不会出现重复声明 i
for (let i = 0; i < 5; i++) {
    console.log(i); // 1, 2, 3, 4, 5,这里输出的是 let 里的 i
}
console.log(i); // 3 这里输出的 i 是 var 声明的 i
  • 闭包
    • 使用 var 声明 for 循环的初始变量 j,最终 j 点击按钮的时候会输出计算后的最终值
    • 使用 let 声明 for 循环的初始变量 j,由于存在块级别作用域,会将 j 的值锁死在当前作用域内,因此点击会输出对应的 j 值
// 使用 var 声明 for 循环的初始变量 j,最终 j 点击按钮的时候会输出计算后的最终值
for (var j = 0; j < 2; j++) {
    document.querySelector('#var').addEventListener('click', () => console.log(j))
}
// var 声明的也可使用闭包解决没全局作用域的问题
for (var k = 0; k < 2; k++) {
    (function(param){
        document.querySelector('#closure').addEventListener('click', () => console.log(param))
    })(k)
}
// 使用 let 声明 for 循环的初始变量 j,由于存在块级别作用域,会将 j 的值锁死在当前作用域内,因此点击会输出对应的 j 值
// let 的写法明显优雅与闭包,但 let 声明变量性能会稍逊于 var,因为编译时会自动生成闭包
for (let j = 0; j < 2; j++) {
    document.querySelector('#let').addEventListener('click', () => console.log(j))
}

let 的写法明显优雅与闭包,但 let 声明变量性能会稍逊于 var,因为编译时会自动生成闭包

代码地址 git repo
commit 3e68005f3f08cdc5249be9c1ebeff82e95bf23ea


const 声明常量

js 一直以来都没有常量这个概念,es6 加入了常量,让使用 const 声明的常量变量不能重新赋值,多用于引入模块保存到常量

// 常量
const log = '常量会被改变吗?';
log = '不会'; // Uncaught TypeError: Assignment to constant variable.
console.log(log);

代码地址 git repo
commit e6dbf861265b7b2901e1acd97fa1fdd1cbdbce2b

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,165评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,720评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,849评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,245评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,596评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,747评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,977评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,708评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,448评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,657评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,141评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,493评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,153评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,890评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,799评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,685评论 2 272

推荐阅读更多精彩内容