前言

JS基础对于我们前端开发的重要性不言而知~于是,我们都会选择去阅读一些书籍来充实自己。那当我们读完那些理论基础之后,你是否依旧迷茫,还是豁然开朗?

透过现象看本质!

我想:有了理论基础作为根据的时候,应该多去思考一些代码的结果来实践这些理论。
就比如解决bug一样,你总得先知道出现bug的原因,再根据原因去解决问题是一样的道理。

code案例

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

这段代码会输出什么呢?(ps:先别着急回答,好好思考一下)
乍一看,这段代码很简单,涉及到的内容是var function IIFE,好像也没什么问题。
这段代码的在严格模式下输出:TypeError: Assignment to constant variable
意思就是:类型错误:对常量变量的赋值
而在非严格模式下输出:

在前端领域混了这几年,总结了一套前端学习的精讲视频和学习路线,如果有对前端开发感兴趣的伙伴,不管你是想转行,或是大学生,还有工作中想提升自己能力的web前端党,欢迎大家的加入我的前端开发交流群:603985993 希望大家诚心交流!,与企业需求同步。好友都在里面学习交流,每天都会有大牛定时讲解前端技术!也可以关注我的微信公众号:【前端留学生】 每天更新最新技术文章干货。

输出分析

分析严格模式下的输出

如果由这个TypeError: Assignment to constant variable.做一个分析的话,那么意味着变量b是不可修改的!

那么现在的问题在于变量b是指外部用var声明的变量b呢,还是立即执行的具名函数b呢?

如果b是立即执行的具名函数名称,说实话我也不大确定它是否是可修改。(ps:大多数的js书籍中都没有明确指出立即执行函数表达式是否能重新赋值的问题)

但是我一定可以确定的是,如果b是指外部用var声明的,那么在此代码中它一定是可修改的。我们都知道用var声明的全局变量它在任何地方肯定是可以修改的,因为该变量处于作用域的最顶端。

所以在这里我想大胆做个假设:变量b是指立即执行的具名函数名称b~

做完这个假设,我想说:那意味着全局变量b在立即执行的具名函数b里访问不到吗?

其实不是的,全局变量b在立即执行的具名函数b是可被访问的,只不过因为具名函数b的内部作用域里也存在了一个用function声明的变量b,所以在代码执行的时候js引擎首先找到用function声明的变量b。正如书籍中讲到的作用域查询是通过从里到外向上查询。(ps:之前也顺手写了一篇关于作用域系列的文章:我是这样理解JavaScript中作用域,望能帮助大家~)

当然在非严格模式下,大家可以试着动手在立即执行的具名函数内部函数打印一下window.b,也可论证全局变量b在立即执行的具名函数b里可被访问! 代码如下:

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

到这里,理清楚了立即执行函数b的内部作用域机制,我的疑问又萌生了:为什么(function b(){}())这样的函数表达式就不能修改呢?

后来,我查阅了资料,明白了IIFE函数的内部机制~
我所理解的是:当遇到具名的函数表达式的时,会创建一个辅助的特定对象,将函数表达式的名称作为唯一的key,用来存储函数表达式的名称,然后添加到函数的作用域链中,该值只读,并且不可以被删除,所以不能对该值进行操作。

所以,在严格模式下,一个不可修改的常量被修改之后就会报TypeError: Assignment to constant variable.。

分析非严格模式的输出

在非严格模式下会静默失败,所以不报错。针对如上的分析之后,会输出立即执行的具名函数b本身。

code扩展

我将代码改写成:

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

那这段又会输出什么呢?

无论在非严格模式还是在严格模式下,这段代码都会输出10,也就是全局变量b的值~

写这段代码的本意并不是为了猜测结果而想的,我想表达的是:为什么立即执行具名函数b在外部是不可访问的?难道所有的表达式在外部都不可访问吗?

为了解决我的疑问,我通过如下函数foo1和foo2进行分析:

//片段1
var foo1 = function () {};
console.log(foo1);
//片段2
(function foo2(){})
console.log(foo2);

片段1是让一个匿名函数表达式赋值给变量foo1,然后该函数可以用foo1这个名称进行访问——foo1()。所以打印是一个函数。

片段2是一个函数表达式,但结果是Uncaught ReferenceError: foo2 is not defined。说明在外部是不可访问的。

可见,立即执行具名函数b是一个函数表达式,在外部是不可访问的!(ps:意味着函数表达式既不可能通过名称在函数声明之前调用它,也不可能在声明之后调用它)。

其实,大多数书籍里介绍以及我之前所理解的片段1这样的代码就是一个函数表达式。但现在我的理解并不是这样的~

foo1是一个变量,匿名函数表达式赋值给变量foo1了,所以foo1它可被访问!
通过自己写了2个代码片段,将我的疑惑迎刃而解了~

思考其他案例

在闲暇之余,我将最原始的代码块再做了改造,运用这些代码来温故并且思考了之前学习的理论基础。

如下的代码片段,我将结果也一并和大家揭晓,但我也会和大家分享一下我的心得~

片段1

var b = 10;
function b() {console.log(12);return 1;
}
console.log(b, b()); //10 TypeError: b is not a function

为什么会打印10呢,而不是函数b呢?

论据:函数声明优先于变量声明~

所以,相当于先利用function声明了函数b,再利用var重写了b。

//片段2
console.log(b, b()); //12 1
var b = 10;
function b() {console.log(12);return 1;
}

为什么会打印函数b的执行结果12和1呢,而不是全局变量b呢?

论据:函数声明优先于变量声明~并且在这个过程中存在变量提升。

片段3

