在线看毛片视频-国产免费av在线-欧美日韩一区二区三区-国产成人无码av在线播放无广告-亚洲人va欧美va人人爽-国产第一草草-西班牙黄色片-四虎在线网站8848-最新av片免费网站入口-东京热无码中文字幕av专区-日本大人吃奶视频xxxx-欧美精品一区二区三区四区五区-国产片天天弄-国产免费内射又粗又爽密桃视频-欧美爱爱网站-日韩v欧美

當前位置:雨林木風下載站 > 網頁設計教程 > 詳細頁面

Javascript作用域的深入解析(代碼示例)

Javascript作用域的深入解析(代碼示例)

更新時間:2025-12-08 文章作者:未知 信息來源:網絡 閱讀次數:

網頁的本質就是超級文本標記語言,通過結合使用其他的Web技術(如:腳本語言、公共網關接口、組件等),可以創造出功能強大的網頁。因而,超級文本標記語言是萬維網(Web)編程的基礎,也就是說萬維網是建立...
網頁的本質就是超級文本標記語言,通過結合使用其他的Web技術(如:腳本語言、公共網關接口、組件等),可以創造出功能強大的網頁。因而,超級文本標記語言是萬維網(Web)編程的基礎,也就是說萬維網是建立在超文本基礎之上的。超級文本標記語言之所以稱為超文本標記語言,是因為文本中包含了所謂“超級鏈接”點。
本篇文章給大家帶來的內容是關于Javascript作用域的深入解析(代碼示例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。

作用域

作用域是一套規則,用于確定在何處以及如何查找變量(標識符)。如果查找的目的是對變量進行賦值,那么就會使用 LHS 查詢;如果目的是獲取變量的值,就會使用 RHS 查詢。賦值操作符會導致 LHS 查詢。 = 操作符或調用函數時傳入參數的操作都會導致關聯作用域的賦值操作。

JavaScript 引擎首先會在代碼執行前對其進行編譯,在這個過程中,像 var a = 2 這樣的聲明會被分解成兩個獨立的步驟:

  1. 首先, var a 在其作用域中聲明新變量。這會在最開始的階段,也就是代碼執行前進行。

  2. 接下來, a = 2 會查詢(LHS 查詢)變量 a 并對其進行賦值。

LHS 和 RHS 查詢都會在當前執行作用域中開始,如果有需要(也就是說它們沒有找到所需的標識符),就會向上級作用域繼續查找目標標識符,這樣每次上升一級作用域(一層樓),最后抵達全局作用域(頂層),無論找到或沒找到都將停止。

不成功的 RHS 引用會導致拋出 ReferenceError 異常。不成功的 LHS 引用會導致自動隱式地創建一個全局變量(非嚴格模式下),該變量使用 LHS 引用的目標作為標識符,或者拋出 ReferenceError 異常(嚴格模式下)。

詞法作用域

詞法作用域意味著作用域是由書寫代碼時函數聲明的位置來決定的。編譯的詞法分析階段基本能夠知道全部標識符在哪里以及是如何聲明的,從而能夠預測在執行過程中如何對它們進行查找。

JavaScript 中有兩個機制可以“欺騙”詞法作用域: eval(..) 和 with 。前者可以對一段包含一個或多個聲明的“代碼”字符串進行演算,并借此來修改已經存在的詞法作用域(在運行時)。后者本質上是通過將一個對象的引用當作作用域來處理,將對象的屬性當作作用域中的標識符來處理,從而創建了一個新的詞法作用域(同樣是在運行時)。

這兩個機制的副作用是引擎無法在編譯時對作用域查找進行優化,因為引擎只能謹慎地認為這樣的優化是無效的。使用這其中任何一個機制都將導致代碼運行變慢。不要使用它們。

因為 JavaScript 采用的是詞法作用域,函數的作用域在函數定義的時候就決定了。

var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f();
}
checkscope();//local scope
var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f;
}
checkscope()();//local scope
var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f;
}

var foo = checkscope();
foo();//local scope

函數表達式和函數聲明

