Introduction
JavaScript is a full-stack language. Especially in 2016, we often hear rumors that JavaScript will dominate the world, and there are even rumors. It is said that you can find a job if you know Vue.js in 2016, just like you can find a job if you know TableView on iOS back then. (tableView is equivalent to Android's ListView, but now RecyclerView is basically used)
2016 The popular front-end technologies are basically related to JavaScript, such as the mobile cross-platform React Native produced by Facebook and Alibaba’s Weex, the hot repair technology JSPath, and the back-end Node.js (a technology stack I like very much). Yesterday I went to gibhub later and took a look. The number of stars in Vue has exceeded that of jQuery. Although the number of stars does not prove anything, at least we have seen that the front-end thinking has changed from the previous document operation to data-driven development (if you are interested) I can combine Android, iOS, and Vue later to use a small demo to demonstrate this change in thinking). Some companies have even begun to try to replace EasyUI with Element produced by Ele.me (students who have done back-end work should know that EasyUI is really an AV painting Quality...)
JS technology emerges in endlessly. There was a very popular article before. What was it like to learn JS in 2016? It scared many people. Everyone paid attention to it. When it comes to frameworks and new technologies, native JS has been left out, so I would like to share some basic JS issues with everyone
##Scope in JavaScript
<script> var str1 = "hello"; var str2 = "world"; function t1() { console.log(str1); console.log(str2); var str2 = "toby"; console.log(str2); } //这里会输出什么? t1(); </script>
##lexical analysis
To know what is happening, you must know why, so let’s look at a few more examples
<script>
function t(userName) {
console.log(userName);//这里输出什么?
function userName() {
console.log('tom');
}
}
t('toby');
</script>
function userName() { console.log('tom'); }
Why Is it a function? In fact, this kind of scope problem can be obtained through a "set of formulas". This formula is the lexical analysis in JS. One of the tasks that must be done before the function in JS is executed is the lexical analysis. So what exactly is needed? Analyze parameters, analyze variable declarations, and analyze function declarations. Then we will use this question to apply the formula
When t('toby') is executed, two stages will begin. , one is the analysis stage. After the analysis, it goes to the execution stage
Analysis stage:● When the function runs, an Active Object object (hereinafter referred to as the AO object) will be generated ), all variables that can be found in a function scope are on AO. At this time, the code is expressed as: t.AO = {}
● Analysis parameters: Receive parameters, use parameter names as attributes, parameters The value is the attribute value. Because there are no parameters, the analysis result is expressed in code: t.AO = {userName : toby}
● Analysis of var statement: There is no var statement in the t function, skip
● Analyze function declaration: This function declaration has a characteristic. If there is an attribute with the same name as the function name on the AO, it will be overwritten by this function. Because the function is also a type of variable in the JS field, it is expressed in code as : t.AO = { userName : function userName() {console.log('tom');}}
Execution phase:Execute t('toby '), when console.log(userName) is executed, t.AO.userName is called, so the final output result is function userName() {console.log('tom');}
Example 2<script>
function t(userName) {
console.log(userName);//这里输出什么?
var userName = function () {
console.log('tom');
}
}
t('toby');
</script>
Before the analysis, we must first understand two concepts, one is called function declaration, and the other is called function expression
//这个叫函数声明 function userName() { console.log('tom'); } //这个叫函数表达式 var userName = function () { console.log('tom'); }
Analysis stage:
● Create AO object, t.AO = {}
● Analysis parameters: t.AO = {userName : toby}
● 分析var声明: 在AO上,形成一个属性,以var的变量名为属性名,值为undefined,(因为是先分析,后执行,这只是词法分析阶段,并不是执行阶段,分析阶段值都是undefined,如果执行阶段有赋值操作,那值会按照正常赋值改变),也就是说代码应该表示为:t.AO = {userName : undefined},但是还有另外一个原则,那就是如果AO有已经有同名属性,则不影响(也就是什么事都不做),由于分析参数时,AO上已经有userName这个属性了,所以按照这个原则,此时什么事都不做,也就是说,此时按照分析参数时的结果t.AO = {userName : toby}
● 分析函数声明: 此时没有函数声明,略过
执行阶段:
调用t.AO.userName,所以,最后的输出结果是toby
例子3
<script> t(); t2(); function t() { console.log('toby');//这里会输出什么? } var t2 = function () { console.log('hello toby');//这里会输出什么? }; </script>
那么我们再来看一个例子,这下彻底回到高中时代,做了两个例子好像感觉掌握了,结果考试你给来看这个?
答案是,t()输出为toby,t2()则会报错.这又是为什么?
● t()可以调用是因为在词法分析的过程,就已经完成了t函数的分析,所以可以调用
● t2()不能调用是因为在词法分析的阶段,分析到有一个t2声明,在AO上只是形成了一个属性,但是值为undefined
例子4
<script> function t(userName) { console.log(userName);//这里输出什么? function userName() { console.log(userName);//这里输出什么? } userName(); } t('toby'); </script>
函数里面套函数,这次竟然又和前面不一样了...这次我不说答案了,直接先套公式走一波
t('toby')的分析和执行阶段
分析阶段:
● 创建AO对象,t.AO = {}
● 分析参数: t.AO = {userName : toby}
● 分析var声明: 有同名属性,不做任何事,还是t.AO = {userName : toby}
● 分析函数声明: 有同名属性,覆盖: t.AO = {userName : function userName() {console.log(userName);}}
执行阶段: t.AO.userName 输出为function userName() {console.log(userName);}}
userName()的分析和执行阶段
这里也要搞清楚两个概念
//执行userName()分析的是 function () { console.log(userName); }; //而不是 var userName = function () { console.log(userName); };
分析阶段:
● 创建AO对象,userName.AO = {}
● 分析参数: 无,略过
● 分析var声明: 无,略过
● 分析函数声明: 无,略过
执行阶段: 因为此时userName.AO = {}是个空对象,无法执行userName.AO.userName,所以会向上一层找,所以输出t.AO.userName的结果,也就是function userName() {console.log(userName);}}
例子5
<script> function t(userName) { console.log(userName);//这里输出什么? var userName = function () { console.log(userName);//这里输出什么? } userName(); } t('toby'); </script>
好吧,我保证这个是最后一道...这个输出结果是什么呢?我们只要坚定公式没问题,就一定能得出结果,那么再套公式走一波
t('toby')的分析和执行阶段
分析阶段:
● 创建AO对象,t.AO = {}
● 分析参数: t.AO = {userName : toby}
● 分析var声明: 有同名属性,不做任何事,还是t.AO = {userName : toby}
● 分析函数声明: 无,略过
执行阶段: 执行console.log(userName);时调用t.AO.userName 输出为toby,执行完后,代码继续往下执行,那么就到了进行var的赋值操作(var的分析和执行的区别看例子2中我有解释),此时t.AO = {userName : function() {console.log(userName);}},代码继续往下执行,接着就执行到了userName()
userName()的分析和执行阶段
分析阶段:
● 创建AO对象,userName.AO = {}
● 分析参数: 无,略过
● 分析var声明: 无,略过
● 分析函数声明: 无,略过
执行阶段: 按照例子4我们知道userName.AO是个空对象,所以会往上调用t.AO.userName,所以输出为:function () {console.log(userName);}
总结
JavaScript作用域会先在自己的AO上找,找不到就到父函数的AO上找,再找不到再找上一层的AO,直到找到window.这样就形成一条链,这条AO链就是JavaScript中的作用域链.