var b = 10;
b = function() {b = 20;console.log(b); //20
return 1;
};
console.log(b, b()); //b函数,1

为什么会打印10呢,而不是函数b呢?

论据:这个过程就是将变量b进行重新赋值。

所以,打印的是10,而不是函数。

片段4

var b = 10;
//  Duplicate declaration "b"
let b = function() {b = 20;console.log(b);return 1;
};

论据:用var声明变量可以可重复声明,但是用let声明变量不可重复声明。

所以js引擎要执行完var b = 10语句之后,遇到了let b之前报错了。

总结

在写业务代码的时候,要尽量去避免声明变量命名冲突的情况,因为以上案例的的写法是不合理的,很容易出现意想不到的结果。
为何不规范要求自己而避开不必要的麻烦呢?
当然,我觉得在学习乏味难啃的理论基础知识时,我觉得应该创造自己的想象力,多去实践多去思考为什么会有这样的结果呢?
根据理论证实结果!
这样才会使得让自己更加理解理论基础,并且更好的运用它们,而不仅仅是背/记。

作者:lin1997 链接:https://juejin.cn/post/6906022950990774286 来源:掘金

如何学习-我是这样学JS理论![不看后悔篇]相关推荐

  1. Sun公司网站上的Swing实例,想学Swing的不看后悔

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 因为公司 ...

  2. 【数据竞赛】学特征工程就看这篇,解析IJCAI18亚军方案之特征工程

    1  搜索竞赛特征工程总结 很多搜索推荐的工业界大模型的特征工程核心可以分为用户侧,商品侧还有一些其他侧(一些i2i,u2i等的上游特征)三大类. 本篇文章,不考虑所有时间等因素,直接调研和搜索相关的 ...

  3. JAVA学习必须掌握的框架,不看后悔

    Web应用,最常见的研发语言是Java和PHP. 后端服务,最常见的研发语言是Java和C/C++. 大数据,最常见的研发语言是Java和Python. 可以说,Java是现阶段中国互联网公司中,覆盖 ...

  4. 学CSS选择器,看这篇文章就够了(近2万字详解)

  5. 北医专科计算机试题及答案,计算机考研怎么复习-病例题考的是同学们把所学的理论知识与临床实践相结合的能力-专业课学习...

    一.各科目备考指导 1.选课本复习资料 课本:选择最新的版本,最好是人民卫生出版社第七版教材 资料:贺银成的<西医综合辅导讲义>,北医"黄皮书",贺银成的同步训练,北医 ...

  6. JS学习笔记六:js中的DOM操作

    1. JS学习笔记六:js中的DOM操作 文章目录 1. JS学习笔记六:js中的DOM操作 1.1. 获取Dom节点 1.2. 元素属性的操作方式 1.3. DOM节点的创建.插入和删除 1.4. ...

  7. 嵌入式学习路线怎么学,如何学习嵌入式系统

    随着互联网的快速发展,嵌入式也越来越火热,更多的人投入到嵌入式开发的行列中来,那么想要学习嵌入式,该从哪里入手学习,嵌入式学习路线图怎么学? 想要学习好嵌入式,想成为嵌入式软件工程师.那么当前企业需要 ...

  8. 女生可以学计算机应用吗,我是女生 学计算机应用技术还是软体技术

    我是女生 学计算机应用技术还是软体技术以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 我是女生 学计算机应用技术还是软体 ...

  9. 吴恩达深度学习课程值不值得学?四晚学完的高手给你建议

    8 月 8 日,吴恩达发布了自己的深度学习在线课程,来自全球的 AI 爱好者再次围在这位人工智能专家身边,希望能从这门课里学到更多知识,正在看这篇文章的你或许也想报名参加,先别忙,有位大神花了四个晚上 ...

最新文章

  1. python用户名密码登录、错误三次结束_Python实现简单的用户登录信息确认,密码输错3次后,用户被锁定...
  2. Java Object中的clone方法
  3. leetcode-242-有效的字母异位词
  4. weblogic请求服务端超时后重发一次请求_记一次后端服务偶发502的排错之旅
  5. 揭秘苹果“地下黑工厂”:临时工薪资无保障,男厕所门口排长龙
  6. 阿里巴巴大规模稀疏模型训练/预测引擎 DeepRec 正式开源
  7. 【Python】字谜游戏
  8. 河南省周口市谷歌高清卫星地图下载
  9. 【小技巧】一种简单的办法在verilog中处理小数运算
  10. 京沪高铁上火车位置的实时监视模拟网站的开发
  11. Cocos2dx游戏开发系列笔记7:一个简单的跑酷游戏《萝莉快跑》的消化(附下载)...
  12. 浅谈互联网赚钱的几种方式
  13. 引用wps进行word转pdf操作
  14. 特斯拉电动汽车售价将平均上调3% 不包括3.5万美元版Model 3
  15. 【JavaScript】 对象 Object
  16. 数据结构通讯录查询系统
  17. Android zxing,轻松实现二维码扫描、生成
  18. 32.768KHz晶振的使用心得
  19. Kali入侵Windows主机
  20. Dr.Elephant简介

热门文章

  1. python图像边缘检测_使用python获取图像中形状的轮廓(x,y)坐标
  2. php文章管理系统_PHP-小程序:(1)开发环境搭建
  3. 从零开始的linux 第五章
  4. 绕过COM,一个巧妙的思路
  5. Java实现一个字符串的反转
  6. 关于c++中运算符的总结
  7. 实验楼第三次实验报告
  8. bzoj 4010: [HNOI2015]菜肴制作 拓扑排序
  9. 大道至简,职场上做人做事做管理(From Jimmy Zhang)
  10. NET2.0配置文件加密(WEBWindows)