js中變量的處理機制,你是否想了解下,想的話上車!!!
在聊到變量提升的時候,我們先聊下`LHS`和`RHS`
## 1、`LHS`、`RHS`
>`javascript`中兩種查找類型,含義是賦值操作的左側和右側
* `LHS`: 對那個賦值對那個進行`LHS`引用,可以理解為賦值操作的目標 如:`a = 2`,如果找不到在非嚴格模式會聲明一個全局變量
* `RHS`: 需要獲取那個變量的值,就對哪個變量進行`RHS`引用,理解為賦值操作的源頭,如果找不到對應的標識符,就會拋出異常:`ReferenceError`
**簡單的講:賦值就是`LHS`,找值就是`RHS`**
來個例子分析分析:
```
function foo(a) {
var b = a;
return b + a;
}
var c= foo()
```
以上代碼有3個`LHS`和4個`RHS`,分析如下:
* 1、`var c`中需要被賦值,在賦值操作的左側,所以對c進行`LHS`引用
* 2、變量`c`需要被賦值,它的值是`foo(2)`,那么`foo(2)`的值是多少呢?,需要查找`foo(2)`的值,在賦值操作的右側,所以對`foo(2)`進行`RHS`引用
* 3、隱含賦值操作,將`2`傳遞給`function foo(a){...}`函數的參數`a`,`a`在賦值操作的左側,對`a`進行`LHS`引用
* 4、`var b = a`,`b`需要被賦值,處于賦值操作的左側,所以對`b`進行`LHS`引用,`b`的值是`a`,那么`a`是多少呢,需要對`a`進行`RHS`引用
* 5、`return b + a`中,需要找到`a`和`b`的來源,`a`和`b`都在賦值操作的右側,對`b + a`進行`RHS`引用
## 2、變量提升
>`js`中變量提升到當前作用域的頂部,而賦值操作在原處不變
舉個例子:
`console.log(a) ;var a = 2;`輸出的值是什么?
很多人可能會報錯`ReferenceError`,但是不是,后面定義了`a`,所以變量會提升,就是在`console.log(a)`前面多寫了一行代碼`var a`,如果是`console.log(a); a = 2;`沒有`var`的情況下,會報`//ReferenceError: a is not defined`
再來一個例子:
```
var name="Bob";
(function(){
????if(typeof name=== 'undefined'){
????????var name='Jack';//此處增加name聲明
// name = 'Jack' // 輸出:hello,Bob
????????console.log('Goodbye'+name);
????}else{
????????console.log('hello'+name);
????}
})() // 輸出:Goodbye Bob
```
修改一下:
```
(function(){
? ? ? ? ? ?name='Jack';
? ? ? ? ? ?if(typeof name=== 'undefined'){
? ? ? ? ? ? ? ? console.log('Goodbye'+name);
? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? console.log('hello'+name);
? ? ? ? ? ? }
? ? })(); // hello Jack
```
?console.log("name:"+name);// name:Jack?(未使用var,默認聲明為全局變量)
注意:多個`script`不可以跨越
```
<script>
console.log(a)
</script>
<script>
var a = 1;
</script><br> // 控制臺報錯`ReferenceError: a is not defined
```
## 3、函數提升
變量提升了,那么函數的聲明也會提升。
**函數的聲明有兩種方式:**
* 1、命名函數式
```
// 聲明式
function foo() {
.....
}
```
* 2、函數字面量式(即函數表達式)
```
// 字面量式
var foo = function() {
.....
}
```
那么重點來了,先看例子:
```
console.log(bar); // f bar() { console.log(123) }
console.log(bar()); // undefined
var bar = 456;
function bar() {
console.log(123); // 123
}
console.log(bar); // 456
bar = 789;
console.log(bar); // 789
console.log(bar()) // bar is not a function
```
相當于:
```
// js執行步驟
// 函數提升,函數提升優先級高于變量提升
var bar = function() {
console.log(123)
};
// 變量提升,變量提升不會覆蓋(同名)函數提升,只有變量再次賦值時,才會被覆蓋
var bar;
console.log(bar);
console.log(bar());
// 變量賦值,覆蓋同名函數字面量
bar = 456;
console.log(bar);
// 再次賦值
bar = 789
console.log(bar);
console.log(bar());
```
兩個例子得到的結果:
```
// js執行結果
f bar() { console.log(123) }
123 // 執行bar()里的console.log
undefined // bar()的返回值,如果函數沒有返回值,默認為:undefined
456
789
[typeError]:bar is not a function
```
**得出結論:**
>函數的提升優先級高于變量的提升,且不會被同名變量聲明時覆蓋,但是會被變量賦值后覆蓋
### ???那么命名函數和字面量式函數的提升有什么不同呢?
* 1、先看命名函數式
```
foo() // 1
function foo() {
console.log('1')
}
```
說明命名函數式的函數本身也會提升到當前作用域的最前面
* 2、再看下字面量式(表達式):
```
foo() // Uncaught TypeError: foo is not a function, 此時的foo為undefined
var foo = function() {
console.log('1')
}
<=>相當與以下代碼
var foo
foo()
foo = function() {
console.log('1')
}
```
注意:同名函數聲明,則覆蓋之前的函數聲明
```
foo() // 4
function foo() {
console.log('3')
}
function foo() {
console.log('4')
}
```
但是同名不同形式的聲明方式是不一樣的
```
foo() // 3 函數提前不覆蓋
function foo() {
console.log('3')
}
var foo = function() {
console.log('4')
}
foo() //4 覆蓋前面的方法
```
最后用一個面試題結尾:
```
function Foo() {
getName = function () { alert (1); };
return this;
}
Foo.getName = function () { alert (2);};
Foo.prototype.getName = function () { alert (3);};
var getName = function () { alert (4);};
function getName() { alert (5);}
//請寫出以下輸出結果:
Foo.getName(); // 2 => Foo的靜態屬性getName
getName(); // 4 => 執行全局環境下的getName
Foo().getName(); // 1 <=>window.getName()
getName(); // 1 => 執行全局環境下的getName
new Foo.getName(); // 2 => 執行Foo的靜態屬性getName的構造函數
new Foo().getName(); // 3 相當于Foo實例原型上的getName
new new Foo().getName(); // 3 相當于Foo實例原型上的getName的構造函數
```
- git-第一天
- Git-第二天
- git-第三天
- http-基礎
- HTTP構成和狀態碼
- 瀏覽器輸入URL,經歷的過程
- TCP/IP 詳解三次握手 四次揮手
- http-DNS系統
- http與https之間的區別
- HTTPS握手和HTTP握手
- HTTP小試牛刀
- Tcp初探
- TCP報文格式
- HTML5
- HTML基礎
- Mock
- css 選擇器
- css 動畫
- css 定位
- position/display/float/z-index第一課時
- 行內、塊、脫標 三種狀態下的元素如何實現、水平、垂直居中
- clientHeight/offsetHeight/scrollHeight
- js 數據類型
- 變量提升
- 堆棧關系