国产99久久精品_欧美日本韩国一区二区_激情小说综合网_欧美一级二级视频_午夜av电影_日本久久精品视频

最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當前位置: 首頁 - 科技 - 知識百科 - 正文

javascript中的作用域和上下文使用簡要概述_基礎知識

來源:懂視網 責編:小采 時間:2020-11-27 21:16:54
文檔

javascript中的作用域和上下文使用簡要概述_基礎知識

javascript中的作用域和上下文使用簡要概述_基礎知識:javascript中的作用域(scope)和上下文(context)是這門語言的獨到之處,這部分歸功于他們帶來的靈活性。每個函數有不同的變量上下文和作用域。這些概念是javascript中一些強大的設計模式的后盾。然而這也給開發人員帶來很大困惑。下面全面揭示了javascr
推薦度:
導讀javascript中的作用域和上下文使用簡要概述_基礎知識:javascript中的作用域(scope)和上下文(context)是這門語言的獨到之處,這部分歸功于他們帶來的靈活性。每個函數有不同的變量上下文和作用域。這些概念是javascript中一些強大的設計模式的后盾。然而這也給開發人員帶來很大困惑。下面全面揭示了javascr

javascript中的作用域(scope)和上下文(context)是這門語言的獨到之處,這部分歸功于他們帶來的靈活性。每個函數有不同的變量上下文和作用域。這些概念是javascript中一些強大的設計模式的后盾。然而這也給開發人員帶來很大困惑。下面全面揭示了javascript中的上下文和作用域的不同,以及各種設計模式如何使用他們。

上下文 vs 作用域

首先需要澄清的問題是上下文和作用域是不同的概念。多年來我注意到許多開發者經常將這兩個術語混淆,錯誤的將一個描述為另一個。平心而論,這些術語變得非常混亂不堪。

每個函數調用都有與之相關的作用域和上下文。從根本上說,范圍是基于函數(function-based)而上下文是基于對象(object-based)。換句話說,作用域是和每次函數調用時變量的訪問有關,并且每次調用都是獨立的。上下文總是關鍵字 this 的值,是調用當前可執行代碼的對象的引用。

變量作用域

變量能夠被定義在局部或者全局作用域,這導致運行時變量的訪問來自不同的作用域。全局變量需被聲明在函數體外,在整個運行過程中都存在,能在任何作用域中訪問和修改。局部變量僅在函數體內定義,并且每次函數調用都有不同的作用域。這主題是僅在調用中的賦值,求值和對值的操作,不能訪問作用域之外的值。

目前javascript不支持塊級作用域,塊級作用域指在if語句,switch語句,循環語句等語句塊中定義變量,這意味著變量不能在語句塊之外被訪問。當前任何在語句塊中定義的變量都能在語句塊之外訪問。然而,這種情況很快會得到改變,let 關鍵字已經正式添加到ES6規范。用它來代替var關鍵字可以將局部變量聲明為塊級作用域。

"this" 上下文

上下文通常是取決于一個函數如何被調用。當函數作為對象的方法被調用時,this 被設置為調用方法的對象:

代碼如下:
var object = {
foo: function(){
alert(this === object);
}
};

object.foo(); // true

同樣的原理適用于當調用一個函數時通過new的操作符創建一個對象的實例。當以這種方式調用時,this 的值將被設置為新創建的實例:
代碼如下:
function foo(){
alert(this);
}

foo() // window
new foo() // foo

當調用一個未綁定函數,this 將被默認設置為 全局上下文(global context) 或window對象(如果在瀏覽器中)。然而如果函數在嚴格模式下被執行("use strict"),this的值將被默認設置為undefined。
執行上下文和作用域鏈

javascript是一個單線程語言,這意味著在瀏覽器中同時只能做一件事情。當javascript解釋器初始執行代碼,它首先默認竟如全局上下文。每次調用一個函數將會創建一個新的執行上下文。

這里經常發生混淆,這術語”執行上下文(execution context)“在這里的所要表達的意思是作用域,不是前面討論的上下文。這是槽糕的命名,然而這術語ECMAScript規范所定義的,無奈的遵守吧。

