日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

作用域,上下文,闭包

發(fā)布時(shí)間:2025/4/16 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 作用域,上下文,闭包 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

作用域

作用域決定了你的代碼里的變量和其他資源在各個(gè)區(qū)域中的可見性,為代碼提供了一個(gè)安全層級(jí),用戶只能訪問他們當(dāng)前需要的東西。

在 JavaScript 中有兩種作用域:

全局作用域:定義在函數(shù)之外的變量會(huì)被保存在全局作用域中,在代碼的任何地方都是可訪問的。

局部作用域函數(shù)作用域):在函數(shù)內(nèi)定義的變量(局部變量)或者函數(shù)的參數(shù),只在當(dāng)前函數(shù)體內(nèi)以及這個(gè)函數(shù)體嵌套的任意函數(shù)體可訪問,函數(shù)外部不能訪問。

?

訪問當(dāng)前作用域的變量速度比訪問其他作用域的快,因?yàn)闀?huì)順著作用域鏈查找,直到找到你要的或者沒有結(jié)果。

?

在一個(gè)函數(shù)中,如果局部變量和全局變量同名,局部變量會(huì)覆蓋全局變量。在函數(shù)體內(nèi)訪問這個(gè)變量,是局部變量的值。所以,在不同的作用域,可以命名相同的變量而不導(dǎo)致沖突,解決了不同范圍的同名變量命名問題

var num = 1; //聲明一個(gè)全局變量function func() {var num = 2; //聲明一個(gè)局部變量return num;}console.log(func()); //輸出:2

局部變量在函數(shù)開始執(zhí)行時(shí)創(chuàng)建,函數(shù)執(zhí)行完后局部變量會(huì)自動(dòng)銷毀。(當(dāng)通過閉包在函數(shù)外面引用了局部變量,當(dāng)函數(shù)執(zhí)行完,局部變量不會(huì)被銷毀)

一個(gè)應(yīng)用中全局作用域的生存周期與該應(yīng)用相同。局部作用域只在該函數(shù)調(diào)用執(zhí)行期間存在。?

?

變量聲明提前

變量在整個(gè)函數(shù)體內(nèi)都是有定義的,所以在賦值前是能訪問的,即變量聲明提升到當(dāng)前函數(shù)體頂部(要是當(dāng)前函數(shù)嵌套了其他函數(shù),其他函數(shù)中聲明的變量,由于作用域鏈的關(guān)系,其他函數(shù)體的變量,在當(dāng)前函數(shù)體內(nèi)是不可訪問的,不存在聲明提升到當(dāng)前函數(shù)體的說法)

function func() {console.log(num); //輸出:undefined,而非報(bào)錯(cuò),因?yàn)樽兞縩um在整個(gè)函數(shù)體內(nèi)都是有定義的var num = 1; //聲明num 在整個(gè)函數(shù)體func內(nèi)都有定義console.log(num);?//輸出:1?
}func();

?

作用域鏈

從當(dāng)前作用域出發(fā),決定了哪些數(shù)據(jù)能被訪問,不講大道理,直接畫圖吧。

比如下圖:想在函數(shù)3里訪問變量a,過程是:先在函數(shù)3里找,沒有就在函數(shù)2里找,再?zèng)]有就在函數(shù)1里找,直到找到全局作用域,看是否有這么個(gè)變量a,是不是像順著一根鏈子找呢,這個(gè)就是作用域鏈。(上一層的作用域也叫做父級(jí)作用域)

?

ECMAScript 6 引入了let和const關(guān)鍵字。這些關(guān)鍵字可以代替var。

let likes = 'Coding'; const skills = 'Javascript and PHP';

?

和var關(guān)鍵字不同,let和const關(guān)鍵字支持在塊級(jí)聲明中創(chuàng)建使用局部作用域

if (true) { var name = 'Hammad'; let likes = 'Coding';、 const skills = 'JavaScript and PHP'; } console.log(name); // logs 'Hammad' console.log(likes); // Uncaught ReferenceError: likes is not defined console.log(skills); // Uncaught ReferenceError: skills is not defined

?

上下文

上下文指的是在相同的作用域中的this的值。可以使用函數(shù)方法改變上下文,上下文是執(zhí)行的時(shí)候確定的

在全局作用域中,上下文總是 Window 對(duì)象。

作為一個(gè)對(duì)象的方法,上下文就是這個(gè)方法所在的那個(gè)對(duì)象。

使用new關(guān)鍵字調(diào)用函數(shù)時(shí)上下文,上下文會(huì)設(shè)置為被調(diào)用的函數(shù)的實(shí)例

當(dāng)在嚴(yán)格模式(strict mode)中調(diào)用函數(shù)時(shí),上下文默認(rèn)是 undefined。

?

使用 .call(), .apply() 和 .bind() 改變上下文

Call 和 Apply 函數(shù)來改變函數(shù)調(diào)用時(shí)的上下文。
context={a:1,y:2};
function hello(a,b) {
alert(this.a);
alert(a);
alert(b);
}
hello();
hello.call(context,"cc","dd"); //1,cc,dd
hello.apply(context,["cc","dd"]); //

?

Bind 并不是自己調(diào)用函數(shù),它只是在函數(shù)調(diào)用之前綁定上下文和其他參數(shù)。

