在全局/私有上下文中:帶VAR和不帶VAR的區別

在介紹區別以前,咱們先來看下解決這個需求的兩種方式:javascript

  • 需求:驗證:name或者age是否是obj的屬性
var obj = {
    name: '小芝麻'
};
複製代碼

方法一:基於判斷屬性值是否爲undefined來驗證是否有這個屬性(不專業方案)java

if (obj.name !== undefined) {
    // OBJ中存在這個屬性
}
if (obj['age'] === undefined) {
    // OBJ不存在這個屬性
}
複製代碼

方法二:基於檢測符 in 來檢測當前屬性是否屬於這個對象 =>語法: 屬性名 in 對象(專業方案)node

if ('age' in obj) {
    // AGE是OBJ屬性返回TRUE,不是它的屬性返回FALSE
}
複製代碼

在講解全局執行上下文中:帶VAR不帶VAR的區別,咱們須要先了解全局對象和全局變量對象的區別瀏覽器

思惟導圖

1、全局對象和全局變量對象的區別

以前咱們說過瀏覽器想要把代碼執行就須要先有個執行環境棧ECStack;函數

與此同時也會建立一個全局對象GO;和其餘的引用類型值同樣,也存儲在堆內存中,有一個十六進制的空間地址; 這裏存儲了不少內置的屬性和方法;ui

  • 執行環境棧ECStack中有個window,讓window指向這個全局對象的空間地址;
  • 咱們平時用的alert("xxx")的方法,全稱:window.alert(...),只不過咱們平時省略了window;

一、全局對象

  • 全局對象:
    • 瀏覽器默認會自帶不少供JS調取使用的內置API,這些屬性方法都在GO中存儲着,在瀏覽器端,把GO對象賦值給window,在node端把GO賦值給了global

咱們在控制檯詳細輸出window,看一下;spa

這些就是咱們的全局對象中的內容

二、全局變量對象

全局變量對象:3d

  • 當全局代碼執行過程當中,會聲明一些變量,這些變量存儲在全局變量對象VO

總結:綜上所屬,咱們知道:

  • 全局對象GO:是瀏覽器天生自帶的存儲屬性和方法的堆,是一個對象;
  • 全局變量對象VO:是咱們本身寫代碼建立的變量要存儲的地方;是棧內存;

徹底是兩個不一樣的東西 code

2、全局執行上下文中:帶VAR不帶VAR的區別

「在全局執行上下文中」,帶VAR不帶VAR定義值是兩套不一樣的機制cdn

  • 帶VAR是建立一個全局變量,存放在全局變量對象VO(G)
  • 不帶VAR建立的不是變量,而是全局對象GO(global object)的一個屬性

知道了上面的內容,咱們來用例題分析一下:

var n = 100;
console.log(n);
console.log(window.n);
m = 200;
console.log(m);
console.log(x);
複製代碼

總結:

全局上下文中:

  • 基於VAR建立變量,會給VO(G)GO中各自存儲一份,
  • 不帶VAR的,只是給GO設置一個屬性而已;
  • 當咱們輸出這個變量值的時候,首先看是否爲全局變量,是則輸出全局變量的值,若是不是,則在看是否爲全局對象的屬性,若是再不是,則報錯!!

3、私有執行上下文中:帶VAR不帶VAR的區別

  • 一、帶VAR的狀況

    在函數裏:var x=100;

    • 在私有上下文的AO(FN)變量對象中聲明一個x的私有變量(x是當前上下文的私有變量,和上下文之外沒有必然聯繫)
  • 二、不帶VAR的狀況

    在函數裏: y=200;

    • 一、瀏覽器發現y不是私有變量,則向其上級上下文中查找(按照SCOPE-CHAIN(做用域鏈,咱們下一篇文章會說)查找),若是上級也沒有則繼續查找…一直到EC(G)全局上下文爲止,找到哪一級,就是哪一級的變量
    • 二、若是找到全局也沒有,則給GO(window)設置一個屬性:window.y=200

4、全局和私有上下文中帶var的區別;

  • 全局執行上下文中:基於VAR建立變量,會給VO(G)GO中各自存儲一份;
  • 私有執行上下文中:只在私有變量對象AO中建立了變量,沒有給window添加屬性;

5、例題

一、輸出結果

/* * 全局上下文中的變量提高 * var a; * ->給VO(G)中新增一個全局變量 a * ->給GO中新增一個屬性 a * ->默認值都是 undefined */
console.log(a); //=>undefined
if (!('a' in window)) {
	// 'a' in window 檢測a是否爲window的一個屬性 =>TRUE
	// !true => FALSE 條件不成立
	var a = 13;
}
console.log(a); //=>undefined
複製代碼

二、輸出結果

/* * 全局上下文中的變量提高(最新版本瀏覽器中) * function fn; * ->VO(G)中存在一個fn全局變量 * ->GO中存在一個fn屬性 */
console.log(fn); //=>undefined
// fn();//=> undefined() =>Uncaught TypeError: fn is not a function JS中,一但當前代碼報錯,那麼下面的代碼都不會再執行了
if ('fn' in window) { 
	fn(); 
	function fn() {
		console.log('哈哈哈');
	}
}
fn();

//================================================

/* * 全局上下文中的變量提高(最新版本瀏覽器中) * function fn; * ->VO(G)中存在一個fn全局變量 * ->GO中存在一個fn屬性 */
console.log(fn); //=>undefined
if ('fn' in window) {  //=>TRUE
	// 進來第一件事情:給FN賦值 fn=function(){ ... }
	fn(); //=>'哈哈哈'
	function fn() {
		console.log('哈哈哈');
	}
}
fn(); //=>'哈哈哈'
複製代碼
相關文章
相關標籤/搜索