每次新創建一個執行上下文,會被添加到作用域鏈的頂部,又是也成為執行或調用棧。瀏覽器總是運行在位于作用域鏈頂部當前執行上下文。一旦完成,它(當前執行上下文)將從棧頂被移除并且將控制權歸還給之前的執行上下文。例如:
代碼如下:
function first(){
second();
function second(){
third();
function third(){
fourth();
function fourth(){
// do something
}
}
}
}
first();

運行前面的代碼將會導致嵌套的函數被從上倒下執行直到 fourth 函數,此時作用域鏈從上到下為: fourth, third, second, first, global。fourth 函數能夠訪問全局變量和任何在first,second和third函數中定義的變量,就如同訪問自己的變量一樣。一旦fourth函數執行完成,fourth暈高興上下文將被從作用域鏈頂端移除并且執行將返回到thrid函數。這一過程持續進行直到所有代碼已完成執行。

不同執行上下文之間的變量命名沖突通過攀爬作用域鏈解決,從局部直到全局。這意味著具有相同名稱的局部變量在作用域鏈中有更高的優先級。

簡單的說,每次你試圖訪問函數執行上下文中的變量時,查找進程總是從自己的變量對象開始。如果在自己的變量對象中沒發現要查找的變量,繼續搜索作用域鏈。它將攀爬作用域鏈檢查每一個執行上下文的變量對象去尋找和變量名稱匹配的值。

閉包

當一個嵌套的函數在定義(作用域)的外面被訪問,以至它可以在外部函數返回后被執行,此時一個閉包形成。它(閉包)維護(在內部函數中)對外部函數中局部變量,arguments和函數聲明的訪問。封裝允許我們從外部作用域中隱藏和保護執行上下文,而暴露公共接口,通過接口進一步操作。一個簡單的例子看起來如下:
代碼如下:
function foo(){
var local = 'private variable';
return function bar(){
return local;
}
}

var getLocalVariable = foo();
getLocalVariable() // private variable

其中最流行的閉包類型是廣為人知的模塊模式。它允許你模擬公共的,私有的和特權成員:
代碼如下:
var Module = (function(){
var privateProperty = 'foo';

function privateMethod(args){
//do something
}

return {

publicProperty: "",

publicMethod: function(args){
//do something
},

privilegedMethod: function(args){
privateMethod(args);
}
}
})();

模塊實際上有些類似于單例,在末尾添加一對括號,當解釋器解釋完后立即執行(立即執行函數)。閉包執行上下位的外部唯一可用的成員是返回對象中公用的方法和屬性(例如Module.publicMethod)。然而,所有的私有屬性和方法在整個程序的生命周期中都將存在,由于(閉包)使執行上下文收到保護,和變量的交互要通過公用的方法。

另一種類型的閉包叫做立即調用函數表達式(immediately-invoked function expression IIFE),無非是一個在window上下文中的自調用匿名函數(self-invoked anonymous function)。
代碼如下:
function(window){

var a = 'foo', b = 'bar';

function private(){
// do something
}

window.Module = {

public: function(){
// do something
}
};

})(this);

對保護全局命名空間,這種表達式非常有用,所有在函數體內聲明的變量都是局部變量,并通過閉包在整個運行環境保持存在。這種封裝源代碼的方式對程序和框架都是非常流行的,通常暴露單一全局接口與外界交互。

Call 和 Apply

這兩個簡單的方法,內建在所有的函數中,允許在自定義上下文中執行函數。call 函數需要參數列表而 apply 函數允許你傳遞參數為數組:
代碼如下:
function user(first, last, age){
// do something
}
user.call(window, 'John', 'Doe', 30);
user.apply(window, ['John', 'Doe', 30]);

執行的結果是相同的,user 函數在window上下文上被調用,并提供了相同的三個參數。

ECMAScript 5 (ES5)引入了Function.prototype.bind方法來控制上下文,它返回一個新函數,這函數(的上下文)被永久綁定到bind方法的第一個參數,無論函數被如何調用。它通過閉包修正函數的上下文,下面是為不支持的瀏覽器提供的方案:
代碼如下:
if(!('bind' in Function.prototype)){
Function.prototype.bind = function(){
var fn = this, context = arguments[0], args = Array.prototype.slice.call(arguments, 1);
return function(){
return fn.apply(context, args);
}
}
}

