From 0ff9b66135adc904491bbd19a14327f59fe8e64d Mon Sep 17 00:00:00 2001 From: qianguyihao Date: Mon, 9 Dec 2019 20:28:14 +0800 Subject: [PATCH] =?UTF-8?q?add:=20=E9=A2=84=E7=BC=96=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 04-JavaScript基础/10-作用域.md | 75 +++++++++++-------- ...变量提升详解.md => 11-预编译及变量提升详解.md} | 64 ++++++++++++++-- 04-JavaScript基础/{11-this.md => 19-this.md} | 0 ...创建&构造函数.md => 20-对象的创建&构造函数.md} | 0 .../{13-原型对象.md => 21-原型对象.md} | 0 .../{14-数组简介.md => 22-数组简介.md} | 0 ...&数组的遍历.md => 23-数组的常见方法&数组的遍历.md} | 0 ...6-内置对象:Date.md => 24-内置对象:Date.md} | 0 ...7-内置对象:Math.md => 25-内置对象:Math.md} | 0 .../{18-包装类.md => 26-包装类.md} | 0 ...置对象:String.md => 27-内置对象:String.md} | 0 .../{20-正则表达式.md => 28-正则表达式.md} | 0 .../{21-事件简介.md => 29-事件简介.md} | 0 ...M简介和DOM操作.md => 30-DOM简介和DOM操作.md} | 0 ...行内样式.md => 31-通过style对象获取和设置行内样式.md} | 0 ...现).md => 32-offset相关属性和匀速动画(含轮播图的实现).md} | 0 ...和缓动动画.md => 33-scroll相关属性和缓动动画.md} | 0 ...)相关属性.md => 34-client(可视区)相关属性.md} | 0 ...件对象Event.md => 35-事件的绑定和事件对象Event.md} | 0 ...播和事件冒泡.md => 36-事件的传播和事件冒泡.md} | 0 .../{29-事件委托.md => 37-事件委托.md} | 0 .../{30-键盘事件.md => 38-键盘事件.md} | 0 ...M简介和navigator.userAgent&History&Location.md} | 0 .../{32-定时器.md => 40-定时器.md} | 0 24 files changed, 103 insertions(+), 36 deletions(-) rename 04-JavaScript基础/{10.2-预编译及变量提升详解.md => 11-预编译及变量提升详解.md} (60%) rename 04-JavaScript基础/{11-this.md => 19-this.md} (100%) rename 04-JavaScript基础/{12-对象的创建&构造函数.md => 20-对象的创建&构造函数.md} (100%) rename 04-JavaScript基础/{13-原型对象.md => 21-原型对象.md} (100%) rename 04-JavaScript基础/{14-数组简介.md => 22-数组简介.md} (100%) rename 04-JavaScript基础/{15-数组的常见方法&数组的遍历.md => 23-数组的常见方法&数组的遍历.md} (100%) rename 04-JavaScript基础/{16-内置对象:Date.md => 24-内置对象:Date.md} (100%) rename 04-JavaScript基础/{17-内置对象:Math.md => 25-内置对象:Math.md} (100%) rename 04-JavaScript基础/{18-包装类.md => 26-包装类.md} (100%) rename 04-JavaScript基础/{19-内置对象:String.md => 27-内置对象:String.md} (100%) rename 04-JavaScript基础/{20-正则表达式.md => 28-正则表达式.md} (100%) rename 04-JavaScript基础/{21-事件简介.md => 29-事件简介.md} (100%) rename 04-JavaScript基础/{22-DOM简介和DOM操作.md => 30-DOM简介和DOM操作.md} (100%) rename 04-JavaScript基础/{23-通过style对象获取和设置行内样式.md => 31-通过style对象获取和设置行内样式.md} (100%) rename 04-JavaScript基础/{24-offset相关属性和匀速动画(含轮播图的实现).md => 32-offset相关属性和匀速动画(含轮播图的实现).md} (100%) rename 04-JavaScript基础/{25-scroll相关属性和缓动动画.md => 33-scroll相关属性和缓动动画.md} (100%) rename 04-JavaScript基础/{26-client(可视区)相关属性.md => 34-client(可视区)相关属性.md} (100%) rename 04-JavaScript基础/{27-事件的绑定和事件对象Event.md => 35-事件的绑定和事件对象Event.md} (100%) rename 04-JavaScript基础/{28-事件的传播和事件冒泡.md => 36-事件的传播和事件冒泡.md} (100%) rename 04-JavaScript基础/{29-事件委托.md => 37-事件委托.md} (100%) rename 04-JavaScript基础/{30-键盘事件.md => 38-键盘事件.md} (100%) rename 04-JavaScript基础/{31-BOM简介和navigator.userAgent&History&Location.md => 39-BOM简介和navigator.userAgent&History&Location.md} (100%) rename 04-JavaScript基础/{32-定时器.md => 40-定时器.md} (100%) diff --git a/04-JavaScript基础/10-作用域.md b/04-JavaScript基础/10-作用域.md index 871aff8..71f516e 100644 --- a/04-JavaScript基础/10-作用域.md +++ b/04-JavaScript基础/10-作用域.md @@ -1,22 +1,54 @@ - > 作用域、变量提升的知识点,面试时会经常遇到。 ## 作用域(Scope)的概念 -作用域指一个变量的作用范围。在js中,一共有两种作用域: +作用域是一个变量或函数的作用范围。作用域在**函数定义**时,就已经确定了。 + +### 作用域的分类 + +在js中,一共有两种作用域: - 全局作用域 - 函数作用域 +在函数作用域中可以访问到全局作用域的变量,在全局作用域中无法访问到函数作用域的变量。 + +代码举例: + +```javascript +var a = 'aaa'; +function foo() { + var b = 'bbb'; + console.log(a); // 打印结果:aaa。说明 内层作用域 可以访问 外层作用域 里的变量 +} + +foo(); +console.log(b); // 报错:Uncaught ReferenceError: b is not defined。说明 外层作用域 无法访问 内层作用域 里的变量 +``` + +定义在全局作用域的变量,叫「全局变量」。 + +定义在函数作用域的变量,叫「局部变量」。 + +### 执行上下文 + +当**函数执行**时,会创建一个执行期上下文的内部对象。每调用一次函数,就会创建一个新的上下文对象,他们之间是相互独立的。当函数执行完毕,它所产生的执行期上下文会被销毁。参考链接: + +**作用域的上下级关系:** + +当在函数作用域操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用(**就近原则**)。如果没有则向上一级作用域中寻找,直到找到全局作用域;如果全局作用域中依然没有找到,则会报错 ReferenceError。 + +在函数中要访问全局变量可以使用window对象。(比如说,全局作用域和函数作用域都定义了变量a,如果想访问全局变量,可以使用`window.a`) + ## 全局作用域 直接编写在script标签中的JS代码,都在全局作用域。 - 全局作用域在页面打开时创建,在页面关闭时销毁。 -- 在全局作用域中有一个全局对象window,它代表的是一个浏览器的窗口,它由浏览器创建我们可以直接使用。 +- 在全局作用域中有一个全局对象window,它代表的是一个浏览器的窗口,由浏览器创建,我们可以直接使用。 在全局作用域中: @@ -38,7 +70,8 @@ ``` -打印结果:undefined。(既然没报错,说明变量 a 被 被提前声明了,只是尚未被赋值) +打印结果:undefined。注意,打印结果并没有报错,而是 undefined,说明变量 a 被提前声明了,只是尚未被赋值。 + 举例2: @@ -57,7 +90,7 @@ 使用`函数声明`的形式创建的函数`function foo(){}`,**会被声明提前**。 -也就是说,整个函数会在所有的代码执行之前就被**创建完成**,所以我们可以在函数声明之前,调用函数。 +也就是说,整个函数会在所有的代码执行之前就被**创建完成**。所以,在代码顺序里,我们可以先调用函数,再定义函数。 代码举例: @@ -74,37 +107,19 @@ 使用`函数表达式`创建的函数`var foo = function(){}`,**不会被声明提前**,所以不能在声明前调用。 -很好理解,因为此时foo被声明了,且为undefined,并没有把 `function(){}` 赋值给 foo。 +很好理解,因为此时foo被声明了(这里是变量声明),且为undefined,并没有把 `function(){}` 赋值给 foo。 所以说,下面的例子,会报错: ![](http://img.smyhvae.com/20180314_2145.png) -## 作用域 +## 函数作用域 -**作用域**:变量和函数生效的区域。作用域在**函数定义**时,就已经确定了。 +**提醒1**:在函数作用域中,也有声明提前的特性: -在函数作用域中可以访问到全局作用域的变量,在全局作用域中无法访问到函数作用域的变量。 +- 函数中,使用var关键字声明的变量,会在函数中所有的代码执行之前被声明 -**执行期上下文**:当**函数执行**时,会创建一个执行期上下文的内部对象。每调用一次函数,就会创建一个新的上下文对象,他们之间是相互独立的。当函数执行完毕,它所产生的执行期上下文会被销毁。参考链接: - - -**作用域的上下级关系:** - -当在函数作用域操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用(**就近原则**)。如果没有则向上一级作用域中寻找,直到找到全局作用域;如果全局作用域中依然没有找到,则会报错ReferenceError。 - -在函数中要访问全局变量可以使用window对象。(比如说,全局作用域和函数作用域都定义了变量a,如果想访问全局变量,可以使用`window.a`) - -**提醒1:** - -在函数作用域也有声明提前的特性: - -- 使用var关键字声明的变量,会在函数中所有的代码执行之前被声明 - -- 函数声明也会在函数中所有的代码执行之前执行 - - -因此,在函数中,没有var声明的变量都是**全局变量**,而且并不会提前声明。 +- 函数中,没有var声明的变量都是**全局变量**,而且并不会提前声明。 举例1: @@ -123,8 +138,7 @@ 上方代码中,foo()的打印结果是`1`。如果去掉第一行代码,打印结果是`Uncaught ReferenceError: a is not defined` - -**提醒2:**定义形参就相当于在函数作用域中声明了变量。 +**提醒2**:定义形参就相当于在函数作用域中声明了变量。 ```javascript function fun6(e) { // 这个函数中,因为有了形参 e,此时就相当于在函数内部的第一行代码里,写了 var e; @@ -135,7 +149,6 @@ fun6(123);//打印结果为123 ``` - ## 我的公众号 想学习**代码之外的技能**?不妨关注我的微信公众号:**千古壹号**(id:`qianguyihao`)。 diff --git a/04-JavaScript基础/10.2-预编译及变量提升详解.md b/04-JavaScript基础/11-预编译及变量提升详解.md similarity index 60% rename from 04-JavaScript基础/10.2-预编译及变量提升详解.md rename to 04-JavaScript基础/11-预编译及变量提升详解.md index 80515be..e953756 100644 --- a/04-JavaScript基础/10.2-预编译及变量提升详解.md +++ b/04-JavaScript基础/11-预编译及变量提升详解.md @@ -15,22 +15,21 @@ ### 两个规律 -**规律1:任何变量,如果未经声明就赋值,此变量是属于 window 的属性**。(注意,无论在哪个作用域内赋值) +**规律1:任何变量,如果未经声明就赋值,此变量是属于 window 的属性**,而且不会做变量提升。(注意,无论在哪个作用域内赋值) 比如说,如果我们直接在代码里写 `console.log(a)`,这肯定会报错的,提示找不到 `a`。但如果我直接写 `a = 100`,这就不会报错,此时,这个 `a` 就是 `window.a`。 -**规律2:一切声明的全局变量,全是window的属性**。(注意,我说的是在全局作用域内声明的变量,不是说局部变量) +**规律2:一切声明的全局变量,全是window的属性**。(注意,我说的是在全局作用域内声明的全局变量,不是说局部变量) 比如说,当我定义 `var a = 200` 时,这此时这个 `a` 就是 `window.a`。 -由此,我们可以看出:**window 代表了全局作用域**。 +由此,我们可以看出:**window 代表了全局作用域**(是说「代表」,没说「等于」)。 ### 举例 掌握了上面两句话之后,我们再来看看下面的例子。 ```javascript - function foo() { var a = b = 100; // 连续赋值 } @@ -38,6 +37,8 @@ function foo() { foo(); console.log(window.b); // 在全局范围内访问 b +console.log(b); // 在全局范围内访问 b,但是前面没有加 window 这个关键字 + console.log(window.a); // 在全局范围内访问 a console.log(a); // 在全局范围内访问 a,但是前面没有加 window 这个关键字 @@ -48,6 +49,8 @@ console.log(a); // 在全局范围内访问 a,但是前面没有加 window 这 ``` 100 +100 + undefined (会报错,提示 Uncaught ReferenceError: a is not defined) @@ -56,7 +59,7 @@ undefined **解释**: -`var a = b = 100` 这行**连续赋值**的代码等价于 `var a = (b = 100)`,其执行顺序是: +当执行了`foo()`函数之后, `var a = b = 100` 这行**连续赋值**的代码等价于 `var a = (b = 100)`,其执行顺序是: (1)先把 100 赋值给 b; @@ -66,6 +69,57 @@ undefined 我们可以看到,b 是未经声明的变量就被赋值了,此时,根据规律1,这个 b 是属于 `window.b`;而 a 的作用域仅限于 foo() 函数内部,不属于 window。所以也就有了这样的打印结果。 +## 预编译 + +### 函数预编译的步骤 + +> 函数预编译,发生在函数执行的前一刻。 + +(1)创建AO对象。AO即 Activation Object 活跃对象,其实就是「执行期上下文」。 + +(2)找形参和变量声明,将形参名和变量作为 AO 的属性名,值为undefined。 + +(3)将实参值和形参统一,实参的值赋给形参。 + +(4)查找函数声明,函数名作为 AO 对象的属性名,值为整个函数体。 + +这个地方比较难理解。但只有了解了函数的预编译,才能理解明白函数的执行顺序。 + +代码举例: + +```javascript +function fn(a) { + console.log(a); + + var a = 666; + + console.log(a); + + function a() {} + + console.log(a); + + var b = function() {}; + + console.log(b); + + function c() {} +} + +fn(1); +``` + +打印结果: + +``` +ƒ a() {} +666 +666 +ƒ () {} +``` + + + ## 参考链接 - JavaScript预编译原理分析: diff --git a/04-JavaScript基础/11-this.md b/04-JavaScript基础/19-this.md similarity index 100% rename from 04-JavaScript基础/11-this.md rename to 04-JavaScript基础/19-this.md diff --git a/04-JavaScript基础/12-对象的创建&构造函数.md b/04-JavaScript基础/20-对象的创建&构造函数.md similarity index 100% rename from 04-JavaScript基础/12-对象的创建&构造函数.md rename to 04-JavaScript基础/20-对象的创建&构造函数.md diff --git a/04-JavaScript基础/13-原型对象.md b/04-JavaScript基础/21-原型对象.md similarity index 100% rename from 04-JavaScript基础/13-原型对象.md rename to 04-JavaScript基础/21-原型对象.md diff --git a/04-JavaScript基础/14-数组简介.md b/04-JavaScript基础/22-数组简介.md similarity index 100% rename from 04-JavaScript基础/14-数组简介.md rename to 04-JavaScript基础/22-数组简介.md diff --git a/04-JavaScript基础/15-数组的常见方法&数组的遍历.md b/04-JavaScript基础/23-数组的常见方法&数组的遍历.md similarity index 100% rename from 04-JavaScript基础/15-数组的常见方法&数组的遍历.md rename to 04-JavaScript基础/23-数组的常见方法&数组的遍历.md diff --git a/04-JavaScript基础/16-内置对象:Date.md b/04-JavaScript基础/24-内置对象:Date.md similarity index 100% rename from 04-JavaScript基础/16-内置对象:Date.md rename to 04-JavaScript基础/24-内置对象:Date.md diff --git a/04-JavaScript基础/17-内置对象:Math.md b/04-JavaScript基础/25-内置对象:Math.md similarity index 100% rename from 04-JavaScript基础/17-内置对象:Math.md rename to 04-JavaScript基础/25-内置对象:Math.md diff --git a/04-JavaScript基础/18-包装类.md b/04-JavaScript基础/26-包装类.md similarity index 100% rename from 04-JavaScript基础/18-包装类.md rename to 04-JavaScript基础/26-包装类.md diff --git a/04-JavaScript基础/19-内置对象:String.md b/04-JavaScript基础/27-内置对象:String.md similarity index 100% rename from 04-JavaScript基础/19-内置对象:String.md rename to 04-JavaScript基础/27-内置对象:String.md diff --git a/04-JavaScript基础/20-正则表达式.md b/04-JavaScript基础/28-正则表达式.md similarity index 100% rename from 04-JavaScript基础/20-正则表达式.md rename to 04-JavaScript基础/28-正则表达式.md diff --git a/04-JavaScript基础/21-事件简介.md b/04-JavaScript基础/29-事件简介.md similarity index 100% rename from 04-JavaScript基础/21-事件简介.md rename to 04-JavaScript基础/29-事件简介.md diff --git a/04-JavaScript基础/22-DOM简介和DOM操作.md b/04-JavaScript基础/30-DOM简介和DOM操作.md similarity index 100% rename from 04-JavaScript基础/22-DOM简介和DOM操作.md rename to 04-JavaScript基础/30-DOM简介和DOM操作.md diff --git a/04-JavaScript基础/23-通过style对象获取和设置行内样式.md b/04-JavaScript基础/31-通过style对象获取和设置行内样式.md similarity index 100% rename from 04-JavaScript基础/23-通过style对象获取和设置行内样式.md rename to 04-JavaScript基础/31-通过style对象获取和设置行内样式.md diff --git a/04-JavaScript基础/24-offset相关属性和匀速动画(含轮播图的实现).md b/04-JavaScript基础/32-offset相关属性和匀速动画(含轮播图的实现).md similarity index 100% rename from 04-JavaScript基础/24-offset相关属性和匀速动画(含轮播图的实现).md rename to 04-JavaScript基础/32-offset相关属性和匀速动画(含轮播图的实现).md diff --git a/04-JavaScript基础/25-scroll相关属性和缓动动画.md b/04-JavaScript基础/33-scroll相关属性和缓动动画.md similarity index 100% rename from 04-JavaScript基础/25-scroll相关属性和缓动动画.md rename to 04-JavaScript基础/33-scroll相关属性和缓动动画.md diff --git a/04-JavaScript基础/26-client(可视区)相关属性.md b/04-JavaScript基础/34-client(可视区)相关属性.md similarity index 100% rename from 04-JavaScript基础/26-client(可视区)相关属性.md rename to 04-JavaScript基础/34-client(可视区)相关属性.md diff --git a/04-JavaScript基础/27-事件的绑定和事件对象Event.md b/04-JavaScript基础/35-事件的绑定和事件对象Event.md similarity index 100% rename from 04-JavaScript基础/27-事件的绑定和事件对象Event.md rename to 04-JavaScript基础/35-事件的绑定和事件对象Event.md diff --git a/04-JavaScript基础/28-事件的传播和事件冒泡.md b/04-JavaScript基础/36-事件的传播和事件冒泡.md similarity index 100% rename from 04-JavaScript基础/28-事件的传播和事件冒泡.md rename to 04-JavaScript基础/36-事件的传播和事件冒泡.md diff --git a/04-JavaScript基础/29-事件委托.md b/04-JavaScript基础/37-事件委托.md similarity index 100% rename from 04-JavaScript基础/29-事件委托.md rename to 04-JavaScript基础/37-事件委托.md diff --git a/04-JavaScript基础/30-键盘事件.md b/04-JavaScript基础/38-键盘事件.md similarity index 100% rename from 04-JavaScript基础/30-键盘事件.md rename to 04-JavaScript基础/38-键盘事件.md diff --git a/04-JavaScript基础/31-BOM简介和navigator.userAgent&History&Location.md b/04-JavaScript基础/39-BOM简介和navigator.userAgent&History&Location.md similarity index 100% rename from 04-JavaScript基础/31-BOM简介和navigator.userAgent&History&Location.md rename to 04-JavaScript基础/39-BOM简介和navigator.userAgent&History&Location.md diff --git a/04-JavaScript基础/32-定时器.md b/04-JavaScript基础/40-定时器.md similarity index 100% rename from 04-JavaScript基础/32-定时器.md rename to 04-JavaScript基础/40-定时器.md