亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

javascript中的作用域和上下文使用簡要概述

2019-11-20 21:30:55
字體:
供稿:網(wǎng)友
javascript中的作用域(scope)和上下文(context)是這門語言的獨到之處,這部分歸功于他們帶來的靈活性。每個函數(shù)有不同的變量上下文和作用域。這些概念是javascript中一些強大的設計模式的后盾。然而這也給開發(fā)人員帶來很大困惑。下面全面揭示了javascript中的上下文和作用域的不同,以及各種設計模式如何使用他們。

上下文 vs 作用域

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

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

變量作用域

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

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

"this" 上下文

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

復制代碼 代碼如下:

var object = {
foo: function(){
alert(this === object);
}
};

object.foo(); // true

同樣的原理適用于當調(diào)用一個函數(shù)時通過new的操作符創(chuàng)建一個對象的實例。當以這種方式調(diào)用時,this 的值將被設置為新創(chuàng)建的實例:
復制代碼 代碼如下:

function foo(){
alert(this);
}

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

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

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

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

每次新創(chuàng)建一個執(zhí)行上下文,會被添加到作用域鏈的頂部,又是也成為執(zhí)行或調(diào)用棧。瀏覽器總是運行在位于作用域鏈頂部當前執(zhí)行上下文。一旦完成,它(當前執(zhí)行上下文)將從棧頂被移除并且將控制權歸還給之前的執(zhí)行上下文。例如:
復制代碼 代碼如下:

function first(){
second();
function second(){
third();
function third(){
fourth();
function fourth(){
// do something
}
}
}
}
first();

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

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

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

閉包

當一個嵌套的函數(shù)在定義(作用域)的外面被訪問,以至它可以在外部函數(shù)返回后被執(zhí)行,此時一個閉包形成。它(閉包)維護(在內(nèi)部函數(shù)中)對外部函數(shù)中局部變量,arguments和函數(shù)聲明的訪問。封裝允許我們從外部作用域中隱藏和保護執(zhí)行上下文,而暴露公共接口,通過接口進一步操作。一個簡單的例子看起來如下:
復制代碼 代碼如下:

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);
}
}
})();

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

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

function(window){

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

function private(){
// do something
}

window.Module = {

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

})(this);

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

Call 和 Apply

這兩個簡單的方法,內(nèi)建在所有的函數(shù)中,允許在自定義上下文中執(zhí)行函數(shù)。call 函數(shù)需要參數(shù)列表而 apply 函數(shù)允許你傳遞參數(shù)為數(shù)組:
復制代碼 代碼如下:

function user(first, last, age){
// do something
}
user.call(window, 'John', 'Doe', 30);
user.apply(window, ['John', 'Doe', 30]);

執(zhí)行的結果是相同的,user 函數(shù)在window上下文上被調(diào)用,并提供了相同的三個參數(shù)。

ECMAScript 5 (ES5)引入了Function.prototype.bind方法來控制上下文,它返回一個新函數(shù),這函數(shù)(的上下文)被永久綁定到bind方法的第一個參數(shù),無論函數(shù)被如何調(diào)用。它通過閉包修正函數(shù)的上下文,下面是為不支持的瀏覽器提供的方案:
復制代碼 代碼如下:

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);
}
}
}

它常用在上下文丟失:面向?qū)ο蠛褪录幚?。這點有必要的因為 節(jié)點的addEventListener 方法總保持函數(shù)執(zhí)行的上下文為事件處理被綁定的節(jié)點,這點很重要。然而如果你使用高級面向?qū)ο蠹夹g并且需要維護回調(diào)函數(shù)的上下文是方法的實例,你必須手動調(diào)整上下文。這就是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函數(shù)的源代碼,你可能注意到下面這一行相對簡單的代碼,調(diào)用Array的一個方法:
復制代碼 代碼如下:

Array.prototype.slice.call(arguments, 1);

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

這種調(diào)用其他對象方法的技術也被應用到面向?qū)ο笾校斣趈avascript中模仿經(jīng)典繼承(類繼承):
復制代碼 代碼如下:

MyClass.prototype.init = function(){
// call the superclass init method in the context of the "MyClass" instance
MySuperClass.prototype.init.apply(this, arguments);
}

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

結論

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

譯者補充

作者實現(xiàn)的bind函數(shù)是不完全的,調(diào)用bind返回的函數(shù)時不能傳遞參數(shù),下面的代碼修復了這個問題:

復制代碼 代碼如下:

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
}
}
}
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
欧美人妻一区二区| 高清在线观看日韩| 欧美精品一区二区三区四区五区| 国产福利第一页| 久久久久女人精品毛片九一| 悠悠资源av网站| 亚洲黑人在线| 久久影视一区二区| 欧美日韩大片在线观看| av网址在线播放| 欧美日韩国产一区二区三区地区| 亚洲一区二区三区精品视频| 国产在线视频二区| 在线观看不卡| 色爱区成人综合网| 在线一区日本视频| 韩国三级av在线免费观看| 日韩毛片视频在线看| 免费人成视频在线| 日本中文在线| 91久久精品国产91久久性色| 女囚岛在线观看| 久草视频一区二区| 日韩av大片免费看| 青青在线观看视频中文字| 一区二区三区欧美激情| 午夜精品久久久久久久99黑人| 97在线视频免费| 日本道在线观看一区二区| 日韩欧美在线不卡| 日韩精品一区二区三区四区五区| 都市激情亚洲色图| eeuss在线播放| 欧美片一区二区三区| 中文字幕乱码一区二区三区| 91麻豆文化传媒在线观看| 亚洲性生活视频在线观看| 99久在线精品99re8热| 成人精品在线观看| 国产精品一区二区三区高清在线| 免费av在线一区| 日韩在线观看高清| 人人澡人人爽| 88av在线播放| 免费看污片网站| 欧美videossex另类| 在线一区亚洲| 国产精品小说在线| 欧美三级欧美成人高清www| 天堂视频中文在线| 黄网站app在线观看| 992kp快乐看片永久免费网址| av在线free| baoyu777.永久免费视频| 粉嫩粉嫩芽的虎白女18在线视频| www.久久久久久久久久| 国产精品美女久久久久| 成人性生交大片免费观看嘿嘿视频| 国产精品久久久久久久龚玥菲| 欧美最猛性xxxxx(亚洲精品)| 男人的午夜天堂| 四虎永久免费地址| 正在播放欧美一区| 在线观看91精品国产入口| 国产精选在线观看91| 精品久久久久久久久久久久久久久久久| 免费高清成人在线| 天堂网av手机版| 亚洲激情男女视频| 羞羞的视频在线| 91福利资源站| 国产在线视频自拍| 狂野欧美性猛交xxxx巴西| 国产高清视频免费| 欧美艳星brazzers| 黄色春季福利在线看| 欧美18—20岁hd第一次| 尤物视频在线观看| 色诱视频网站一区| 欧美成人三级伦在线观看| 国产在线资源一区| 久久93精品国产91久久综合| 三级全黄的视频在线观看| 亚洲免费资源在线播放| 污视频网站免费观看| 日韩免费视频一区二区视频在线观看| 91免费版视频| 国产精品劲爆视频| 在线视频中文亚洲| 免费不卡亚洲欧美| 高潮白浆视频| 7777精品伊人久久久大香线蕉完整版| 欧美日韩午夜电影网| 国产毛片毛片毛片毛片| 91午夜精品亚洲一区二区三区| 国产精品国产高清国产| 久久亚洲精品网站| 无码少妇一区二区| 国产精品日本精品| 国产精品xxx在线观看www| 国产精品一区二区你懂的| 91大神福利视频在线| 中国xxxx性xxxx产国| 日本1区2区3区中文字幕| 免费亚洲婷婷| 免费看污片网站| 成人免费精品动漫网站| 亚洲人成伊人成综合网久久久| 精品国产一区二区三区四区四| 国产xxxx做受性欧美88| 成人三级视频在线观看| www.亚洲天堂.com| www.69av| 在线观看精品一区| 96精品视频在线| 女人黄色一级片| 欧美日韩在线免费观看视频| 暖暖在线中文免费日本| 亚洲 国产 日韩 综合一区| 999久久久免费精品国产牛牛| 91在线无精精品白丝| 1769在线观看| 爽爽爽在线观看| 国产精品国产自产拍高清av水多| 国产在线综合视频| 91老司机精品视频| 日韩欧美国产免费播放| 综合激情视频| 麻豆电影在线| 美日韩精品免费| www.天天干.com| av免费观看国产| 精品免费av一区二区三区| 三级毛片在线看| 无码精品一区二区三区在线播放| 极品国产人妖chinesets亚洲人妖| 亚洲女人被黑人巨大进入| 国产一二三av| 国产日产精品_国产精品毛片| 日韩激情在线观看| 精品在线免费观看视频| 成人欧美一区二区| 午夜av入18在线| 欧美性xxxxxx少妇| 在线成人动漫| 欧美日韩一级在线观看| 亚洲成人tv网| 欧美三级蜜桃2在线观看| 日日躁夜夜躁人人揉av五月天| 国产乱对白刺激视频不卡| 久久五月天小说| 国产精品久久久久久久久妇女| 国产日韩成人内射视频| 成人午夜电影免费在线观看| 国自产拍偷拍福利精品免费一| 国产精品日韩久久久| 久久久精品在线视频| 69av成年福利视频| 国产福利精品一区二区| 狠狠综合久久| 亚洲国产成人不卡| 欧美成人一级视频| 国产一区二区精彩视频| 精品久久久久久久久久久久久久| 日韩一区二区三区观看| 色狠狠av一区二区三区香蕉蜜桃| av手机天堂网| 国产精品电影久久久久电影网| 欧美亚洲三级| 午夜久久免费观看| 天堂在线中文网官网| 日本中文字幕在线观看视频| 欧美日韩国产精品一区二区三区四区| 欧美成人亚洲成人日韩成人| 福利视频在线看| 欧洲成人性视频| 欧美日韩视频在线一区二区观看视频| 午夜国产福利视频| 精品久久久久久亚洲| 亚洲欧美另类图片| 国产精品美女av| 国产在线视频网站| 性色av一区| 欧美酷刑日本凌虐凌虐| 美女91精品| 91精品在线国产| 亚洲91久久| 亚洲图片欧美激情| 久久嫩草捆绑紧缚| 一区二区三区四区国产精品| 欧美大荫蒂xxx| 无码人妻精品一区二区蜜桃百度| 欧美日韩高清丝袜| 视频在线观看一区| 国产一级又黄| 理论电影国产精品| 亚洲第一综合网| 成熟老妇女视频| 久久亚洲综合色一区二区三区| 韩国女同性做爰三级| 精品国产麻豆免费人成网站| 精品一区二区久久久久久久网站| 久久视频一区二区三区| 久久精品超碰| 最近中文字幕在线| 国产成年人视频网站| 亚洲自拍的二区三区| 午夜神马福利影院| 日本69式三人交| 中文字幕在线国产精品| 国产av无码专区亚洲av毛网站| 俺去了亚洲欧美日韩| 国产ts人妖调教重口男| 天天影院图片亚洲| 美女视频亚洲色图| av网址在线播放| 女女调教被c哭捆绑喷水百合| 欧美在线1区| 国产欧美视频一区二区| 黄色精品一区| 免费网站观看www在线观看| 日韩精品在线视频免费观看| 久久亚洲欧美国产精品乐播| 国产wwwxx| 国产污视频在线播放| bbw丰满大肥奶肥婆| 亚洲欧洲无码一区二区三区| 国产特级aaaaaa大片| 在线观看亚洲黄色| 香蕉av在线| 黄色片免费看| 视频一区二区综合| 国产精品电影| 欧美一级大片免费看| 韩国久久久久久| 国产风韵犹存在线视精品| 99久久婷婷国产一区二区三区| 日韩激情视频网站| bbw在线视频| 色播在线视频| 亚洲字幕久久| 欧美一级片黄色| 999久久欧美人妻一区二区| 国产又爽又黄又舒服又刺激视频| 韩国主播福利视频一区二区三区| 高清av免费一区中文字幕| 精品国产a一区二区三区v免费| 国内不卡的二区三区中文字幕| 国产九九在线观看| 国产男女猛烈无遮挡a片漫画| 影音先锋男人每日资源站| 艳妇乳肉豪妇荡乳av无码福利| 人妻少妇精品一区二区三区| 超碰97国产在线| 五月天婷婷综合社区| 91制片厂免费观看| 日本高清久久| 国产精品对白刺激| 暗呦丨小u女国产精品| 男女视频在线观看免费| 精品毛片乱码1区2区3区| 亚洲 自拍 另类小说综合图区| 国产精品一区二区三区在线| 国产精品自偷自拍| 亚洲国产综合久久| 很很鲁在线视频播放影院| 蜜臀在线免费观看| 国产精品久久777777| 亚洲欧美日韩精品在线| 小说区图片区图片区另类灬| 免费不卡视频| 麻豆视频一区二区| 日韩电影大全免费观看2023年上| 欧美精品网站| 久久无码高潮喷水| 日韩一区中文字幕| 欧美色大人视频| 日本欧美黄色| 拍拍拍无挡免费播放视频在线观看| 亚洲精品综合网| 黄页网站在线免费观看| 欧美顶级毛片在线播放| 国产精华一区| 蜜桃成人免费视频| 亚洲男人天堂av| 99精品电影| 极品粉嫩饱满一线天在线| 久久精品视频导航| 亚洲天堂一区二区三区| 亚洲美女性视频| xfplay先锋影音夜色资源站| 亚洲高清av一区二区三区| 欧美午夜一区二区福利视频| 国产极品嫩模在线观看91精品| 一区二区电影免费观看| 蜜臀av性久久久久av蜜臀妖精| 一个人免费观看视频www在线播放| 69国产精品| 免费av观看网站| 免费白白视频| 有没有片在线看www| 蜜臀91精品国产高清在线观看| 日韩一级免费片| 日本一级一片免费视频| 厕沟全景美女厕沟精品| 99r国产精品| 成人午夜激情视频| 精品国模一区二区三区欧美| 中文字幕乱码av| 日本一区二区三区免费乱视频| jlzzjlzzjlzz亚洲人| 可以直接看的黄色网址| 国产精品无码免费播放| 国产精品bbw一区二区三区| 一区二区三区在线| 国产精品久久久久久精| 国产精欧美一区二区三区白种人| 一级特黄a大片免费| 国产熟女一区二区丰满| 亚洲天堂影院在线观看| 无码人妻精品一区二区蜜桃网站| 免费在线性爱视频| 国产三级三级三级精品8ⅰ区| 国产精品中文久久久久久| 国产a国产a国产a| heyzo中文字幕在线| 日韩高清不卡| 色婷婷综合久色|