函數聲明:function 函數名稱 (參數:可選){ 函數體 }
函數表達式:function 函數名稱(可選)(參數:可選){ 函數體 }

辨別:

  • 如果不聲明函數名稱,它肯定是表達式。

  • 如果function foo(){}是作為賦值表達式的一部分的話,那它就是一個函數表達式,如果function foo(){}被包含在一個函數體內,或者位于程序的最頂部的話,那它就是一個函數聲明。

  • 被括號括住的(function foo(){}),他是表達式的原因是因為括號 ()是一個分組操作符,它的內部只能包含表達式

  function foo(){} // 聲明,因為它是程序的一部分

  (function(){
    function bar(){} // 聲明,因為它是函數體的一部分
  })();

  var bar = function foo(){}; // 表達式,因為它是賦值表達式的一部分
  new function bar(){}; // 表達式,因為它是new表達式
  (function foo(){}); // 表達式:包含在分組操作符內
  
  try {
    (var x = 5); // 分組操作符,只能包含表達式而不能包含語句:這里的var就是語句
  } catch(err) {
    // SyntaxError
  }
  • 函數聲明在條件語句內雖然可以用,但是沒有被標準化,最好使用函數表達式

  • 函數聲明會覆蓋變量聲明,但不會覆蓋變量賦值

function value(){
    return 1;
}
var value;
alert(typeof value);    //"function"

函數作用域和塊作用域

函數是 JavaScript 中最常見的作用域單元。本質上,聲明在一個函數內部的變量或函數會在所處的作用域中“隱藏”起來,這是有意為之的良好軟件的設計原則。但函數不是唯一的作用域單元。

塊作用域指的是變量和函數不僅可以屬于所處的作用域,也可以屬于某個代碼塊(通常指 { .. } 內部)。

從 ES3 開始, try/catch 結構在 catch 分句中具有塊作用域。

在 ES6 中引入了 let 關鍵字( var 關鍵字的表親),用來在任意代碼塊中聲明變量。
if(..) { let a = 2; } 會聲明一個劫持了 if 的 { .. } 塊的變量,并且將變量添加到這個塊中。

有些人認為塊作用域不應該完全作為函數作用域的替代方案。兩種功能應該同時存在,開發者可以并且也應該根據需要選擇使用何種作用域,創造可讀、可維護的優良代碼。

提升

我們習慣將 var a = 2; 看作一個聲明,而實際上 JavaScript 引擎并不這么認為。它將 var a和 a = 2 當作兩個單獨的聲明,第一個是編譯階段的任務,而第二個則是執行階段的任務。

這意味著無論作用域中的聲明出現在什么地方,都將在代碼本身被執行前首先進行處理。可以將這個過程形象地想象成所有的聲明(變量和函數)都會被“移動”到各自作用域的最頂端,這個過程被稱為提升。

聲明本身會被提升,而包括函數表達式的賦值在內的賦值操作并不會提升。
要注意避免重復聲明,特別是當普通的 var 聲明和函數聲明混合在一起的時候,否則會引
起很多危險的問題!

var a;
if (!("a" in window)) {
    a = 1;
}
alert(a);

作用域閉包

通常,程序員會錯誤的認為,只有匿名函數才是閉包。其實并非如此,正如我們所看到的 —— 正是因為作用域鏈,使得所有的函數都是閉包(與函數類型無關: 匿名函數,FE,NFE,FD都是閉包), 這里只有一類函數除外,那就是通過Function構造器創建的函數,因為其[[Scope]]只包含全局對象。 為了更好的澄清該問題,我們對ECMAScript中的閉包作兩個定義(即兩種閉包):

ECMAScript中,閉包指的是:

從理論角度:所有的函數。因為它們都在創建的時候就將上層上下文的數據保存起來了。哪怕是簡單的全局變量也是如此,因為函數中訪問全局變量就相當于是在訪問自由變量,這個時候使用最外層的作用域。
從實踐角度:以下函數才算是閉包:
即使創建它的上下文已經銷毀,它仍然存在(比如,內部函數從父函數中返回)
在代碼中引用了自由變量

循環閉包