它常用在上下文丟失:面向對象和事件處理。這點有必要的因為 節點的addEventListener 方法總保持函數執行的上下文為事件處理被綁定的節點,這點很重要。然而如果你使用高級面向對象技術并且需要維護回調函數的上下文是方法的實例,你必須手動調整上下文。這就是bind 帶來的方便:
代碼如下:
function MyClass(){
this.element = document.createElement('div');
this.element.addEventListener('click', this.onClick.bind(this), false);
}

MyClass.prototype.onClick = function(e){
// do something
};

當回顧bind函數的源代碼,你可能注意到下面這一行相對簡單的代碼,調用Array的一個方法:
代碼如下:
Array.prototype.slice.call(arguments, 1);

有趣的是,這里需要注意的是arguments對象實際上并不是一個數組,然而它經常被描述為類數組(array-like)對象,很向 nodelist(document.getElementsByTagName()方法返回的結果)。他們包含lenght屬性,值能夠被索引,但他們仍然不是數組,由于他們不支持原生的數組方法,比如slice和push。然而,由于他們有和數組類似的行為,數組的方法能被調用和劫持。如果你想這樣,在類數組的上下文中執行數組方法,可參照上面的例子。

這種調用其他對象方法的技術也被應用到面向對象中,當在javascript中模仿經典繼承(類繼承):
代碼如下:
MyClass.prototype.init = function(){
// call the superclass init method in the context of the "MyClass" instance
MySuperClass.prototype.init.apply(this, arguments);
}

通過在子類(MyClass)的實例中調用超類(MySuperClass)的方法,我們能重現這種強大的設計模式。

結論

在你開始學習高級設計模式之前理解這些概念是非常重要的,由于作用域和上下文在現代javascript中扮演重要的和根本的角色。無論我們談論閉包,面向對象,和繼承或各種原生實現,上下文和作用域都扮演重要角色。如果你的目標是掌握javascript語言并深入了解它的組成,作用域和上下文應該是你的起點。

譯者補充

作者實現的bind函數是不完全的,調用bind返回的函數時不能傳遞參數,下面的代碼修復了這個問題:

代碼如下:
if(!(‘bind' in Function.prototype)){
Function.prototype.bind = function(){
var fn = this, context = arguments[0], args = Array.prototype.slice.call(arguments, 1);
return function(){
return fn.apply(context, args.concat(arguments));//fixed
}
}
}

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

javascript中的作用域和上下文使用簡要概述_基礎知識

javascript中的作用域和上下文使用簡要概述_基礎知識:javascript中的作用域(scope)和上下文(context)是這門語言的獨到之處,這部分歸功于他們帶來的靈活性。每個函數有不同的變量上下文和作用域。這些概念是javascript中一些強大的設計模式的后盾。然而這也給開發人員帶來很大困惑。下面全面揭示了javascr
推薦度:
  • 熱門焦點

最新推薦

猜你喜歡

熱門推薦

專題
Top
主站蜘蛛池模板: 可播放的免费男男videos不卡 | 成人亚洲欧美日韩在线 | 91导航在线观看 | 国产精品资源在线播放 | 亚洲十欧美十日韩十国产 | 国产拍拍拍免费视频网站 | 国产精品视频久久久 | 亚洲国产成人影院播放 | 亚洲欧美日韩精品久久久 | 国产精品视频专区 | 国产一区二区三区久久 | 国产69精品久久久久777 | 精品国产一区二区三区在线观看 | 久久久久久亚洲精品影院 | 欧美国产激情二区三区 | 一道本一区二区三区 | 国产在线播放免费 | 一级黄网站 | 91热这里只有精品 | 日韩欧美亚洲国产高清在线 | 久久综合精品国产一区二区三区 | 香蕉在线观看 | 亚洲欧美日韩中文v在线 | 国产精品一区二区三区四区五区 | 精品国产91久久久久 | 国产精品久久久久久久久免费 | 欧美曰韩 | 欧美在线播放视频 | 国产成人精品第一区二区 | 日韩毛片在线 | 国产精品久久久久毛片 | 欧美一区二区三区在线观看 | 婷婷伊人 | 国产一区二区三区在线 | 欧美一区二| 亚洲一区二区三区一品精 | 免费国产小视频在线观看 | 性夜影院爽黄a爽免费看网站 | 成人黄色在线 | 亚洲国产视频网 | 最近中文字幕电影在线看 |