(function introduce(name, interest) { console.log('Hi! I'm '+ name +' and I like '+ interest +'.'); console.log('The value of this is '+ this +'.') }).bind(window, 'Hammad', 'Cosmology')();

?

函數(shù)的運(yùn)行過程

第一階段是創(chuàng)建階段,是函數(shù)剛被調(diào)用但代碼并未執(zhí)行的時(shí)候。創(chuàng)建階段主要發(fā)生了 3 件事。

創(chuàng)建變量對(duì)象

創(chuàng)建作用域鏈

設(shè)置上下文(this)的值

第二個(gè)階段就是代碼執(zhí)行階段,進(jìn)行其他賦值操作并且代碼最終被執(zhí)行。

?

詞法作用域

詞法作用域(靜態(tài)作用域)的意思是在函數(shù)嵌套中,內(nèi)層函數(shù)可以訪問父級(jí)作用域的變量等資源,在定義時(shí)就確定。

?

閉包

當(dāng)內(nèi)部函數(shù)試著訪問外部函數(shù)的作用域鏈(詞法作用域之外的變量)時(shí)產(chǎn)生閉包。閉包包括它們自己的作用域鏈、父級(jí)作用域鏈和全局作用域。

閉包不僅能訪問外部函數(shù)的變量,也能訪問外部函數(shù)的參數(shù)。

即使函數(shù)已經(jīng)return,閉包仍然能訪問外部函數(shù)的變量。這意味著return的函數(shù)允許持續(xù)訪問外部函數(shù)的所有資源

當(dāng)你的外部函數(shù)return一個(gè)內(nèi)部函數(shù),調(diào)用外部函數(shù)時(shí)return的函數(shù)并不會(huì)被調(diào)用。你必須先用一個(gè)單獨(dú)的變量保存外部函數(shù)的調(diào)用,然后將這個(gè)變量當(dāng)做函數(shù)來調(diào)用。

用閉包實(shí)現(xiàn)共有作用域和私有作用域

(function () { // private scope })();

?

函數(shù)結(jié)尾的括號(hào)告訴解析器立即執(zhí)行此函數(shù)。我們可以在其中加入變量和函數(shù),外部無法訪問。但如果我們想在外部訪問它們,也就是說我們希望它們一部分是公開的,一部分是私有的。我們可以使用閉包的一種形式,稱為模塊模式(Module Pattern),它允許我們用一個(gè)對(duì)象中的公有作用域和私有作用域來劃分函數(shù)。

模塊模式

var Module = (function() { function privateMethod() { // do something } return { publicMethod: function() { // can call privateMethod(); } }; })(); Module.publicMethod(); // works Module.privateMethod(); // Uncaught ReferenceError: privateMethod is not defined

?

Module 的return語句包含了我們的公共函數(shù)。私有函數(shù)并沒有被return。函數(shù)沒有被return確保了它們?cè)?Module 命名空間無法訪問。但我們的共有函數(shù)可以訪問我們的私有函數(shù),方便它們使用有用的函數(shù)、AJAX 調(diào)用或其他東西。

一種習(xí)慣是以下劃線作為開始命名私有函數(shù),并返回包含共有函數(shù)的匿名對(duì)象。這使它們?cè)诤荛L(zhǎng)的對(duì)象中很容易被管理。向下面這樣:

var Module = (function () { function _privateMethod() { // do something } function publicMethod() { // do something } return { publicMethod: publicMethod, } })();

?

立即執(zhí)行函數(shù)表達(dá)式(IIFE)

另一種形式的閉包是立即執(zhí)行函數(shù)表達(dá)式(Immediately-Invoked Function Expression,IIFE)。這是一種在 window 上下文中自調(diào)用的匿名函數(shù),也就是說this的值是window。它暴露了一個(gè)單一全局接口用來交互。如下所示:

(function(window) { // do anything })(this);

?

?兩段好玩的閉包代碼

1、返回一個(gè)函數(shù)

function createComparisonFunction(propertyName) { return function(object1, object2){
  var value1 = object1[propertyName];
  var value2 = object2[propertyName];
  if (value1 < value2){
    return -1;
  } else if (value1 > value2){
    return 1;
  } else {
    return 0;
  }
  }; }
var compare = createComparisonFunction("name");
//createComparisonFunction函數(shù)返回后,閉包的作用域鏈開始初始化,包含了Comparison作用鏈上的對(duì)象;Comparison返回后作用域鏈被銷毀,但是上面的活動(dòng)對(duì)象內(nèi)存得不到釋放,直到匿名函數(shù)被銷毀
var result = compare({ name: "Nicholas" }, { name: "Greg" }); compare=' ';//解除對(duì)匿名函數(shù)的引用,釋放內(nèi)存。此時(shí)result已經(jīng)達(dá)到目的指向了需要引用的函數(shù)

2,循環(huán)引用造成的內(nèi)存泄漏

var el = document.getElementById('MyElement');var func = function () {// }el.func = func;func.element = el;//通常循環(huán)引用發(fā)生在為dom元素添加閉包作為expendo的時(shí)候。 function init() {var el = document.getElementById('MyElement');el.onclick = function () {//…… }}init();解除引用:function init() {var el = document.getElementById('MyElement');el.onclick = function () {//…… }el = null; }init();

?

轉(zhuǎn)載于:https://www.cnblogs.com/yaoyao-sun/p/10365422.html

《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的作用域,上下文,闭包的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。