for (var i=1; i<=5; i++) {
    (function(j) {
        setTimeout( function timer() {
        console.log( j );
        }, j*1000 );
    })( i );
}

for (var i=1; i<=5; i++) {
    let j = i; // 是的,閉包的塊作用域!
    setTimeout( function timer() {
    console.log( j );
    }, j*1000 );
}

for (let i=1; i<=5; i++) {
    setTimeout( function timer() {
    console.log( i );
    }, i*1000 );
}
var data = [];

for (var i = 0; i < 3; i++) {
  data[i] = function () {
    console.log(i);
  };
}

data[0]();//3
data[1]();//3
data[2]();//3

模塊

模塊有兩個主要特征:(1)為創建內部作用域而調用了一個包裝函數;(2)包裝函數的返回
值必須至少包括一個對內部函數的引用,這樣就會創建涵蓋整個包裝函數內部作用域的閉
包。

現代模塊機制

var MyModules = (function Manager() {
    var modules = {};
    function define(name, deps, impl) {
        for (var i=0; i<deps.length; i++) {
            deps[i] = modules[deps[i]];
        }
        modules[name] = impl.apply( impl, deps );
    }
    function get(name) {
        return modules[name];
    }
    return {
        define: define,
        get: get
    };
})();

未來模塊機制

//bar.js
function hello(who) {
    return "Let me introduce: " + who;
}
export hello;
//foo.js
// 僅從 "bar" 模塊導入 hello()
import hello from "bar";
var hungry = "hippo";
function awesome() {
    console.log(
        hello( hungry ).toUpperCase()
    );
}
export awesome;
baz.js
// 導入完整的 "foo" 和 "bar" 模塊
module foo from "foo";
module bar from "bar";
console.log(
    bar.hello( "rhino" )
); // Let me introduce: rhino
foo.awesome(); // LET ME INTRODUCE: HIPPO

塊作用域替代方案

Google 維護著一個名為 Traceur 的項目,該項目正是用來將 ES6 代碼轉換成兼容 ES6 之前的環境(大部分是 ES5,但不是全部)。TC39 委員會依賴這個工具(也有其他工具)來測試他們指定的語義化相關的功能。

{
    try {
        throw undefined;
    } catch (a) {
        a = 2;
        console.log( a );
    }
}
console.log( a )

上下文

EC(執行環境或者執行上下文,Execution Context)

EC={
    VO:{/* 函數中的arguments對象, 參數, 內部的變量以及函數聲明 */},
    this:{},
    Scope:{ /* VO以及所有父執行上下文中的VO */}
}

ECS(執行環境棧Execution Context Stack)

//ECS=[Window]
A(//ECS=[Window,A]
    B(//ECS=[Window,A,B]
        //run B 
    )
    //ECS=[Window,A]
)
//ECS=[Window]

VO(變量對象,Variable Object)

var a = 10;
function test(x) {
  var b = 20;
};
test(30);
/*
VO(globalContext)
  a: 10,
  test: 
VO(test functionContext)
  x: 30
  b: 20
*/

AO(活動對象,Active Object)

function test(a, b) {
  var c = 10;
  function d() {}
  var e = function _e() {};
  (function x() {});
} 
test(10);
/*
AO(test) = {
  a: 10,
  b: undefined,
  c: undefined,
  d: <reference to FunctionDeclaration "d">
  e: undefined
};
*/

scope chain(作用域鏈)和[[scope]]屬性

Scope = AO|VO + [[Scope]]

例子

var x = 10;
 
function foo() {
  var y = 20;
 
  function bar() {
    var z = 30;
    alert(x +  y + z);
  }
 
  bar();
}
 
foo(); // 60
  • 全局上下文的變量對象是:

globalContext.VO === Global = {
  x: 10
  foo: <reference to function>
};
  • 在“foo”創建時,“foo”的[[scope]]屬性是:

foo.[[Scope]] = [
  globalContext.VO
];
  • 在“foo”激活時(進入上下文),“foo”上下文的活動對象是:

fooContext.AO = {
  y: 20,
  bar: <reference to function>
};
  • “foo”上下文的作用域鏈為:

fooContext.Scope = fooContext.AO + foo.[[Scope]] // i.e.:
 
fooContext.Scope = [
  fooContext.AO,
  globalContext.VO
];
  • 內部函數“bar”創建時,其[[scope]]為:

bar.[[Scope]] = [
  fooContext.AO,
  globalContext.VO
];
  • 在“bar”激活時,“bar”上下文的活動對象為:

barContext.AO = {
  z: 30
};
  • “bar”上下文的作用域鏈為:

barContext.Scope = barContext.AO + bar.[[Scope]] // i.e.:
 
barContext.Scope = [
  barContext.AO,
  fooContext.AO,
  globalContext.VO
];
  • 對“x”、“y”、“z”的標識符解析如下:

- "x"
-- barContext.AO // not found
-- fooContext.AO // not found
   globalContext.VO // found - 10

- "y"
-- barContext.AO // not found
   fooContext.AO // found - 20

- "z"
   barContext.AO // found - 30

以上就是Javascript作用域的深入解析(代碼示例)的詳細內容,更多請關注php中文網其它相關文章!


網站建設是一個廣義的術語,涵蓋了許多不同的技能和學科中所使用的生產和維護的網站。

溫馨提示:喜歡本站的話,請收藏一下本站!

本類教程下載

系統下載排行

在线看毛片视频-国产免费av在线-欧美日韩一区二区三区-国产成人无码av在线播放无广告-亚洲人va欧美va人人爽-国产第一草草-西班牙黄色片-四虎在线网站8848-最新av片免费网站入口-东京热无码中文字幕av专区-日本大人吃奶视频xxxx-欧美精品一区二区三区四区五区-国产片天天弄-国产免费内射又粗又爽密桃视频-欧美爱爱网站-日韩v欧美
  • <li id="86scu"><menu id="86scu"></menu></li>
    <li id="86scu"></li>
    <button id="86scu"></button>
  • <s id="86scu"></s><button id="86scu"><menu id="86scu"></menu></button>
  • 91国在线高清视频| 青青草视频国产| 97在线播放视频| www婷婷av久久久影片| 在线观看日本www| 91视频这里只有精品| 久久久久久久久久久久久国产精品 | 小早川怜子一区二区三区| 精品久久久久久久无码| 国产精品拍拍拍| 手机在线免费观看毛片| 99视频在线视频| 九一精品久久久| 精品少妇人妻av一区二区| www.色.com| 久久久久久www| 丰满人妻中伦妇伦精品app| 99热在线这里只有精品| 丰满爆乳一区二区三区| 欧美成人免费高清视频| 色播五月综合网| av电影一区二区三区| 成人午夜视频在线观看免费| 妞干网在线免费视频| 国产福利精品一区二区三区| 99热这里只有精品免费| 欧美 日韩 国产 高清| 人妻丰满熟妇av无码区app| av污在线观看| 日本黄色片一级片| 久久精品香蕉视频| 日本一级淫片演员| 黄色a级片免费| 桥本有菜av在线| 日韩 欧美 高清| 美女av免费观看| 欧美日韩中文在线视频| 天天干天天曰天天操| 国产视频一视频二| 九一精品久久久| 免费无码国产v片在线观看| 欧美视频亚洲图片| 熟女人妇 成熟妇女系列视频| 99精品一区二区三区的区别| 丰满人妻中伦妇伦精品app| dy888午夜| 一级黄色特级片| 99精品视频播放| 免费一级淫片aaa片毛片a级| 亚洲一区二区在线视频观看| 日本三级免费观看| 霍思燕三级露全乳照| 免费看av软件| 99视频在线观看视频| 国产高潮免费视频| 久久国产乱子伦免费精品| 久久手机在线视频| 99精品一区二区三区的区别| 91福利免费观看| 亚洲视频一二三四| 精品人妻一区二区三区四区在线 | 成人毛片100部免费看| 小早川怜子一区二区三区| 日本免费a视频| wwwwwxxxx日本| 中文字幕av专区| 精品www久久久久奶水| 逼特逼视频在线| 国产极品尤物在线| 黄色免费观看视频网站| 青青青免费在线| 国产免费一区二区三区视频| 成人在线观看你懂的| 久久久久免费看黄a片app| 亚洲理论电影在线观看| 99国产精品白浆在线观看免费| 成人免费看片视频在线观看| 夜夜爽久久精品91| 成人手机在线播放| 国产天堂视频在线观看| 日本香蕉视频在线观看| 男人和女人啪啪网站| 成人免费毛片网| 国产91色在线观看| 免费久久久久久| 国内精品视频一区二区三区| 日本wwww视频| 日韩一区二区三区不卡视频| 热这里只有精品| www.xxx麻豆| 日韩免费高清在线| 亚洲最新免费视频| 免费看国产一级片| 国产精品久久久毛片| 黄色小视频大全| 免费观看日韩毛片| 欧美激情第3页| 日韩亚洲欧美视频| 久久久久久蜜桃一区二区| 日韩视频一二三| 黑人糟蹋人妻hd中文字幕| 日韩va在线观看| 欧美久久久久久久久久久久久| 无码内射中文字幕岛国片| 五月天婷婷在线观看视频| 大陆极品少妇内射aaaaa| 久久精品国产露脸对白| 波多野结衣综合网| 免费观看中文字幕| 热久久精品免费视频| 国产xxxx振车| 日韩第一页在线观看| 欧美v在线观看| 中文字幕精品在线播放| 亚洲国产精品三区| 国产免费成人在线| 女同性恋一区二区| 日韩av片免费观看| 国产又大又黄又粗又爽| 成人黄色av片| 青青青青草视频| 国产1区2区3区中文字幕| 日韩欧美亚洲另类| 91最新在线观看| 国内外成人免费激情视频| 成人黄色av片| 可以在线看的av网站| 91精品国产毛片武则天| 亚洲美女自拍偷拍| 一级黄色大片儿| 青青草原国产免费| 亚洲av毛片在线观看| 亚洲黄色片免费| 国产又粗又猛大又黄又爽| 日日夜夜精品视频免费观看 | 黄色一级视频播放| 中文字幕制服丝袜在线| www.日本久久| 国产a级片免费看| 天堂а√在线中文在线| 国产一二三四五| 自拍日韩亚洲一区在线| 欧美精品久久久久久久自慰 | 97碰在线视频| 久久久久久久久久久99| 青青草原成人网| 向日葵污视频在线观看| 波多野结衣国产精品| 熟女视频一区二区三区| 精品国偷自产一区二区三区| 成年人午夜免费视频| 国产性生交xxxxx免费| 中文字幕av不卡在线| 手机在线免费毛片| 国产freexxxx性播放麻豆| www黄色日本| 最新天堂中文在线| 三级在线免费观看| 农村妇女精品一二区| gai在线观看免费高清| 日韩精品一区二区三区四| 国产白丝袜美女久久久久| 中文字幕在线观看第三页| 国产精品探花在线播放| 日韩中字在线观看| theporn国产精品| 你真棒插曲来救救我在线观看| 国产日韩成人内射视频 | 激情久久综合网| 国产av天堂无码一区二区三区| 久久久精品麻豆| 日本香蕉视频在线观看| 一起操在线视频| 国产中文字幕视频在线观看| 久久久九九九热| 亚洲成色www.777999| 色哟哟免费网站| 911av视频| 欧美成人免费高清视频| 免费高清一区二区三区| 天天久久综合网| 五月天亚洲视频| 欧美性久久久久| 日本五级黄色片| 国产一级片中文字幕| 黑森林精品导航| 日韩精品一区二区三区不卡| 欧美大片在线播放| 久久久天堂国产精品| 欧美日韩视频免费在线观看| 91 在线视频观看| 成人亚洲精品777777大片| 91精品91久久久中77777老牛 | 日日噜噜夜夜狠狠久久丁香五月| 中文字幕国产传媒| 毛片av免费在线观看| 欧美视频第一区| 免费av网址在线| 免费日韩视频在线观看| 国语对白做受xxxxx在线中国|